pax_global_header00006660000000000000000000000064145161444420014517gustar00rootroot0000000000000052 comment=d638f05c95ea76ee175f5b80aac5d7504b98050d cli-1.39.0/000077500000000000000000000000001451614444200123605ustar00rootroot00000000000000cli-1.39.0/.devcontainer/000077500000000000000000000000001451614444200151175ustar00rootroot00000000000000cli-1.39.0/.devcontainer/Dockerfile000066400000000000000000000020071451614444200171100ustar00rootroot00000000000000ARG GO_VERSION=1.19 ARG ALPINE_VERSION=3.16 FROM golang:${GO_VERSION}-alpine${ALPINE_VERSION} # CA certificates RUN apk add -q --update --progress --no-cache ca-certificates make curl gpg dirmngr bash sudo bat file tzdata git mandoc git-doc openssh-client zsh zsh-vcs vim libstdc++ github-cli ENV EDITOR=vim ENV LANG=en_US.UTF-8 ENV TERM=xterm ENV GO111MODULE=on # install golang tools RUN curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.49.0 RUN go install github.com/cweill/gotests/... && \ go install github.com/swaggo/swag/cmd/swag@latest && \ go install github.com/go-delve/delve/cmd/dlv@latest && \ go install github.com/fatih/gomodifytags@latest && \ go install github.com/vektra/mockery/v2@latest && \ go install github.com/golang/mock/mockgen@v1.6.0 && \ go install golang.org/x/tools/gopls@latest && \ go install github.com/josharian/impl@latest && \ go install github.com/uudashr/gopkgs/v2/cmd/gopkgs@latest cli-1.39.0/.devcontainer/devcontainer.json000066400000000000000000000050721451614444200204770ustar00rootroot00000000000000// For format details, see https://aka.ms/vscode-remote/devcontainer.json or this file's README at: // https://github.com/microsoft/vscode-dev-containers/tree/v0.137.0/containers/go { "name": "Go", "build": { "dockerfile": "Dockerfile" }, "runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined" ], // Set *default* container specific settings.json values on container create. "settings": { "go.toolsManagement.autoUpdate": false, "go.toolsManagement.checkForUpdates": "off", "go.gopath": "/go", "go.lintOnSave": "package", "go.vetOnSave": "package", "go.formatTool": "goimports", "go.useLanguageServer": true, "go.autocompleteUnimportedPackages": true, "go.gotoSymbol.includeImports": true, "go.gotoSymbol.includeGoroot": true, "go.editorContextMenuCommands": { "toggleTestFile": true, "addTags": true, "removeTags": false, "fillStruct": true, "testAtCursor": true, "testFile": false, "testPackage": false, "generateTestForFunction": true, "generateTestForFile": false, "generateTestForPackage": false, "addImport": true, "testCoverage": true, "playground": true, "debugTestAtCursor": true, "benchmarkAtCursor": false }, "go.enableCodeLens": { "references": true, "runtest": true }, "codeQL.telemetry.enableTelemetry": false, "codeQL.runningQueries.memory": 2048, "codeQL.runningQueries.debug": true, "git.autofetch": true, "editor.experimental.stickyScroll.enabled": true, "editor.guides.bracketPairs": true, "editor.renderFinalNewline": true, "editor.codeLens": true, "editor.insertSpaces": true, "editor.formatOnSave": true, "editor.formatOnPaste": true, "editor.snippetSuggestions": "none", "editor.codeActionsOnSave": { "source.organizeImports": true, "source.fixAll": true }, "workbench.iconTheme": "vscode-icons", "files.trimTrailingWhitespace": true }, // Add the IDs of extensions you want installed when the container is created. "extensions": [ "golang.Go", "ms-azuretools.vscode-docker", "github.vscode-codeql", "davidanson.vscode-markdownlint", "shardulm94.trailing-spaces", "github.vscode-pull-request-github", "eamodio.gitlens", "IBM.output-colorizer", "bungcip.better-toml" ], // Use 'forwardPorts' to make a list of ports inside the container available locally. // "forwardPorts": [9000], // Use 'postCreateCommand' to run commands after the container is created. //"postCreateCommand": "", // Uncomment to connect as a non-root user. See https://aka.ms/vscode-remote/containers/non-root. //"remoteUser": "vscode" }cli-1.39.0/.github/000077500000000000000000000000001451614444200137205ustar00rootroot00000000000000cli-1.39.0/.github/CODEOWNERS000066400000000000000000000000351451614444200153110ustar00rootroot00000000000000* @hetznercloud/integrations cli-1.39.0/.github/secrets/000077500000000000000000000000001451614444200153705ustar00rootroot00000000000000cli-1.39.0/.github/secrets/hcloud_cli.p12.gpg000066400000000000000000000064111451614444200205770ustar00rootroot00000000000000  lG3I(Eh(L%Њ1 'Noؾ( U7Bӧ55q`zzݵ SK[PסՏiXyd*۾hBΧ^ >.0Z/_U|}Uf2 19N]M"Ӟ۶nV{řa4YXM$u[k]Up{k6M]vxQh\0=wPt:MK.'g2x@vt@䠥B <sB*>eэr'3mc=Lgrf Jub-.Jom G9tlཔNaZ q/Bl">Bz mdf]RtV\n#&w̝CVm.R{6GG1#?!"RSn %m~^vArN:q٪%9!Q$i2P~C65KìYαY R|NBC r LXE{&%/ 4/f23y|g'eu QXW';hl[)&v׏ }խ<¼N V_V_7<&$YHMqh5"K)uJ 4F,MLym9@2YB}8Wh$rrs+C5 }lߺ2}Xk 2a]2"!:(wEe>~_rYnH<.*Iz Y=zd>ȉ)V88kL^۱:G$d[E#Ș;2sSՀ?'# W+mjwȿosSМ>0D#[)Еĵ|< ޲GS&YXk`6آwqZg:$˓gn LDvR&o-0غCZO\b?j|TDq6W`$;k,4N*N $1 ktr%t6r?O )qlGpt˻ ǽ 9{EWbuäHu U@af`|g@/{PM``SΖo?\s^fr w*/a}ȪA*&?<$vr:6 msZ ҊڿU\ׄ*H J<0Y#0@N=kFF I}v&M&4- $@(ΐ+n+[M^Fɕ)- Z  rOH])Ⱘ|SqPh&FB]rmG%n@-'1y -wz>W\W^rXbn؄v؅ qG:,?#[J?LOv |'pAmtR#9EWv.B9`¢-&=K(#iLRGĖ7!C;˃+lnf|٫h @0^$0 OrO X<Į]1K8֦"D>P ݍWc՛o3f3N?rny |{LěMAudMo9 KD+QpEREՎ$WIz{0$-jfzw,5ߊrNݒ1L̊u=,ԋ 0p\@MST_+,s7cd+{1=H3uK;fcY{S_\YuNNY%<6ަ'!gI^iWIbWUk8K¯^ 4ҿ d8R,e +s``@>6!\7!wFOQv]v́Ymoq[ߛ߃S/Uu>Ag'. C;tj="W w~E#IH6W#|Z᭛:_/|sgMl ~+jγz#ҺJԸ=񰿬\APDȦSJIkԒE&3S MNqNe nh#v^Z ԅE?^%#[Gf2Qlc*Mw;%Ŧ{jR;I2y99UϚ9Ƿtav'zH%0D\(! 5$*Qn?ӞݓY03TyPG(R/;/- ءiR1?pu=-hn4jp{s֖Y xJvu3wY$P(2l/cǰ(\#¯nkX*x6l􏨌"U+[1[͍ MHgHҤ wU|m<-S\{>Uh"Z(N P , RI6P=ÜYX;ph)e4,IH31}Mؾxs>77HJ'gb=cOm~ \'oakXy50tA"S{1ϊiA͝E,# tģ 0?Nsb:0wK4DQKjKX |d_#]rԀ7jag`5Q #㭟Dc˵O{Ql[{oT~הRȆ:~`'}5 H=E| sλp;1=|Z1qgB˝M*v~~*Km{*:l-\14|E s5WE^{bэENNdžy$eReBhW AB_q4mKl;]? _cli-1.39.0/.github/workflows/000077500000000000000000000000001451614444200157555ustar00rootroot00000000000000cli-1.39.0/.github/workflows/build.yml000066400000000000000000000010731451614444200176000ustar00rootroot00000000000000name: Build on: push: branches: [main] pull_request: jobs: build: runs-on: macos-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Set up Go uses: actions/setup-go@v4 with: go-version: "1.21" - name: Run GoReleaser uses: goreleaser/goreleaser-action@v5 with: version: latest args: release --clean --snapshot --skip=sign - uses: actions/upload-artifact@v3 with: name: Preview Binaries path: dist/hcloud-*/hcloud cli-1.39.0/.github/workflows/ci.yml000066400000000000000000000017071451614444200171000ustar00rootroot00000000000000name: CI on: push: branches: [main] pull_request: jobs: lint: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Set up Go uses: actions/setup-go@v4 with: go-version: "1.21" - name: Run gofmt run: diff -u <(echo -n) <(gofmt -d -s .) - name: Run golangci-lint uses: golangci/golangci-lint-action@v3 with: # Required: the version of golangci-lint is required and must be specified with patch version version: v1.54.2 # In general linting is quite fast with warm caches, but a fresh run might take some time. args: --timeout 5m test: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Set up Go uses: actions/setup-go@v4 with: go-version: "1.21" - name: Run tests run: go test -v -race ./... cli-1.39.0/.github/workflows/release-please.yml000066400000000000000000000006651451614444200213760ustar00rootroot00000000000000name: Release-please on: push: branches: [main] jobs: release-please: # The secret HCLOUD_BOT_TOKEN is only available on the main repo, not in forks. if: github.repository == 'hetznercloud/cli' runs-on: ubuntu-latest steps: - uses: google-github-actions/release-please-action@v3 with: token: ${{ secrets.HCLOUD_BOT_TOKEN }} release-type: go package-name: hcloud-cli cli-1.39.0/.github/workflows/release.yml000066400000000000000000000021111451614444200201130ustar00rootroot00000000000000name: Release on: push: tags: - "v*.*.*" jobs: release: runs-on: macos-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Set up Go uses: actions/setup-go@v4 with: go-version: "1.21" - name: Set up gon run: brew install mitchellh/gon/gon - name: Import GPG key id: import_gpg uses: crazy-max/ghaction-import-gpg@v6 with: gpg_private_key: ${{ secrets.GPG_KEY }} - name: Decrypt Secrets env: SECRETS_PASSWORD: ${{ secrets.SECRETS_PASSWORD }} run: bash script/decrypt_secrets.sh - name: Run GoReleaser uses: goreleaser/goreleaser-action@v5 with: version: latest args: release --clean --skip=validate env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} HC_APPLE_DEVELOPER_USER: ${{ secrets.HC_APPLE_DEVELOPER_USER }} HC_APPLE_DEVELOPER_PASSWORD: ${{ secrets.HC_APPLE_DEVELOPER_PASSWORD }} HC_APPLE_IDENTITY: ${{ secrets.HC_APPLE_IDENTITY }} cli-1.39.0/.github/workflows/stale.yml000066400000000000000000000003251451614444200176100ustar00rootroot00000000000000name: Close stale issues on: schedule: - cron: "30 12 * * *" jobs: stale: permissions: issues: write pull-requests: write uses: hetznercloud/.github/.github/workflows/stale.yml@main cli-1.39.0/.gitignore000066400000000000000000000000661451614444200143520ustar00rootroot00000000000000/hcloud /dist /bats /cmd/hcloud/hcloud hcloud_cli.p12 cli-1.39.0/.gitlab-ci.yml000066400000000000000000000025641451614444200150230ustar00rootroot00000000000000include: - project: cloud/integrations/ci file: - default.yml variables: COVERAGE_FILE: .testCoverage.txt workflow: rules: - # Do not execute on main branch if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH when: never - # Do not execute on tag if: $CI_COMMIT_TAG != null when: never - # Avoid duplicate pipelines in MRs if: $CI_PIPELINE_SOURCE == 'merge_request_event' when: never - when: always test:golangci-lint: stage: test image: golangci/golangci-lint:v1.54.2 script: - golangci-lint run -v test:go-mod-tidy: stage: test image: golang:1.21 script: - go mod tidy -v - git diff --exit-code test:go-generate: stage: test image: golang:1.21 variables: GOBIN: "$CI_PROJECT_DIR/bin" before_script: - script/install_tools.sh script: - export PATH="$GOBIN:$PATH" - go generate ./... - git diff --exit-code test:tests: stage: test image: golang:1.21 script: - | go test -v \ -race \ -coverprofile=$COVERAGE_FILE \ ./... - go tool cover -func=$COVERAGE_FILE | tail -n1 - GOBIN="$CI_PROJECT_DIR/bin" script/install_tools.sh - $CI_PROJECT_DIR/bin/gocover-cobertura < $COVERAGE_FILE > coverage.xml artifacts: reports: coverage_report: coverage_format: cobertura path: coverage.xml cli-1.39.0/.gitlab/000077500000000000000000000000001451614444200137005ustar00rootroot00000000000000cli-1.39.0/.gitlab/CODEOWNERS000066400000000000000000000000261451614444200152710ustar00rootroot00000000000000* @cloud/integrations cli-1.39.0/.golangci.yml000066400000000000000000000043521451614444200147500ustar00rootroot00000000000000--- linters-settings: gci: sections: - standard - default - prefix(github.com/hetznercloud) exhaustive: default-signifies-exhaustive: true gomodguard: blocked: modules: - github.com/tj/assert: recommendations: - github.com/stretchr/testify/assert reason: | One assertion library is enough and we use testify/assert everywhere. - gotest.tools/assert: recommendations: - github.com/stretchr/testify/assert reason: | One assertion library is enough and we use testify/assert everywhere. - github.com/magiconair/properties: recommendations: - github.com/stretchr/testify/assert reason: > We do not currently need to parse properties files. At the same time this module has an assert package which tends to get imported by accident. It is therefore blocked. - github.com/gogo/protobuf: recommendations: - google.golang.org/protobuf reason: > This is not the protobuf module that we want to import. - github.com/golang/protobuf: recommendations: - google.golang.org/protobuf reason: > This is the legacy import location of Google's protobuf module. Use the new one instead. misspell: locale: "US" revive: exported: true import-shadowing: true indent-error-flow: true linters: disable-all: true # Some of these are temporarily disabled until we fix the numerous issues we have. enable: - bodyclose # - dupl # - errcheck - exhaustive # - gocritic # - golint - gci - gomodguard - gosec # - gosimple - govet # - ineffassign # - misspell # - revive - rowserrcheck # - scopelint # - staticcheck - typecheck # - unparam - unused # - whitespace issues: include: - EXC0002 # disable excluding of issues about comments from golint exclude-rules: - path: _test\.go linters: - dupl - gosec - linters: - gosec text: "G204:" cli-1.39.0/.goreleaser.yml000066400000000000000000000026611451614444200153160ustar00rootroot00000000000000before: hooks: - go mod tidy builds: - id: hcloud-build main: ./cmd/hcloud/main.go binary: hcloud ldflags: - -w -X github.com/hetznercloud/cli/internal/version.Version={{.Version}} env: - CGO_ENABLED=0 goos: - freebsd - windows - linux goarch: - amd64 - arm - arm64 - "386" goarm: - "6" - "7" - id: hcloud-build-darwin main: ./cmd/hcloud/main.go binary: hcloud ldflags: - -w -X github.com/hetznercloud/cli/internal/version.Version={{.Version}} env: - CGO_ENABLED=0 goos: - darwin goarch: - amd64 - arm64 hooks: post: - cmd: bash script/gon.sh "{{ .Path }}" output: true checksum: name_template: checksums.txt algorithm: sha256 signs: - artifacts: all signature: ${artifact}.sig id: hcloud-sign ids: - hcloud-build - hcloud-build-darwin args: - --batch - --local-user=github-bot@hetzner-cloud.de - --pinentry-mode=loopback - --output=${signature} - --detach-sign - ${artifact} archives: - id: hcloud-archive builds: - hcloud-build - hcloud-build-darwin name_template: "{{ .Binary }}-{{ .Os }}-{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}" format_overrides: - goos: windows format: zip files: - LICENSE - README.md release: draft: false cli-1.39.0/CHANGELOG.md000066400000000000000000000552321451614444200142000ustar00rootroot00000000000000# Changelog ## [1.39.0](https://github.com/hetznercloud/cli/compare/v1.38.3...v1.39.0) (2023-10-25) ### Features * add --enable-protection flag to "create" commands ([#567](https://github.com/hetznercloud/cli/issues/567)) ([e313e69](https://github.com/hetznercloud/cli/commit/e313e6900f3fcf05eeace9af0c8697654b868df4)) * add "all list" command to list all resources in the project ([6d3b064](https://github.com/hetznercloud/cli/commit/6d3b064920f65807bccbf2f41f1acbc4836a760c)) * **iso:** allow to filter list by type (public, private) ([#573](https://github.com/hetznercloud/cli/issues/573)) ([140cbc3](https://github.com/hetznercloud/cli/commit/140cbc3931007e8b95e2e02d2bd9c20076da9d96)) * **primary-ip:** enable/disable-protection accept levels as arguments ([#564](https://github.com/hetznercloud/cli/issues/564)) ([b11e223](https://github.com/hetznercloud/cli/commit/b11e223c4ff51ebe46e452a10a22ca8ab002ac3b)) * **server:** add --enable-backup flag to "create" command ([#568](https://github.com/hetznercloud/cli/issues/568)) ([15adee0](https://github.com/hetznercloud/cli/commit/15adee05069e3470a9733c2cf95669436f88a253)) * **server:** add --wait flag to "shutdown" command ([#569](https://github.com/hetznercloud/cli/issues/569)) ([3ce048c](https://github.com/hetznercloud/cli/commit/3ce048cc576b21d7978daf308f48db75ebfc1f2f)) ### Bug Fixes * **floating-ip:** list command only returns first 50 entries ([#574](https://github.com/hetznercloud/cli/issues/574)) ([f3fa881](https://github.com/hetznercloud/cli/commit/f3fa8815dbec92d3f770dd2c441021aed5ce386b)) * **image:** list does not parse "type" flag correctly ([#578](https://github.com/hetznercloud/cli/issues/578)) ([9a0487a](https://github.com/hetznercloud/cli/commit/9a0487a5438e89feffe558f911522ec7b4daadf1)) * list outputs null instead of empty array when listing in JSON ([#579](https://github.com/hetznercloud/cli/issues/579)) ([93bed7e](https://github.com/hetznercloud/cli/commit/93bed7eb6b9c4d0f0b81f455c8f2ff2ba7e8e52b)) ## [1.38.3](https://github.com/hetznercloud/cli/compare/v1.38.2...v1.38.3) (2023-10-16) ### Bug Fixes * **build:** ensure signature is properly generated ([#562](https://github.com/hetznercloud/cli/issues/562)) ([77b313c](https://github.com/hetznercloud/cli/commit/77b313c4db3c4c707fd5ad454be79a3edf7e4d04)) ## [1.38.2](https://github.com/hetznercloud/cli/compare/v1.38.2-rc.0...v1.38.2) (2023-10-13) ### Bug Fixes * **build:** create release from previous candidates ([cf6eb47](https://github.com/hetznercloud/cli/commit/cf6eb472de8162c71f8de4355b714e6b0aa3a75f)) ## [1.38.2-rc.0](https://github.com/hetznercloud/cli/compare/v1.38.1...v1.38.2-rc.0) (2023-10-13) ### Bug Fixes * **build:** ensure unique tmp files for gon script ([#558](https://github.com/hetznercloud/cli/issues/558)) ([c20a78b](https://github.com/hetznercloud/cli/commit/c20a78b10c86747de5c50d117264666e6b5bb3c8)) ## [1.38.1](https://github.com/hetznercloud/cli/compare/v1.38.0...v1.38.1) (2023-10-13) ### Bug Fixes * **build:** goreleaser failed building binaries for release ([8e4cd29](https://github.com/hetznercloud/cli/commit/8e4cd2942e0b941ca0b9a61873214d9632614e76)) ## [1.38.0](https://github.com/hetznercloud/cli/compare/v1.37.0...v1.38.0) (2023-10-12) ### Features * build with Go 1.21 ([#543](https://github.com/hetznercloud/cli/issues/543)) ([368bfae](https://github.com/hetznercloud/cli/commit/368bfae953e074b4f6e81887bc437025b7dc0779)) * **iso:** support deprecation info API ([#555](https://github.com/hetznercloud/cli/issues/555)) ([2b0a0fa](https://github.com/hetznercloud/cli/commit/2b0a0fa47f01e5f22646e56840c7fa5663d2af6b)) * **load-balancer:** Add health status to list output ([#542](https://github.com/hetznercloud/cli/issues/542)) ([272cc63](https://github.com/hetznercloud/cli/commit/272cc635787a1ea09fb418fde5f5bba6252212d0)) ### Bug Fixes * typo in primary ipv6 not found error message ([#534](https://github.com/hetznercloud/cli/issues/534)) ([b9451f2](https://github.com/hetznercloud/cli/commit/b9451f2ac92bbcfb6201f6ca803c3fdc52cb557f)) ## [1.37.0](https://github.com/hetznercloud/cli/compare/v1.36.0...v1.37.0) (2023-08-17) ### Features * allow formatting a volume without automounting it ([#530](https://github.com/hetznercloud/cli/issues/530)) ([a435c9a](https://github.com/hetznercloud/cli/commit/a435c9a98a216eab3b1a2319092bd4a10a26cc9c)) * upgrade to hcloud-go v2 ([#512](https://github.com/hetznercloud/cli/issues/512)) ([e2df229](https://github.com/hetznercloud/cli/commit/e2df229c0f105c3138584424632a0a8ce3248e71)) ### Bug Fixes * make image subcommand descriptions consistent ([#519](https://github.com/hetznercloud/cli/issues/519)) ([34beff0](https://github.com/hetznercloud/cli/commit/34beff0910d63b9dae6a406c2076d3be4e23e760)) * **output:** ID column could not be selected ([#520](https://github.com/hetznercloud/cli/issues/520)) ([7d5594b](https://github.com/hetznercloud/cli/commit/7d5594bb29314b4eed5902302514fa73e1d9b445)) * **primary-ip:** assignee-id was not correctly passed when creating the IP ([#506](https://github.com/hetznercloud/cli/issues/506)) ([8c027b6](https://github.com/hetznercloud/cli/commit/8c027b65e6dd02b470f457c516aea3230e18b535)) * **server:** show actual progress on image-create ([a2f0874](https://github.com/hetznercloud/cli/commit/a2f0874af5e49d0c52df2dd5b2baebf39c7915e3)) ## [1.36.0](https://github.com/hetznercloud/cli/compare/v1.35.0...v1.36.0) (2023-06-22) ### Features * **network:** add support for exposing routes to vswitch connection ([#504](https://github.com/hetznercloud/cli/issues/504)) ([339cee9](https://github.com/hetznercloud/cli/commit/339cee9edb416b5055cf2d401124d2b9efe4ab1d)) ## [1.35.0](https://github.com/hetznercloud/cli/compare/v1.34.1...v1.35.0) (2023-06-13) ### Features * show server-type deprecation warnings ([#490](https://github.com/hetznercloud/cli/issues/490)) ([c5c0527](https://github.com/hetznercloud/cli/commit/c5c052732f0e87f7040640e20f372d8b2c2ba315)) ## [1.34.1](https://github.com/hetznercloud/cli/compare/v1.34.0...v1.34.1) (2023-06-01) ### Bug Fixes * **server:** wait for delete before returning ([#482](https://github.com/hetznercloud/cli/issues/482)) ([62cb07f](https://github.com/hetznercloud/cli/commit/62cb07f5aa6938cbdb066113e42672f16e882287)) ## [1.34.0](https://github.com/hetznercloud/cli/compare/v1.33.2...v1.34.0) (2023-05-15) ### Features * **servertype:** show included traffic ([#480](https://github.com/hetznercloud/cli/issues/480)) ([17c5f4f](https://github.com/hetznercloud/cli/commit/17c5f4f02f4753f6ce2b8e843725db9da1f78737)) ## [1.33.2](https://github.com/hetznercloud/cli/compare/v1.33.1...v1.33.2) (2023-05-08) ### Bug Fixes * **iso:** list only shows the first 50 results & missing field in json output ([#474](https://github.com/hetznercloud/cli/issues/474)) ([9d7c6a4](https://github.com/hetznercloud/cli/commit/9d7c6a416c33c98d30b6e5a0546a91ac25d5dced)) ## v1.33.1 ### What's Changed * fix: crash on server create with missing server type by @apricote in https://github.com/hetznercloud/cli/pull/469 **Full Changelog**: https://github.com/hetznercloud/cli/compare/v1.33.0...v1.33.1 ## v1.33.0 Affordable, sustainable & powerful! 🚀You can now get one of our Arm64 CAX servers to optimize your operations while minimizing your costs! Discover Ampere’s efficient and robust Arm64 architecture and be ready to get blown away with its performance. 😎 Learn more: https://www.hetzner.com/news/arm64-cloud ### What's Changed * test: fix gitlab test setup by @apricote in https://github.com/hetznercloud/cli/pull/466 * fix: send debug output to stderr by @apricote in https://github.com/hetznercloud/cli/pull/467 * feat: add support for ARM APIs by @apricote in https://github.com/hetznercloud/cli/pull/468 **Full Changelog**: https://github.com/hetznercloud/cli/compare/v1.32.0...v1.33.0 ## v1.32.0 ### Notable Changes * Adding "loadbalancer" as an alias to the "load-balancer" command by @cedi in https://github.com/hetznercloud/cli/pull/424 * feat(primary-ip): add and remove labels by @apricote in https://github.com/hetznercloud/cli/pull/435 * feat(server): return password on rebuild by @apricote in https://github.com/hetznercloud/cli/pull/460 * fix(placement-group): invalid json response #464 by @apricote in https://github.com/hetznercloud/cli/pull/465 ### All Changes * Adding "loadbalancer" as an alias to the "load-balancer" command by @cedi in https://github.com/hetznercloud/cli/pull/424 * feat(primary-ip): add and remove labels by @apricote in https://github.com/hetznercloud/cli/pull/435 * chore: remove unused hcapi.CertificateClient by @samcday in https://github.com/hetznercloud/cli/pull/441 * chore: remove unused hcapi.PrimaryIPClient by @samcday in https://github.com/hetznercloud/cli/pull/442 * chore: remove unused hcapi.DataCenterClient by @samcday in https://github.com/hetznercloud/cli/pull/443 * chore: migrate hcapi.ISOClient usage to hcapi2 by @samcday in https://github.com/hetznercloud/cli/pull/444 * Adding a .devcontainer configuration for usage in GitHub Codespaces by @cedi in https://github.com/hetznercloud/cli/pull/419 * chore: replace hcapi.ImageClient usage with hcapi2 by @samcday in https://github.com/hetznercloud/cli/pull/445 * chore: replace hcapi.LocationClient usage with hcapi2 by @samcday in https://github.com/hetznercloud/cli/pull/446 * fix: improve unset version specifier by @apricote in https://github.com/hetznercloud/cli/pull/447 * Bump golang.org/x/net from 0.2.0 to 0.7.0 by @dependabot in https://github.com/hetznercloud/cli/pull/448 * chore: remove unused hcapi.PlacementGroupClient by @samcday in https://github.com/hetznercloud/cli/pull/450 * chore: migrate hcapi.SSHKeyClient usages to hcapi2 by @samcday in https://github.com/hetznercloud/cli/pull/449 * chore: migrate hcapi.VolumeClient usage to hcapi2 by @samcday in https://github.com/hetznercloud/cli/pull/451 * chore: replace hcapi.FloatingIPClient usages with hcapi2 by @samcday in https://github.com/hetznercloud/cli/pull/452 * chore: migrate hcapi.FirewallClient usages to hcapi2 by @samcday in https://github.com/hetznercloud/cli/pull/454 * chore: migrate hcapi.NetworkClient usages to hcapi2 by @samcday in https://github.com/hetznercloud/cli/pull/453 * chore: replace hcapi.LoadBalancerClient usages with hcapi2 by @samcday in https://github.com/hetznercloud/cli/pull/455 * chore: replace hcapi.ServerClient usages with hcapi2 by @samcday in https://github.com/hetznercloud/cli/pull/456 * chore(deps): update module github.com/hetznercloud/hcloud-go to v1.41.0 by @apricote in https://github.com/hetznercloud/cli/pull/459 * feat(server): return password on rebuild by @apricote in https://github.com/hetznercloud/cli/pull/460 * fix(placement-group): invalid json response #464 by @apricote in https://github.com/hetznercloud/cli/pull/465 ### New Contributors * @samcday made their first contribution in https://github.com/hetznercloud/cli/pull/441 * @dependabot made their first contribution in https://github.com/hetznercloud/cli/pull/448 **Full Changelog**: https://github.com/hetznercloud/cli/compare/v1.31.1...v1.32.0 ## v1.31.1 ### What's Changed * ci: fix issue where release pipeline fails and no assets are produced by @apricote in https://github.com/hetznercloud/cli/pull/430 * fix(ci): race-condition in signing macos binaries by @apricote in https://github.com/hetznercloud/cli/pull/433 **Full Changelog**: https://github.com/hetznercloud/cli/compare/v1.31.0...v1.31.1 ## v1.31.0 ### What's Changed * server/list: Add missing PlacementGroup to JSON by @tomsiewert in https://github.com/hetznercloud/cli/pull/416 * Update the toml library to the latest version by @cedi in https://github.com/hetznercloud/cli/pull/422 * Adding an age column to the cli, closes #417 by @cedi in https://github.com/hetznercloud/cli/pull/420 * feat(completion): read network zones from API by @apricote in https://github.com/hetznercloud/cli/pull/426 ### New Contributors * @cedi made their first contribution in https://github.com/hetznercloud/cli/pull/422 **Full Changelog**: https://github.com/hetznercloud/cli/compare/v1.30.4...v1.30.5 ## v1.30.4 ### What's Changed * chore: update hcloud-go to v1.37.0 by @apricote in https://github.com/hetznercloud/cli/pull/413 * fix: primary-ip list returns max 50 items by @apricote in https://github.com/hetznercloud/cli/pull/415 ### New Contributors * @apricote made their first contribution in https://github.com/hetznercloud/cli/pull/414 **Full Changelog**: https://github.com/hetznercloud/cli/compare/v1.30.3...v1.30.4 ## v1.30.3 ### What's Changed * Fix hcloud server-type describe completion by @LKaemmerling in https://github.com/hetznercloud/cli/pull/407 * Improve hcloud server ssh command to use IPv6 automatically if no IPv… by @LKaemmerling in https://github.com/hetznercloud/cli/pull/406 **Full Changelog**: https://github.com/hetznercloud/cli/compare/v1.30.2...v1.30.3 ## v1.30.2 ### What's Changed * Update Dependencies by @LKaemmerling in https://github.com/hetznercloud/cli/pull/402 * Fix primary-ip list -o json by @LKaemmerling in https://github.com/hetznercloud/cli/pull/403 **Full Changelog**: https://github.com/hetznercloud/cli/compare/v1.30.1...v1.30.2 ## v1.30.1 ### What's Changed * Fix hcloud server ssh with flexible network options by @LKaemmerling in https://github.com/hetznercloud/cli/pull/396 **Full Changelog**: https://github.com/hetznercloud/cli/compare/v1.30.0...v1.30.1 ## v1.30.0 ### What's Changed * Add Alpine Linux to third-party packages by @firefly-cpp in https://github.com/hetznercloud/cli/pull/387 * Add Fedora to the list of third-party providers by @wULLSnpAXbWZGYDYyhWTKKspEQoaYxXyhoisqHf in https://github.com/hetznercloud/cli/pull/388 * fix(readme): correct messed-up columns ... by @wULLSnpAXbWZGYDYyhWTKKspEQoaYxXyhoisqHf in https://github.com/hetznercloud/cli/pull/389 * Remove freebsd64 rescue system type by @LKaemmerling in https://github.com/hetznercloud/cli/pull/391 * Remove Third-party packages Table by @LKaemmerling in https://github.com/hetznercloud/cli/pull/392 * Add Primary IP Support by @LKaemmerling in https://github.com/hetznercloud/cli/pull/393 ### New Contributors * @firefly-cpp made their first contribution in https://github.com/hetznercloud/cli/pull/387 * @wULLSnpAXbWZGYDYyhWTKKspEQoaYxXyhoisqHf made their first contribution in https://github.com/hetznercloud/cli/pull/388 **Full Changelog**: https://github.com/hetznercloud/cli/compare/v1.29.5...v1.30.0 ## v1.29.5 ### What's Changed * Fix: Use the correct object to return in case of created_from flag by @4ND3R50N in https://github.com/hetznercloud/cli/pull/385 ### New Contributors * @4ND3R50N made their first contribution in https://github.com/hetznercloud/cli/pull/385 **Full Changelog**: https://github.com/hetznercloud/cli/compare/v1.29.4...v1.29.5 ## v1.29.4 **Full Changelog**: https://github.com/hetznercloud/cli/compare/v1.29.0...v1.29.4 ## v1.29.1 ### What's Changed * Fix installation instructions by @fhofherr in https://github.com/hetznercloud/cli/pull/368 * Fix missing new line on hcloud describe command by @LKaemmerling in https://github.com/hetznercloud/cli/pull/380 * Use Go 1.18 for building & testing by @LKaemmerling in https://github.com/hetznercloud/cli/pull/381 * Trim and lowercase for column selectors by @gadelkareem in https://github.com/hetznercloud/cli/pull/375 ### New Contributors * @gadelkareem made their first contribution in https://github.com/hetznercloud/cli/pull/375 **Full Changelog**: https://github.com/hetznercloud/cli/compare/v1.29.0...v1.29.1 ## v1.29.0 - Add support for network zone `us-east` - Build with Go 1.17 The binary for Apple Silicon is omitted for this release because of issues with the Apple Notary Service. ## v1.28.1 ### Changelog * 4410fb4 Fix panic on iso & location list as json (#361) * 94b5d5f Move RDNS Commands to RDNS Client (#357) ## v1.28.0 ### Changelog * 3d7078a Add support for LB DNS PTRs (#355) * eee45a9 Remove no longer used build scripts (#353) ## v1.27.0 ### Changelog * 4b8ed4d Placement groups (#352) ## v1.26.1 ### Changelog * 2ab6137 Fix firewall description * 01180ad Update hcloud-go to 1.29.1 ## v1.26.0 ### Changelog * b4c1d1b Add description field to firewall rules * caa9bf2 Fix pagination of list commands (#347) ## v1.25.1 ### Changelog * 687f623 internal/cmd: Remove redundant DescribeJSON from JSONSchema (#345) ## v1.25.0 ### Changelog * 830d0bc Add support for App images (#344) * ac23982 Fix changelog generation ## v1.25.0-alpha.1 ### Changelog This release contains a major refactoring of the code and is marked as alpha. We recommend using the latest stable release, but feel free to test this release and report bugs if you find something. ## v1.24.0 ### Changelog * 08da869 Add Support for Firewall Protocol GRE & ESP (#331) ## v1.23.0 ### Changelog * 234dd6d Implement Firewall resource label selector (#328) * 5ea977e5dda83022d701e056157f7e218c7674c6 Support getting Firewalls by label selector (#327) * bb30002002cd2c8af6b20269eff549d09f7204a5 server: Add ability to get traffic as column (#325) * 8d0f07e802cebf6df44daa3ad8933cebe489a8d1 firewall: Add empty slices for respective direction instead of nil-slices (#324) ## v1.22.1 ### Changelog * 4e97f5c Add Powershell completion (#316) * b93bb4fe2716a34d79504e588d90f55dc8cf8ab9 Fix output option broke with last release (#315) ## v1.22.0 ### Changelog * 7969d5b Add support for managed certificates ## v1.21.1 ### Changelog * 5442833 The cli normalized the given CIDRs by default, so when a user entered 10.0.0.1/8 (as a sample) the cli normalized it to 10.0.0.0/8 silent. After this MR we now validate that the given IP is the start of the CIDR block (e.g. 10.0.0.0/8). (#304) ## v1.21.0 ### Changelog * 6c04c99 Specify timeout on release jobs * afd597adb2e7bda63cd497546a7ecbb1186307cb Implement Firewall support (#301) * 67ba0adc61faf4ce4696626abb0c322029f6240d Update to Go 1.16 and support Apple Silicon (darwin/arm64) (#298) ## v1.20.0 ### Changelog * 178bf96 Add vswitch integration (#283) * 9d209c0 Update to cobra 1.1.1 (#282) ## v1.19.1 ### Changelog ## v1.19.0 ### Changelog * d5d2fec Update hcloud-go to 1.22.0 and expose correct disk size for resized without disk server (#269) * 5049b00 Add handling for deprecated Images (#263) * be48b5e Use go 1.15 (#267) * ad3a564 Improve/Rewrite Shell completions (#266) ## v1.18.0 ### Changelog * 290c168 hcloud server describe use correct unit for traffic counter (#259) * c1bd46c Implement Label Selector and IP target support (#258) * d5a31ce Expose the new traffic fields and add load-balancer change-type command (#256) * Add pricing per location to load-balancer-type describe and server-type describe (#254) * 5fc1464 Fix context list nil pointer when no active context was given. (#252) * 8245b2f Add (required) to help text of all required args (#253) * 03c3c82 Fix typos (#251) * 506c1b1 added instructions for completion with antigen in zsh. (#240) * 5d6f1bb Add command to request a VNC console (#238) ## v1.17.0 ### Changelog * 50a7de3 Add support for Load Balancers and Certificates (#245) * 196557e Show Server Type CPU Type on server-type list, server-type describe and server describe (#244) * b2d33f1 Allow the created field to be within the list responses (#237) ## v1.16.2 ### Changelog * 3bc0379 Fix completion of server name on hcloud server ssh (#233) * cc8786c Update to go 1.14 (#234) * 8c32195 Add missing labels to hcloud server list -o json response (#231) ## v1.16.1 ### Changelog * eef73ac Bugfix: Add private_net to server list json response (#229) ## v1.16.0 ### Changelog * 613eafc Add option to label servers, volumes, images, floating ips and ssh keys on creation (#227) * 0ff7a1b Add JSON output option to all hcloud list commands (#225) ## v1.15.0 ### Changelog * 381f133 Switch Build and Release System to Github Actions (#223) * 85e971e Add stale bot (#221) ## v1.14.0 * Expose server’s MAC address in networks on `hcloud server describe` * Add support for names to Floating IP commands * Make `--ip-range` on `hcloud network add-subnet` optional * Add debug mode (use `HCLOUD_DEBUG` and `HCLOUD_DEBUG_FILE`) * Add `hcloud server ip` command * Expose `Created` on `hcloud floating-ip|image|ssh-key|volume describe` * Refactor progressbar and add loading animation for running actions ## v1.13.0 * Show server name instead of ID on `hcloud floating-ip|volume|image list` * Add support for networks ## v1.12.0 * Add support for executing commands via `hcloud server ssh ` * Make overriding context via `HCLOUD_CONTEXT` work * Add support for JSON and Go template output * Add support for multiple user data files * Add length validation for API token on `hcloud context create` * Add `active` column to context list on `hcloud context list` ## v1.11.0 * Add support for automounting and formatting volumes ## v1.10.0 * Fix creating a volume when server is specified by its name * Deprecate and ignore the `--window` flag on `hcloud server enable-backup` * Add output columns `type|labels|volumes|protection` to `hcloud server list` * Add output columns `labels|protection` to `hcloud volume list` * Add output column `labels` to `hcloud image list` * Add output column `labels` to `hcloud floating-ip list` * Add output column `labels` to `hcloud ssh-key list` ## v1.9.1 * Fix formatting issue on `hcloud volume list` and `hcloud volume describe` ## v1.9.0 * Add support for volumes * Add `--start-after-create` flag to `hcloud server create` command ## v1.8.0 * Add `hcloud ssh-key update` command * Add `-u/--user` and `-p/--port` flags to `hcloud server ssh` command * Add `hcloud server set-rdns` command * Add `hcloud floating-ip set-rdns` command ## v1.7.0 * Add type filter flag `-t` / `--type` to `image list` command * Expose labels of servers, Floating IPs, images, and SSH Keys * Add `hcloud {server|ssh-key|image|floating-ip} {add-label|remove-label}` commands ## v1.6.1 * Fix invalid formatting of integers in `hcloud * list` commands ## v1.6.0 * Show IP address upon creating a server * Add `--poll-interval` flag for controlling the polling interval (for example for action progress updates) ## v1.5.0 * Add `hcloud server ssh` command to open an SSH connection to the server ## v1.4.0 * Document `-o` flag for controlling output formatting * Add commands `enable-protection` and `disable-protection` for images, Floating IPs, and servers ## v1.3.2 * Show progress for every action * Show datacenter in `server list` and `server describe` ## v1.3.1 * Only poll action progress every 500ms (instead of every 100ms) * Document `HCLOUD_TOKEN` and make it work when there is no active context ## v1.3.0 * Print dates in local time * Do not echo token when creating a context * Add `--user-data-from-file` flag to `hcloud server create` command ## v1.2.0 * Update hcloud library to v1.2.0 fixing rate limit check ## v1.1.0 * Show image information in `hcloud server describe` * Auto-activate created context on `hcloud context create` * Fix `hcloud version` not showing correct version cli-1.39.0/LICENSE000066400000000000000000000020631451614444200133660ustar00rootroot00000000000000MIT License Copyright (c) 2018 Hetzner Cloud GmbH 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. cli-1.39.0/README.md000066400000000000000000000121041451614444200136350ustar00rootroot00000000000000# hcloud: Command-line interface for Hetzner Cloud [![Build status](https://travis-ci.org/hetznercloud/cli.svg?branch=master)](https://travis-ci.org/hetznercloud/cli) `hcloud` is a command-line interface for interacting with Hetzner Cloud. [![asciicast](https://asciinema.org/a/157991.png)](https://asciinema.org/a/157991) ## Installation You can download pre-built binaries for Linux, FreeBSD, macOS, and Windows on the [releases page](https://github.com/hetznercloud/cli/releases). On macOS and Linux, you can install `hcloud` via [Homebrew](https://brew.sh/): brew install hcloud On Windows, you can install `hcloud` via [Scoop](https://scoop.sh/) scoop install hcloud ### Third-party packages There are unofficial packages maintained by third-party users. Please note that these packages aren’t supported nor maintained by Hetzner Cloud and may not always be up-to-date. Downloading the binary or building from source is still the recommended install method. ### Build manually If you have Go installed, you can build and install the latest version of `hcloud` with: go install github.com/hetznercloud/cli/cmd/hcloud@latest > Binaries built in this way do not have the correct version embedded. Use our prebuilt binaries or check out [`.goreleaser.yml`](.goreleaser.yml) to learn how to embed it yourself. ## Getting Started 1. Visit the Hetzner Cloud Console at [console.hetzner.cloud](https://console.hetzner.cloud/), select your project, and create a new API token. 2. Configure the `hcloud` program to use your token: hcloud context create my-project 3. You’re ready to use the program. For example, to get a list of available server types, run: hcloud server-type list See `hcloud help` for a list of commands. ## Shell Completion `hcloud` provides completions for various shells. ### Bash To load completions into the current shell execute: source <(hcloud completion bash) In order to make the completions permanent, append the line above to your `.bashrc`. ### Zsh If shell completions are not already enabled for your environment need to enable them. Add the following line to your `~/.zshrc` file: autoload -Uz compinit; compinit To load completions for each session execute the following commands: mkdir -p ~/.config/hcloud/completion/zsh hcloud completion zsh > ~/.config/hcloud/completion/zsh/_hcloud Finally, add the following line to your `~/.zshrc` file, *before* you call the `compinit` function: fpath+=(~/.config/hcloud/completion/zsh) In the end your `~/.zshrc` file should contain the following two lines in the order given here. fpath+=(~/.config/hcloud/completion/zsh) # ... anything else that needs to be done before compinit autoload -Uz compinit; compinit # ... You will need to start a new shell for this setup to take effect. ### Fish To load completions into the current shell execute: hcloud completion fish | source In order to make the completions permanent execute once: hcloud completion fish > ~/.config/fish/completions/hcloud.fish ### PowerShell: To load completions into the current shell execute: PS> hcloud completion powershell | Out-String | Invoke-Expression To load completions for every new session, run and source this file from your PowerShell profile. PS> hcloud completion powershell > hcloud.ps1 ## Output configuration You can control output via the `-o` option: * For `list` commands, you can specify `-o noheader` to omit the table header. * For `list` commands, you can specify `-o columns=id,name` to only show certain columns in the table. * For `describe` commands, you can specify `-o json` to get a JSON representation of the resource. The schema is identical to those in the Hetzner Cloud API which are documented at [docs.hetzner.cloud](https://docs.hetzner.cloud). * For `describe` commands, you can specify `-o format={{.ID}}` to format output according to the given [Go template](https://golang.org/pkg/text/template/). The template’s input is the resource’s corresponding struct in the [hcloud-go](https://godoc.org/github.com/hetznercloud/hcloud-go/hcloud) library. ## Configure hcloud using environment variables You can use the following environment variables to configure `hcloud`: * `HCLOUD_TOKEN` * `HCLOUD_CONTEXT` * `HCLOUD_CONFIG` When using `hcloud` in scripts, for example, it may be cumbersome to work with contexts. Instead of creating a context, you can set the token via the `HCLOUD_TOKEN` environment variable. When combined with tools like [direnv](https://direnv.net), you can configure a per-directory context by setting `HCLOUD_CONTEXT=my-context` via `.envrc`. ## Examples ### List all servers ``` $ hcloud server list ID NAME STATUS IPV4 210216 test1 running 78.46.122.12 210729 ubuntu-8gb-nbg1-dc3-1 running 94.130.177.158 ``` ### Create a server ``` $ hcloud server create --name test --image debian-9 --type cx11 --ssh-key demo 7s [====================================================================] 100% Server 325211 created ``` ## License MIT license cli-1.39.0/cmd/000077500000000000000000000000001451614444200131235ustar00rootroot00000000000000cli-1.39.0/cmd/hcloud/000077500000000000000000000000001451614444200144015ustar00rootroot00000000000000cli-1.39.0/cmd/hcloud/main.go000066400000000000000000000015501451614444200156550ustar00rootroot00000000000000package main import ( "log" "os" "github.com/hetznercloud/cli/internal/cli" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" ) func init() { log.SetFlags(0) log.SetPrefix("hcloud: ") log.SetOutput(os.Stderr) } func main() { cliState := state.New() if cliState.ConfigPath != "" { _, err := os.Stat(cliState.ConfigPath) switch { case err == nil: if err := cliState.ReadConfig(); err != nil { log.Fatalf("unable to read config file %q: %s\n", cliState.ConfigPath, err) } case os.IsNotExist(err): break default: log.Fatalf("unable to read config file %q: %s\n", cliState.ConfigPath, err) } } cliState.ReadEnv() apiClient := hcapi2.NewClient(cliState.Client()) rootCommand := cli.NewRootCommand(cliState, apiClient) if err := rootCommand.Execute(); err != nil { log.Fatalln(err) } } cli-1.39.0/examples/000077500000000000000000000000001451614444200141765ustar00rootroot00000000000000cli-1.39.0/examples/firewall_rules.json000066400000000000000000000007061451614444200201130ustar00rootroot00000000000000[ { "direction": "in", "source_ips": [ "28.239.13.1/32", "28.239.14.0/24", "ff21:1eac:9a3b:ee58:5ca:990c:8bc9:c03b/128" ], "destination_ips": [], "protocol": "tcp", "port": "80" }, { "direction": "out", "source_ips": [], "destination_ips": [ "28.239.13.1/32", "28.239.14.0/24", "ff21:1eac:9a3b:ee58:5ca:990c:8bc9:c03b/128" ], "protocol": "tcp", "port": "80" } ] cli-1.39.0/go.mod000066400000000000000000000033711451614444200134720ustar00rootroot00000000000000module github.com/hetznercloud/cli go 1.21.1 require ( github.com/boumenot/gocover-cobertura v1.2.0 github.com/cheggaaa/pb/v3 v3.1.4 github.com/dustin/go-humanize v1.0.1 github.com/fatih/structs v1.1.0 github.com/golang/mock v1.6.0 github.com/google/go-cmp v0.6.0 github.com/guptarohit/asciigraph v0.5.6 github.com/hetznercloud/hcloud-go/v2 v2.4.0 github.com/pelletier/go-toml/v2 v2.1.0 github.com/rjeczalik/interfaces v0.3.0 github.com/spf13/cobra v1.7.0 github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.8.4 golang.org/x/crypto v0.14.0 ) require ( github.com/VividCortex/ewma v1.2.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/fatih/color v1.15.0 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.19 // indirect github.com/mattn/go-runewidth v0.0.14 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_golang v1.17.0 // indirect github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 // indirect github.com/prometheus/common v0.44.0 // indirect github.com/prometheus/procfs v0.11.1 // indirect github.com/rivo/uniseg v0.2.0 // indirect golang.org/x/mod v0.9.0 // indirect golang.org/x/net v0.17.0 // indirect golang.org/x/sys v0.13.0 // indirect golang.org/x/term v0.13.0 // indirect golang.org/x/text v0.13.0 // indirect golang.org/x/tools v0.6.0 // indirect google.golang.org/protobuf v1.31.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) cli-1.39.0/go.sum000066400000000000000000000302351451614444200135160ustar00rootroot00000000000000github.com/VividCortex/ewma v1.2.0 h1:f58SaIzcDXrSy3kWaHNvuJgJ3Nmz59Zji6XoJR/q1ow= github.com/VividCortex/ewma v1.2.0/go.mod h1:nz4BbCtbLyFDeC9SUHbtcT5644juEuWfUAUnGx7j5l4= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/boumenot/gocover-cobertura v1.2.0 h1:g+VROIASoEHBrEilIyaCmgo7HGm+AV5yKEPLk0qIY+s= github.com/boumenot/gocover-cobertura v1.2.0/go.mod h1:fz7ly8dslE42VRR5ZWLt2OHGDHjkTiA2oNvKgJEjLT0= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cheggaaa/pb/v3 v3.1.4 h1:DN8j4TVVdKu3WxVwcRKu0sG00IIU6FewoABZzXbRQeo= github.com/cheggaaa/pb/v3 v3.1.4/go.mod h1:6wVjILNBaXMs8c21qRiaUM8BR82erfgau1DQ4iUXmSA= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/guptarohit/asciigraph v0.5.6 h1:0tra3HEhfdj1sP/9IedrCpfSiXYTtHdCgBhBL09Yx6E= github.com/guptarohit/asciigraph v0.5.6/go.mod h1:dYl5wwK4gNsnFf9Zp+l06rFiDZ5YtXM6x7SRWZ3KGag= github.com/hetznercloud/hcloud-go/v2 v2.4.0 h1:MqlAE+w125PLvJRCpAJmEwrIxoVdUdOyuFUhE/Ukbok= github.com/hetznercloud/hcloud-go/v2 v2.4.0/go.mod h1:l7fA5xsncFBzQTyw29/dw5Yr88yEGKKdc6BHf24ONS0= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 h1:v7DLqVdK4VrYkVD5diGdl4sxJurKJEMnODWRJlxV9oM= github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI= github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rjeczalik/interfaces v0.3.0 h1:BM+eRAwfOcvW5qVhxv7x09x/0jwHN6z2GB9HsSA2weM= github.com/rjeczalik/interfaces v0.3.0/go.mod h1:wfGcwiM/PXv9l6U/CPCb4Yh5KngED3dR3OppEVHMWuU= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs= golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200526224456-8b020aee10d2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= cli-1.39.0/internal/000077500000000000000000000000001451614444200141745ustar00rootroot00000000000000cli-1.39.0/internal/cli/000077500000000000000000000000001451614444200147435ustar00rootroot00000000000000cli-1.39.0/internal/cli/root.go000066400000000000000000000047331451614444200162640ustar00rootroot00000000000000package cli import ( "time" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/all" "github.com/hetznercloud/cli/internal/cmd/certificate" "github.com/hetznercloud/cli/internal/cmd/completion" "github.com/hetznercloud/cli/internal/cmd/context" "github.com/hetznercloud/cli/internal/cmd/datacenter" "github.com/hetznercloud/cli/internal/cmd/firewall" "github.com/hetznercloud/cli/internal/cmd/floatingip" "github.com/hetznercloud/cli/internal/cmd/image" "github.com/hetznercloud/cli/internal/cmd/iso" "github.com/hetznercloud/cli/internal/cmd/loadbalancer" "github.com/hetznercloud/cli/internal/cmd/loadbalancertype" "github.com/hetznercloud/cli/internal/cmd/location" "github.com/hetznercloud/cli/internal/cmd/network" "github.com/hetznercloud/cli/internal/cmd/placementgroup" "github.com/hetznercloud/cli/internal/cmd/primaryip" "github.com/hetznercloud/cli/internal/cmd/server" "github.com/hetznercloud/cli/internal/cmd/servertype" "github.com/hetznercloud/cli/internal/cmd/sshkey" "github.com/hetznercloud/cli/internal/cmd/version" "github.com/hetznercloud/cli/internal/cmd/volume" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" ) func NewRootCommand(state *state.State, client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "hcloud", Short: "Hetzner Cloud CLI", Long: "A command-line interface for Hetzner Cloud", TraverseChildren: true, SilenceUsage: true, SilenceErrors: true, DisableFlagsInUseLine: true, } cmd.AddCommand( all.NewCommand(state, client), floatingip.NewCommand(state, client), image.NewCommand(state, client), server.NewCommand(state, client), sshkey.NewCommand(state, client), version.NewCommand(state), completion.NewCommand(state), servertype.NewCommand(state, client), context.NewCommand(state), datacenter.NewCommand(state, client), location.NewCommand(state, client), iso.NewCommand(state, client), volume.NewCommand(state, client), network.NewCommand(state, client), loadbalancer.NewCommand(state, client), loadbalancertype.NewCommand(state, client), certificate.NewCommand(state, client), firewall.NewCommand(state, client), placementgroup.NewCommand(state, client), primaryip.NewCommand(state, client), ) cmd.PersistentFlags().Duration("poll-interval", 500*time.Millisecond, "Interval at which to poll information, for example action progress") return cmd } cli-1.39.0/internal/cmd/000077500000000000000000000000001451614444200147375ustar00rootroot00000000000000cli-1.39.0/internal/cmd/all/000077500000000000000000000000001451614444200155075ustar00rootroot00000000000000cli-1.39.0/internal/cmd/all/all.go000066400000000000000000000010241451614444200166030ustar00rootroot00000000000000package all import ( "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" ) func NewCommand(cli *state.State, client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "all", Short: "Commands that apply to all resources", Args: cobra.NoArgs, TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.AddCommand( listCmd.CobraCommand(cli.Context, client, cli, cli), ) return cmd } cli-1.39.0/internal/cmd/all/list.go000066400000000000000000000111651451614444200170150ustar00rootroot00000000000000package all import ( "context" "encoding/json" "fmt" "strings" "github.com/spf13/cobra" "github.com/spf13/pflag" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/certificate" "github.com/hetznercloud/cli/internal/cmd/firewall" "github.com/hetznercloud/cli/internal/cmd/floatingip" "github.com/hetznercloud/cli/internal/cmd/image" "github.com/hetznercloud/cli/internal/cmd/iso" "github.com/hetznercloud/cli/internal/cmd/loadbalancer" "github.com/hetznercloud/cli/internal/cmd/network" "github.com/hetznercloud/cli/internal/cmd/output" "github.com/hetznercloud/cli/internal/cmd/placementgroup" "github.com/hetznercloud/cli/internal/cmd/primaryip" "github.com/hetznercloud/cli/internal/cmd/server" "github.com/hetznercloud/cli/internal/cmd/sshkey" "github.com/hetznercloud/cli/internal/cmd/volume" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var allCmds = []base.ListCmd{ server.ListCmd, image.ListCmd, placementgroup.ListCmd, primaryip.ListCmd, iso.ListCmd, volume.ListCmd, loadbalancer.ListCmd, floatingip.ListCmd, network.ListCmd, firewall.ListCmd, certificate.ListCmd, sshkey.ListCmd, } var listCmd = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { var resources []string for _, cmd := range allCmds { resources = append(resources, " - "+cmd.ResourceNamePlural) } cmd := &cobra.Command{ Use: "list FLAGS", Short: "List all resources in the project", Long: `List all resources in the project. This does not include static/public resources like locations, public ISOs, etc. Listed resources are: ` + strings.Join(resources, "\n"), } cmd.Flags().StringP("selector", "l", "", "Selector to filter by labels") cmd.Flags().Bool("paid", false, "Only list resources that cost money") output.AddFlag(cmd, output.OptionJSON()) return cmd }, Run: func(ctx context.Context, client hcapi2.Client, actionWaiter state.ActionWaiter, cmd *cobra.Command, args []string) error { paid, _ := cmd.Flags().GetBool("paid") labelSelector, _ := cmd.Flags().GetString("selector") outOpts := output.FlagsForCommand(cmd) var cmds []base.ListCmd if paid { cmds = []base.ListCmd{ server.ListCmd, image.ListCmd, primaryip.ListCmd, volume.ListCmd, loadbalancer.ListCmd, floatingip.ListCmd, } } else { cmds = []base.ListCmd{ server.ListCmd, image.ListCmd, placementgroup.ListCmd, primaryip.ListCmd, iso.ListCmd, volume.ListCmd, loadbalancer.ListCmd, floatingip.ListCmd, network.ListCmd, firewall.ListCmd, certificate.ListCmd, sshkey.ListCmd, } } type response struct { result []any err error } responseChs := make([]chan response, len(cmds)) // Start all requests in parallel in order to minimize response time for i, lc := range cmds { i, lc := i, lc ch := make(chan response) responseChs[i] = ch go func() { defer close(ch) listOpts := hcloud.ListOpts{ LabelSelector: labelSelector, } flagSet := pflag.NewFlagSet(lc.JSONKeyGetByName, pflag.ExitOnError) switch lc.JSONKeyGetByName { case image.ListCmd.JSONKeyGetByName: flagSet.StringSlice("type", []string{"backup", "snapshot"}, "") case iso.ListCmd.JSONKeyGetByName: flagSet.StringSlice("type", []string{"private"}, "") } // FlagSet has to be parsed to be populated. // We pass an empty slice because we defined the flags earlier. _ = flagSet.Parse([]string{}) result, err := lc.Fetch(ctx, client, flagSet, listOpts, []string{}) ch <- response{result, err} }() } // Wait for all requests to finish and collect results resources := make([][]any, len(cmds)) for i, responseCh := range responseChs { response := <-responseCh if err := response.err; err != nil { return err } resources[i] = response.result } if outOpts.IsSet("json") { jsonSchema := make(map[string]any) for i, lc := range cmds { jsonSchema[lc.JSONKeyGetByName] = lc.JSONSchema(resources[i]) } jsonBytes, err := json.Marshal(jsonSchema) if err != nil { return err } fmt.Printf("%s\n", jsonBytes) return nil } for i, lc := range cmds { cols := lc.DefaultColumns table := lc.OutputTable(client) table.WriteHeader(cols) if len(resources[i]) == 0 { continue } fmt.Print(strings.ToUpper(lc.ResourceNamePlural) + "\n---\n") for _, resource := range resources[i] { table.Write(cols, resource) } if err := table.Flush(); err != nil { return err } fmt.Println() } return nil }, } cli-1.39.0/internal/cmd/all/list_test.go000066400000000000000000000214121451614444200200500ustar00rootroot00000000000000package all import ( "context" "net" "testing" "time" "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" "github.com/hetznercloud/cli/internal/testutil" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) func TestListAll(t *testing.T) { fx := testutil.NewFixture(t) defer fx.Finish() time.Local = time.UTC cmd := listCmd.CobraCommand( context.Background(), fx.Client, fx.TokenEnsurer, fx.ActionWaiter) fx.ExpectEnsureToken() fx.Client.ServerClient.EXPECT(). AllWithOpts(gomock.Any(), hcloud.ServerListOpts{}). Return([]*hcloud.Server{ { ID: 123, Name: "my server", Status: hcloud.ServerStatusRunning, PublicNet: hcloud.ServerPublicNet{ IPv4: hcloud.ServerPublicNetIPv4{ IP: net.ParseIP("192.0.2.1"), }, }, Created: time.Now().Add(-72 * time.Hour), Datacenter: &hcloud.Datacenter{Name: "hel1-dc2"}, }, }, nil) fx.Client.NetworkClient.EXPECT(). AllWithOpts(gomock.Any(), hcloud.NetworkListOpts{}). Return([]*hcloud.Network{ { ID: 123, Name: "test-net", IPRange: &net.IPNet{IP: net.ParseIP("192.0.2.1"), Mask: net.CIDRMask(24, 32)}, Servers: []*hcloud.Server{{ID: 3421}}, Created: time.Now().Add(-10 * time.Second), }, }, nil) fx.Client.LoadBalancerClient.EXPECT(). AllWithOpts(gomock.Any(), hcloud.LoadBalancerListOpts{}). Return([]*hcloud.LoadBalancer{ { ID: 123, LoadBalancerType: &hcloud.LoadBalancerType{Name: "lb11"}, Location: &hcloud.Location{Name: "fsn1", NetworkZone: hcloud.NetworkZoneEUCentral}, Name: "foobar", PublicNet: hcloud.LoadBalancerPublicNet{ IPv4: hcloud.LoadBalancerPublicNetIPv4{ IP: net.ParseIP("192.0.2.1"), }, IPv6: hcloud.LoadBalancerPublicNetIPv6{ IP: net.IPv6zero, }, }, Created: time.Now().Add(-5 * time.Hour), }, }, nil) fx.Client.CertificateClient.EXPECT(). AllWithOpts(gomock.Any(), hcloud.CertificateListOpts{}). Return([]*hcloud.Certificate{ { ID: 123, Name: "test", Type: hcloud.CertificateTypeManaged, DomainNames: []string{"example.com"}, NotValidAfter: time.Date(2036, 8, 20, 12, 0, 0, 0, time.UTC), Created: time.Now().Add(-10 * time.Hour), }, }, nil) fx.Client.FirewallClient.EXPECT(). AllWithOpts(gomock.Any(), hcloud.FirewallListOpts{}). Return([]*hcloud.Firewall{ { ID: 123, Name: "test", Created: time.Now().Add(-7 * time.Minute), Rules: make([]hcloud.FirewallRule, 5), AppliedTo: make([]hcloud.FirewallResource, 2), }, }, nil) fx.Client.PrimaryIPClient.EXPECT(). AllWithOpts(gomock.Any(), hcloud.PrimaryIPListOpts{}). Return([]*hcloud.PrimaryIP{ { ID: 123, Name: "test", Created: time.Now().Add(-2 * time.Hour), Datacenter: &hcloud.Datacenter{Name: "fsn1-dc14"}, Type: hcloud.PrimaryIPTypeIPv4, IP: net.ParseIP("127.0.0.1"), }, }, nil) fx.Client.FloatingIPClient.EXPECT(). AllWithOpts(gomock.Any(), hcloud.FloatingIPListOpts{}). Return([]*hcloud.FloatingIP{ { ID: 123, Name: "test", Created: time.Now().Add(-24 * time.Hour), Type: hcloud.FloatingIPTypeIPv4, IP: net.ParseIP("127.0.0.1"), HomeLocation: &hcloud.Location{Name: "fsn1"}, }, }, nil) fx.Client.ImageClient.EXPECT(). AllWithOpts(gomock.Any(), hcloud.ImageListOpts{Type: []hcloud.ImageType{hcloud.ImageTypeBackup, hcloud.ImageTypeSnapshot}, IncludeDeprecated: true}). Return([]*hcloud.Image{ { ID: 1, Type: hcloud.ImageTypeBackup, Name: "test", Created: time.Date(2036, 8, 20, 12, 0, 0, 0, time.UTC), Architecture: hcloud.ArchitectureARM, DiskSize: 20, }, }, nil) fx.Client.VolumeClient.EXPECT(). AllWithOpts(gomock.Any(), hcloud.VolumeListOpts{}). Return([]*hcloud.Volume{ { ID: 123, Name: "test", Location: &hcloud.Location{Name: "fsn1"}, Size: 50, Created: time.Now().Add(-500 * time.Hour), }, }, nil) fx.Client.ISOClient.EXPECT(). AllWithOpts(gomock.Any(), hcloud.ISOListOpts{}). Return([]*hcloud.ISO{ { ID: 123, Name: "test", Type: hcloud.ISOTypePrivate, Architecture: hcloud.Ptr(hcloud.ArchitectureARM), }, }, nil) fx.Client.PlacementGroupClient.EXPECT(). AllWithOpts(gomock.Any(), hcloud.PlacementGroupListOpts{}). Return([]*hcloud.PlacementGroup{ { ID: 123, Name: "test", Created: time.Now().Add(-10 * time.Hour), Type: hcloud.PlacementGroupTypeSpread, Servers: make([]int64, 5), }, }, nil) fx.Client.SSHKeyClient.EXPECT(). AllWithOpts(gomock.Any(), hcloud.SSHKeyListOpts{}). Return([]*hcloud.SSHKey{ { ID: 123, Name: "test", Created: time.Now().Add(-2 * time.Hour), }, }, nil) out, err := fx.Run(cmd, []string{}) expOut := `SERVERS --- ID NAME STATUS IPV4 IPV6 PRIVATE NET DATACENTER AGE 123 my server running 192.0.2.1 - - hel1-dc2 3d IMAGES --- ID TYPE NAME DESCRIPTION ARCHITECTURE IMAGE SIZE DISK SIZE CREATED DEPRECATED 1 backup test - arm - 20 GB Wed Aug 20 12:00:00 UTC 2036 - PLACEMENT GROUPS --- ID NAME SERVERS TYPE AGE 123 test 5 servers spread 10h PRIMARY IPS --- ID TYPE NAME IP ASSIGNEE DNS AUTO DELETE AGE 123 ipv4 test 127.0.0.1 - - no 2h ISOS --- ID NAME DESCRIPTION TYPE ARCHITECTURE 123 test - private arm VOLUMES --- ID NAME SIZE SERVER LOCATION AGE 123 test 50 GB - fsn1 20d LOAD BALANCER --- ID NAME HEALTH IPV4 IPV6 TYPE LOCATION NETWORK ZONE AGE 123 foobar healthy 192.0.2.1 :: lb11 fsn1 eu-central 5h FLOATING IPS --- ID TYPE NAME DESCRIPTION IP HOME SERVER DNS AGE 123 ipv4 test - 127.0.0.1 fsn1 - - 1d NETWORKS --- ID NAME IP RANGE SERVERS AGE 123 test-net 192.0.2.1/24 1 server 10s FIREWALLS --- ID NAME RULES COUNT APPLIED TO COUNT 123 test 5 Rules 2 Servers | 0 Label Selectors CERTIFICATES --- ID NAME TYPE DOMAIN NAMES NOT VALID AFTER AGE 123 test managed example.com Wed Aug 20 12:00:00 UTC 2036 10h SSH KEYS --- ID NAME FINGERPRINT AGE 123 test - 2h ` assert.NoError(t, err) assert.Equal(t, expOut, out) } func TestListAllPaidJSON(t *testing.T) { fx := testutil.NewFixture(t) defer fx.Finish() time.Local = time.UTC cmd := listCmd.CobraCommand( context.Background(), fx.Client, fx.TokenEnsurer, fx.ActionWaiter) fx.ExpectEnsureToken() fx.Client.ServerClient.EXPECT(). AllWithOpts(gomock.Any(), hcloud.ServerListOpts{}). Return([]*hcloud.Server{}, nil) fx.Client.LoadBalancerClient.EXPECT(). AllWithOpts(gomock.Any(), hcloud.LoadBalancerListOpts{}). Return([]*hcloud.LoadBalancer{}, nil) fx.Client.PrimaryIPClient.EXPECT(). AllWithOpts(gomock.Any(), hcloud.PrimaryIPListOpts{}). Return([]*hcloud.PrimaryIP{}, nil) fx.Client.FloatingIPClient.EXPECT(). AllWithOpts(gomock.Any(), hcloud.FloatingIPListOpts{}). Return([]*hcloud.FloatingIP{}, nil) fx.Client.ImageClient.EXPECT(). AllWithOpts(gomock.Any(), hcloud.ImageListOpts{Type: []hcloud.ImageType{hcloud.ImageTypeBackup, hcloud.ImageTypeSnapshot}, IncludeDeprecated: true}). Return([]*hcloud.Image{ { ID: 114690387, Name: "debian-12", Description: "Debian 12", Type: hcloud.ImageTypeSystem, Status: hcloud.ImageStatusAvailable, RapidDeploy: true, OSVersion: "12", OSFlavor: "debian", DiskSize: 5, Architecture: hcloud.ArchitectureX86, Created: time.Date(2023, 6, 13, 6, 0, 0, 0, time.UTC), }, }, nil) fx.Client.VolumeClient.EXPECT(). AllWithOpts(gomock.Any(), hcloud.VolumeListOpts{}). Return([]*hcloud.Volume{}, nil) out, err := fx.Run(cmd, []string{"--paid", "-o=json"}) expOut := "{\"floating_ips\":[],\"images\":[{\"id\":114690387,\"status\":\"available\",\"type\":\"system\"," + "\"name\":\"debian-12\",\"description\":\"Debian 12\",\"image_size\":0,\"disk_size\":5,\"created\":" + "\"2023-06-13T06:00:00Z\",\"created_from\":null,\"bound_to\":null,\"os_flavor\":\"debian\",\"os_version\":" + "\"12\",\"architecture\":\"x86\",\"rapid_deploy\":true,\"protection\":{\"delete\":false},\"deprecated\":" + "\"0001-01-01T00:00:00Z\",\"deleted\":\"0001-01-01T00:00:00Z\",\"labels\":null}],\"load_balancers\":[]," + "\"primary_ips\":[],\"servers\":[],\"volumes\":[]}\n" assert.NoError(t, err) assert.Equal(t, expOut, out) } cli-1.39.0/internal/cmd/base/000077500000000000000000000000001451614444200156515ustar00rootroot00000000000000cli-1.39.0/internal/cmd/base/cmd.go000066400000000000000000000021361451614444200167450ustar00rootroot00000000000000package base import ( "context" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" ) // Cmd allows defining commands for generic resource-based commands type Cmd struct { BaseCobraCommand func(hcapi2.Client) *cobra.Command Run func(context.Context, hcapi2.Client, state.ActionWaiter, *cobra.Command, []string) error } // CobraCommand creates a command that can be registered with cobra. func (gc *Cmd) CobraCommand( ctx context.Context, client hcapi2.Client, tokenEnsurer state.TokenEnsurer, actionWaiter state.ActionWaiter, ) *cobra.Command { cmd := gc.BaseCobraCommand(client) if cmd.Args == nil { cmd.Args = cobra.NoArgs } cmd.TraverseChildren = true cmd.DisableFlagsInUseLine = true if cmd.PreRunE != nil { cmd.PreRunE = util.ChainRunE(cmd.PreRunE, tokenEnsurer.EnsureToken) } else { cmd.PreRunE = tokenEnsurer.EnsureToken } cmd.RunE = func(cmd *cobra.Command, args []string) error { return gc.Run(ctx, client, actionWaiter, cmd, args) } return cmd } cli-1.39.0/internal/cmd/base/delete.go000066400000000000000000000047671451614444200174600ustar00rootroot00000000000000package base import ( "context" "fmt" "reflect" "strings" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) // DeleteCmd allows defining commands for deleting a resource. type DeleteCmd struct { ResourceNameSingular string // e.g. "server" ShortDescription string NameSuggestions func(client hcapi2.Client) func() []string AdditionalFlags func(*cobra.Command) Fetch func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) Delete func(ctx context.Context, client hcapi2.Client, actionWaiter state.ActionWaiter, cmd *cobra.Command, resource interface{}) error } // CobraCommand creates a command that can be registered with cobra. func (dc *DeleteCmd) CobraCommand( ctx context.Context, client hcapi2.Client, tokenEnsurer state.TokenEnsurer, actionWaiter state.ActionWaiter, ) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("delete [FLAGS] %s", strings.ToUpper(dc.ResourceNameSingular)), Short: dc.ShortDescription, Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(dc.NameSuggestions(client))), TraverseChildren: true, DisableFlagsInUseLine: true, PreRunE: util.ChainRunE(tokenEnsurer.EnsureToken), RunE: func(cmd *cobra.Command, args []string) error { return dc.Run(ctx, client, actionWaiter, cmd, args) }, } if dc.AdditionalFlags != nil { dc.AdditionalFlags(cmd) } return cmd } // Run executes a describe command. func (dc *DeleteCmd) Run(ctx context.Context, client hcapi2.Client, actionWaiter state.ActionWaiter, cmd *cobra.Command, args []string) error { idOrName := args[0] resource, _, err := dc.Fetch(ctx, client, cmd, idOrName) if err != nil { return err } // resource is an interface that always has a type, so the interface is never nil // (i.e. == nil) is always false. if reflect.ValueOf(resource).IsNil() { return fmt.Errorf("%s not found: %s", dc.ResourceNameSingular, idOrName) } if err := dc.Delete(ctx, client, actionWaiter, cmd, resource); err != nil { return fmt.Errorf("deleting %s %s failed: %s", dc.ResourceNameSingular, idOrName, err) } fmt.Printf("%s %v deleted\n", dc.ResourceNameSingular, idOrName) return nil } cli-1.39.0/internal/cmd/base/describe.go000066400000000000000000000064451451614444200177710ustar00rootroot00000000000000package base import ( "context" "encoding/json" "fmt" "io" "reflect" "strings" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/cmd/output" "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) // DescribeCmd allows defining commands for describing a resource. type DescribeCmd struct { ResourceNameSingular string // e.g. "server" ShortDescription string // key in API response JSON to use for extracting object from response body for JSON output. JSONKeyGetByID string // e.g. "server" JSONKeyGetByName string // e.g. "servers" NameSuggestions func(client hcapi2.Client) func() []string AdditionalFlags func(*cobra.Command) Fetch func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) PrintText func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, resource interface{}) error } // CobraCommand creates a command that can be registered with cobra. func (dc *DescribeCmd) CobraCommand( ctx context.Context, client hcapi2.Client, tokenEnsurer state.TokenEnsurer, ) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe [FLAGS] %s", strings.ToUpper(dc.ResourceNameSingular)), Short: dc.ShortDescription, Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(dc.NameSuggestions(client))), TraverseChildren: true, DisableFlagsInUseLine: true, PreRunE: util.ChainRunE(tokenEnsurer.EnsureToken), RunE: func(cmd *cobra.Command, args []string) error { return dc.Run(ctx, client, cmd, args) }, } output.AddFlag(cmd, output.OptionJSON(), output.OptionFormat()) if dc.AdditionalFlags != nil { dc.AdditionalFlags(cmd) } return cmd } // Run executes a describe command. func (dc *DescribeCmd) Run(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, args []string) error { outputFlags := output.FlagsForCommand(cmd) idOrName := args[0] resource, resp, err := dc.Fetch(ctx, client, cmd, idOrName) if err != nil { return err } // resource is an interface that always has a type, so the interface is never nil // (i.e. == nil) is always false. if reflect.ValueOf(resource).IsNil() { return fmt.Errorf("%s not found: %s", dc.ResourceNameSingular, idOrName) } switch { case outputFlags.IsSet("json"): return dc.describeJSON(resp.Body) case outputFlags.IsSet("format"): return util.DescribeFormat(resource, outputFlags["format"][0]) default: return dc.PrintText(ctx, client, cmd, resource) } } func (dc *DescribeCmd) describeJSON(body io.ReadCloser) error { var data map[string]interface{} if err := json.NewDecoder(body).Decode(&data); err != nil { return err } if resource, ok := data[dc.JSONKeyGetByID]; ok { return util.DescribeJSON(resource) } if resources, ok := data[dc.JSONKeyGetByName].([]interface{}); ok { // We check whether we got a resource at all above (see reflect-based nil check), so it's // ok to assume there's an element in resources. return util.DescribeJSON(resources[0]) } return fmt.Errorf("got invalid JSON response") } cli-1.39.0/internal/cmd/base/labels.go000066400000000000000000000113571451614444200174510ustar00rootroot00000000000000package base import ( "context" "errors" "fmt" "strings" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" ) // LabelCmds allows defining commands for adding labels to resources. type LabelCmds struct { ResourceNameSingular string ShortDescriptionAdd string ShortDescriptionRemove string NameSuggestions func(client hcapi2.Client) func() []string LabelKeySuggestions func(client hcapi2.Client) func(idOrName string) []string FetchLabels func(ctx context.Context, client hcapi2.Client, idOrName string) (map[string]string, int64, error) SetLabels func(ctx context.Context, client hcapi2.Client, id int64, labels map[string]string) error } // AddCobraCommand creates a command that can be registered with cobra. func (lc *LabelCmds) AddCobraCommand( ctx context.Context, client hcapi2.Client, tokenEnsurer state.TokenEnsurer, ) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("add-label [FLAGS] %s LABEL", strings.ToUpper(lc.ResourceNameSingular)), Short: lc.ShortDescriptionAdd, Args: cobra.ExactArgs(2), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(lc.NameSuggestions(client))), TraverseChildren: true, DisableFlagsInUseLine: true, PreRunE: util.ChainRunE(validateAddLabel, tokenEnsurer.EnsureToken), RunE: func(cmd *cobra.Command, args []string) error { return lc.RunAdd(ctx, client, cmd, args) }, } cmd.Flags().BoolP("overwrite", "o", false, "Overwrite label if it exists already") return cmd } // RunAdd executes an add label command func (lc *LabelCmds) RunAdd(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, args []string) error { overwrite, _ := cmd.Flags().GetBool("overwrite") idOrName := args[0] labels, id, err := lc.FetchLabels(ctx, client, idOrName) if err != nil { return err } if labels == nil { labels = map[string]string{} } key, val := util.SplitLabelVars(args[1]) if _, ok := labels[key]; ok && !overwrite { return fmt.Errorf("label %s on %s %d already exists", key, lc.ResourceNameSingular, id) } labels[key] = val if err := lc.SetLabels(ctx, client, id, labels); err != nil { return err } fmt.Printf("Label %s added to %s %d\n", key, lc.ResourceNameSingular, id) return nil } func validateAddLabel(cmd *cobra.Command, args []string) error { label := util.SplitLabel(args[1]) if len(label) != 2 { return fmt.Errorf("invalid label: %s", args[1]) } return nil } // RemoveCobraCommand creates a command that can be registered with cobra. func (lc *LabelCmds) RemoveCobraCommand( ctx context.Context, client hcapi2.Client, tokenEnsurer state.TokenEnsurer, ) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("remove-label [FLAGS] %s LABEL", strings.ToUpper(lc.ResourceNameSingular)), Short: lc.ShortDescriptionRemove, Args: cobra.RangeArgs(1, 2), ValidArgsFunction: cmpl.SuggestArgs( cmpl.SuggestCandidatesF(lc.NameSuggestions(client)), cmpl.SuggestCandidatesCtx(func(_ *cobra.Command, args []string) []string { if len(args) != 1 { return nil } return lc.LabelKeySuggestions(client)(args[0]) }), ), TraverseChildren: true, DisableFlagsInUseLine: true, PreRunE: util.ChainRunE(validateRemoveLabel, tokenEnsurer.EnsureToken), RunE: func(cmd *cobra.Command, args []string) error { return lc.RunRemove(ctx, client, cmd, args) }, } cmd.Flags().BoolP("all", "a", false, "Remove all labels") return cmd } // RunRemove executes a remove label command func (lc *LabelCmds) RunRemove(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, args []string) error { all, _ := cmd.Flags().GetBool("all") idOrName := args[0] labels, id, err := lc.FetchLabels(ctx, client, idOrName) if err != nil { return err } if all { labels = make(map[string]string) } else { key := args[1] if _, ok := labels[key]; !ok { return fmt.Errorf("label %s on %s %d does not exist", key, lc.ResourceNameSingular, id) } delete(labels, key) } if err := lc.SetLabels(ctx, client, id, labels); err != nil { return err } if all { fmt.Printf("All labels removed from %s %d\n", lc.ResourceNameSingular, id) } else { fmt.Printf("Label %s removed from %s %d\n", args[1], lc.ResourceNameSingular, id) } return nil } func validateRemoveLabel(cmd *cobra.Command, args []string) error { all, _ := cmd.Flags().GetBool("all") if all && len(args) == 2 { return errors.New("must not specify a label key when using --all/-a") } if !all && len(args) != 2 { return errors.New("must specify a label key when not using --all/-a") } return nil } cli-1.39.0/internal/cmd/base/list.go000066400000000000000000000052021451614444200171520ustar00rootroot00000000000000package base import ( "context" "fmt" "github.com/spf13/cobra" "github.com/spf13/pflag" "github.com/hetznercloud/cli/internal/cmd/output" "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) // ListCmd allows defining commands for listing resources type ListCmd struct { ResourceNamePlural string // e.g. "servers" JSONKeyGetByName string // e.g. "servers" DefaultColumns []string Fetch func(context.Context, hcapi2.Client, *pflag.FlagSet, hcloud.ListOpts, []string) ([]interface{}, error) AdditionalFlags func(*cobra.Command) OutputTable func(client hcapi2.Client) *output.Table JSONSchema func([]interface{}) interface{} } // CobraCommand creates a command that can be registered with cobra. func (lc *ListCmd) CobraCommand( ctx context.Context, client hcapi2.Client, tokenEnsurer state.TokenEnsurer, ) *cobra.Command { outputColumns := lc.OutputTable(client).Columns() cmd := &cobra.Command{ Use: "list [FlAGS]", Short: fmt.Sprintf("List %s", lc.ResourceNamePlural), Long: util.ListLongDescription( fmt.Sprintf("Displays a list of %s.", lc.ResourceNamePlural), outputColumns, ), TraverseChildren: true, DisableFlagsInUseLine: true, PreRunE: tokenEnsurer.EnsureToken, RunE: func(cmd *cobra.Command, args []string) error { return lc.Run(ctx, client, cmd) }, } output.AddFlag(cmd, output.OptionNoHeader(), output.OptionColumns(outputColumns), output.OptionJSON()) cmd.Flags().StringP("selector", "l", "", "Selector to filter by labels") if lc.AdditionalFlags != nil { lc.AdditionalFlags(cmd) } cmd.Flags().StringSliceP("sort", "s", []string{"id:asc"}, "Determine the sorting of the result") return cmd } // Run executes a list command func (lc *ListCmd) Run(ctx context.Context, client hcapi2.Client, cmd *cobra.Command) error { outOpts := output.FlagsForCommand(cmd) labelSelector, _ := cmd.Flags().GetString("selector") listOpts := hcloud.ListOpts{ LabelSelector: labelSelector, PerPage: 50, } sorts, _ := cmd.Flags().GetStringSlice("sort") resources, err := lc.Fetch(ctx, client, cmd.Flags(), listOpts, sorts) if err != nil { return err } if outOpts.IsSet("json") { return util.DescribeJSON(lc.JSONSchema(resources)) } cols := lc.DefaultColumns if outOpts.IsSet("columns") { cols = outOpts["columns"] } table := lc.OutputTable(client) if !outOpts.IsSet("noheader") { table.WriteHeader(cols) } for _, resource := range resources { table.Write(cols, resource) } table.Flush() return nil } cli-1.39.0/internal/cmd/base/set_rdns.go000066400000000000000000000056021451614444200200240ustar00rootroot00000000000000package base import ( "context" "fmt" "net" "reflect" "strings" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) // SetRdnsCmd allows defining commands for setting the RDNS of a resource. type SetRdnsCmd struct { ResourceNameSingular string // e.g. "server" ShortDescription string NameSuggestions func(client hcapi2.Client) func() []string AdditionalFlags func(*cobra.Command) Fetch func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) GetDefaultIP func(resource interface{}) net.IP } // CobraCommand creates a command that can be registered with cobra. func (rc *SetRdnsCmd) CobraCommand( ctx context.Context, client hcapi2.Client, tokenEnsurer state.TokenEnsurer, actionWaiter state.ActionWaiter, ) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("set-rdns [FLAGS] %s", strings.ToUpper(rc.ResourceNameSingular)), Short: rc.ShortDescription, Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(rc.NameSuggestions(client))), TraverseChildren: true, DisableFlagsInUseLine: true, PreRunE: util.ChainRunE(tokenEnsurer.EnsureToken), RunE: func(cmd *cobra.Command, args []string) error { return rc.Run(ctx, client, cmd, actionWaiter, args) }, } cmd.Flags().StringP("hostname", "r", "", "Hostname to set as a reverse DNS PTR entry (required)") cmd.MarkFlagRequired("hostname") cmd.Flags().IPP("ip", "i", net.IP{}, "IP address for which the reverse DNS entry should be set") if rc.AdditionalFlags != nil { rc.AdditionalFlags(cmd) } return cmd } // Run executes a setRDNS command. func (rc *SetRdnsCmd) Run(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, actionWaiter state.ActionWaiter, args []string) error { idOrName := args[0] resource, _, err := rc.Fetch(ctx, client, cmd, idOrName) if err != nil { return err } // resource is an interface that always has a type, so the interface is never nil // (i.e. == nil) is always false. if reflect.ValueOf(resource).IsNil() { return fmt.Errorf("%s not found: %s", rc.ResourceNameSingular, idOrName) } ip, _ := cmd.Flags().GetIP("ip") if ip.IsUnspecified() || ip == nil { ip = rc.GetDefaultIP(resource) } hostname, _ := cmd.Flags().GetString("hostname") action, _, err := client.RDNS().ChangeDNSPtr(ctx, resource.(hcloud.RDNSSupporter), ip, hcloud.String(hostname)) if err != nil { return err } if err := actionWaiter.ActionProgress(ctx, action); err != nil { return err } fmt.Printf("Reverse DNS of %s %s changed\n", rc.ResourceNameSingular, idOrName) return nil } cli-1.39.0/internal/cmd/base/update.go000066400000000000000000000054641451614444200174730ustar00rootroot00000000000000package base import ( "context" "fmt" "reflect" "strings" "github.com/spf13/cobra" "github.com/spf13/pflag" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) // UpdateCmd allows defining commands for updating a resource. type UpdateCmd struct { ResourceNameSingular string // e.g. "server" ShortDescription string NameSuggestions func(client hcapi2.Client) func() []string DefineFlags func(*cobra.Command) Fetch func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) Update func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, resource interface{}, flags map[string]pflag.Value) error } // CobraCommand creates a command that can be registered with cobra. func (uc *UpdateCmd) CobraCommand( ctx context.Context, client hcapi2.Client, tokenEnsurer state.TokenEnsurer, ) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("update [FLAGS] %s", strings.ToUpper(uc.ResourceNameSingular)), Short: uc.ShortDescription, Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(uc.NameSuggestions(client))), TraverseChildren: true, DisableFlagsInUseLine: true, PreRunE: util.ChainRunE(tokenEnsurer.EnsureToken), RunE: func(cmd *cobra.Command, args []string) error { return uc.Run(ctx, client, cmd, args) }, } uc.DefineFlags(cmd) return cmd } // Run executes a update command. func (uc *UpdateCmd) Run(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, args []string) error { idOrName := args[0] resource, _, err := uc.Fetch(ctx, client, cmd, idOrName) if err != nil { return err } // resource is an interface that always has a type, so the interface is never nil // (i.e. == nil) is always false. if reflect.ValueOf(resource).IsNil() { return fmt.Errorf("%s not found: %s", uc.ResourceNameSingular, idOrName) } // The inherited commands should not need to parse the flags themselves // or use the cobra command, therefore we fill them in a map here and // pass the map then to the update method. A caller can/should rely on // the map to contain all the flag keys that were specified. flags := make(map[string]pflag.Value, cmd.Flags().NFlag()) cmd.Flags().VisitAll(func(flag *pflag.Flag) { flags[flag.Name] = flag.Value }) if err := uc.Update(ctx, client, cmd, resource, flags); err != nil { return fmt.Errorf("updating %s %s failed: %s", uc.ResourceNameSingular, idOrName, err) } fmt.Printf("%s %v updated\n", uc.ResourceNameSingular, idOrName) return nil } cli-1.39.0/internal/cmd/certificate/000077500000000000000000000000001451614444200172215ustar00rootroot00000000000000cli-1.39.0/internal/cmd/certificate/certificate.go000066400000000000000000000014741451614444200220400ustar00rootroot00000000000000package certificate import ( "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" ) func NewCommand(cli *state.State, client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "certificate", Short: "Manage certificates", Args: cobra.NoArgs, TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.AddCommand( ListCmd.CobraCommand(cli.Context, client, cli), newCreateCommand(cli), updateCmd.CobraCommand(cli.Context, client, cli), labelCmds.AddCobraCommand(cli.Context, client, cli), labelCmds.RemoveCobraCommand(cli.Context, client, cli), deleteCmd.CobraCommand(cli.Context, client, cli, cli), describeCmd.CobraCommand(cli.Context, client, cli), ) return cmd } cli-1.39.0/internal/cmd/certificate/create.go000066400000000000000000000073141451614444200210200ustar00rootroot00000000000000package certificate import ( "fmt" "io/ioutil" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) func newCreateCommand(cli *state.State) *cobra.Command { cmd := &cobra.Command{ Use: "create [FLAGS]", Short: "Create or upload a Certificate", Args: cobra.NoArgs, TraverseChildren: true, DisableFlagsInUseLine: true, PreRunE: cli.EnsureToken, RunE: cli.Wrap(runCreate), } cmd.Flags().String("name", "", "Certificate name (required)") cmd.MarkFlagRequired("name") cmd.Flags().StringP("type", "t", string(hcloud.CertificateTypeUploaded), fmt.Sprintf("Type of certificate to create. Valid choices: %v, %v", hcloud.CertificateTypeUploaded, hcloud.CertificateTypeManaged)) cmd.RegisterFlagCompletionFunc( "type", cmpl.SuggestCandidates(string(hcloud.CertificateTypeUploaded), string(hcloud.CertificateTypeManaged)), ) cmd.Flags().String("cert-file", "", "File containing the PEM encoded certificate (required if type is uploaded)") cmd.Flags().String("key-file", "", "File containing the PEM encoded private key for the certificate (required if type is uploaded)") cmd.Flags().StringSlice("domain", nil, "One or more domains the certificate is valid for.") return cmd } func runCreate(cli *state.State, cmd *cobra.Command, args []string) error { certType, err := cmd.Flags().GetString("type") if err != nil { return err } switch hcloud.CertificateType(certType) { case hcloud.CertificateTypeUploaded: return createUploaded(cli, cmd, args) case hcloud.CertificateTypeManaged: return createManaged(cli, cmd, args) default: return createUploaded(cli, cmd, args) } } func createUploaded(cli *state.State, cmd *cobra.Command, args []string) error { var ( name string certFile, keyFile string certPEM, keyPEM []byte cert *hcloud.Certificate err error ) if err = util.ValidateRequiredFlags(cmd.Flags(), "cert-file", "key-file"); err != nil { return err } if name, err = cmd.Flags().GetString("name"); err != nil { return err } if certFile, err = cmd.Flags().GetString("cert-file"); err != nil { return err } if keyFile, err = cmd.Flags().GetString("key-file"); err != nil { return err } if certPEM, err = ioutil.ReadFile(certFile); err != nil { return err } if keyPEM, err = ioutil.ReadFile(keyFile); err != nil { return err } createOpts := hcloud.CertificateCreateOpts{ Name: name, Type: hcloud.CertificateTypeUploaded, Certificate: string(certPEM), PrivateKey: string(keyPEM), } if cert, _, err = cli.Client().Certificate.Create(cli.Context, createOpts); err != nil { return err } fmt.Printf("Certificate %d created\n", cert.ID) return nil } func createManaged(cli *state.State, cmd *cobra.Command, args []string) error { var ( name string domains []string res hcloud.CertificateCreateResult err error ) if name, err = cmd.Flags().GetString("name"); err != nil { return nil } if err = util.ValidateRequiredFlags(cmd.Flags(), "domain"); err != nil { return err } if domains, err = cmd.Flags().GetStringSlice("domain"); err != nil { return nil } createOpts := hcloud.CertificateCreateOpts{ Name: name, Type: hcloud.CertificateTypeManaged, DomainNames: domains, } if res, _, err = cli.Client().Certificate.CreateCertificate(cli.Context, createOpts); err != nil { return err } if err := cli.ActionProgress(cli.Context, res.Action); err != nil { return err } fmt.Printf("Certificate %d created\n", res.Certificate.ID) return nil } cli-1.39.0/internal/cmd/certificate/delete.go000066400000000000000000000016621451614444200210170ustar00rootroot00000000000000package certificate import ( "context" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var deleteCmd = base.DeleteCmd{ ResourceNameSingular: "certificate", ShortDescription: "Delete a certificate", NameSuggestions: func(c hcapi2.Client) func() []string { return c.Firewall().Names }, Fetch: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) { return client.Certificate().Get(ctx, idOrName) }, Delete: func(ctx context.Context, client hcapi2.Client, _ state.ActionWaiter, cmd *cobra.Command, resource interface{}) error { certificate := resource.(*hcloud.Certificate) if _, err := client.Certificate().Delete(ctx, certificate); err != nil { return err } return nil }, } cli-1.39.0/internal/cmd/certificate/describe.go000066400000000000000000000050461451614444200213350ustar00rootroot00000000000000package certificate import ( "context" "fmt" "github.com/dustin/go-humanize" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var describeCmd = base.DescribeCmd{ ResourceNameSingular: "certificate", ShortDescription: "Describe an certificate", JSONKeyGetByID: "certificate", JSONKeyGetByName: "certificates", NameSuggestions: func(c hcapi2.Client) func() []string { return c.Certificate().Names }, Fetch: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) { return client.Certificate().Get(ctx, idOrName) }, PrintText: func(_ context.Context, client hcapi2.Client, cmd *cobra.Command, resource interface{}) error { cert := resource.(*hcloud.Certificate) fmt.Printf("ID:\t\t\t%d\n", cert.ID) fmt.Printf("Name:\t\t\t%s\n", cert.Name) fmt.Printf("Type:\t\t\t%s\n", cert.Type) fmt.Printf("Fingerprint:\t\t%s\n", cert.Fingerprint) fmt.Printf("Created:\t\t%s (%s)\n", util.Datetime(cert.Created), humanize.Time(cert.Created)) fmt.Printf("Not valid before:\t%s (%s)\n", util.Datetime(cert.NotValidBefore), humanize.Time(cert.NotValidBefore)) fmt.Printf("Not valid after:\t%s (%s)\n", util.Datetime(cert.NotValidAfter), humanize.Time(cert.NotValidAfter)) if cert.Status != nil { fmt.Printf("Status:\n") fmt.Printf(" Issuance: %s\n", cert.Status.Issuance) fmt.Printf(" Renewal: %s\n", cert.Status.Renewal) if cert.Status.IsFailed() { fmt.Printf(" Failure reason: %s\n", cert.Status.Error.Message) } } fmt.Printf("Domain names:\n") for _, domainName := range cert.DomainNames { fmt.Printf(" - %s\n", domainName) } fmt.Print("Labels:\n") if len(cert.Labels) == 0 { fmt.Print(" No labels\n") } else { for key, value := range cert.Labels { fmt.Printf(" %s:\t%s\n", key, value) } } fmt.Println("Used By:") if len(cert.UsedBy) == 0 { fmt.Println(" Certificate unused") } else { for _, ub := range cert.UsedBy { fmt.Printf(" - Type: %s", ub.Type) // Currently certificates can be only attached to load balancers. // If we ever get something that is not a load balancer fall back // to printing the ID. if ub.Type != hcloud.CertificateUsedByRefTypeLoadBalancer { fmt.Printf(" - ID: %d", ub.ID) continue } fmt.Printf(" - Name: %s", client.LoadBalancer().LoadBalancerName(ub.ID)) } } return nil }, } cli-1.39.0/internal/cmd/certificate/labels.go000066400000000000000000000023351451614444200210150ustar00rootroot00000000000000package certificate import ( "context" "fmt" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var labelCmds = base.LabelCmds{ ResourceNameSingular: "certificate", ShortDescriptionAdd: "Add a label to an certificate", ShortDescriptionRemove: "Remove a label from an certificate", NameSuggestions: func(c hcapi2.Client) func() []string { return c.Certificate().Names }, LabelKeySuggestions: func(c hcapi2.Client) func(idOrName string) []string { return c.Certificate().LabelKeys }, FetchLabels: func(ctx context.Context, client hcapi2.Client, idOrName string) (map[string]string, int64, error) { certificate, _, err := client.Certificate().Get(ctx, idOrName) if err != nil { return nil, 0, err } if certificate == nil { return nil, 0, fmt.Errorf("certificate not found: %s", idOrName) } return certificate.Labels, certificate.ID, nil }, SetLabels: func(ctx context.Context, client hcapi2.Client, id int64, labels map[string]string) error { opts := hcloud.CertificateUpdateOpts{ Labels: labels, } _, _, err := client.Certificate().Update(ctx, &hcloud.Certificate{ID: id}, opts) return err }, } cli-1.39.0/internal/cmd/certificate/list.go000066400000000000000000000070411451614444200205250ustar00rootroot00000000000000package certificate import ( "context" "strings" "time" "github.com/spf13/pflag" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/output" "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" "github.com/hetznercloud/hcloud-go/v2/hcloud/schema" ) var ListCmd = base.ListCmd{ ResourceNamePlural: "Certificates", JSONKeyGetByName: "certificates", DefaultColumns: []string{"id", "name", "type", "domain_names", "not_valid_after", "age"}, Fetch: func(ctx context.Context, client hcapi2.Client, _ *pflag.FlagSet, listOpts hcloud.ListOpts, sorts []string) ([]interface{}, error) { opts := hcloud.CertificateListOpts{ListOpts: listOpts} if len(sorts) > 0 { opts.Sort = sorts } certificates, err := client.Certificate().AllWithOpts(ctx, opts) var resources []interface{} for _, n := range certificates { resources = append(resources, n) } return resources, err }, OutputTable: func(_ hcapi2.Client) *output.Table { return output.NewTable(). AddAllowedFields(hcloud.Certificate{}). RemoveAllowedField("certificate", "chain"). AddFieldFn("labels", output.FieldFn(func(obj interface{}) string { cert := obj.(*hcloud.Certificate) return util.LabelsToString(cert.Labels) })). AddFieldFn("not_valid_before", func(obj interface{}) string { cert := obj.(*hcloud.Certificate) return util.Datetime(cert.NotValidBefore) }). AddFieldFn("not_valid_after", func(obj interface{}) string { cert := obj.(*hcloud.Certificate) return util.Datetime(cert.NotValidAfter) }). AddFieldFn("issuance_status", func(obj interface{}) string { cert := obj.(*hcloud.Certificate) if cert.Type != hcloud.CertificateTypeManaged { return "n/a" } return string(cert.Status.Issuance) }). AddFieldFn("renewal_status", func(obj interface{}) string { cert := obj.(*hcloud.Certificate) if cert.Type != hcloud.CertificateTypeManaged || cert.Status.Renewal == hcloud.CertificateStatusTypeUnavailable { return "n/a" } return string(cert.Status.Renewal) }). AddFieldFn("domain_names", func(obj interface{}) string { cert := obj.(*hcloud.Certificate) return strings.Join(cert.DomainNames, ", ") }). AddFieldFn("created", output.FieldFn(func(obj interface{}) string { cert := obj.(*hcloud.Certificate) return util.Datetime(cert.Created) })). AddFieldFn("age", output.FieldFn(func(obj interface{}) string { cert := obj.(*hcloud.Certificate) return util.Age(cert.Created, time.Now()) })) }, JSONSchema: func(resources []interface{}) interface{} { certSchemas := make([]schema.Certificate, 0, len(resources)) for _, resource := range resources { cert := resource.(*hcloud.Certificate) certSchema := schema.Certificate{ ID: cert.ID, Certificate: cert.Certificate, Created: cert.Created, DomainNames: cert.DomainNames, Fingerprint: cert.Fingerprint, Labels: cert.Labels, Name: cert.Name, Type: string(cert.Type), NotValidAfter: cert.NotValidAfter, NotValidBefore: cert.NotValidBefore, } if len(cert.UsedBy) > 0 { certSchema.UsedBy = make([]schema.CertificateUsedByRef, len(cert.UsedBy)) for i, ub := range cert.UsedBy { certSchema.UsedBy[i] = schema.CertificateUsedByRef{ ID: ub.ID, Type: string(ub.Type), } } } certSchemas = append(certSchemas, certSchema) } return certSchemas }, } cli-1.39.0/internal/cmd/certificate/update.go000066400000000000000000000021451451614444200210340ustar00rootroot00000000000000package certificate import ( "context" "github.com/spf13/cobra" "github.com/spf13/pflag" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var updateCmd = base.UpdateCmd{ ResourceNameSingular: "certificate", ShortDescription: "Update a certificate", NameSuggestions: func(c hcapi2.Client) func() []string { return c.Firewall().Names }, Fetch: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) { return client.Certificate().Get(ctx, idOrName) }, DefineFlags: func(cmd *cobra.Command) { cmd.Flags().String("name", "", "Certificate Name") }, Update: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, resource interface{}, flags map[string]pflag.Value) error { certificate := resource.(*hcloud.Certificate) updOpts := hcloud.CertificateUpdateOpts{ Name: flags["name"].String(), } _, _, err := client.Certificate().Update(ctx, certificate, updOpts) if err != nil { return err } return nil }, } cli-1.39.0/internal/cmd/cmpl/000077500000000000000000000000001451614444200156725ustar00rootroot00000000000000cli-1.39.0/internal/cmd/cmpl/suggestions.go000066400000000000000000000066771451614444200206130ustar00rootroot00000000000000package cmpl import ( "strings" "github.com/spf13/cobra" ) // SuggestCandidates returns a function that selects all items from the list of // candidates cs which have the prefix toComplete. If toComplete is empty cs is // returned. // // The returned function is mainly intended to be passed to // cobra/Command.RegisterFlagCompletionFunc or assigned to // cobra/Command.ValidArgsFunction. func SuggestCandidates(cs ...string) func(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective) { return SuggestCandidatesF(func() []string { return cs }) } // SuggestCandidatesF returns a function that calls the candidate function cf // to obtain a list of completion candidates. Once the list of candidates is // obtained the function returned by SuggestCandidatesF behaves like the // function returned by SuggestCandidates. func SuggestCandidatesF( cf func() []string, ) func(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective) { return SuggestCandidatesCtx(func(*cobra.Command, []string) []string { return cf() }) } // SuggestCandidatesCtx returns a function that uses the candidate function cf // to obtain a list of completion candidates in the context of previously // selected arguments and flags. This is mainly useful for completion candidates that // depend on a previously selected item like a server. // // Once the list of candidates is obtained the function returned by // SuggestCandidatesF behaves like the function returned by SuggestCandidates. func SuggestCandidatesCtx( cf func(*cobra.Command, []string) []string, ) func(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective) { return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { cs := cf(cmd, args) if toComplete == "" { return cs, cobra.ShellCompDirectiveDefault } var sel []string for _, c := range cs { if !strings.HasPrefix(c, toComplete) { continue } sel = append(sel, c) } return sel, cobra.ShellCompDirectiveDefault } } // SuggestNothing returns a function that provides no suggestions. func SuggestNothing() func(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective) { return func(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective) { return nil, cobra.ShellCompDirectiveDefault } } // SuggestArgs returns a function that uses the slice of valid argument // functions vfs to provide completion suggestions for the passed command line // arguments. // // The selection of the respective entry in vfs is positional, i.e. to // determine the suggestions for the fourth command line argument SuggestArgs // calls the function at vfs[4] if it exists. To skip suggestions for an // argument in the middle of a list of arguments pass either nil or // SuggestNothing. Using SuggestNothing is preferred. func SuggestArgs( vfs ...func(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective), ) func(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective) { return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { // Number of argument to suggest. args contains the already present // command line arguments. argNo := len(args) // Skip completion if not enough vfs have been passed, or if vfs at // argNo is nil. if len(vfs) <= argNo || vfs[argNo] == nil { return nil, cobra.ShellCompDirectiveDefault } f := vfs[argNo] return f(cmd, args, toComplete) } } cli-1.39.0/internal/cmd/cmpl/suggestions_test.go000066400000000000000000000047211451614444200216360ustar00rootroot00000000000000package cmpl_test import ( "testing" "github.com/spf13/cobra" "github.com/stretchr/testify/assert" "github.com/hetznercloud/cli/internal/cmd/cmpl" ) func TestSuggestCandidates(t *testing.T) { tests := []struct { name string cs []string toComplete string sug []string d cobra.ShellCompDirective }{ { name: "no prefix available", cs: []string{"yaml", "json", "toml"}, sug: []string{"yaml", "json", "toml"}, }, { name: "prefix available", cs: []string{"a", "aa", "aaa", "bbb"}, toComplete: "aa", sug: []string{"aa", "aaa"}, }, } for _, tt := range tests { tt := tt t.Run(tt.name, func(t *testing.T) { f := cmpl.SuggestCandidates(tt.cs...) sug, d := f(nil, nil, tt.toComplete) assert.Equal(t, tt.sug, sug) assert.Equal(t, tt.d, d) }) } } func TestSuggestArgs(t *testing.T) { tests := []struct { name string vfs []func(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective) args []string sug []string d cobra.ShellCompDirective }{ { name: "suggest first argument but no vfs provided", }, { name: "suggest second argument but no vfs provided", args: []string{"aaaa"}, }, { name: "suggest the only argument", vfs: []func(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective){ cmpl.SuggestCandidates("aaaa"), }, sug: []string{"aaaa"}, }, { name: "suggest the second of three possible arguments", vfs: []func(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective){ cmpl.SuggestCandidates("aaaa"), cmpl.SuggestCandidates("bbbb"), cmpl.SuggestCandidates("cccc"), }, args: []string{"aaaa"}, sug: []string{"bbbb"}, }, { name: "skip suggestions using SuggestNothing", vfs: []func(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective){ cmpl.SuggestCandidates("aaaa"), cmpl.SuggestNothing(), cmpl.SuggestCandidates("cccc"), }, args: []string{"aaaa"}, }, { name: "skip suggestions using nil", vfs: []func(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective){ cmpl.SuggestCandidates("aaaa"), nil, cmpl.SuggestCandidates("cccc"), }, args: []string{"aaaa"}, }, } for _, tt := range tests { tt := tt t.Run(tt.name, func(t *testing.T) { f := cmpl.SuggestArgs(tt.vfs...) sug, d := f(nil, tt.args, "") assert.Equal(t, tt.sug, sug) assert.Equal(t, tt.d, d) }) } } cli-1.39.0/internal/cmd/completion/000077500000000000000000000000001451614444200171105ustar00rootroot00000000000000cli-1.39.0/internal/cmd/completion/completion.go000066400000000000000000000064031451614444200216130ustar00rootroot00000000000000package completion import ( "fmt" "os" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/state" ) // const ( // completionShortDescription = "Output shell completion code for the specified shell (bash or zsh)" // completionLongDescription = completionShortDescription + ` // Note: this requires the bash-completion framework, which is not installed by default on Mac. This can be installed by using homebrew: // $ brew install bash-completion // Once installed, bash completion must be evaluated. This can be done by adding the following line to the .bash profile: // $ source $(brew --prefix)/etc/bash_completion // Note for zsh users: [1] zsh completions are only supported in versions of zsh >= 5.2 // Examples: // # Load the hcloud completion code for bash into the current shell // source <(hcloud completion bash) // # Load the hcloud completion code for zsh into the current shell // source <(hcloud completion zsh)` // ) func NewCommand(cli *state.State) *cobra.Command { cmd := &cobra.Command{ Use: "completion [FLAGS] SHELL", Short: "Output shell completion code for the specified shell", Long: `To load completions: ### Bash To load completions into the current shell execute: source <(hcloud completion bash) In order to make the completions permanent, append the line above to your .bashrc. ### Zsh If shell completions are not already enabled for your environment need to enable them. Add the following line to your ~/.zshrc file: autoload -Uz compinit; compinit To load completions for each session execute the following commands: mkdir -p ~/.config/hcloud/completion/zsh hcloud completion zsh > ~/.config/hcloud/completion/zsh/_hcloud Finally add the following line to your ~/.zshrc file, *before* you call the compinit function: fpath+=(~/.config/hcloud/completion/zsh) In the end your ~/.zshrc file should contain the following two lines in the order given here. fpath+=(~/.config/hcloud/completion/zsh) # ... anything else that needs to be done before compinit autoload -Uz compinit; compinit # ... You will need to start a new shell for this setup to take effect. ### Fish To load completions into the current shell execute: hcloud completion fish | source In order to make the completions permanent execute once: hcloud completion fish > ~/.config/fish/completions/hcloud.fish ### PowerShell: To load completions into the current shell execute: PS> hcloud completion powershell | Out-String | Invoke-Expression To load completions for every new session, run and source this file from your PowerShell profile. PS> hcloud completion powershell > hcloud.ps1 `, Args: cobra.ExactArgs(1), ValidArgs: []string{"bash", "fish", "zsh", "powershell"}, DisableFlagsInUseLine: true, RunE: func(cmd *cobra.Command, args []string) error { var err error switch args[0] { case "bash": err = cmd.Root().GenBashCompletion(os.Stdout) case "fish": err = cmd.Root().GenFishCompletion(os.Stdout, true) case "zsh": err = cmd.Root().GenZshCompletion(os.Stdout) case "powershell": err = cmd.Root().GenPowerShellCompletion(os.Stdout) default: err = fmt.Errorf("Unsupported shell: %s", args[0]) } return err }, } return cmd } cli-1.39.0/internal/cmd/context/000077500000000000000000000000001451614444200164235ustar00rootroot00000000000000cli-1.39.0/internal/cmd/context/active.go000066400000000000000000000011571451614444200202310ustar00rootroot00000000000000package context import ( "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/state" ) func newActiveCommand(cli *state.State) *cobra.Command { cmd := &cobra.Command{ Use: "active [FLAGS]", Short: "Show active context", Args: cobra.NoArgs, TraverseChildren: true, DisableFlagsInUseLine: true, RunE: cli.Wrap(runActive), } return cmd } func runActive(cli *state.State, cmd *cobra.Command, args []string) error { if cli.Config.ActiveContext != nil { fmt.Println(cli.Config.ActiveContext.Name) } return nil } cli-1.39.0/internal/cmd/context/context.go000066400000000000000000000010131451614444200204310ustar00rootroot00000000000000package context import ( "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/state" ) func NewCommand(cli *state.State) *cobra.Command { cmd := &cobra.Command{ Use: "context [FLAGS]", Short: "Manage contexts", Args: cobra.NoArgs, TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.AddCommand( newCreateCommand(cli), newActiveCommand(cli), newUseCommand(cli), newDeleteCommand(cli), newListCommand(cli), ) return cmd } cli-1.39.0/internal/cmd/context/create.go000066400000000000000000000030071451614444200202150ustar00rootroot00000000000000package context import ( "bytes" "errors" "fmt" "strings" "syscall" "github.com/spf13/cobra" "golang.org/x/crypto/ssh/terminal" "github.com/hetznercloud/cli/internal/state" ) func newCreateCommand(cli *state.State) *cobra.Command { cmd := &cobra.Command{ Use: "create [FLAGS] NAME", Short: "Create a new context", Args: cobra.ExactArgs(1), TraverseChildren: true, DisableFlagsInUseLine: true, RunE: cli.Wrap(runCreate), } return cmd } func runCreate(cli *state.State, _ *cobra.Command, args []string) error { if !state.StdoutIsTerminal() { return errors.New("context create is an interactive command") } name := strings.TrimSpace(args[0]) if name == "" { return errors.New("invalid name") } if cli.Config.ContextByName(name) != nil { return errors.New("name already used") } context := &state.ConfigContext{Name: name} for { fmt.Printf("Token: ") btoken, err := terminal.ReadPassword(int(syscall.Stdin)) fmt.Print("\n") if err != nil { return err } token := string(bytes.TrimSpace(btoken)) if token == "" { continue } if len(token) != 64 { fmt.Print("Entered token is invalid (must be exactly 64 characters long)\n") continue } context.Token = token break } cli.Config.Contexts = append(cli.Config.Contexts, context) cli.Config.ActiveContext = context if err := cli.WriteConfig(); err != nil { return err } fmt.Printf("Context %s created and activated\n", name) return nil } cli-1.39.0/internal/cmd/context/delete.go000066400000000000000000000016651451614444200202240ustar00rootroot00000000000000package context import ( "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/state" ) func newDeleteCommand(cli *state.State) *cobra.Command { cmd := &cobra.Command{ Use: "delete [FLAGS] NAME", Short: "Delete a context", Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(cli.Config.ContextNames)), TraverseChildren: true, DisableFlagsInUseLine: true, RunE: cli.Wrap(runDelete), } return cmd } func runDelete(cli *state.State, cmd *cobra.Command, args []string) error { name := args[0] context := cli.Config.ContextByName(name) if context == nil { return fmt.Errorf("context not found: %v", name) } if cli.Config.ActiveContext == context { cli.Config.ActiveContext = nil } cli.Config.RemoveContext(context) return cli.WriteConfig() } cli-1.39.0/internal/cmd/context/list.go000066400000000000000000000031511451614444200177250ustar00rootroot00000000000000package context import ( "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/output" "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/state" ) var listTableOutput *output.Table type ContextPresentation struct { Name string Token string Active string } func init() { listTableOutput = output.NewTable(). AddAllowedFields(ContextPresentation{}). RemoveAllowedField("token") } func newListCommand(cli *state.State) *cobra.Command { cmd := &cobra.Command{ Use: "list [FLAGS]", Short: "List contexts", Long: util.ListLongDescription( "Displays a list of contexts.", listTableOutput.Columns(), ), Args: cobra.NoArgs, TraverseChildren: true, DisableFlagsInUseLine: true, RunE: cli.Wrap(runList), } output.AddFlag(cmd, output.OptionNoHeader(), output.OptionColumns(listTableOutput.Columns())) return cmd } func runList(cli *state.State, cmd *cobra.Command, args []string) error { outOpts := output.FlagsForCommand(cmd) cols := []string{"active", "name"} if outOpts.IsSet("columns") { cols = outOpts["columns"] } tw := listTableOutput if err := tw.ValidateColumns(cols); err != nil { return err } if !outOpts.IsSet("noheader") { tw.WriteHeader(cols) } for _, context := range cli.Config.Contexts { presentation := ContextPresentation{ Name: context.Name, Token: context.Token, Active: " ", } if cli.Config.ActiveContext != nil && cli.Config.ActiveContext.Name == context.Name { presentation.Active = "*" } tw.Write(cols, presentation) } tw.Flush() return nil } cli-1.39.0/internal/cmd/context/use.go000066400000000000000000000015311451614444200175460ustar00rootroot00000000000000package context import ( "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/state" ) func newUseCommand(cli *state.State) *cobra.Command { cmd := &cobra.Command{ Use: "use [FLAGS] NAME", Short: "Use a context", Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(cli.Config.ContextNames)), TraverseChildren: true, DisableFlagsInUseLine: true, RunE: cli.Wrap(runUse), } return cmd } func runUse(cli *state.State, cmd *cobra.Command, args []string) error { name := args[0] context := cli.Config.ContextByName(name) if context == nil { return fmt.Errorf("context not found: %v", name) } cli.Config.ActiveContext = context return cli.WriteConfig() } cli-1.39.0/internal/cmd/datacenter/000077500000000000000000000000001451614444200170515ustar00rootroot00000000000000cli-1.39.0/internal/cmd/datacenter/datacenter.go000066400000000000000000000011011451614444200215030ustar00rootroot00000000000000package datacenter import ( "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" ) func NewCommand(cli *state.State, client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "datacenter", Short: "Manage datacenters", Args: cobra.NoArgs, TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.AddCommand( ListCmd.CobraCommand(cli.Context, client, cli), describeCmd.CobraCommand(cli.Context, client, cli), ) return cmd } cli-1.39.0/internal/cmd/datacenter/describe.go000066400000000000000000000042331451614444200211620ustar00rootroot00000000000000package datacenter import ( "context" "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var describeCmd = base.DescribeCmd{ ResourceNameSingular: "datacenter", ShortDescription: "Describe an datacenter", JSONKeyGetByID: "datacenter", JSONKeyGetByName: "datacenters", NameSuggestions: func(c hcapi2.Client) func() []string { return c.Datacenter().Names }, Fetch: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) { return client.Datacenter().Get(ctx, idOrName) }, PrintText: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, resource interface{}) error { datacenter := resource.(*hcloud.Datacenter) fmt.Printf("ID:\t\t%d\n", datacenter.ID) fmt.Printf("ID:\t\t%d\n", datacenter.ID) fmt.Printf("Name:\t\t%s\n", datacenter.Name) fmt.Printf("Description:\t%s\n", datacenter.Description) fmt.Printf("Location:\n") fmt.Printf(" Name:\t\t%s\n", datacenter.Location.Name) fmt.Printf(" Description:\t%s\n", datacenter.Location.Description) fmt.Printf(" Country:\t%s\n", datacenter.Location.Country) fmt.Printf(" City:\t\t%s\n", datacenter.Location.City) fmt.Printf(" Latitude:\t%f\n", datacenter.Location.Latitude) fmt.Printf(" Longitude:\t%f\n", datacenter.Location.Longitude) fmt.Printf("Server Types:\n") printServerTypes := func(list []*hcloud.ServerType) { for _, t := range list { fmt.Printf(" - ID:\t\t %d\n", t.ID) fmt.Printf(" Name:\t %s\n", client.ServerType().ServerTypeName(t.ID)) fmt.Printf(" Description: %s\n", client.ServerType().ServerTypeDescription(t.ID)) } } fmt.Printf(" Available:\n") if len(datacenter.ServerTypes.Available) > 0 { printServerTypes(datacenter.ServerTypes.Available) } else { fmt.Printf(" No available server types\n") } fmt.Printf(" Supported:\n") if len(datacenter.ServerTypes.Supported) > 0 { printServerTypes(datacenter.ServerTypes.Supported) } else { fmt.Printf(" No supported server types\n") } return nil }, } cli-1.39.0/internal/cmd/datacenter/list.go000066400000000000000000000030201451614444200203460ustar00rootroot00000000000000package datacenter import ( "context" "github.com/spf13/pflag" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/output" "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" "github.com/hetznercloud/hcloud-go/v2/hcloud/schema" ) var ListCmd = base.ListCmd{ ResourceNamePlural: "Datacenters", JSONKeyGetByName: "datacenters", DefaultColumns: []string{"id", "name", "description", "location"}, Fetch: func(ctx context.Context, client hcapi2.Client, _ *pflag.FlagSet, listOpts hcloud.ListOpts, sorts []string) ([]interface{}, error) { opts := hcloud.DatacenterListOpts{ListOpts: listOpts} if len(sorts) > 0 { opts.Sort = sorts } datacenters, _, err := client.Datacenter().List(ctx, opts) var resources []interface{} for _, n := range datacenters { resources = append(resources, n) } return resources, err }, OutputTable: func(_ hcapi2.Client) *output.Table { return output.NewTable(). AddAllowedFields(hcloud.Datacenter{}). AddFieldFn("location", output.FieldFn(func(obj interface{}) string { datacenter := obj.(*hcloud.Datacenter) return datacenter.Location.Name })) }, JSONSchema: func(resources []interface{}) interface{} { dcSchemas := make([]schema.Datacenter, 0, len(resources)) for _, resource := range resources { dc := resource.(*hcloud.Datacenter) dcSchemas = append(dcSchemas, util.DatacenterToSchema(*dc)) } return dcSchemas }, } cli-1.39.0/internal/cmd/firewall/000077500000000000000000000000001451614444200165445ustar00rootroot00000000000000cli-1.39.0/internal/cmd/firewall/add_rule.go000066400000000000000000000074501451614444200206600ustar00rootroot00000000000000package firewall import ( "context" "fmt" "net" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var AddRuleCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "add-rule FIREWALL FLAGS", Short: "Add a single rule to a firewall", Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.Firewall().Names)), TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.Flags().String("direction", "", "Direction (in, out) (required)") cmd.RegisterFlagCompletionFunc("direction", cmpl.SuggestCandidates("in", "out")) cmd.MarkFlagRequired("direction") cmd.Flags().String("protocol", "", "Protocol (icmp, esp, gre, udp or tcp) (required)") cmd.RegisterFlagCompletionFunc("protocol", cmpl.SuggestCandidates("icmp", "udp", "tcp", "esp", "gre")) cmd.MarkFlagRequired("protocol") cmd.Flags().StringArray("source-ips", []string{}, "Source IPs (CIDR Notation) (required when direction is in)") cmd.Flags().StringArray("destination-ips", []string{}, "Destination IPs (CIDR Notation) (required when direction is out)") cmd.Flags().String("port", "", "Port to which traffic will be allowed, only applicable for protocols TCP and UDP, you can specify port ranges, sample: 80-85") cmd.Flags().String("description", "", "Description of the firewall rule") return cmd }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { direction, _ := cmd.Flags().GetString("direction") protocol, _ := cmd.Flags().GetString("protocol") sourceIPs, _ := cmd.Flags().GetStringArray("source-ips") destinationIPs, _ := cmd.Flags().GetStringArray("destination-ips") port, _ := cmd.Flags().GetString("port") description, _ := cmd.Flags().GetString("description") idOrName := args[0] firewall, _, err := client.Firewall().Get(ctx, idOrName) if err != nil { return err } if firewall == nil { return fmt.Errorf("Firewall not found: %v", idOrName) } d := hcloud.FirewallRuleDirection(direction) rule := hcloud.FirewallRule{ Direction: d, Protocol: hcloud.FirewallRuleProtocol(protocol), } if port != "" { rule.Port = hcloud.String(port) } if description != "" { rule.Description = hcloud.String(description) } switch rule.Protocol { case hcloud.FirewallRuleProtocolTCP: case hcloud.FirewallRuleProtocolUDP: if port == "" { return fmt.Errorf("port is required") } default: if port != "" { return fmt.Errorf("port is not allowed for this protocol") } } switch d { case hcloud.FirewallRuleDirectionOut: rule.DestinationIPs = make([]net.IPNet, len(destinationIPs)) for i, ip := range destinationIPs { n, err := validateFirewallIP(ip) if err != nil { return fmt.Errorf("destination error on index %d: %s", i, err) } rule.DestinationIPs[i] = *n } case hcloud.FirewallRuleDirectionIn: rule.SourceIPs = make([]net.IPNet, len(sourceIPs)) for i, ip := range sourceIPs { n, err := validateFirewallIP(ip) if err != nil { return fmt.Errorf("source ips error on index %d: %s", i, err) } rule.SourceIPs[i] = *n } } rules := append(firewall.Rules, rule) actions, _, err := client.Firewall().SetRules(ctx, firewall, hcloud.FirewallSetRulesOpts{Rules: rules}, ) if err != nil { return err } if err := waiter.WaitForActions(ctx, actions); err != nil { return err } fmt.Printf("Firewall Rules for Firewall %d updated\n", firewall.ID) return nil }, } cli-1.39.0/internal/cmd/firewall/apply_to_resource.go000066400000000000000000000061131451614444200226320ustar00rootroot00000000000000package firewall import ( "context" "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var ApplyToResourceCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "apply-to-resource FIREWALL FLAGS", Short: "Applies a Firewall to a single resource", Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.Firewall().Names)), TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.Flags().String("type", "", "Resource Type (server) (required)") cmd.RegisterFlagCompletionFunc("type", cmpl.SuggestCandidates("server", "label_selector")) cmd.MarkFlagRequired("type") cmd.Flags().String("server", "", "Server name of ID (required when type is server)") cmd.RegisterFlagCompletionFunc("server", cmpl.SuggestCandidatesF(client.Server().Names)) cmd.Flags().StringP("label-selector", "l", "", "Label Selector") return cmd }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { resourceType, _ := cmd.Flags().GetString("type") switch resourceType { case string(hcloud.FirewallResourceTypeServer): server, _ := cmd.Flags().GetString("server") if server == "" { return fmt.Errorf("type %s need a --server specific", resourceType) } case string(hcloud.FirewallResourceTypeLabelSelector): labelSelector, _ := cmd.Flags().GetString("label-selector") if labelSelector == "" { return fmt.Errorf("type %s need a --label-selector specific", resourceType) } default: return fmt.Errorf("unknown type %s", resourceType) } serverIdOrName, _ := cmd.Flags().GetString("server") labelSelector, _ := cmd.Flags().GetString("label-selector") idOrName := args[0] firewall, _, err := client.Firewall().Get(ctx, idOrName) if err != nil { return err } if firewall == nil { return fmt.Errorf("Firewall not found: %v", idOrName) } opts := hcloud.FirewallResource{Type: hcloud.FirewallResourceType(resourceType)} switch opts.Type { case hcloud.FirewallResourceTypeServer: server, _, err := client.Server().Get(ctx, serverIdOrName) if err != nil { return err } if server == nil { return fmt.Errorf("Server not found: %v", serverIdOrName) } opts.Server = &hcloud.FirewallResourceServer{ID: server.ID} case hcloud.FirewallResourceTypeLabelSelector: opts.LabelSelector = &hcloud.FirewallResourceLabelSelector{Selector: labelSelector} default: return fmt.Errorf("unknown type %s", opts.Type) } actions, _, err := client.Firewall().ApplyResources(ctx, firewall, []hcloud.FirewallResource{opts}) if err != nil { return err } if err := waiter.WaitForActions(ctx, actions); err != nil { return err } fmt.Printf("Firewall %d applied\n", firewall.ID) return nil }, } cli-1.39.0/internal/cmd/firewall/create.go000066400000000000000000000047021451614444200203410ustar00rootroot00000000000000package firewall import ( "encoding/json" "fmt" "io/ioutil" "net" "os" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" "github.com/hetznercloud/hcloud-go/v2/hcloud/schema" ) func newCreateCommand(cli *state.State) *cobra.Command { cmd := &cobra.Command{ Use: "create FLAGS", Short: "Create a Firewall", Args: cobra.NoArgs, TraverseChildren: true, DisableFlagsInUseLine: true, PreRunE: util.ChainRunE(cli.EnsureToken), RunE: cli.Wrap(runFirewallCreate), } cmd.Flags().String("name", "", "Name") cmd.MarkFlagRequired("name") cmd.Flags().StringToString("label", nil, "User-defined labels ('key=value') (can be specified multiple times)") cmd.Flags().String("rules-file", "", "JSON file containing your routes (use - to read from stdin). The structure of the file needs to be the same as within the API: https://docs.hetzner.cloud/#firewalls-get-a-firewall ") return cmd } func runFirewallCreate(cli *state.State, cmd *cobra.Command, args []string) error { name, _ := cmd.Flags().GetString("name") labels, _ := cmd.Flags().GetStringToString("label") opts := hcloud.FirewallCreateOpts{ Name: name, Labels: labels, } rulesFile, _ := cmd.Flags().GetString("rules-file") if len(rulesFile) > 0 { var data []byte var err error if rulesFile == "-" { data, err = ioutil.ReadAll(os.Stdin) } else { data, err = ioutil.ReadFile(rulesFile) } if err != nil { return err } var rules []schema.FirewallRule err = json.Unmarshal(data, &rules) if err != nil { return err } for _, rule := range rules { var sourceNets []net.IPNet for i, sourceIP := range rule.SourceIPs { _, sourceNet, err := net.ParseCIDR(sourceIP) if err != nil { return fmt.Errorf("invalid CIDR on index %d : %s", i, err) } sourceNets = append(sourceNets, *sourceNet) } opts.Rules = append(opts.Rules, hcloud.FirewallRule{ Direction: hcloud.FirewallRuleDirection(rule.Direction), SourceIPs: sourceNets, Protocol: hcloud.FirewallRuleProtocol(rule.Protocol), Port: rule.Port, Description: rule.Description, }) } } result, _, err := cli.Client().Firewall.Create(cli.Context, opts) if err != nil { return err } fmt.Printf("Firewall %d created\n", result.Firewall.ID) return nil } cli-1.39.0/internal/cmd/firewall/delete.go000066400000000000000000000016321451614444200203370ustar00rootroot00000000000000package firewall import ( "context" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var deleteCmd = base.DeleteCmd{ ResourceNameSingular: "firewall", ShortDescription: "Delete a firewall", NameSuggestions: func(c hcapi2.Client) func() []string { return c.Firewall().Names }, Fetch: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) { return client.Firewall().Get(ctx, idOrName) }, Delete: func(ctx context.Context, client hcapi2.Client, _ state.ActionWaiter, cmd *cobra.Command, resource interface{}) error { firewall := resource.(*hcloud.Firewall) if _, err := client.Firewall().Delete(ctx, firewall); err != nil { return err } return nil }, } cli-1.39.0/internal/cmd/firewall/delete_rule.go000066400000000000000000000102041451614444200213610ustar00rootroot00000000000000package firewall import ( "context" "fmt" "net" "reflect" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var DeleteRuleCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "delete-rule FIREWALL FLAGS", Short: "Delete a single rule to a firewall", Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.Firewall().Names)), TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.Flags().String("direction", "", "Direction (in, out) (required)") cmd.RegisterFlagCompletionFunc("direction", cmpl.SuggestCandidates("in", "out")) cmd.MarkFlagRequired("direction") cmd.Flags().String("protocol", "", "Protocol (icmp, esp, gre, udp or tcp) (required)") cmd.RegisterFlagCompletionFunc("protocol", cmpl.SuggestCandidates("icmp", "udp", "tcp", "esp", "gre")) cmd.MarkFlagRequired("protocol") cmd.Flags().StringArray("source-ips", []string{}, "Source IPs (CIDR Notation) (required when direction is in)") cmd.Flags().StringArray("destination-ips", []string{}, "Destination IPs (CIDR Notation) (required when direction is out)") cmd.Flags().String("port", "", "Port to which traffic will be allowed, only applicable for protocols TCP and UDP") cmd.Flags().String("description", "", "Description of the firewall rule") return cmd }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { direction, _ := cmd.Flags().GetString("direction") protocol, _ := cmd.Flags().GetString("protocol") sourceIPs, _ := cmd.Flags().GetStringArray("source-ips") destinationIPs, _ := cmd.Flags().GetStringArray("destination-ips") port, _ := cmd.Flags().GetString("port") description, _ := cmd.Flags().GetString("description") idOrName := args[0] firewall, _, err := client.Firewall().Get(ctx, idOrName) if err != nil { return err } if firewall == nil { return fmt.Errorf("Firewall not found: %v", idOrName) } d := hcloud.FirewallRuleDirection(direction) rule := hcloud.FirewallRule{ Direction: d, Protocol: hcloud.FirewallRuleProtocol(protocol), } if port != "" { rule.Port = hcloud.String(port) } if description != "" { rule.Description = hcloud.String(description) } switch rule.Protocol { case hcloud.FirewallRuleProtocolTCP: case hcloud.FirewallRuleProtocolUDP: if port == "" { return fmt.Errorf("port is required") } default: if port != "" { return fmt.Errorf("port is not allowed for this protocol") } } switch d { case hcloud.FirewallRuleDirectionOut: rule.DestinationIPs = make([]net.IPNet, len(destinationIPs)) for i, ip := range destinationIPs { n, err := validateFirewallIP(ip) if err != nil { return fmt.Errorf("destination ips error on index %d: %s", i, err) } rule.DestinationIPs[i] = *n rule.SourceIPs = make([]net.IPNet, 0) } case hcloud.FirewallRuleDirectionIn: rule.SourceIPs = make([]net.IPNet, len(sourceIPs)) for i, ip := range sourceIPs { n, err := validateFirewallIP(ip) if err != nil { return fmt.Errorf("source ips error on index %d: %s", i, err) } rule.DestinationIPs = make([]net.IPNet, 0) rule.SourceIPs[i] = *n } } var rules []hcloud.FirewallRule for _, existingRule := range firewall.Rules { if !reflect.DeepEqual(existingRule, rule) { rules = append(rules, existingRule) } } if len(rules) == len(firewall.Rules) { return fmt.Errorf("the specified rule was not found in the ruleset of Firewall %d", firewall.ID) } actions, _, err := client.Firewall().SetRules(ctx, firewall, hcloud.FirewallSetRulesOpts{Rules: rules}, ) if err != nil { return err } if err := waiter.WaitForActions(ctx, actions); err != nil { return err } fmt.Printf("Firewall Rules for Firewall %d updated\n", firewall.ID) return nil }, } cli-1.39.0/internal/cmd/firewall/describe.go000066400000000000000000000052211451614444200206530ustar00rootroot00000000000000package firewall import ( "context" "fmt" "net" "github.com/dustin/go-humanize" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var describeCmd = base.DescribeCmd{ ResourceNameSingular: "firewall", ShortDescription: "Describe an firewall", JSONKeyGetByID: "firewall", JSONKeyGetByName: "firewalls", NameSuggestions: func(c hcapi2.Client) func() []string { return c.Firewall().Names }, Fetch: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) { return client.Firewall().Get(ctx, idOrName) }, PrintText: func(_ context.Context, client hcapi2.Client, cmd *cobra.Command, resource interface{}) error { firewall := resource.(*hcloud.Firewall) fmt.Printf("ID:\t\t%d\n", firewall.ID) fmt.Printf("Name:\t\t%s\n", firewall.Name) fmt.Printf("Created:\t%s (%s)\n", util.Datetime(firewall.Created), humanize.Time(firewall.Created)) fmt.Print("Labels:\n") if len(firewall.Labels) == 0 { fmt.Print(" No labels\n") } else { for key, value := range firewall.Labels { fmt.Printf(" %s: %s\n", key, value) } } fmt.Print("Rules:\n") if len(firewall.Rules) == 0 { fmt.Print(" No rules\n") } else { for _, rule := range firewall.Rules { fmt.Printf(" - Direction:\t\t%s\n", rule.Direction) if rule.Description != nil { fmt.Printf(" Description:\t%s\n", *rule.Description) } fmt.Printf(" Protocol:\t\t%s\n", rule.Protocol) if rule.Port != nil { fmt.Printf(" Port:\t\t%s\n", *rule.Port) } var ips []net.IPNet switch rule.Direction { case hcloud.FirewallRuleDirectionIn: fmt.Print(" Source IPs:\n") ips = rule.SourceIPs case hcloud.FirewallRuleDirectionOut: fmt.Print(" Destination IPs:\n") ips = rule.DestinationIPs } for _, cidr := range ips { fmt.Printf(" \t\t\t%s\n", cidr.String()) } } } fmt.Print("Applied To:\n") if len(firewall.AppliedTo) == 0 { fmt.Print(" Not applied\n") } else { for _, resource := range firewall.AppliedTo { fmt.Printf(" - Type:\t\t%s\n", resource.Type) switch resource.Type { case hcloud.FirewallResourceTypeServer: fmt.Printf(" Server ID:\t\t%d\n", resource.Server.ID) fmt.Printf(" Server Name:\t%s\n", client.Server().ServerName(resource.Server.ID)) case hcloud.FirewallResourceTypeLabelSelector: fmt.Printf(" Label Selector:\t%s\n", resource.LabelSelector.Selector) } } } return nil }, } cli-1.39.0/internal/cmd/firewall/firewall.go000066400000000000000000000022031451614444200206750ustar00rootroot00000000000000package firewall import ( "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" ) func NewCommand(cli *state.State, client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "firewall", Short: "Manage Firewalls", Args: cobra.NoArgs, TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.AddCommand( ListCmd.CobraCommand(cli.Context, client, cli), describeCmd.CobraCommand(cli.Context, client, cli), newCreateCommand(cli), updateCmd.CobraCommand(cli.Context, client, cli), ReplaceRulesCommand.CobraCommand(cli.Context, client, cli, cli), deleteCmd.CobraCommand(cli.Context, client, cli, cli), AddRuleCommand.CobraCommand(cli.Context, client, cli, cli), DeleteRuleCommand.CobraCommand(cli.Context, client, cli, cli), ApplyToResourceCommand.CobraCommand(cli.Context, client, cli, cli), RemoveFromResourceCommand.CobraCommand(cli.Context, client, cli, cli), labelCmds.AddCobraCommand(cli.Context, client, cli), labelCmds.RemoveCobraCommand(cli.Context, client, cli), ) return cmd } cli-1.39.0/internal/cmd/firewall/labels.go000066400000000000000000000022601451614444200203350ustar00rootroot00000000000000package firewall import ( "context" "fmt" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var labelCmds = base.LabelCmds{ ResourceNameSingular: "firewall", ShortDescriptionAdd: "Add a label to an firewall", ShortDescriptionRemove: "Remove a label from an firewall", NameSuggestions: func(c hcapi2.Client) func() []string { return c.Firewall().Names }, LabelKeySuggestions: func(c hcapi2.Client) func(idOrName string) []string { return c.Firewall().LabelKeys }, FetchLabels: func(ctx context.Context, client hcapi2.Client, idOrName string) (map[string]string, int64, error) { firewall, _, err := client.Firewall().Get(ctx, idOrName) if err != nil { return nil, 0, err } if firewall == nil { return nil, 0, fmt.Errorf("firewall not found: %s", idOrName) } return firewall.Labels, firewall.ID, nil }, SetLabels: func(ctx context.Context, client hcapi2.Client, id int64, labels map[string]string) error { opts := hcloud.FirewallUpdateOpts{ Labels: labels, } _, _, err := client.Firewall().Update(ctx, &hcloud.Firewall{ID: id}, opts) return err }, } cli-1.39.0/internal/cmd/firewall/list.go000066400000000000000000000070201451614444200200450ustar00rootroot00000000000000package firewall import ( "context" "fmt" "github.com/spf13/pflag" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/output" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" "github.com/hetznercloud/hcloud-go/v2/hcloud/schema" ) var ListCmd = base.ListCmd{ ResourceNamePlural: "Firewalls", JSONKeyGetByName: "firewalls", DefaultColumns: []string{"id", "name", "rules_count", "applied_to_count"}, Fetch: func(ctx context.Context, client hcapi2.Client, _ *pflag.FlagSet, listOpts hcloud.ListOpts, sorts []string) ([]interface{}, error) { opts := hcloud.FirewallListOpts{ListOpts: listOpts} if len(sorts) > 0 { opts.Sort = sorts } firewalls, err := client.Firewall().AllWithOpts(ctx, opts) var resources []interface{} for _, n := range firewalls { resources = append(resources, n) } return resources, err }, OutputTable: func(client hcapi2.Client) *output.Table { return output.NewTable(). AddAllowedFields(hcloud.Firewall{}). AddFieldFn("rules_count", output.FieldFn(func(obj interface{}) string { firewall := obj.(*hcloud.Firewall) count := len(firewall.Rules) if count == 1 { return fmt.Sprintf("%d Rule", count) } return fmt.Sprintf("%d Rules", count) })). AddFieldFn("applied_to_count", output.FieldFn(func(obj interface{}) string { firewall := obj.(*hcloud.Firewall) servers := 0 labelSelectors := 0 for _, r := range firewall.AppliedTo { if r.Type == hcloud.FirewallResourceTypeLabelSelector { labelSelectors++ continue } servers++ } serversText := "Servers" if servers == 1 { serversText = "Server" } labelSelectorsText := "Label Selectors" if labelSelectors == 1 { labelSelectorsText = "Label Selector" } return fmt.Sprintf("%d %s | %d %s", servers, serversText, labelSelectors, labelSelectorsText) })) }, JSONSchema: func(resources []interface{}) interface{} { firewallSchemas := make([]schema.Firewall, 0, len(resources)) for _, resource := range resources { firewall := resource.(*hcloud.Firewall) firewallSchema := schema.Firewall{ ID: firewall.ID, Name: firewall.Name, Labels: firewall.Labels, Created: firewall.Created, } for _, rule := range firewall.Rules { var sourceNets []string for _, sourceIP := range rule.SourceIPs { sourceNets = append(sourceNets, sourceIP.Network()) } var destinationNets []string for _, destinationIP := range rule.DestinationIPs { destinationNets = append(destinationNets, destinationIP.Network()) } firewallSchema.Rules = append(firewallSchema.Rules, schema.FirewallRule{ Direction: string(rule.Direction), SourceIPs: sourceNets, DestinationIPs: destinationNets, Protocol: string(rule.Protocol), Port: rule.Port, Description: rule.Description, }) } for _, AppliedTo := range firewall.AppliedTo { s := schema.FirewallResource{ Type: string(AppliedTo.Type), } switch AppliedTo.Type { case hcloud.FirewallResourceTypeServer: s.Server = &schema.FirewallResourceServer{ID: AppliedTo.Server.ID} case hcloud.FirewallResourceTypeLabelSelector: s.LabelSelector = &schema.FirewallResourceLabelSelector{Selector: AppliedTo.LabelSelector.Selector} } firewallSchema.AppliedTo = append(firewallSchema.AppliedTo, s) } firewallSchemas = append(firewallSchemas, firewallSchema) } return firewallSchemas }, } cli-1.39.0/internal/cmd/firewall/remove_from_resource.go000066400000000000000000000061231451614444200233240ustar00rootroot00000000000000package firewall import ( "context" "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var RemoveFromResourceCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "remove-from-resource FIREWALL FLAGS", Short: "Removes a Firewall from a single resource", Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.Firewall().Names)), TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.Flags().String("type", "", "Resource Type (server) (required)") cmd.RegisterFlagCompletionFunc("type", cmpl.SuggestCandidates("server", "label_selector")) cmd.MarkFlagRequired("type") cmd.Flags().String("server", "", "Server name of ID (required when type is server)") cmd.RegisterFlagCompletionFunc("server", cmpl.SuggestCandidatesF(client.Server().Names)) cmd.Flags().StringP("label-selector", "l", "", "Label Selector") return cmd }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { resourceType, _ := cmd.Flags().GetString("type") switch resourceType { case string(hcloud.FirewallResourceTypeServer): server, _ := cmd.Flags().GetString("server") if server == "" { return fmt.Errorf("type %s need a --server specific", resourceType) } case string(hcloud.FirewallResourceTypeLabelSelector): labelSelector, _ := cmd.Flags().GetString("label-selector") if labelSelector == "" { return fmt.Errorf("type %s need a --label-selector specific", resourceType) } default: return fmt.Errorf("unknown type %s", resourceType) } serverIdOrName, _ := cmd.Flags().GetString("server") labelSelector, _ := cmd.Flags().GetString("label-selector") idOrName := args[0] firewall, _, err := client.Firewall().Get(ctx, idOrName) if err != nil { return err } if firewall == nil { return fmt.Errorf("Firewall not found: %v", idOrName) } opts := hcloud.FirewallResource{Type: hcloud.FirewallResourceType(resourceType)} switch opts.Type { case hcloud.FirewallResourceTypeServer: server, _, err := client.Server().Get(ctx, serverIdOrName) if err != nil { return err } if server == nil { return fmt.Errorf("Server not found: %v", serverIdOrName) } opts.Server = &hcloud.FirewallResourceServer{ID: server.ID} case hcloud.FirewallResourceTypeLabelSelector: opts.LabelSelector = &hcloud.FirewallResourceLabelSelector{Selector: labelSelector} default: return fmt.Errorf("unknown type %s", opts.Type) } actions, _, err := client.Firewall().RemoveResources(ctx, firewall, []hcloud.FirewallResource{opts}) if err != nil { return err } if err := waiter.WaitForActions(ctx, actions); err != nil { return err } fmt.Printf("Firewall %d applied\n", firewall.ID) return nil }, } cli-1.39.0/internal/cmd/firewall/replace_rules.go000066400000000000000000000057771451614444200217400ustar00rootroot00000000000000package firewall import ( "context" "encoding/json" "fmt" "io/ioutil" "net" "os" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" "github.com/hetznercloud/hcloud-go/v2/hcloud/schema" ) var ReplaceRulesCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "replace-rules FIREWALL FLAGS", Short: "Replaces all rules from a Firewall from a file", Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.Firewall().Names)), TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.Flags().String("rules-file", "", "JSON file containing your routes (use - to read from stdin). The structure of the file needs to be the same as within the API: https://docs.hetzner.cloud/#firewalls-get-a-firewall") cmd.MarkFlagRequired("rules-file") return cmd }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { idOrName := args[0] firewall, _, err := client.Firewall().Get(ctx, idOrName) if err != nil { return err } if firewall == nil { return fmt.Errorf("Firewall not found: %v", idOrName) } opts := hcloud.FirewallSetRulesOpts{} rulesFile, _ := cmd.Flags().GetString("rules-file") var data []byte if rulesFile == "-" { data, err = ioutil.ReadAll(os.Stdin) } else { data, err = ioutil.ReadFile(rulesFile) } if err != nil { return err } var rules []schema.FirewallRule err = json.Unmarshal(data, &rules) if err != nil { return err } for _, rule := range rules { d := hcloud.FirewallRuleDirection(rule.Direction) r := hcloud.FirewallRule{ Direction: d, Protocol: hcloud.FirewallRuleProtocol(rule.Protocol), Port: rule.Port, Description: rule.Description, } switch d { case hcloud.FirewallRuleDirectionOut: r.DestinationIPs = make([]net.IPNet, len(rule.DestinationIPs)) for i, ip := range rule.DestinationIPs { _, n, err := net.ParseCIDR(ip) if err != nil { return fmt.Errorf("invalid CIDR on index %d : %s", i, err) } r.DestinationIPs[i] = *n } case hcloud.FirewallRuleDirectionIn: r.SourceIPs = make([]net.IPNet, len(rule.SourceIPs)) for i, ip := range rule.SourceIPs { _, n, err := net.ParseCIDR(ip) if err != nil { return fmt.Errorf("invalid CIDR on index %d : %s", i, err) } r.SourceIPs[i] = *n } } opts.Rules = append(opts.Rules, r) } actions, _, err := client.Firewall().SetRules(ctx, firewall, opts) if err != nil { return err } if err := waiter.WaitForActions(ctx, actions); err != nil { return err } fmt.Printf("Firewall Rules for Firewall %d updated\n", firewall.ID) return nil }, } cli-1.39.0/internal/cmd/firewall/update.go000066400000000000000000000021071451614444200203550ustar00rootroot00000000000000package firewall import ( "context" "github.com/spf13/cobra" "github.com/spf13/pflag" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var updateCmd = base.UpdateCmd{ ResourceNameSingular: "Firewall", ShortDescription: "Update a firewall", NameSuggestions: func(c hcapi2.Client) func() []string { return c.Firewall().Names }, Fetch: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) { return client.Firewall().Get(ctx, idOrName) }, DefineFlags: func(cmd *cobra.Command) { cmd.Flags().String("name", "", "Firewall name") }, Update: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, resource interface{}, flags map[string]pflag.Value) error { firewall := resource.(*hcloud.Firewall) updOpts := hcloud.FirewallUpdateOpts{ Name: flags["name"].String(), } _, _, err := client.Firewall().Update(ctx, firewall, updOpts) if err != nil { return err } return nil }, } cli-1.39.0/internal/cmd/firewall/validation.go000066400000000000000000000005001451614444200212200ustar00rootroot00000000000000package firewall import ( "fmt" "net" ) func validateFirewallIP(ip string) (*net.IPNet, error) { i, n, err := net.ParseCIDR(ip) if err != nil { return nil, fmt.Errorf("%s", err) } if i.String() != n.IP.String() { return nil, fmt.Errorf("%s is not the start of the cidr block %s", ip, n) } return n, nil } cli-1.39.0/internal/cmd/firewall/validation_test.go000066400000000000000000000023311451614444200222630ustar00rootroot00000000000000package firewall import ( "fmt" "testing" "github.com/stretchr/testify/assert" ) func TestValidateFirewallIP(t *testing.T) { tests := []struct { name string ip string err error }{ { name: "Valid CIDR (IPv4)", ip: "10.0.0.0/8", }, { name: "Valid CIDR (IPv6)", ip: "fe80::/128", }, { name: "Invalid IP", ip: "test", err: fmt.Errorf("invalid CIDR address: test"), }, { name: "Missing CIDR notation (IPv4)", ip: "10.0.0.0", err: fmt.Errorf("invalid CIDR address: 10.0.0.0"), }, { name: "Missing CIDR notation (IPv6)", ip: "fe80::", err: fmt.Errorf("invalid CIDR address: fe80::"), }, { name: "Host bit set (IPv4)", ip: "10.0.0.5/8", err: fmt.Errorf("10.0.0.5/8 is not the start of the cidr block 10.0.0.0/8"), }, { name: "Host bit set (IPv6)", ip: "fe80::1337/64", err: fmt.Errorf("fe80::1337/64 is not the start of the cidr block fe80::/64"), }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { net, err := validateFirewallIP(test.ip) if test.err != nil { assert.Equal(t, err, test.err) assert.Nil(t, net) return } assert.NoError(t, err) assert.NotNil(t, net) }) } } cli-1.39.0/internal/cmd/floatingip/000077500000000000000000000000001451614444200170735ustar00rootroot00000000000000cli-1.39.0/internal/cmd/floatingip/assign.go000066400000000000000000000030431451614444200207060ustar00rootroot00000000000000package floatingip import ( "context" "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" ) var AssignCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { return &cobra.Command{ Use: "assign [FLAGS] FLOATINGIP SERVER", Short: "Assign a Floating IP to a server", Args: cobra.ExactArgs(2), ValidArgsFunction: cmpl.SuggestArgs( cmpl.SuggestCandidatesF(client.FloatingIP().Names), cmpl.SuggestCandidatesF(client.Server().Names), ), TraverseChildren: true, DisableFlagsInUseLine: true, } }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { idOrName := args[0] floatingIP, _, err := client.FloatingIP().Get(ctx, idOrName) if err != nil { return err } if floatingIP == nil { return fmt.Errorf("Floating IP not found: %v", idOrName) } serverIDOrName := args[1] server, _, err := client.Server().Get(ctx, serverIDOrName) if err != nil { return err } if server == nil { return fmt.Errorf("server not found: %s", serverIDOrName) } action, _, err := client.FloatingIP().Assign(ctx, floatingIP, server) if err != nil { return err } if err := waiter.ActionProgress(ctx, action); err != nil { return err } fmt.Printf("Floating IP %d assigned to server %d\n", floatingIP.ID, server.ID) return nil }, } cli-1.39.0/internal/cmd/floatingip/create.go000066400000000000000000000062071451614444200206720ustar00rootroot00000000000000package floatingip import ( "context" "errors" "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var CreateCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "create FLAGS", Short: "Create a Floating IP", Args: cobra.NoArgs, TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.Flags().String("type", "", "Type (ipv4 or ipv6) (required)") cmd.RegisterFlagCompletionFunc("type", cmpl.SuggestCandidates("ipv4", "ipv6")) cmd.MarkFlagRequired("type") cmd.Flags().String("description", "", "Description") cmd.Flags().String("name", "", "Name") cmd.Flags().String("home-location", "", "Home location") cmd.RegisterFlagCompletionFunc("home-location", cmpl.SuggestCandidatesF(client.Location().Names)) cmd.Flags().String("server", "", "Server to assign Floating IP to") cmd.RegisterFlagCompletionFunc("server", cmpl.SuggestCandidatesF(client.Server().Names)) cmd.Flags().StringToString("label", nil, "User-defined labels ('key=value') (can be specified multiple times)") cmd.Flags().StringSlice("enable-protection", []string{}, "Enable protection (delete) (default: none)") cmd.RegisterFlagCompletionFunc("enable-protection", cmpl.SuggestCandidates("delete")) return cmd }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { typ, _ := cmd.Flags().GetString("type") if typ == "" { return errors.New("type is required") } homeLocation, _ := cmd.Flags().GetString("home-location") server, _ := cmd.Flags().GetString("server") if homeLocation == "" && server == "" { return errors.New("one of --home-location or --server is required") } name, _ := cmd.Flags().GetString("name") description, _ := cmd.Flags().GetString("description") serverNameOrID, _ := cmd.Flags().GetString("server") labels, _ := cmd.Flags().GetStringToString("label") protection, _ := cmd.Flags().GetStringSlice("enable-protection") protectionOps, err := getChangeProtectionOpts(true, protection) if err != nil { return err } createOpts := hcloud.FloatingIPCreateOpts{ Type: hcloud.FloatingIPType(typ), Description: &description, Labels: labels, } if name != "" { createOpts.Name = &name } if homeLocation != "" { createOpts.HomeLocation = &hcloud.Location{Name: homeLocation} } if serverNameOrID != "" { server, _, err := client.Server().Get(ctx, serverNameOrID) if err != nil { return err } if server == nil { return fmt.Errorf("server not found: %s", serverNameOrID) } createOpts.Server = server } result, _, err := client.FloatingIP().Create(ctx, createOpts) if err != nil { return err } fmt.Printf("Floating IP %d created\n", result.FloatingIP.ID) return changeProtection(ctx, client, waiter, result.FloatingIP, true, protectionOps) }, } cli-1.39.0/internal/cmd/floatingip/delete.go000066400000000000000000000016561451614444200206740ustar00rootroot00000000000000package floatingip import ( "context" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var deleteCmd = base.DeleteCmd{ ResourceNameSingular: "Floating IP", ShortDescription: "Delete a Floating IP", NameSuggestions: func(c hcapi2.Client) func() []string { return c.FloatingIP().Names }, Fetch: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) { return client.FloatingIP().Get(ctx, idOrName) }, Delete: func(ctx context.Context, client hcapi2.Client, _ state.ActionWaiter, cmd *cobra.Command, resource interface{}) error { floatingIP := resource.(*hcloud.FloatingIP) if _, err := client.FloatingIP().Delete(ctx, floatingIP); err != nil { return err } return nil }, } cli-1.39.0/internal/cmd/floatingip/describe.go000066400000000000000000000044101451614444200212010ustar00rootroot00000000000000package floatingip import ( "context" "fmt" "github.com/dustin/go-humanize" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var describeCmd = base.DescribeCmd{ ResourceNameSingular: "Floating IP", ShortDescription: "Describe an Floating IP", JSONKeyGetByID: "floating_ip", JSONKeyGetByName: "floating_ips", NameSuggestions: func(c hcapi2.Client) func() []string { return c.FloatingIP().Names }, Fetch: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) { return client.FloatingIP().Get(ctx, idOrName) }, PrintText: func(_ context.Context, client hcapi2.Client, cmd *cobra.Command, resource interface{}) error { floatingIP := resource.(*hcloud.FloatingIP) fmt.Printf("ID:\t\t%d\n", floatingIP.ID) fmt.Printf("Type:\t\t%s\n", floatingIP.Type) fmt.Printf("Name:\t\t%s\n", floatingIP.Name) fmt.Printf("Description:\t%s\n", util.NA(floatingIP.Description)) fmt.Printf("Created:\t%s (%s)\n", util.Datetime(floatingIP.Created), humanize.Time(floatingIP.Created)) if floatingIP.Network != nil { fmt.Printf("IP:\t\t%s\n", floatingIP.Network.String()) } else { fmt.Printf("IP:\t\t%s\n", floatingIP.IP.String()) } fmt.Printf("Blocked:\t%s\n", util.YesNo(floatingIP.Blocked)) fmt.Printf("Home Location:\t%s\n", floatingIP.HomeLocation.Name) if floatingIP.Server != nil { fmt.Printf("Server:\n") fmt.Printf(" ID:\t%d\n", floatingIP.Server.ID) fmt.Printf(" Name:\t%s\n", client.Server().ServerName(floatingIP.Server.ID)) } else { fmt.Print("Server:\n Not assigned\n") } fmt.Print("DNS:\n") if len(floatingIP.DNSPtr) == 0 { fmt.Print(" No reverse DNS entries\n") } else { for ip, dns := range floatingIP.DNSPtr { fmt.Printf(" %s: %s\n", ip, dns) } } fmt.Printf("Protection:\n") fmt.Printf(" Delete:\t%s\n", util.YesNo(floatingIP.Protection.Delete)) fmt.Print("Labels:\n") if len(floatingIP.Labels) == 0 { fmt.Print(" No labels\n") } else { for key, value := range floatingIP.Labels { fmt.Printf(" %s: %s\n", key, value) } } return nil }, } cli-1.39.0/internal/cmd/floatingip/disable_protection.go000066400000000000000000000024201451614444200232710ustar00rootroot00000000000000package floatingip import ( "context" "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" ) var DisableProtectionCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { return &cobra.Command{ Use: "disable-protection [FLAGS] FLOATINGIP PROTECTIONLEVEL [PROTECTIONLEVEL...]", Short: "Disable resource protection for a Floating IP", Args: cobra.MinimumNArgs(2), ValidArgsFunction: cmpl.SuggestArgs( cmpl.SuggestCandidatesF(client.FloatingIP().Names), cmpl.SuggestCandidates("delete"), ), TraverseChildren: true, DisableFlagsInUseLine: true, } }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { idOrName := args[0] floatingIP, _, err := client.FloatingIP().Get(ctx, idOrName) if err != nil { return err } if floatingIP == nil { return fmt.Errorf("Floating IP not found: %v", idOrName) } opts, err := getChangeProtectionOpts(false, args[1:]) if err != nil { return err } return changeProtection(ctx, client, waiter, floatingIP, false, opts) }, } cli-1.39.0/internal/cmd/floatingip/enable_protection.go000066400000000000000000000046261451614444200231260ustar00rootroot00000000000000package floatingip import ( "context" "fmt" "strings" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) func getChangeProtectionOpts(enable bool, flags []string) (hcloud.FloatingIPChangeProtectionOpts, error) { opts := hcloud.FloatingIPChangeProtectionOpts{} var unknown []string for _, arg := range flags { switch strings.ToLower(arg) { case "delete": opts.Delete = hcloud.Ptr(enable) default: unknown = append(unknown, arg) } } if len(unknown) > 0 { return opts, fmt.Errorf("unknown protection level: %s", strings.Join(unknown, ", ")) } return opts, nil } func changeProtection(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, floatingIP *hcloud.FloatingIP, enable bool, opts hcloud.FloatingIPChangeProtectionOpts) error { if opts.Delete == nil { return nil } action, _, err := client.FloatingIP().ChangeProtection(ctx, floatingIP, opts) if err != nil { return err } if err := waiter.ActionProgress(ctx, action); err != nil { return err } if enable { fmt.Printf("Resource protection enabled for floating IP %d\n", floatingIP.ID) } else { fmt.Printf("Resource protection disabled for floating IP %d\n", floatingIP.ID) } return nil } var EnableProtectionCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { return &cobra.Command{ Use: "enable-protection [FLAGS] FLOATINGIP PROTECTIONLEVEL [PROTECTIONLEVEL...]", Short: "Enable resource protection for a Floating IP", Args: cobra.MinimumNArgs(2), ValidArgsFunction: cmpl.SuggestArgs( cmpl.SuggestCandidatesF(client.FloatingIP().Names), cmpl.SuggestCandidates("delete"), ), TraverseChildren: true, DisableFlagsInUseLine: true, } }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { idOrName := args[0] floatingIP, _, err := client.FloatingIP().Get(ctx, idOrName) if err != nil { return err } if floatingIP == nil { return fmt.Errorf("Floating IP not found: %v", idOrName) } opts, err := getChangeProtectionOpts(true, args[1:]) if err != nil { return err } return changeProtection(ctx, client, waiter, floatingIP, true, opts) }, } cli-1.39.0/internal/cmd/floatingip/floatingip.go000066400000000000000000000022431451614444200215570ustar00rootroot00000000000000package floatingip import ( "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" ) func NewCommand(cli *state.State, client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "floating-ip", Short: "Manage Floating IPs", Args: cobra.NoArgs, TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.AddCommand( updateCmd.CobraCommand(cli.Context, client, cli), ListCmd.CobraCommand(cli.Context, client, cli), CreateCommand.CobraCommand(cli.Context, client, cli, cli), describeCmd.CobraCommand(cli.Context, client, cli), AssignCommand.CobraCommand(cli.Context, client, cli, cli), UnassignCommand.CobraCommand(cli.Context, client, cli, cli), deleteCmd.CobraCommand(cli.Context, client, cli, cli), EnableProtectionCommand.CobraCommand(cli.Context, client, cli, cli), DisableProtectionCommand.CobraCommand(cli.Context, client, cli, cli), labelCmds.AddCobraCommand(cli.Context, client, cli), labelCmds.RemoveCobraCommand(cli.Context, client, cli), setRDNSCmd.CobraCommand(cli.Context, client, cli, cli), ) return cmd } cli-1.39.0/internal/cmd/floatingip/labels.go000066400000000000000000000023221451614444200206630ustar00rootroot00000000000000package floatingip import ( "context" "fmt" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var labelCmds = base.LabelCmds{ ResourceNameSingular: "Floating IP", ShortDescriptionAdd: "Add a label to an Floating IP", ShortDescriptionRemove: "Remove a label from an Floating IP", NameSuggestions: func(c hcapi2.Client) func() []string { return c.FloatingIP().Names }, LabelKeySuggestions: func(c hcapi2.Client) func(idOrName string) []string { return c.FloatingIP().LabelKeys }, FetchLabels: func(ctx context.Context, client hcapi2.Client, idOrName string) (map[string]string, int64, error) { floatingIP, _, err := client.FloatingIP().Get(ctx, idOrName) if err != nil { return nil, 0, err } if floatingIP == nil { return nil, 0, fmt.Errorf("floating IP not found: %s", idOrName) } return floatingIP.Labels, floatingIP.ID, nil }, SetLabels: func(ctx context.Context, client hcapi2.Client, id int64, labels map[string]string) error { opts := hcloud.FloatingIPUpdateOpts{ Labels: labels, } _, _, err := client.FloatingIP().Update(ctx, &hcloud.FloatingIP{ID: id}, opts) return err }, } cli-1.39.0/internal/cmd/floatingip/list.go000066400000000000000000000100361451614444200203750ustar00rootroot00000000000000package floatingip import ( "context" "fmt" "strings" "time" "github.com/spf13/pflag" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/output" "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" "github.com/hetznercloud/hcloud-go/v2/hcloud/schema" ) var ListCmd = base.ListCmd{ ResourceNamePlural: "Floating IPs", JSONKeyGetByName: "floating_ips", DefaultColumns: []string{"id", "type", "name", "description", "ip", "home", "server", "dns", "age"}, Fetch: func(ctx context.Context, client hcapi2.Client, _ *pflag.FlagSet, listOpts hcloud.ListOpts, sorts []string) ([]interface{}, error) { opts := hcloud.FloatingIPListOpts{ListOpts: listOpts} if len(sorts) > 0 { opts.Sort = sorts } floatingIPs, err := client.FloatingIP().AllWithOpts(ctx, opts) var resources []interface{} for _, n := range floatingIPs { resources = append(resources, n) } return resources, err }, OutputTable: func(client hcapi2.Client) *output.Table { return output.NewTable(). AddAllowedFields(hcloud.FloatingIP{}). AddFieldFn("dns", output.FieldFn(func(obj interface{}) string { floatingIP := obj.(*hcloud.FloatingIP) var dns string if len(floatingIP.DNSPtr) == 1 { for _, v := range floatingIP.DNSPtr { dns = v } } if len(floatingIP.DNSPtr) > 1 { dns = fmt.Sprintf("%d entries", len(floatingIP.DNSPtr)) } return util.NA(dns) })). AddFieldFn("server", output.FieldFn(func(obj interface{}) string { floatingIP := obj.(*hcloud.FloatingIP) var server string if floatingIP.Server != nil { return client.Server().ServerName(floatingIP.Server.ID) } return util.NA(server) })). AddFieldFn("home", output.FieldFn(func(obj interface{}) string { floatingIP := obj.(*hcloud.FloatingIP) return floatingIP.HomeLocation.Name })). AddFieldFn("ip", output.FieldFn(func(obj interface{}) string { floatingIP := obj.(*hcloud.FloatingIP) if floatingIP.Network != nil { return floatingIP.Network.String() } return floatingIP.IP.String() })). AddFieldFn("protection", output.FieldFn(func(obj interface{}) string { floatingIP := obj.(*hcloud.FloatingIP) var protection []string if floatingIP.Protection.Delete { protection = append(protection, "delete") } return strings.Join(protection, ", ") })). AddFieldFn("labels", output.FieldFn(func(obj interface{}) string { floatingIP := obj.(*hcloud.FloatingIP) return util.LabelsToString(floatingIP.Labels) })). AddFieldFn("created", output.FieldFn(func(obj interface{}) string { floatingIP := obj.(*hcloud.FloatingIP) return util.Datetime(floatingIP.Created) })). AddFieldFn("age", output.FieldFn(func(obj interface{}) string { floatingIP := obj.(*hcloud.FloatingIP) return util.Age(floatingIP.Created, time.Now()) })) }, JSONSchema: func(resources []interface{}) interface{} { floatingIPSchemas := make([]schema.FloatingIP, 0, len(resources)) for _, resource := range resources { floatingIP := resource.(*hcloud.FloatingIP) floatingIPSchema := schema.FloatingIP{ ID: floatingIP.ID, Name: floatingIP.Name, Description: hcloud.String(floatingIP.Description), IP: floatingIP.IP.String(), Created: floatingIP.Created, Type: string(floatingIP.Type), HomeLocation: util.LocationToSchema(*floatingIP.HomeLocation), Blocked: floatingIP.Blocked, Protection: schema.FloatingIPProtection{Delete: floatingIP.Protection.Delete}, Labels: floatingIP.Labels, } for ip, dnsPtr := range floatingIP.DNSPtr { floatingIPSchema.DNSPtr = append(floatingIPSchema.DNSPtr, schema.FloatingIPDNSPtr{ IP: ip, DNSPtr: dnsPtr, }) } if floatingIP.Server != nil { floatingIPSchema.Server = hcloud.Ptr(floatingIP.Server.ID) } floatingIPSchemas = append(floatingIPSchemas, floatingIPSchema) } return floatingIPSchemas }, } cli-1.39.0/internal/cmd/floatingip/set_rdns.go000066400000000000000000000013711451614444200212450ustar00rootroot00000000000000package floatingip import ( "context" "net" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var setRDNSCmd = base.SetRdnsCmd{ ResourceNameSingular: "Floating IP", ShortDescription: "Change reverse DNS of a Floating IP", NameSuggestions: func(c hcapi2.Client) func() []string { return c.FloatingIP().Names }, Fetch: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) { return client.FloatingIP().Get(ctx, idOrName) }, GetDefaultIP: func(resource interface{}) net.IP { floatingIP := resource.(*hcloud.FloatingIP) return floatingIP.IP }, } cli-1.39.0/internal/cmd/floatingip/unassign.go000066400000000000000000000024341451614444200212540ustar00rootroot00000000000000package floatingip import ( "context" "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" ) var UnassignCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { return &cobra.Command{ Use: "unassign [FLAGS] FLOATINGIP", Short: "Unassign a Floating IP", Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.FloatingIP().Names)), TraverseChildren: true, DisableFlagsInUseLine: true, } }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { idOrName := args[0] floatingIP, _, err := client.FloatingIP().Get(ctx, idOrName) if err != nil { return err } if floatingIP == nil { return fmt.Errorf("Floating IP not found: %v", idOrName) } action, _, err := client.FloatingIP().Unassign(ctx, floatingIP) if err != nil { return err } if err := waiter.ActionProgress(ctx, action); err != nil { return err } fmt.Printf("Floating IP %d unassigned\n", floatingIP.ID) return nil }, } cli-1.39.0/internal/cmd/floatingip/update.go000066400000000000000000000023311451614444200207030ustar00rootroot00000000000000package floatingip import ( "context" "github.com/spf13/cobra" "github.com/spf13/pflag" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var updateCmd = base.UpdateCmd{ ResourceNameSingular: "Floating IP", ShortDescription: "Update a Floating IP", NameSuggestions: func(c hcapi2.Client) func() []string { return c.FloatingIP().Names }, Fetch: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) { return client.FloatingIP().Get(ctx, idOrName) }, DefineFlags: func(cmd *cobra.Command) { cmd.Flags().String("name", "", "Floating IP name") cmd.Flags().String("description", "", "Floating IP description") }, Update: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, resource interface{}, flags map[string]pflag.Value) error { floatingIP := resource.(*hcloud.FloatingIP) updOpts := hcloud.FloatingIPUpdateOpts{ Name: flags["name"].String(), Description: flags["description"].String(), } _, _, err := client.FloatingIP().Update(ctx, floatingIP, updOpts) if err != nil { return err } return nil }, } cli-1.39.0/internal/cmd/image/000077500000000000000000000000001451614444200160215ustar00rootroot00000000000000cli-1.39.0/internal/cmd/image/delete.go000066400000000000000000000016001451614444200176070ustar00rootroot00000000000000package image import ( "context" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var deleteCmd = base.DeleteCmd{ ResourceNameSingular: "image", ShortDescription: "Delete an image", NameSuggestions: func(c hcapi2.Client) func() []string { return c.Image().Names }, Fetch: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) { return client.Image().Get(ctx, idOrName) }, Delete: func(ctx context.Context, client hcapi2.Client, _ state.ActionWaiter, cmd *cobra.Command, resource interface{}) error { image := resource.(*hcloud.Image) if _, err := client.Image().Delete(ctx, image); err != nil { return err } return nil }, } cli-1.39.0/internal/cmd/image/describe.go000066400000000000000000000055761451614444200201450ustar00rootroot00000000000000package image import ( "context" "fmt" "os" humanize "github.com/dustin/go-humanize" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var describeCmd = base.DescribeCmd{ ResourceNameSingular: "image", ShortDescription: "Describe an image", JSONKeyGetByID: "image", JSONKeyGetByName: "images", AdditionalFlags: func(cmd *cobra.Command) { cmd.Flags().StringP("architecture", "a", string(hcloud.ArchitectureX86), "architecture of the image, default is x86") cmd.RegisterFlagCompletionFunc("architecture", cmpl.SuggestCandidates(string(hcloud.ArchitectureX86), string(hcloud.ArchitectureARM))) }, NameSuggestions: func(c hcapi2.Client) func() []string { return c.Image().Names }, Fetch: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) { arch, err := cmd.Flags().GetString("architecture") if err != nil { return nil, nil, err } if !cmd.Flags().Changed("architecture") { _, _ = fmt.Fprintln(os.Stderr, "INFO: This command only returns x86 images by default. Explicitly set the --architecture=x86|arm flag to hide this message.") } return client.Image().GetForArchitecture(ctx, idOrName, hcloud.Architecture(arch)) }, PrintText: func(_ context.Context, _ hcapi2.Client, _ *cobra.Command, resource interface{}) error { image := resource.(*hcloud.Image) fmt.Printf("ID:\t\t%d\n", image.ID) fmt.Printf("Type:\t\t%s\n", image.Type) fmt.Printf("Status:\t\t%s\n", image.Status) fmt.Printf("Name:\t\t%s\n", util.NA(image.Name)) fmt.Printf("Created:\t%s (%s)\n", util.Datetime(image.Created), humanize.Time(image.Created)) if !image.Deprecated.IsZero() { fmt.Printf("Deprecated:\t%s (%s)\n", util.Datetime(image.Deprecated), humanize.Time(image.Deprecated)) } fmt.Printf("Description:\t%s\n", image.Description) if image.ImageSize != 0 { fmt.Printf("Image size:\t%.2f GB\n", image.ImageSize) } else { fmt.Printf("Image size:\t%s\n", util.NA("")) } fmt.Printf("Disk size:\t%.0f GB\n", image.DiskSize) fmt.Printf("OS flavor:\t%s\n", image.OSFlavor) fmt.Printf("OS version:\t%s\n", util.NA(image.OSVersion)) fmt.Printf("Architecture:\t%s\n", image.Architecture) fmt.Printf("Rapid deploy:\t%s\n", util.YesNo(image.RapidDeploy)) fmt.Printf("Protection:\n") fmt.Printf(" Delete:\t%s\n", util.YesNo(image.Protection.Delete)) fmt.Print("Labels:\n") if len(image.Labels) == 0 { fmt.Print(" No labels\n") } else { for key, value := range image.Labels { fmt.Printf(" %s: %s\n", key, value) } } if !image.Deprecated.IsZero() { fmt.Printf("\nAttention: This image is deprecated and will be removed in the future.\n") } return nil }, } cli-1.39.0/internal/cmd/image/disable_protection.go000066400000000000000000000023771451614444200222320ustar00rootroot00000000000000package image import ( "context" "errors" "strconv" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var DisableProtectionCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { return &cobra.Command{ Use: "disable-protection [FLAGS] IMAGE PROTECTIONLEVEL [PROTECTIONLEVEL...]", Short: "Disable resource protection for an image", Args: cobra.MinimumNArgs(2), ValidArgsFunction: cmpl.SuggestArgs( cmpl.SuggestCandidatesF(client.Image().Names), cmpl.SuggestCandidates("delete"), ), TraverseChildren: true, DisableFlagsInUseLine: true, } }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, command *cobra.Command, args []string) error { imageID, err := strconv.ParseInt(args[0], 10, 64) if err != nil { return errors.New("invalid image ID") } image := &hcloud.Image{ID: imageID} opts, err := getChangeProtectionOpts(false, args[1:]) if err != nil { return err } return changeProtection(ctx, client, waiter, image, false, opts) }, } cli-1.39.0/internal/cmd/image/enable_protection.go000066400000000000000000000044441451614444200220520ustar00rootroot00000000000000package image import ( "context" "errors" "fmt" "strconv" "strings" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) func getChangeProtectionOpts(enable bool, flags []string) (hcloud.ImageChangeProtectionOpts, error) { opts := hcloud.ImageChangeProtectionOpts{} var unknown []string for _, arg := range flags { switch strings.ToLower(arg) { case "delete": opts.Delete = hcloud.Ptr(enable) default: unknown = append(unknown, arg) } } if len(unknown) > 0 { return opts, fmt.Errorf("unknown protection level: %s", strings.Join(unknown, ", ")) } return opts, nil } func changeProtection(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, image *hcloud.Image, enable bool, opts hcloud.ImageChangeProtectionOpts) error { if opts.Delete == nil { return nil } action, _, err := client.Image().ChangeProtection(ctx, image, opts) if err != nil { return err } if err := waiter.ActionProgress(ctx, action); err != nil { return err } if enable { fmt.Printf("Resource protection enabled for image %d\n", image.ID) } else { fmt.Printf("Resource protection disabled for image %d\n", image.ID) } return nil } var EnableProtectionCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { return &cobra.Command{ Use: "enable-protection [FLAGS] IMAGE PROTECTIONLEVEL [PROTECTIONLEVEL...]", Short: "Enable resource protection for an image", Args: cobra.MinimumNArgs(2), ValidArgsFunction: cmpl.SuggestArgs( cmpl.SuggestCandidatesF(client.Image().Names), cmpl.SuggestCandidates("delete"), ), TraverseChildren: true, DisableFlagsInUseLine: true, } }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, command *cobra.Command, args []string) error { imageID, err := strconv.ParseInt(args[0], 10, 64) if err != nil { return errors.New("invalid image ID") } image := &hcloud.Image{ID: imageID} opts, err := getChangeProtectionOpts(true, args[1:]) if err != nil { return err } return changeProtection(ctx, client, waiter, image, true, opts) }, } cli-1.39.0/internal/cmd/image/image.go000066400000000000000000000016371451614444200174410ustar00rootroot00000000000000package image import ( "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" ) func NewCommand(cli *state.State, client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "image", Short: "Manage images", Args: cobra.NoArgs, TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.AddCommand( ListCmd.CobraCommand(cli.Context, client, cli), deleteCmd.CobraCommand(cli.Context, client, cli, cli), describeCmd.CobraCommand(cli.Context, client, cli), updateCmd.CobraCommand(cli.Context, client, cli), EnableProtectionCommand.CobraCommand(cli.Context, client, cli, cli), DisableProtectionCommand.CobraCommand(cli.Context, client, cli, cli), labelCmds.AddCobraCommand(cli.Context, client, cli), labelCmds.RemoveCobraCommand(cli.Context, client, cli), ) return cmd } cli-1.39.0/internal/cmd/image/labels.go000066400000000000000000000022031451614444200176070ustar00rootroot00000000000000package image import ( "context" "fmt" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var labelCmds = base.LabelCmds{ ResourceNameSingular: "image", ShortDescriptionAdd: "Add a label to an image", ShortDescriptionRemove: "Remove a label from an image", NameSuggestions: func(c hcapi2.Client) func() []string { return c.Image().Names }, LabelKeySuggestions: func(c hcapi2.Client) func(idOrName string) []string { return c.Image().LabelKeys }, FetchLabels: func(ctx context.Context, client hcapi2.Client, idOrName string) (map[string]string, int64, error) { image, _, err := client.Image().Get(ctx, idOrName) if err != nil { return nil, 0, err } if image == nil { return nil, 0, fmt.Errorf("image not found: %s", idOrName) } return image.Labels, image.ID, nil }, SetLabels: func(ctx context.Context, client hcapi2.Client, id int64, labels map[string]string) error { opts := hcloud.ImageUpdateOpts{ Labels: labels, } _, _, err := client.Image().Update(ctx, &hcloud.Image{ID: id}, opts) return err }, } cli-1.39.0/internal/cmd/image/list.go000066400000000000000000000121501451614444200173220ustar00rootroot00000000000000package image import ( "context" "fmt" "strings" "time" humanize "github.com/dustin/go-humanize" "github.com/spf13/cobra" "github.com/spf13/pflag" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/cmd/output" "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" "github.com/hetznercloud/hcloud-go/v2/hcloud/schema" ) var ListCmd = base.ListCmd{ ResourceNamePlural: "Images", JSONKeyGetByName: "images", DefaultColumns: []string{"id", "type", "name", "description", "architecture", "image_size", "disk_size", "created", "deprecated"}, AdditionalFlags: func(cmd *cobra.Command) { cmd.Flags().StringSliceP("type", "t", []string{}, "Only show images of given type") cmd.RegisterFlagCompletionFunc("type", cmpl.SuggestCandidates("backup", "snapshot", "system", "app")) cmd.Flags().StringSliceP("architecture", "a", []string{}, "Only show images of given architecture: x86|arm") cmd.RegisterFlagCompletionFunc("architecture", cmpl.SuggestCandidates(string(hcloud.ArchitectureX86), string(hcloud.ArchitectureARM))) }, Fetch: func(ctx context.Context, client hcapi2.Client, flags *pflag.FlagSet, listOpts hcloud.ListOpts, sorts []string) ([]interface{}, error) { opts := hcloud.ImageListOpts{ListOpts: listOpts, IncludeDeprecated: true} types, _ := flags.GetStringSlice("type") var ( unknown []string ) for _, imageType := range types { switch imageType { case string(hcloud.ImageTypeBackup), string(hcloud.ImageTypeSnapshot), string(hcloud.ImageTypeSystem), string(hcloud.ImageTypeApp): opts.Type = append(opts.Type, hcloud.ImageType(imageType)) default: unknown = append(unknown, imageType) } } if len(unknown) > 0 { return nil, fmt.Errorf("unknown image type: %s\n", strings.Join(unknown, ", ")) } architecture, _ := flags.GetStringSlice("architecture") if len(architecture) > 0 { for _, arch := range architecture { opts.Architecture = append(opts.Architecture, hcloud.Architecture(arch)) } } if len(sorts) > 0 { opts.Sort = sorts } images, err := client.Image().AllWithOpts(ctx, opts) var resources []interface{} for _, n := range images { resources = append(resources, n) } return resources, err }, OutputTable: func(client hcapi2.Client) *output.Table { return output.NewTable(). AddAllowedFields(hcloud.Image{}). AddFieldAlias("imagesize", "image size"). AddFieldAlias("disksize", "disk size"). AddFieldAlias("osflavor", "os flavor"). AddFieldAlias("osversion", "os version"). AddFieldAlias("rapiddeploy", "rapid deploy"). AddFieldAlias("createdfrom", "created from"). AddFieldAlias("boundto", "bound to"). AddFieldFn("name", output.FieldFn(func(obj interface{}) string { image := obj.(*hcloud.Image) return util.NA(image.Name) })). AddFieldFn("image_size", output.FieldFn(func(obj interface{}) string { image := obj.(*hcloud.Image) if image.ImageSize == 0 { return util.NA("") } return fmt.Sprintf("%.2f GB", image.ImageSize) })). AddFieldFn("disk_size", output.FieldFn(func(obj interface{}) string { image := obj.(*hcloud.Image) return fmt.Sprintf("%.0f GB", image.DiskSize) })). AddFieldFn("created", output.FieldFn(func(obj interface{}) string { image := obj.(*hcloud.Image) return humanize.Time(image.Created) })). AddFieldFn("bound_to", output.FieldFn(func(obj interface{}) string { image := obj.(*hcloud.Image) if image.BoundTo != nil { return client.Server().ServerName(image.BoundTo.ID) } return util.NA("") })). AddFieldFn("created_from", output.FieldFn(func(obj interface{}) string { image := obj.(*hcloud.Image) if image.CreatedFrom != nil { return client.Server().ServerName(image.CreatedFrom.ID) } return util.NA("") })). AddFieldFn("protection", output.FieldFn(func(obj interface{}) string { image := obj.(*hcloud.Image) var protection []string if image.Protection.Delete { protection = append(protection, "delete") } return strings.Join(protection, ", ") })). AddFieldFn("labels", output.FieldFn(func(obj interface{}) string { image := obj.(*hcloud.Image) return util.LabelsToString(image.Labels) })). AddFieldFn("created", output.FieldFn(func(obj interface{}) string { image := obj.(*hcloud.Image) return util.Datetime(image.Created) })). AddFieldFn("age", output.FieldFn(func(obj interface{}) string { image := obj.(*hcloud.Image) return util.Age(image.Created, time.Now()) })). AddFieldFn("deprecated", output.FieldFn(func(obj interface{}) string { image := obj.(*hcloud.Image) if image.Deprecated.IsZero() { return "-" } return util.Datetime(image.Deprecated) })) }, JSONSchema: func(resources []interface{}) interface{} { imageSchemas := make([]schema.Image, 0, len(resources)) for _, resource := range resources { image := resource.(*hcloud.Image) imageSchemas = append(imageSchemas, util.ImageToSchema(*image)) } return imageSchemas }, } cli-1.39.0/internal/cmd/image/update.go000066400000000000000000000025031451614444200176320ustar00rootroot00000000000000package image import ( "context" "github.com/spf13/cobra" "github.com/spf13/pflag" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var updateCmd = base.UpdateCmd{ ResourceNameSingular: "Image", ShortDescription: "Update an image", NameSuggestions: func(c hcapi2.Client) func() []string { return c.Image().Names }, Fetch: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) { return client.Image().Get(ctx, idOrName) }, DefineFlags: func(cmd *cobra.Command) { cmd.Flags().String("description", "", "Image description") cmd.Flags().String("type", "", "Image type") cmd.RegisterFlagCompletionFunc("type", cmpl.SuggestCandidates("backup", "snapshot")) }, Update: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, resource interface{}, flags map[string]pflag.Value) error { image := resource.(*hcloud.Image) updOpts := hcloud.ImageUpdateOpts{ Description: hcloud.String(flags["description"].String()), Type: hcloud.ImageType(flags["type"].String()), } _, _, err := client.Image().Update(ctx, image, updOpts) if err != nil { return err } return nil }, } cli-1.39.0/internal/cmd/iso/000077500000000000000000000000001451614444200155315ustar00rootroot00000000000000cli-1.39.0/internal/cmd/iso/describe.go000066400000000000000000000024041451614444200176400ustar00rootroot00000000000000package iso import ( "context" "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) // DescribeCmd defines a command for describing a iso. var DescribeCmd = base.DescribeCmd{ ResourceNameSingular: "iso", ShortDescription: "Describe a iso", JSONKeyGetByID: "iso", JSONKeyGetByName: "isos", NameSuggestions: func(c hcapi2.Client) func() []string { return c.Location().Names }, Fetch: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) { return client.ISO().Get(ctx, idOrName) }, PrintText: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, resource interface{}) error { iso := resource.(*hcloud.ISO) fmt.Printf("ID:\t\t%d\n", iso.ID) fmt.Printf("Name:\t\t%s\n", iso.Name) fmt.Printf("Description:\t%s\n", iso.Description) fmt.Printf("Type:\t\t%s\n", iso.Type) fmt.Printf(util.DescribeDeprecation(iso)) architecture := "-" if iso.Architecture != nil { architecture = string(*iso.Architecture) } fmt.Printf("Architecture:\t%s\n", architecture) return nil }, } cli-1.39.0/internal/cmd/iso/iso.go000066400000000000000000000010541451614444200166520ustar00rootroot00000000000000package iso import ( "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" ) func NewCommand(cli *state.State, client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "iso", Short: "Manage ISOs", Args: cobra.NoArgs, TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.AddCommand( ListCmd.CobraCommand(cli.Context, client, cli), DescribeCmd.CobraCommand(cli.Context, client, cli), ) return cmd } cli-1.39.0/internal/cmd/iso/list.go000066400000000000000000000060701451614444200170360ustar00rootroot00000000000000package iso import ( "context" "fmt" "slices" "strings" "github.com/spf13/cobra" "github.com/spf13/pflag" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/cmd/output" "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" "github.com/hetznercloud/hcloud-go/v2/hcloud/schema" ) var ListCmd = base.ListCmd{ ResourceNamePlural: "ISOs", JSONKeyGetByName: "isos", DefaultColumns: []string{"id", "name", "description", "type", "architecture"}, AdditionalFlags: func(cmd *cobra.Command) { cmd.Flags().StringSlice("architecture", []string{}, "Only show images of given architecture: x86|arm") cmd.RegisterFlagCompletionFunc("architecture", cmpl.SuggestCandidates(string(hcloud.ArchitectureX86), string(hcloud.ArchitectureARM))) cmd.Flags().Bool("include-architecture-wildcard", false, "Include ISOs with unknown architecture, only required if you want so show custom ISOs and still filter for architecture.") cmd.Flags().StringSlice("type", []string{"public", "private"}, "Types to include (public, private)") cmd.RegisterFlagCompletionFunc("type", cmpl.SuggestCandidates("public", "private")) }, Fetch: func(ctx context.Context, client hcapi2.Client, flags *pflag.FlagSet, listOpts hcloud.ListOpts, sorts []string) ([]interface{}, error) { opts := hcloud.ISOListOpts{ListOpts: listOpts} types, _ := flags.GetStringSlice("type") var unknown []string for _, t := range types { switch t { case string(hcloud.ISOTypePublic), string(hcloud.ISOTypePrivate): break default: unknown = append(unknown, t) } } if len(unknown) > 0 { return nil, fmt.Errorf("unknown ISO types %s\n", strings.Join(unknown, ", ")) } architecture, _ := flags.GetStringSlice("architecture") if len(architecture) > 0 { for _, arch := range architecture { opts.Architecture = append(opts.Architecture, hcloud.Architecture(arch)) } } includeArchitectureWildcard, _ := flags.GetBool("include-architecture-wildcard") if includeArchitectureWildcard { opts.IncludeWildcardArchitecture = includeArchitectureWildcard } if len(sorts) > 0 { opts.Sort = sorts } isos, err := client.ISO().AllWithOpts(ctx, opts) var resources []interface{} for _, iso := range isos { if slices.Contains(types, string(iso.Type)) { resources = append(resources, iso) } } return resources, err }, OutputTable: func(_ hcapi2.Client) *output.Table { return output.NewTable(). AddAllowedFields(hcloud.ISO{}). AddFieldFn("architecture", func(obj interface{}) string { iso := obj.(*hcloud.ISO) if iso.Architecture == nil { return "-" } else { return string(*iso.Architecture) } }) }, JSONSchema: func(resources []interface{}) interface{} { isoSchemas := make([]schema.ISO, 0, len(resources)) for _, resource := range resources { iso := resource.(*hcloud.ISO) isoSchemas = append(isoSchemas, util.ISOToSchema(*iso)) } return isoSchemas }, } cli-1.39.0/internal/cmd/loadbalancer/000077500000000000000000000000001451614444200173465ustar00rootroot00000000000000cli-1.39.0/internal/cmd/loadbalancer/add_service.go000066400000000000000000000107061451614444200221510ustar00rootroot00000000000000package loadbalancer import ( "context" "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var AddServiceCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "add-service LOADBALANCER FLAGS", Short: "Add a service to a Load Balancer", Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.LoadBalancer().Names)), TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.Flags().String("protocol", "", "Protocol of the service (required)") cmd.MarkFlagRequired("protocol") cmd.Flags().Int("listen-port", 0, "Listen port of the service") cmd.Flags().Int("destination-port", 0, "Destination port of the service on the targets") cmd.Flags().Bool("proxy-protocol", false, "Enable proxyprotocol") cmd.Flags().Bool("http-sticky-sessions", false, "Enable Sticky Sessions") cmd.Flags().String("http-cookie-name", "", "Sticky Sessions: Cookie Name we set") cmd.Flags().Duration("http-cookie-lifetime", 0, "Sticky Sessions: Lifetime of the cookie") cmd.Flags().Int64Slice("http-certificates", []int64{}, "ID of Certificates which are attached to this Load Balancer") cmd.Flags().Bool("http-redirect-http", false, "Redirect all traffic on port 80 to port 443") return cmd }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { protocol, _ := cmd.Flags().GetString("protocol") listenPort, _ := cmd.Flags().GetInt("listen-port") destinationPort, _ := cmd.Flags().GetInt("destination-port") httpCertificates, _ := cmd.Flags().GetInt64Slice("http-certificates") if protocol == "" { return fmt.Errorf("required flag protocol not set") } switch hcloud.LoadBalancerServiceProtocol(protocol) { case hcloud.LoadBalancerServiceProtocolHTTP: break case hcloud.LoadBalancerServiceProtocolTCP: if listenPort == 0 { return fmt.Errorf("please specify a listen port") } if destinationPort == 0 { return fmt.Errorf("please specify a destination port") } break case hcloud.LoadBalancerServiceProtocolHTTPS: if len(httpCertificates) == 0 { return fmt.Errorf("no certificate specified") } default: return fmt.Errorf("%s is not a valid protocol", protocol) } if listenPort > 65535 { return fmt.Errorf("%d is not a valid listen port", listenPort) } if destinationPort > 65535 { return fmt.Errorf("%d is not a valid destination port", destinationPort) } idOrName := args[0] proxyProtocol, _ := cmd.Flags().GetBool("proxy-protocol") httpStickySessions, _ := cmd.Flags().GetBool("http-sticky-sessions") httpCookieName, _ := cmd.Flags().GetString("http-cookie-name") httpCookieLifetime, _ := cmd.Flags().GetDuration("http-cookie-lifetime") httpRedirect, _ := cmd.Flags().GetBool("http-redirect-http") loadBalancer, _, err := client.LoadBalancer().Get(ctx, idOrName) if err != nil { return err } if loadBalancer == nil { return fmt.Errorf("Load Balancer not found: %s", idOrName) } opts := hcloud.LoadBalancerAddServiceOpts{ Protocol: hcloud.LoadBalancerServiceProtocol(protocol), Proxyprotocol: hcloud.Bool(proxyProtocol), } if listenPort != 0 { opts.ListenPort = hcloud.Int(listenPort) } if destinationPort != 0 { opts.DestinationPort = hcloud.Int(destinationPort) } if protocol != string(hcloud.LoadBalancerServiceProtocolTCP) { opts.HTTP = &hcloud.LoadBalancerAddServiceOptsHTTP{ StickySessions: hcloud.Bool(httpStickySessions), RedirectHTTP: hcloud.Bool(httpRedirect), } if httpCookieName != "" { opts.HTTP.CookieName = hcloud.String(httpCookieName) } if httpCookieLifetime != 0 { opts.HTTP.CookieLifetime = hcloud.Duration(httpCookieLifetime) } for _, certificateID := range httpCertificates { opts.HTTP.Certificates = append(opts.HTTP.Certificates, &hcloud.Certificate{ID: certificateID}) } } action, _, err := client.LoadBalancer().AddService(ctx, loadBalancer, opts) if err != nil { return err } if err := waiter.ActionProgress(ctx, action); err != nil { return err } fmt.Printf("Service was added to Load Balancer %d\n", loadBalancer.ID) return nil }, } cli-1.39.0/internal/cmd/loadbalancer/add_target.go000066400000000000000000000064401451614444200217770ustar00rootroot00000000000000package loadbalancer import ( "context" "fmt" "net" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var AddTargetCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "add-target LOADBALANCER FLAGS", Short: "Add a target to a Load Balancer", Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.LoadBalancer().Names)), TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.Flags().String("server", "", "Name or ID of the server") cmd.RegisterFlagCompletionFunc("server", cmpl.SuggestCandidatesF(client.Server().Names)) cmd.Flags().String("label-selector", "", "Label Selector") cmd.Flags().Bool("use-private-ip", false, "Determine if the Load Balancer should connect to the target via the network") cmd.Flags().String("ip", "", "Use the passed IP address as target") return cmd }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { var ( action *hcloud.Action loadBalancer *hcloud.LoadBalancer err error ) idOrName := args[0] usePrivateIP, _ := cmd.Flags().GetBool("use-private-ip") serverIDOrName, _ := cmd.Flags().GetString("server") labelSelector, _ := cmd.Flags().GetString("label-selector") ipAddr, _ := cmd.Flags().GetString("ip") if !util.ExactlyOneSet(serverIDOrName, labelSelector, ipAddr) { return fmt.Errorf("--server, --label-selector, and --ip are mutually exclusive") } if loadBalancer, _, err = client.LoadBalancer().Get(ctx, idOrName); err != nil { return err } if loadBalancer == nil { return fmt.Errorf("Load Balancer not found: %s", idOrName) } switch { case serverIDOrName != "": server, _, err := client.Server().Get(ctx, serverIDOrName) if err != nil { return err } if server == nil { return fmt.Errorf("server not found: %s", serverIDOrName) } action, _, err = client.LoadBalancer().AddServerTarget(ctx, loadBalancer, hcloud.LoadBalancerAddServerTargetOpts{ Server: server, UsePrivateIP: hcloud.Bool(usePrivateIP), }) if err != nil { return err } case labelSelector != "": action, _, err = client.LoadBalancer().AddLabelSelectorTarget(ctx, loadBalancer, hcloud.LoadBalancerAddLabelSelectorTargetOpts{ Selector: labelSelector, UsePrivateIP: hcloud.Bool(usePrivateIP), }) if err != nil { return err } case ipAddr != "": ip := net.ParseIP(ipAddr) if ip == nil { return fmt.Errorf("invalid ip provided") } action, _, err = client.LoadBalancer().AddIPTarget(ctx, loadBalancer, hcloud.LoadBalancerAddIPTargetOpts{ IP: ip, }) if err != nil { return err } default: return fmt.Errorf("specify one of --server, --label-selector, or --ip") } if err := waiter.ActionProgress(ctx, action); err != nil { return err } fmt.Printf("Target added to Load Balancer %d\n", loadBalancer.ID) return nil }, } cli-1.39.0/internal/cmd/loadbalancer/attach_to_network.go000066400000000000000000000041321451614444200234140ustar00rootroot00000000000000package loadbalancer import ( "context" "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var AttachToNetworkCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "attach-to-network [FLAGS] LOADBALANCER", Short: "Attach a Load Balancer to a Network", Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.LoadBalancer().Names)), TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.Flags().StringP("network", "n", "", "Network (ID or name) (required)") cmd.RegisterFlagCompletionFunc("network", cmpl.SuggestCandidatesF(client.Network().Names)) cmd.MarkFlagRequired("network") cmd.Flags().IP("ip", nil, "IP address to assign to the Load Balancer (auto-assigned if omitted)") return cmd }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { idOrName := args[0] loadBalancer, _, err := client.LoadBalancer().Get(ctx, idOrName) if err != nil { return err } if loadBalancer == nil { return fmt.Errorf("Load Balancer not found: %s", idOrName) } networkIDOrName, _ := cmd.Flags().GetString("network") network, _, err := client.Network().Get(ctx, networkIDOrName) if err != nil { return err } if network == nil { return fmt.Errorf("network not found: %s", networkIDOrName) } ip, _ := cmd.Flags().GetIP("ip") opts := hcloud.LoadBalancerAttachToNetworkOpts{ Network: network, IP: ip, } action, _, err := client.LoadBalancer().AttachToNetwork(ctx, loadBalancer, opts) if err != nil { return err } if err := waiter.ActionProgress(ctx, action); err != nil { return err } fmt.Printf("Load Balancer %d attached to network %d\n", loadBalancer.ID, network.ID) return nil }, } cli-1.39.0/internal/cmd/loadbalancer/change_algorithm.go000066400000000000000000000035731451614444200232000ustar00rootroot00000000000000package loadbalancer import ( "context" "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var ChangeAlgorithmCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "change-algorithm LOADBALANCER FLAGS", Short: "Changes the algorithm of a Load Balancer", Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.LoadBalancer().Names)), TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.Flags().String("algorithm-type", "", "The new algorithm of the Load Balancer") cmd.RegisterFlagCompletionFunc("algorithm-type", cmpl.SuggestCandidates( string(hcloud.LoadBalancerAlgorithmTypeRoundRobin), string(hcloud.LoadBalancerAlgorithmTypeLeastConnections), )) cmd.MarkFlagRequired("algorithm-type") return cmd }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { idOrName := args[0] algorithm, _ := cmd.Flags().GetString("algorithm-type") loadBalancer, _, err := client.LoadBalancer().Get(ctx, idOrName) if err != nil { return err } if loadBalancer == nil { return fmt.Errorf("Load Balancer not found: %s", idOrName) } action, _, err := client.LoadBalancer().ChangeAlgorithm(ctx, loadBalancer, hcloud.LoadBalancerChangeAlgorithmOpts{Type: hcloud.LoadBalancerAlgorithmType(algorithm)}) if err != nil { return err } if err := waiter.ActionProgress(ctx, action); err != nil { return err } fmt.Printf("Algorithm for Load Balancer %d was changed\n", loadBalancer.ID) return nil }, } cli-1.39.0/internal/cmd/loadbalancer/change_type.go000066400000000000000000000034551451614444200221720ustar00rootroot00000000000000package loadbalancer import ( "context" "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var ChangeTypeCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { return &cobra.Command{ Use: "change-type [FLAGS] LOADBALANCER LOADBALANCERTYPE", Short: "Change type of a Load Balancer", Args: cobra.ExactArgs(2), ValidArgsFunction: cmpl.SuggestArgs( cmpl.SuggestCandidatesF(client.LoadBalancer().Names), cmpl.SuggestCandidatesF(client.LoadBalancerType().Names), ), TraverseChildren: true, DisableFlagsInUseLine: true, } }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { idOrName := args[0] loadBalancer, _, err := client.LoadBalancer().Get(ctx, idOrName) if err != nil { return err } if loadBalancer == nil { return fmt.Errorf("Load Balancer not found: %s", idOrName) } loadBalancerTypeIDOrName := args[1] loadBalancerType, _, err := client.LoadBalancerType().Get(ctx, loadBalancerTypeIDOrName) if err != nil { return err } if loadBalancerType == nil { return fmt.Errorf("Load Balancer type not found: %s", loadBalancerTypeIDOrName) } opts := hcloud.LoadBalancerChangeTypeOpts{ LoadBalancerType: loadBalancerType, } action, _, err := client.LoadBalancer().ChangeType(ctx, loadBalancer, opts) if err != nil { return err } if err := waiter.ActionProgress(ctx, action); err != nil { return err } fmt.Printf("LoadBalancer %d changed to type %s\n", loadBalancer.ID, loadBalancerType.Name) return nil }, } cli-1.39.0/internal/cmd/loadbalancer/create.go000066400000000000000000000070531451614444200211450ustar00rootroot00000000000000package loadbalancer import ( "context" "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var CreateCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "create [FLAGS]", Short: "Create a Load Balancer", Args: cobra.NoArgs, TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.Flags().String("name", "", "Load Balancer name (required)") cmd.MarkFlagRequired("name") cmd.Flags().String("type", "", "Load Balancer type (ID or name) (required)") cmd.RegisterFlagCompletionFunc("type", cmpl.SuggestCandidatesF(client.LoadBalancerType().Names)) cmd.MarkFlagRequired("type") cmd.Flags().String("algorithm-type", "", "Algorithm Type name (round_robin or least_connections)") cmd.RegisterFlagCompletionFunc("algorithm-type", cmpl.SuggestCandidates( string(hcloud.LoadBalancerAlgorithmTypeLeastConnections), string(hcloud.LoadBalancerAlgorithmTypeRoundRobin), )) cmd.Flags().String("location", "", "Location (ID or name)") cmd.RegisterFlagCompletionFunc("location", cmpl.SuggestCandidatesF(client.Location().Names)) cmd.Flags().String("network-zone", "", "Network Zone") cmd.RegisterFlagCompletionFunc("network-zone", cmpl.SuggestCandidatesF(client.Location().NetworkZones)) cmd.Flags().StringToString("label", nil, "User-defined labels ('key=value') (can be specified multiple times)") cmd.Flags().StringSlice("enable-protection", []string{}, "Enable protection (delete) (default: none)") cmd.RegisterFlagCompletionFunc("enable-protection", cmpl.SuggestCandidates("delete")) return cmd }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { name, _ := cmd.Flags().GetString("name") serverType, _ := cmd.Flags().GetString("type") algorithmType, _ := cmd.Flags().GetString("algorithm-type") location, _ := cmd.Flags().GetString("location") networkZone, _ := cmd.Flags().GetString("network-zone") labels, _ := cmd.Flags().GetStringToString("label") protection, _ := cmd.Flags().GetStringSlice("enable-protection") protectionOpts, err := getChangeProtectionOpts(true, protection) if err != nil { return err } createOpts := hcloud.LoadBalancerCreateOpts{ Name: name, LoadBalancerType: &hcloud.LoadBalancerType{ Name: serverType, }, Labels: labels, } if algorithmType != "" { createOpts.Algorithm = &hcloud.LoadBalancerAlgorithm{Type: hcloud.LoadBalancerAlgorithmType(algorithmType)} } if networkZone != "" { createOpts.NetworkZone = hcloud.NetworkZone(networkZone) } if location != "" { createOpts.Location = &hcloud.Location{Name: location} } result, _, err := client.LoadBalancer().Create(ctx, createOpts) if err != nil { return err } if err := waiter.ActionProgress(ctx, result.Action); err != nil { return err } loadBalancer, _, err := client.LoadBalancer().GetByID(ctx, result.LoadBalancer.ID) if err != nil { return err } fmt.Printf("Load Balancer %d created\n", loadBalancer.ID) if err := changeProtection(ctx, client, waiter, loadBalancer, true, protectionOpts); err != nil { return err } fmt.Printf("IPv4: %s\n", loadBalancer.PublicNet.IPv4.IP.String()) fmt.Printf("IPv6: %s\n", loadBalancer.PublicNet.IPv6.IP.String()) return nil }, } cli-1.39.0/internal/cmd/loadbalancer/delete.go000066400000000000000000000017001451614444200211350ustar00rootroot00000000000000package loadbalancer import ( "context" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var deleteCmd = base.DeleteCmd{ ResourceNameSingular: "Load Balancer", ShortDescription: "Delete a Load Balancer", NameSuggestions: func(c hcapi2.Client) func() []string { return c.LoadBalancer().Names }, Fetch: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) { return client.LoadBalancer().Get(ctx, idOrName) }, Delete: func(ctx context.Context, client hcapi2.Client, _ state.ActionWaiter, cmd *cobra.Command, resource interface{}) error { loadBalancer := resource.(*hcloud.LoadBalancer) if _, err := client.LoadBalancer().Delete(ctx, loadBalancer); err != nil { return err } return nil }, } cli-1.39.0/internal/cmd/loadbalancer/delete_service.go000066400000000000000000000027701451614444200226650ustar00rootroot00000000000000package loadbalancer import ( "context" "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" ) var DeleteServiceCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "delete-service [FLAGS] LOADBALANCER", Short: "Deletes a service from a Load Balancer", ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.LoadBalancer().Names)), Args: cobra.RangeArgs(1, 2), TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.Flags().Int("listen-port", 0, "The listen port of the service you want to delete (required)") cmd.MarkFlagRequired("listen-port") return cmd }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { listenPort, _ := cmd.Flags().GetInt("listen-port") idOrName := args[0] loadBalancer, _, err := client.LoadBalancer().Get(ctx, idOrName) if err != nil { return err } if loadBalancer == nil { return fmt.Errorf("Load Balancer not found: %s", idOrName) } _, _, err = client.LoadBalancer().DeleteService(ctx, loadBalancer, listenPort) if err != nil { return err } fmt.Printf("Service on port %d deleted from Load Balancer %d\n", listenPort, loadBalancer.ID) return nil }, } cli-1.39.0/internal/cmd/loadbalancer/describe.go000066400000000000000000000162641451614444200214660ustar00rootroot00000000000000package loadbalancer import ( "context" "fmt" humanize "github.com/dustin/go-humanize" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) // DescribeCmd defines a command for describing a LoadBalancer. var DescribeCmd = base.DescribeCmd{ ResourceNameSingular: "Load Balancer", ShortDescription: "Describe a Load Balancer", JSONKeyGetByID: "load_balancer", JSONKeyGetByName: "load_balancers", NameSuggestions: func(c hcapi2.Client) func() []string { return c.LoadBalancer().Names }, Fetch: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) { return client.LoadBalancer().Get(ctx, idOrName) }, AdditionalFlags: func(cmd *cobra.Command) { cmd.Flags().Bool("expand-targets", false, "Expand all label_selector targets") }, PrintText: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, resource interface{}) error { withLabelSelectorTargets, _ := cmd.Flags().GetBool("expand-targets") loadBalancer := resource.(*hcloud.LoadBalancer) fmt.Printf("ID:\t\t\t\t%d\n", loadBalancer.ID) fmt.Printf("Name:\t\t\t\t%s\n", loadBalancer.Name) fmt.Printf("Created:\t\t\t%s (%s)\n", util.Datetime(loadBalancer.Created), humanize.Time(loadBalancer.Created)) fmt.Printf("Public Net:\n") fmt.Printf(" Enabled:\t\t\t%s\n", util.YesNo(loadBalancer.PublicNet.Enabled)) fmt.Printf(" IPv4:\t\t\t\t%s\n", loadBalancer.PublicNet.IPv4.IP.String()) fmt.Printf(" IPv4 DNS PTR:\t\t\t%s\n", loadBalancer.PublicNet.IPv4.DNSPtr) fmt.Printf(" IPv6:\t\t\t\t%s\n", loadBalancer.PublicNet.IPv6.IP.String()) fmt.Printf(" IPv6 DNS PTR:\t\t\t%s\n", loadBalancer.PublicNet.IPv6.DNSPtr) fmt.Printf("Private Net:\n") if len(loadBalancer.PrivateNet) > 0 { for _, n := range loadBalancer.PrivateNet { fmt.Printf(" - ID:\t\t\t%d\n", n.Network.ID) fmt.Printf(" Name:\t\t%s\n", client.Network().Name(n.Network.ID)) fmt.Printf(" IP:\t\t\t%s\n", n.IP.String()) } } else { fmt.Printf(" No Private Network\n") } fmt.Printf("Algorithm:\t\t\t%s\n", loadBalancer.Algorithm.Type) fmt.Printf("Load Balancer Type:\t\t%s (ID: %d)\n", loadBalancer.LoadBalancerType.Name, loadBalancer.LoadBalancerType.ID) fmt.Printf(" ID:\t\t\t\t%d\n", loadBalancer.LoadBalancerType.ID) fmt.Printf(" Name:\t\t\t\t%s\n", loadBalancer.LoadBalancerType.Name) fmt.Printf(" Description:\t\t\t%s\n", loadBalancer.LoadBalancerType.Description) fmt.Printf(" Max Services:\t\t\t%d\n", loadBalancer.LoadBalancerType.MaxServices) fmt.Printf(" Max Connections:\t\t%d\n", loadBalancer.LoadBalancerType.MaxConnections) fmt.Printf(" Max Targets:\t\t\t%d\n", loadBalancer.LoadBalancerType.MaxTargets) fmt.Printf(" Max assigned Certificates:\t%d\n", loadBalancer.LoadBalancerType.MaxAssignedCertificates) fmt.Printf("Services:\n") if len(loadBalancer.Services) == 0 { fmt.Print(" No services\n") } else { for _, service := range loadBalancer.Services { fmt.Printf(" - Protocol:\t\t\t%s\n", service.Protocol) fmt.Printf(" Listen Port:\t\t%d\n", service.ListenPort) fmt.Printf(" Destination Port:\t\t%d\n", service.DestinationPort) fmt.Printf(" Proxy Protocol:\t\t%s\n", util.YesNo(service.Proxyprotocol)) if service.Protocol != hcloud.LoadBalancerServiceProtocolTCP { fmt.Printf(" Sticky Sessions:\t\t%s\n", util.YesNo(service.HTTP.StickySessions)) if service.HTTP.StickySessions { fmt.Printf(" Sticky Cookie Name:\t\t%s\n", service.HTTP.CookieName) fmt.Printf(" Sticky Cookie Lifetime:\t%vs\n", service.HTTP.CookieLifetime.Seconds()) } if service.Protocol == hcloud.LoadBalancerServiceProtocolHTTPS { fmt.Printf(" Certificates:\n") for _, cert := range service.HTTP.Certificates { fmt.Printf(" - ID: \t\t\t%v\n", cert.ID) } } } fmt.Printf(" Health Check:\n") fmt.Printf(" Protocol:\t\t\t%s\n", service.HealthCheck.Protocol) fmt.Printf(" Timeout:\t\t\t%vs\n", service.HealthCheck.Timeout.Seconds()) fmt.Printf(" Interval:\t\t\tevery %vs\n", service.HealthCheck.Interval.Seconds()) fmt.Printf(" Retries:\t\t\t%d\n", service.HealthCheck.Retries) if service.HealthCheck.Protocol != hcloud.LoadBalancerServiceProtocolTCP { fmt.Printf(" HTTP Domain:\t\t%s\n", service.HealthCheck.HTTP.Domain) fmt.Printf(" HTTP Path:\t\t%s\n", service.HealthCheck.HTTP.Path) fmt.Printf(" Response:\t\t%s\n", service.HealthCheck.HTTP.Response) fmt.Printf(" TLS:\t\t\t%s\n", util.YesNo(service.HealthCheck.HTTP.TLS)) fmt.Printf(" Status Codes:\t\t%v\n", service.HealthCheck.HTTP.StatusCodes) } } } fmt.Printf("Targets:\n") if len(loadBalancer.Targets) == 0 { fmt.Print(" No targets\n") } for _, target := range loadBalancer.Targets { fmt.Printf(" - Type:\t\t\t%s\n", target.Type) switch target.Type { case hcloud.LoadBalancerTargetTypeServer: fmt.Printf(" Server:\n") fmt.Printf(" ID:\t\t\t%d\n", target.Server.Server.ID) fmt.Printf(" Name:\t\t\t%s\n", client.Server().ServerName(target.Server.Server.ID)) fmt.Printf(" Use Private IP:\t\t%s\n", util.YesNo(target.UsePrivateIP)) fmt.Printf(" Status:\n") for _, healthStatus := range target.HealthStatus { fmt.Printf(" - Service:\t\t\t%d\n", healthStatus.ListenPort) fmt.Printf(" Status:\t\t\t%s\n", healthStatus.Status) } case hcloud.LoadBalancerTargetTypeLabelSelector: fmt.Printf(" Label Selector:\t\t%s\n", target.LabelSelector.Selector) fmt.Printf(" Targets: (%d)\n", len(target.Targets)) if len(target.Targets) == 0 { fmt.Print(" No targets\n") } if !withLabelSelectorTargets { continue } for _, lbtarget := range target.Targets { fmt.Printf(" - Type:\t\t\t\t%s\n", lbtarget.Type) fmt.Printf(" Server ID:\t\t\t%d\n", lbtarget.Server.Server.ID) fmt.Printf(" Status:\n") for _, healthStatus := range lbtarget.HealthStatus { fmt.Printf(" - Service:\t\t\t%d\n", healthStatus.ListenPort) fmt.Printf(" Status:\t\t\t%s\n", healthStatus.Status) } } case hcloud.LoadBalancerTargetTypeIP: fmt.Printf(" IP:\t\t\t\t%s\n", target.IP.IP) fmt.Printf(" Status:\n") for _, healthStatus := range target.HealthStatus { fmt.Printf(" - Service:\t\t\t%d\n", healthStatus.ListenPort) fmt.Printf(" Status:\t\t\t%s\n", healthStatus.Status) } } } fmt.Printf("Traffic:\n") fmt.Printf(" Outgoing:\t%v\n", humanize.IBytes(loadBalancer.OutgoingTraffic)) fmt.Printf(" Ingoing:\t%v\n", humanize.IBytes(loadBalancer.IngoingTraffic)) fmt.Printf(" Included:\t%v\n", humanize.IBytes(loadBalancer.IncludedTraffic)) fmt.Printf("Protection:\n") fmt.Printf(" Delete:\t%s\n", util.YesNo(loadBalancer.Protection.Delete)) fmt.Print("Labels:\n") if len(loadBalancer.Labels) == 0 { fmt.Print(" No labels\n") } else { for key, value := range loadBalancer.Labels { fmt.Printf(" %s: %s\n", key, value) } } return nil }, } cli-1.39.0/internal/cmd/loadbalancer/detach_from_network.go000066400000000000000000000037111451614444200237230ustar00rootroot00000000000000package loadbalancer import ( "context" "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var DetachFromNetworkCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "detach-from-network [FLAGS] LOADBALANCER", Short: "Detach a Load Balancer from a Network", Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.LoadBalancer().Names)), TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.Flags().StringP("network", "n", "", "Network (ID or name) (required)") cmd.RegisterFlagCompletionFunc("network", cmpl.SuggestCandidatesF(client.Network().Names)) cmd.MarkFlagRequired("network") return cmd }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { idOrName := args[0] loadBalancer, _, err := client.LoadBalancer().Get(ctx, idOrName) if err != nil { return err } if loadBalancer == nil { return fmt.Errorf("Load Balancer not found: %s", idOrName) } networkIDOrName, _ := cmd.Flags().GetString("network") network, _, err := client.Network().Get(ctx, networkIDOrName) if err != nil { return err } if network == nil { return fmt.Errorf("network not found: %s", networkIDOrName) } opts := hcloud.LoadBalancerDetachFromNetworkOpts{ Network: network, } action, _, err := client.LoadBalancer().DetachFromNetwork(ctx, loadBalancer, opts) if err != nil { return err } if err := waiter.ActionProgress(ctx, action); err != nil { return err } fmt.Printf("Load Balancer %d detached from Network %d\n", loadBalancer.ID, network.ID) return nil }, } cli-1.39.0/internal/cmd/loadbalancer/disable_protection.go000066400000000000000000000024421451614444200235500ustar00rootroot00000000000000package loadbalancer import ( "context" "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" ) var DisableProtectionCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { return &cobra.Command{ Use: "disable-protection [FLAGS] LOADBALANCER PROTECTIONLEVEL [PROTECTIONLEVEL...]", Short: "Disable resource protection for a Load Balancer", Args: cobra.MinimumNArgs(2), ValidArgsFunction: cmpl.SuggestArgs( cmpl.SuggestCandidatesF(client.LoadBalancer().Names), cmpl.SuggestCandidates("delete"), ), TraverseChildren: true, DisableFlagsInUseLine: true, } }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { idOrName := args[0] loadBalancer, _, err := client.LoadBalancer().Get(ctx, idOrName) if err != nil { return err } if loadBalancer == nil { return fmt.Errorf("Load Balancer not found: %s", idOrName) } opts, err := getChangeProtectionOpts(false, args[1:]) if err != nil { return err } return changeProtection(ctx, client, waiter, loadBalancer, false, opts) }, } cli-1.39.0/internal/cmd/loadbalancer/disable_public_interface.go000066400000000000000000000026151451614444200246620ustar00rootroot00000000000000package loadbalancer import ( "context" "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" ) var DisablePublicInterfaceCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { return &cobra.Command{ Use: "disable-public-interface [FLAGS] LOADBALANCER", Short: "Disable the public interface of a Load Balancer", Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.LoadBalancer().Names)), TraverseChildren: true, DisableFlagsInUseLine: true, } }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { idOrName := args[0] loadBalancer, _, err := client.LoadBalancer().Get(ctx, idOrName) if err != nil { return err } if loadBalancer == nil { return fmt.Errorf("Load Balancer not found: %s", idOrName) } action, _, err := client.LoadBalancer().DisablePublicInterface(ctx, loadBalancer) if err != nil { return err } if err := waiter.ActionProgress(ctx, action); err != nil { return err } fmt.Printf("Public interface of Load Balancer %d was disabled\n", loadBalancer.ID) return nil }, } cli-1.39.0/internal/cmd/loadbalancer/enable_protection.go000066400000000000000000000046751451614444200234050ustar00rootroot00000000000000package loadbalancer import ( "context" "fmt" "strings" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) func getChangeProtectionOpts(enable bool, flags []string) (hcloud.LoadBalancerChangeProtectionOpts, error) { opts := hcloud.LoadBalancerChangeProtectionOpts{} var unknown []string for _, arg := range flags { switch strings.ToLower(arg) { case "delete": opts.Delete = hcloud.Ptr(enable) default: unknown = append(unknown, arg) } } if len(unknown) > 0 { return opts, fmt.Errorf("unknown protection level: %s", strings.Join(unknown, ", ")) } return opts, nil } func changeProtection(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, loadBalancer *hcloud.LoadBalancer, enable bool, opts hcloud.LoadBalancerChangeProtectionOpts) error { if opts.Delete == nil { return nil } action, _, err := client.LoadBalancer().ChangeProtection(ctx, loadBalancer, opts) if err != nil { return err } if err := waiter.ActionProgress(ctx, action); err != nil { return err } if enable { fmt.Printf("Resource protection enabled for Load Balancer %d\n", loadBalancer.ID) } else { fmt.Printf("Resource protection disabled for Load Balancer %d\n", loadBalancer.ID) } return nil } var EnableProtectionCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { return &cobra.Command{ Use: "enable-protection [FLAGS] LOADBALANCER PROTECTIONLEVEL [PROTECTIONLEVEL...]", Short: "Enable resource protection for a Load Balancer", Args: cobra.MinimumNArgs(2), ValidArgsFunction: cmpl.SuggestArgs( cmpl.SuggestCandidatesF(client.LoadBalancer().Names), cmpl.SuggestCandidates("delete"), ), TraverseChildren: true, DisableFlagsInUseLine: true, } }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { idOrName := args[0] loadBalancer, _, err := client.LoadBalancer().Get(ctx, idOrName) if err != nil { return err } if loadBalancer == nil { return fmt.Errorf("Load Balancer not found: %s", idOrName) } opts, err := getChangeProtectionOpts(true, args[1:]) if err != nil { return err } return changeProtection(ctx, client, waiter, loadBalancer, true, opts) }, } cli-1.39.0/internal/cmd/loadbalancer/enable_public_interface.go000066400000000000000000000026101451614444200245000ustar00rootroot00000000000000package loadbalancer import ( "context" "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" ) var EnablePublicInterfaceCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { return &cobra.Command{ Use: "enable-public-interface [FLAGS] LOADBALANCER", Short: "Enable the public interface of a Load Balancer", Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.LoadBalancer().Names)), TraverseChildren: true, DisableFlagsInUseLine: true, } }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { idOrName := args[0] loadBalancer, _, err := client.LoadBalancer().Get(ctx, idOrName) if err != nil { return err } if loadBalancer == nil { return fmt.Errorf("Load Balancer not found: %s", idOrName) } action, _, err := client.LoadBalancer().EnablePublicInterface(ctx, loadBalancer) if err != nil { return err } if err := waiter.ActionProgress(ctx, action); err != nil { return err } fmt.Printf("Public interface of Load Balancer %d was enabled\n", loadBalancer.ID) return nil }, } cli-1.39.0/internal/cmd/loadbalancer/labels.go000066400000000000000000000023561451614444200211450ustar00rootroot00000000000000package loadbalancer import ( "context" "fmt" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var labelCmds = base.LabelCmds{ ResourceNameSingular: "Load Balancer", ShortDescriptionAdd: "Add a label to a Load Balancer", ShortDescriptionRemove: "Remove a label from a Load Balancer", NameSuggestions: func(c hcapi2.Client) func() []string { return c.LoadBalancer().Names }, LabelKeySuggestions: func(c hcapi2.Client) func(idOrName string) []string { return c.LoadBalancer().LabelKeys }, FetchLabels: func(ctx context.Context, client hcapi2.Client, idOrName string) (map[string]string, int64, error) { loadBalancer, _, err := client.LoadBalancer().Get(ctx, idOrName) if err != nil { return nil, 0, err } if loadBalancer == nil { return nil, 0, fmt.Errorf("load balancer not found: %s", idOrName) } return loadBalancer.Labels, loadBalancer.ID, nil }, SetLabels: func(ctx context.Context, client hcapi2.Client, id int64, labels map[string]string) error { opts := hcloud.LoadBalancerUpdateOpts{ Labels: labels, } _, _, err := client.LoadBalancer().Update(ctx, &hcloud.LoadBalancer{ID: id}, opts) return err }, } cli-1.39.0/internal/cmd/loadbalancer/list.go000066400000000000000000000167171451614444200206640ustar00rootroot00000000000000package loadbalancer import ( "context" "strings" "time" "github.com/spf13/pflag" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/output" "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" "github.com/hetznercloud/hcloud-go/v2/hcloud/schema" ) var ListCmd = base.ListCmd{ ResourceNamePlural: "Load Balancer", JSONKeyGetByName: "load_balancers", DefaultColumns: []string{"id", "name", "health", "ipv4", "ipv6", "type", "location", "network_zone", "age"}, Fetch: func(ctx context.Context, client hcapi2.Client, _ *pflag.FlagSet, listOpts hcloud.ListOpts, sorts []string) ([]interface{}, error) { opts := hcloud.LoadBalancerListOpts{ListOpts: listOpts} if len(sorts) > 0 { opts.Sort = sorts } loadBalancers, err := client.LoadBalancer().AllWithOpts(ctx, opts) var resources []interface{} for _, r := range loadBalancers { resources = append(resources, r) } return resources, err }, OutputTable: func(client hcapi2.Client) *output.Table { return output.NewTable(). AddAllowedFields(hcloud.LoadBalancer{}). AddFieldFn("ipv4", output.FieldFn(func(obj interface{}) string { loadbalancer := obj.(*hcloud.LoadBalancer) return loadbalancer.PublicNet.IPv4.IP.String() })). AddFieldFn("ipv6", output.FieldFn(func(obj interface{}) string { loadbalancer := obj.(*hcloud.LoadBalancer) return loadbalancer.PublicNet.IPv6.IP.String() })). AddFieldFn("type", output.FieldFn(func(obj interface{}) string { loadbalancer := obj.(*hcloud.LoadBalancer) return loadbalancer.LoadBalancerType.Name })). AddFieldFn("location", output.FieldFn(func(obj interface{}) string { loadbalancer := obj.(*hcloud.LoadBalancer) return loadbalancer.Location.Name })). AddFieldFn("network_zone", output.FieldFn(func(obj interface{}) string { loadbalancer := obj.(*hcloud.LoadBalancer) return string(loadbalancer.Location.NetworkZone) })). AddFieldFn("labels", output.FieldFn(func(obj interface{}) string { loadBalancer := obj.(*hcloud.LoadBalancer) return util.LabelsToString(loadBalancer.Labels) })). AddFieldFn("protection", output.FieldFn(func(obj interface{}) string { loadBalancer := obj.(*hcloud.LoadBalancer) var protection []string if loadBalancer.Protection.Delete { protection = append(protection, "delete") } return strings.Join(protection, ", ") })). AddFieldFn("created", output.FieldFn(func(obj interface{}) string { loadBalancer := obj.(*hcloud.LoadBalancer) return util.Datetime(loadBalancer.Created) })). AddFieldFn("age", output.FieldFn(func(obj interface{}) string { loadBalancer := obj.(*hcloud.LoadBalancer) return util.Age(loadBalancer.Created, time.Now()) })). AddFieldFn("health", output.FieldFn(func(obj interface{}) string { loadBalancer := obj.(*hcloud.LoadBalancer) return loadBalancerHealth(loadBalancer) })) }, JSONSchema: func(resources []interface{}) interface{} { loadBalancerSchemas := make([]schema.LoadBalancer, 0, len(resources)) for _, resource := range resources { loadBalancer := resource.(*hcloud.LoadBalancer) loadBalancerSchema := schema.LoadBalancer{ ID: loadBalancer.ID, Name: loadBalancer.Name, PublicNet: schema.LoadBalancerPublicNet{ Enabled: loadBalancer.PublicNet.Enabled, IPv4: schema.LoadBalancerPublicNetIPv4{ IP: loadBalancer.PublicNet.IPv4.IP.String(), }, IPv6: schema.LoadBalancerPublicNetIPv6{ IP: loadBalancer.PublicNet.IPv6.IP.String(), }, }, Created: loadBalancer.Created, Labels: loadBalancer.Labels, LoadBalancerType: util.LoadBalancerTypeToSchema(*loadBalancer.LoadBalancerType), Location: util.LocationToSchema(*loadBalancer.Location), IncludedTraffic: loadBalancer.IncludedTraffic, OutgoingTraffic: &loadBalancer.OutgoingTraffic, IngoingTraffic: &loadBalancer.IngoingTraffic, Protection: schema.LoadBalancerProtection{ Delete: loadBalancer.Protection.Delete, }, Algorithm: schema.LoadBalancerAlgorithm{Type: string(loadBalancer.Algorithm.Type)}, } for _, service := range loadBalancer.Services { serviceSchema := schema.LoadBalancerService{ Protocol: string(service.Protocol), ListenPort: service.ListenPort, DestinationPort: service.DestinationPort, Proxyprotocol: service.Proxyprotocol, HealthCheck: &schema.LoadBalancerServiceHealthCheck{ Protocol: string(service.HealthCheck.Protocol), Port: service.HealthCheck.Port, Interval: int(service.HealthCheck.Interval.Seconds()), Timeout: int(service.HealthCheck.Timeout.Seconds()), Retries: service.HealthCheck.Retries, }, } if service.Protocol != hcloud.LoadBalancerServiceProtocolTCP { serviceSchema.HTTP = &schema.LoadBalancerServiceHTTP{ StickySessions: service.HTTP.StickySessions, CookieName: service.HTTP.CookieName, CookieLifetime: int(service.HTTP.CookieLifetime.Seconds()), RedirectHTTP: service.HTTP.RedirectHTTP, } } if service.HealthCheck.HTTP != nil { serviceSchema.HealthCheck.HTTP = &schema.LoadBalancerServiceHealthCheckHTTP{ Domain: service.HealthCheck.HTTP.Domain, Path: service.HealthCheck.HTTP.Path, StatusCodes: service.HealthCheck.HTTP.StatusCodes, TLS: service.HealthCheck.HTTP.TLS, Response: service.HealthCheck.HTTP.Response, } } loadBalancerSchema.Services = append(loadBalancerSchema.Services, serviceSchema) } for _, target := range loadBalancer.Targets { targetSchema := schema.LoadBalancerTarget{ Type: string(target.Type), UsePrivateIP: target.UsePrivateIP, } if target.Type == hcloud.LoadBalancerTargetTypeServer { targetSchema.Server = &schema.LoadBalancerTargetServer{ID: target.Server.Server.ID} } if target.Type == hcloud.LoadBalancerTargetTypeLabelSelector { targetSchema.LabelSelector = &schema.LoadBalancerTargetLabelSelector{Selector: target.LabelSelector.Selector} } if target.Type == hcloud.LoadBalancerTargetTypeIP { targetSchema.IP = &schema.LoadBalancerTargetIP{IP: target.IP.IP} } for _, healthStatus := range target.HealthStatus { targetSchema.HealthStatus = append(targetSchema.HealthStatus, schema.LoadBalancerTargetHealthStatus{ ListenPort: healthStatus.ListenPort, Status: string(healthStatus.Status), }) } loadBalancerSchema.Targets = append(loadBalancerSchema.Targets, targetSchema) } loadBalancerSchemas = append(loadBalancerSchemas, loadBalancerSchema) } return loadBalancerSchemas }, } func loadBalancerHealth(l *hcloud.LoadBalancer) string { healthyCount := 0 unhealthyCount := 0 unknownCount := 0 for _, lbTarget := range l.Targets { for _, svcHealth := range lbTarget.HealthStatus { switch svcHealth.Status { case hcloud.LoadBalancerTargetHealthStatusStatusHealthy: healthyCount++ case hcloud.LoadBalancerTargetHealthStatusStatusUnhealthy: unhealthyCount++ default: unknownCount++ } } } switch len(l.Targets) * len(l.Services) { case healthyCount: return string(hcloud.LoadBalancerTargetHealthStatusStatusHealthy) case unhealthyCount: return string(hcloud.LoadBalancerTargetHealthStatusStatusUnhealthy) case unknownCount: return string(hcloud.LoadBalancerTargetHealthStatusStatusUnknown) default: return "mixed" } } cli-1.39.0/internal/cmd/loadbalancer/list_test.go000066400000000000000000000116011451614444200217060ustar00rootroot00000000000000package loadbalancer import ( "testing" "github.com/stretchr/testify/assert" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) func TestLoadBalancerHealth(t *testing.T) { tests := []struct { name string lb *hcloud.LoadBalancer expected string }{ { name: "healthy", lb: &hcloud.LoadBalancer{ Name: "foobar", Services: make([]hcloud.LoadBalancerService, 1), Targets: []hcloud.LoadBalancerTarget{ { HealthStatus: []hcloud.LoadBalancerTargetHealthStatus{ { Status: hcloud.LoadBalancerTargetHealthStatusStatusHealthy, }, }, }, }, }, expected: string(hcloud.LoadBalancerTargetHealthStatusStatusHealthy), }, { name: "unhealthy", lb: &hcloud.LoadBalancer{ Name: "foobar", Services: make([]hcloud.LoadBalancerService, 1), Targets: []hcloud.LoadBalancerTarget{ { HealthStatus: []hcloud.LoadBalancerTargetHealthStatus{ { Status: hcloud.LoadBalancerTargetHealthStatusStatusUnhealthy, }, }, }, }, }, expected: string(hcloud.LoadBalancerTargetHealthStatusStatusUnhealthy), }, { name: "unknown", lb: &hcloud.LoadBalancer{ Name: "foobar", Services: make([]hcloud.LoadBalancerService, 1), Targets: []hcloud.LoadBalancerTarget{ { HealthStatus: []hcloud.LoadBalancerTargetHealthStatus{ { Status: hcloud.LoadBalancerTargetHealthStatusStatusUnknown, }, }, }, }, }, expected: string(hcloud.LoadBalancerTargetHealthStatusStatusUnknown), }, { name: "mixed", lb: &hcloud.LoadBalancer{ Name: "foobar", Services: make([]hcloud.LoadBalancerService, 1), Targets: []hcloud.LoadBalancerTarget{ { HealthStatus: []hcloud.LoadBalancerTargetHealthStatus{ { Status: hcloud.LoadBalancerTargetHealthStatusStatusHealthy, }, }, }, { HealthStatus: []hcloud.LoadBalancerTargetHealthStatus{ { Status: hcloud.LoadBalancerTargetHealthStatusStatusUnhealthy, }, }, }, { HealthStatus: []hcloud.LoadBalancerTargetHealthStatus{ { Status: hcloud.LoadBalancerTargetHealthStatusStatusUnknown, }, }, }, }, }, expected: "mixed", }, { name: "mixed_many_services_grouped_by_target", lb: &hcloud.LoadBalancer{ Name: "foobar", Services: make([]hcloud.LoadBalancerService, 3), Targets: []hcloud.LoadBalancerTarget{ { HealthStatus: []hcloud.LoadBalancerTargetHealthStatus{ { Status: hcloud.LoadBalancerTargetHealthStatusStatusHealthy, }, { Status: hcloud.LoadBalancerTargetHealthStatusStatusHealthy, }, { Status: hcloud.LoadBalancerTargetHealthStatusStatusHealthy, }, }, }, { HealthStatus: []hcloud.LoadBalancerTargetHealthStatus{ { Status: hcloud.LoadBalancerTargetHealthStatusStatusUnhealthy, }, { Status: hcloud.LoadBalancerTargetHealthStatusStatusUnhealthy, }, { Status: hcloud.LoadBalancerTargetHealthStatusStatusUnhealthy, }, }, }, { HealthStatus: []hcloud.LoadBalancerTargetHealthStatus{ { Status: hcloud.LoadBalancerTargetHealthStatusStatusUnknown, }, { Status: hcloud.LoadBalancerTargetHealthStatusStatusUnknown, }, { Status: hcloud.LoadBalancerTargetHealthStatusStatusUnknown, }, }, }, }, }, expected: "mixed", }, { name: "mixed_many_services_mixed", lb: &hcloud.LoadBalancer{ Name: "foobar", Services: make([]hcloud.LoadBalancerService, 3), Targets: []hcloud.LoadBalancerTarget{ { HealthStatus: []hcloud.LoadBalancerTargetHealthStatus{ { Status: hcloud.LoadBalancerTargetHealthStatusStatusHealthy, }, { Status: hcloud.LoadBalancerTargetHealthStatusStatusUnhealthy, }, { Status: hcloud.LoadBalancerTargetHealthStatusStatusUnknown, }, }, }, { HealthStatus: []hcloud.LoadBalancerTargetHealthStatus{ { Status: hcloud.LoadBalancerTargetHealthStatusStatusHealthy, }, { Status: hcloud.LoadBalancerTargetHealthStatusStatusUnhealthy, }, { Status: hcloud.LoadBalancerTargetHealthStatusStatusUnknown, }, }, }, { HealthStatus: []hcloud.LoadBalancerTargetHealthStatus{ { Status: hcloud.LoadBalancerTargetHealthStatusStatusHealthy, }, { Status: hcloud.LoadBalancerTargetHealthStatusStatusUnhealthy, }, { Status: hcloud.LoadBalancerTargetHealthStatusStatusUnknown, }, }, }, }, }, expected: "mixed", }, } for _, test := range tests { res := loadBalancerHealth(test.lb) assert.Equal(t, test.expected, res, test.name) } } cli-1.39.0/internal/cmd/loadbalancer/load_balancer.go000066400000000000000000000036301451614444200224450ustar00rootroot00000000000000package loadbalancer import ( "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" ) func NewCommand(cli *state.State, client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "load-balancer", Short: "Manage Load Balancers", Aliases: []string{"loadbalancer"}, Args: cobra.NoArgs, TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.AddCommand( CreateCommand.CobraCommand(cli.Context, client, cli, cli), ListCmd.CobraCommand(cli.Context, client, cli), DescribeCmd.CobraCommand(cli.Context, client, cli), deleteCmd.CobraCommand(cli.Context, client, cli, cli), updateCmd.CobraCommand(cli.Context, client, cli), labelCmds.AddCobraCommand(cli.Context, client, cli), labelCmds.RemoveCobraCommand(cli.Context, client, cli), AddTargetCommand.CobraCommand(cli.Context, client, cli, cli), RemoveTargetCommand.CobraCommand(cli.Context, client, cli, cli), ChangeAlgorithmCommand.CobraCommand(cli.Context, client, cli, cli), UpdateServiceCommand.CobraCommand(cli.Context, client, cli, cli), DeleteServiceCommand.CobraCommand(cli.Context, client, cli, cli), AddServiceCommand.CobraCommand(cli.Context, client, cli, cli), EnableProtectionCommand.CobraCommand(cli.Context, client, cli, cli), DisableProtectionCommand.CobraCommand(cli.Context, client, cli, cli), AttachToNetworkCommand.CobraCommand(cli.Context, client, cli, cli), DetachFromNetworkCommand.CobraCommand(cli.Context, client, cli, cli), EnablePublicInterfaceCommand.CobraCommand(cli.Context, client, cli, cli), DisablePublicInterfaceCommand.CobraCommand(cli.Context, client, cli, cli), ChangeTypeCommand.CobraCommand(cli.Context, client, cli, cli), MetricsCommand.CobraCommand(cli.Context, client, cli, cli), setRDNSCmd.CobraCommand(cli.Context, client, cli, cli), ) return cmd } cli-1.39.0/internal/cmd/loadbalancer/metrics.go000066400000000000000000000070271451614444200213510ustar00rootroot00000000000000package loadbalancer import ( "context" "encoding/json" "fmt" "sort" "strconv" "time" "github.com/guptarohit/asciigraph" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/cmd/output" "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var MetricsCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "metrics [FLAGS] LOADBALANCER", Short: "[ALPHA] Metrics from a Load Balancer", Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.LoadBalancer().Names)), TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.Flags().String("type", "", "Type of metrics you want to show") cmd.MarkFlagRequired("type") cmd.RegisterFlagCompletionFunc("type", cmpl.SuggestCandidates("open_connections", "connections_per_second", "requests_per_second", "bandwidth")) cmd.Flags().String("start", "", "ISO 8601 timestamp") cmd.Flags().String("end", "", "ISO 8601 timestamp") output.AddFlag(cmd, output.OptionJSON()) return cmd }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { outputFlags := output.FlagsForCommand(cmd) idOrName := args[0] LoadBalancer, _, err := client.LoadBalancer().Get(ctx, idOrName) if err != nil { return err } if LoadBalancer == nil { return fmt.Errorf("LoadBalancer not found: %s", idOrName) } metricType, _ := cmd.Flags().GetString("type") start, _ := cmd.Flags().GetString("start") startTime := time.Now().Add(-30 * time.Minute) if start != "" { startTime, err = time.Parse(time.RFC3339, start) if err != nil { return fmt.Errorf("start date has an invalid format. It should be ISO 8601, like: %s", time.Now().Format(time.RFC3339)) } } end, _ := cmd.Flags().GetString("end") endTime := time.Now() if end != "" { endTime, err = time.Parse(time.RFC3339, end) if err != nil { return fmt.Errorf("end date has an invalid format. It should be ISO 8601, like: %s", time.Now().Format(time.RFC3339)) } } m, resp, err := client.LoadBalancer().GetMetrics(ctx, LoadBalancer, hcloud.LoadBalancerGetMetricsOpts{ Types: []hcloud.LoadBalancerMetricType{hcloud.LoadBalancerMetricType(metricType)}, Start: startTime, End: endTime, }) if err != nil { return err } switch { case outputFlags.IsSet("json"): var data map[string]interface{} if err := json.NewDecoder(resp.Body).Decode(&data); err != nil { return err } return util.DescribeJSON(data) default: var keys []string for k := range m.TimeSeries { keys = append(keys, k) } sort.Strings(keys) for _, k := range keys { if len(m.TimeSeries[k]) == 0 { fmt.Printf("Currently there are now metrics available. Please try it again later.") return nil } fmt.Printf("Load Balancer: %s \t Metric: %s \t Start: %s \t End: %s\n", LoadBalancer.Name, k, m.Start.String(), m.End.String()) var data []float64 for _, m := range m.TimeSeries[k] { d, _ := strconv.ParseFloat(m.Value, 64) data = append(data, d) } graph := asciigraph.Plot(data, asciigraph.Height(20), asciigraph.Width(100)) fmt.Println(graph) fmt.Printf("\n\n") } } return nil }, } cli-1.39.0/internal/cmd/loadbalancer/remove_target.go000066400000000000000000000055471451614444200225530ustar00rootroot00000000000000package loadbalancer import ( "context" "fmt" "net" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var RemoveTargetCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "remove-target LOADBALANCER FLAGS", Short: "Remove a target from a Load Balancer", Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.LoadBalancer().Names)), TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.Flags().String("server", "", "Name or ID of the server") cmd.RegisterFlagCompletionFunc("server", cmpl.SuggestCandidatesF(client.Server().Names)) cmd.Flags().String("label-selector", "", "Label Selector") cmd.Flags().String("ip", "", "IP address of an IP target") return cmd }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { var ( action *hcloud.Action loadBalancer *hcloud.LoadBalancer err error ) serverIDOrName, _ := cmd.Flags().GetString("server") labelSelector, _ := cmd.Flags().GetString("label-selector") ipAddr, _ := cmd.Flags().GetString("ip") idOrName := args[0] loadBalancer, _, err = client.LoadBalancer().Get(ctx, idOrName) if err != nil { return err } if loadBalancer == nil { return fmt.Errorf("Load Balancer not found: %s", idOrName) } if !util.ExactlyOneSet(serverIDOrName, labelSelector, ipAddr) { return fmt.Errorf("--server, --label-selector, and --ip are mutually exclusive") } switch { case serverIDOrName != "": server, _, err := client.Server().Get(ctx, serverIDOrName) if err != nil { return err } if server == nil { return fmt.Errorf("server not found: %s", serverIDOrName) } action, _, err = client.LoadBalancer().RemoveServerTarget(ctx, loadBalancer, server) if err != nil { return err } case labelSelector != "": action, _, err = client.LoadBalancer().RemoveLabelSelectorTarget(ctx, loadBalancer, labelSelector) if err != nil { return err } case ipAddr != "": ip := net.ParseIP(ipAddr) if ip == nil { return fmt.Errorf("invalid ip provided") } if action, _, err = client.LoadBalancer().RemoveIPTarget(ctx, loadBalancer, ip); err != nil { return err } default: return fmt.Errorf("specify one of --server, --label-selector, or --ip") } if err := waiter.ActionProgress(ctx, action); err != nil { return err } fmt.Printf("Target removed from Load Balancer %d\n", loadBalancer.ID) return nil }, } cli-1.39.0/internal/cmd/loadbalancer/set_rdns.go000066400000000000000000000014301451614444200215140ustar00rootroot00000000000000package loadbalancer import ( "context" "net" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var setRDNSCmd = base.SetRdnsCmd{ ResourceNameSingular: "Load Balancer", ShortDescription: "Change reverse DNS of a Load Balancer", NameSuggestions: func(c hcapi2.Client) func() []string { return c.LoadBalancer().Names }, Fetch: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) { return client.LoadBalancer().Get(ctx, idOrName) }, GetDefaultIP: func(resource interface{}) net.IP { loadBalancer := resource.(*hcloud.LoadBalancer) return loadBalancer.PublicNet.IPv4.IP }, } cli-1.39.0/internal/cmd/loadbalancer/update.go000066400000000000000000000021611451614444200211570ustar00rootroot00000000000000package loadbalancer import ( "context" "github.com/spf13/cobra" "github.com/spf13/pflag" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var updateCmd = base.UpdateCmd{ ResourceNameSingular: "Load Balancer", ShortDescription: "Update a Load Balancer", NameSuggestions: func(c hcapi2.Client) func() []string { return c.LoadBalancer().Names }, Fetch: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) { return client.LoadBalancer().Get(ctx, idOrName) }, DefineFlags: func(cmd *cobra.Command) { cmd.Flags().String("name", "", "LoadBalancer name") }, Update: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, resource interface{}, flags map[string]pflag.Value) error { floatingIP := resource.(*hcloud.LoadBalancer) updOpts := hcloud.LoadBalancerUpdateOpts{ Name: flags["name"].String(), } _, _, err := client.LoadBalancer().Update(ctx, floatingIP, updOpts) if err != nil { return err } return nil }, } cli-1.39.0/internal/cmd/loadbalancer/update_service.go000066400000000000000000000173011451614444200227010ustar00rootroot00000000000000package loadbalancer import ( "context" "fmt" "time" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var UpdateServiceCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "update-service LOADBALANCER FLAGS", Short: "Updates a service from a Load Balancer", Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.LoadBalancer().Names)), TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.Flags().Int("listen-port", 0, "The listen port of the service that you want to update (required)") cmd.MarkFlagRequired("listen-port") cmd.Flags().Int("destination-port", 0, "Destination port of the service on the targets") cmd.Flags().String("protocol", "", "The protocol to use for load balancing traffic") cmd.Flags().Bool("proxy-protocol", false, "Enable or disable (with --proxy-protocol=false) Proxy Protocol") cmd.Flags().Bool("http-redirect-http", false, "Enable or disable redirect all traffic on port 80 to port 443") cmd.Flags().Bool("http-sticky-sessions", false, "Enable or disable (with --http-sticky-sessions=false) Sticky Sessions") cmd.Flags().String("http-cookie-name", "", "Sticky Sessions: Cookie Name which will be set") cmd.Flags().Duration("http-cookie-lifetime", 0, "Sticky Sessions: Lifetime of the cookie") cmd.Flags().Int64Slice("http-certificates", []int64{}, "ID of Certificates which are attached to this Load Balancer") cmd.Flags().String("health-check-protocol", "", "The protocol the health check is performed over") cmd.Flags().Int("health-check-port", 0, "The port the health check is performed over") cmd.Flags().Duration("health-check-interval", 15*time.Second, "The interval the health check is performed") cmd.Flags().Duration("health-check-timeout", 10*time.Second, "The timeout after a health check is marked as failed") cmd.Flags().Int("health-check-retries", 3, "Number of retries after a health check is marked as failed") cmd.Flags().String("health-check-http-domain", "", "The domain we request when performing a http health check") cmd.Flags().String("health-check-http-path", "", "The path we request when performing a http health check") cmd.Flags().StringSlice("health-check-http-status-codes", []string{}, "List of status codes we expect to determine a target as healthy") cmd.Flags().String("health-check-http-response", "", "The response we expect to determine a target as healthy") cmd.Flags().Bool("health-check-http-tls", false, "Determine if the health check should verify if the target answers with a valid TLS certificate") return cmd }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { idOrName := args[0] listenPort, _ := cmd.Flags().GetInt("listen-port") loadBalancer, _, err := client.LoadBalancer().Get(ctx, idOrName) if err != nil { return err } if loadBalancer == nil { return fmt.Errorf("Load Balancer not found: %s", idOrName) } var service hcloud.LoadBalancerService for _, _service := range loadBalancer.Services { if _service.ListenPort == listenPort { if _service.HealthCheck.HTTP != nil { service = _service } } } opts := hcloud.LoadBalancerUpdateServiceOpts{ HTTP: &hcloud.LoadBalancerUpdateServiceOptsHTTP{}, HealthCheck: &hcloud.LoadBalancerUpdateServiceOptsHealthCheck{}, } if cmd.Flag("protocol").Changed { protocol, _ := cmd.Flags().GetString("protocol") opts.Protocol = hcloud.LoadBalancerServiceProtocol(protocol) } if cmd.Flag("destination-port").Changed { destinationPort, _ := cmd.Flags().GetInt("destination-port") opts.DestinationPort = &destinationPort } if cmd.Flag("proxy-protocol").Changed { proxyProtocol, _ := cmd.Flags().GetBool("proxy-protocol") opts.Proxyprotocol = hcloud.Bool(proxyProtocol) } // HTTP if cmd.Flag("http-redirect-http").Changed { redirectHTTP, _ := cmd.Flags().GetBool("http-redirect-http") opts.HTTP.RedirectHTTP = hcloud.Bool(redirectHTTP) } if cmd.Flag("http-sticky-sessions").Changed { stickySessions, _ := cmd.Flags().GetBool("http-sticky-sessions") opts.HTTP.StickySessions = hcloud.Bool(stickySessions) } if cmd.Flag("http-cookie-name").Changed { cookieName, _ := cmd.Flags().GetString("http-cookie-name") opts.HTTP.CookieName = hcloud.String(cookieName) } if cmd.Flag("http-cookie-lifetime").Changed { cookieLifetime, _ := cmd.Flags().GetDuration("http-cookie-lifetime") opts.HTTP.CookieLifetime = hcloud.Duration(cookieLifetime) } if cmd.Flag("http-certificates").Changed { certificates, _ := cmd.Flags().GetInt64Slice("http-certificates") for _, certificateID := range certificates { opts.HTTP.Certificates = append(opts.HTTP.Certificates, &hcloud.Certificate{ID: certificateID}) } } // Health Check if cmd.Flag("health-check-protocol").Changed { healthCheckProtocol, _ := cmd.Flags().GetString("health-check-protocol") opts.HealthCheck.Protocol = hcloud.LoadBalancerServiceProtocol(healthCheckProtocol) } if cmd.Flag("health-check-port").Changed { healthCheckPort, _ := cmd.Flags().GetInt("health-check-port") opts.HealthCheck.Port = hcloud.Int(healthCheckPort) } if cmd.Flag("health-check-interval").Changed { healthCheckInterval, _ := cmd.Flags().GetDuration("health-check-interval") opts.HealthCheck.Interval = hcloud.Duration(healthCheckInterval) } if cmd.Flag("health-check-timeout").Changed { healthCheckTimeout, _ := cmd.Flags().GetDuration("health-check-timeout") opts.HealthCheck.Timeout = hcloud.Duration(healthCheckTimeout) } if cmd.Flag("health-check-retries").Changed { healthCheckRetries, _ := cmd.Flags().GetInt("health-check-retries") opts.HealthCheck.Retries = hcloud.Int(healthCheckRetries) } // Health Check HTTP healthCheckProtocol, _ := cmd.Flags().GetString("health-check-protocol") if healthCheckProtocol != string(hcloud.LoadBalancerServiceProtocolTCP) || service.HealthCheck.Protocol != hcloud.LoadBalancerServiceProtocolTCP { opts.HealthCheck.HTTP = &hcloud.LoadBalancerUpdateServiceOptsHealthCheckHTTP{} if cmd.Flag("health-check-http-domain").Changed { healthCheckHTTPDomain, _ := cmd.Flags().GetString("health-check-http-domain") opts.HealthCheck.HTTP.Domain = hcloud.String(healthCheckHTTPDomain) } if cmd.Flag("health-check-http-path").Changed { healthCheckHTTPPath, _ := cmd.Flags().GetString("health-check-http-path") opts.HealthCheck.HTTP.Path = hcloud.String(healthCheckHTTPPath) } if cmd.Flag("health-check-http-response").Changed { healthCheckHTTPResponse, _ := cmd.Flags().GetString("health-check-http-response") opts.HealthCheck.HTTP.Response = hcloud.String(healthCheckHTTPResponse) } if cmd.Flag("health-check-http-status-codes").Changed { healthCheckHTTPStatusCodes, _ := cmd.Flags().GetStringSlice("health-check-http-status-codes") opts.HealthCheck.HTTP.StatusCodes = healthCheckHTTPStatusCodes } if cmd.Flag("health-check-http-tls").Changed { healthCheckHTTPTLS, _ := cmd.Flags().GetBool("health-check-http-tls") opts.HealthCheck.HTTP.TLS = hcloud.Bool(healthCheckHTTPTLS) } } action, _, err := client.LoadBalancer().UpdateService(ctx, loadBalancer, listenPort, opts) if err != nil { return err } if err := waiter.ActionProgress(ctx, action); err != nil { return err } fmt.Printf("Service %d on Load Balancer %d was updated\n", listenPort, loadBalancer.ID) return nil }, } cli-1.39.0/internal/cmd/loadbalancertype/000077500000000000000000000000001451614444200202505ustar00rootroot00000000000000cli-1.39.0/internal/cmd/loadbalancertype/describe.go000066400000000000000000000032251451614444200223610ustar00rootroot00000000000000package loadbalancertype import ( "context" "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var describeCmd = base.DescribeCmd{ ResourceNameSingular: "Load Balancer Type", ShortDescription: "Describe a Load Balancer type", JSONKeyGetByID: "load_balancer_type", JSONKeyGetByName: "load_balancer_types", NameSuggestions: func(c hcapi2.Client) func() []string { return c.LoadBalancerType().Names }, Fetch: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) { return client.LoadBalancerType().Get(ctx, idOrName) }, PrintText: func(_ context.Context, _ hcapi2.Client, _ *cobra.Command, resource interface{}) error { loadBalancerType := resource.(*hcloud.LoadBalancerType) fmt.Printf("ID:\t\t\t\t%d\n", loadBalancerType.ID) fmt.Printf("Name:\t\t\t\t%s\n", loadBalancerType.Name) fmt.Printf("Description:\t\t\t%s\n", loadBalancerType.Description) fmt.Printf("Max Services:\t\t\t%d\n", loadBalancerType.MaxServices) fmt.Printf("Max Connections:\t\t%d\n", loadBalancerType.MaxConnections) fmt.Printf("Max Targets:\t\t\t%d\n", loadBalancerType.MaxTargets) fmt.Printf("Max assigned Certificates:\t%d\n", loadBalancerType.MaxAssignedCertificates) fmt.Printf("Pricings per Location:\n") for _, price := range loadBalancerType.Pricings { fmt.Printf(" - Location:\t%s:\n", price.Location.Name) fmt.Printf(" Hourly:\t€ %s\n", price.Hourly.Gross) fmt.Printf(" Monthly:\t€ %s\n", price.Monthly.Gross) } return nil }, } cli-1.39.0/internal/cmd/loadbalancertype/list.go000066400000000000000000000030631451614444200215540ustar00rootroot00000000000000package loadbalancertype import ( "context" "github.com/spf13/pflag" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/output" "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" "github.com/hetznercloud/hcloud-go/v2/hcloud/schema" ) var ListCmd = base.ListCmd{ ResourceNamePlural: "Load Balancer Types", JSONKeyGetByName: "load_balancer_types", DefaultColumns: []string{"id", "name", "description", "max_services", "max_connections", "max_targets"}, Fetch: func(ctx context.Context, client hcapi2.Client, _ *pflag.FlagSet, listOpts hcloud.ListOpts, sorts []string) ([]interface{}, error) { opts := hcloud.LoadBalancerTypeListOpts{ListOpts: listOpts} if len(sorts) > 0 { opts.Sort = sorts } loadBalancerTypes, _, err := client.LoadBalancerType().List(ctx, opts) var resources []interface{} for _, r := range loadBalancerTypes { resources = append(resources, r) } return resources, err }, OutputTable: func(client hcapi2.Client) *output.Table { return output.NewTable(). AddAllowedFields(hcloud.LoadBalancerType{}) }, JSONSchema: func(resources []interface{}) interface{} { loadBalancerTypeSchemas := make([]schema.LoadBalancerType, 0, len(resources)) for _, resource := range resources { loadBalancerType := resource.(*hcloud.LoadBalancerType) loadBalancerTypeSchemas = append(loadBalancerTypeSchemas, util.LoadBalancerTypeToSchema(*loadBalancerType)) } return loadBalancerTypeSchemas }, } cli-1.39.0/internal/cmd/loadbalancertype/load_balancer_type.go000066400000000000000000000011271451614444200244070ustar00rootroot00000000000000package loadbalancertype import ( "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" ) func NewCommand(cli *state.State, client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "load-balancer-type", Short: "Manage Load Balancer types", Args: cobra.NoArgs, TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.AddCommand( describeCmd.CobraCommand(cli.Context, client, cli), ListCmd.CobraCommand(cli.Context, client, cli), ) return cmd } cli-1.39.0/internal/cmd/location/000077500000000000000000000000001451614444200165475ustar00rootroot00000000000000cli-1.39.0/internal/cmd/location/describe.go000066400000000000000000000024421451614444200206600ustar00rootroot00000000000000package location import ( "context" "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) // DescribeCmd defines a command for describing a location. var DescribeCmd = base.DescribeCmd{ ResourceNameSingular: "location", ShortDescription: "Describe a location", JSONKeyGetByID: "location", JSONKeyGetByName: "locations", NameSuggestions: func(c hcapi2.Client) func() []string { return c.Location().Names }, Fetch: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) { return client.Location().Get(ctx, idOrName) }, PrintText: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, resource interface{}) error { location := resource.(*hcloud.Location) fmt.Printf("ID:\t\t%d\n", location.ID) fmt.Printf("Name:\t\t%s\n", location.Name) fmt.Printf("Description:\t%s\n", location.Description) fmt.Printf("Network Zone:\t%s\n", location.NetworkZone) fmt.Printf("Country:\t%s\n", location.Country) fmt.Printf("City:\t\t%s\n", location.City) fmt.Printf("Latitude:\t%f\n", location.Latitude) fmt.Printf("Longitude:\t%f\n", location.Longitude) return nil }, } cli-1.39.0/internal/cmd/location/describe_test.go000066400000000000000000000020561451614444200217200ustar00rootroot00000000000000package location_test import ( "context" "testing" "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" "github.com/hetznercloud/cli/internal/cmd/location" "github.com/hetznercloud/cli/internal/testutil" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) func TestDescribe(t *testing.T) { fx := testutil.NewFixture(t) defer fx.Finish() cmd := location.DescribeCmd.CobraCommand( context.Background(), fx.Client, fx.TokenEnsurer) fx.ExpectEnsureToken() fx.Client.LocationClient.EXPECT(). Get(gomock.Any(), "hel1"). Return(&hcloud.Location{ ID: 3, Name: "hel1", Description: "Helsinki DC Park 1", NetworkZone: "eu-central", Country: "FI", City: "Helsinki", Latitude: 60.169855, Longitude: 24.938379, }, nil, nil) out, err := fx.Run(cmd, []string{"hel1"}) expOut := `ID: 3 Name: hel1 Description: Helsinki DC Park 1 Network Zone: eu-central Country: FI City: Helsinki Latitude: 60.169855 Longitude: 24.938379 ` assert.NoError(t, err) assert.Equal(t, expOut, out) } cli-1.39.0/internal/cmd/location/list.go000066400000000000000000000026261451614444200200570ustar00rootroot00000000000000package location import ( "context" "github.com/spf13/pflag" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/output" "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" "github.com/hetznercloud/hcloud-go/v2/hcloud/schema" ) var ListCmd = base.ListCmd{ ResourceNamePlural: "locations", JSONKeyGetByName: "locations", DefaultColumns: []string{"id", "name", "description", "network_zone", "country", "city"}, Fetch: func(ctx context.Context, client hcapi2.Client, _ *pflag.FlagSet, listOpts hcloud.ListOpts, sorts []string) ([]interface{}, error) { opts := hcloud.LocationListOpts{ListOpts: listOpts} if len(sorts) > 0 { opts.Sort = sorts } locations, _, err := client.Location().List(ctx, opts) var resources []interface{} for _, n := range locations { resources = append(resources, n) } return resources, err }, OutputTable: func(_ hcapi2.Client) *output.Table { return output.NewTable(). AddAllowedFields(hcloud.Location{}) }, JSONSchema: func(resources []interface{}) interface{} { locationSchemas := make([]schema.Location, 0, len(resources)) for _, resource := range resources { location := resource.(*hcloud.Location) locationSchemas = append(locationSchemas, util.LocationToSchema(*location)) } return locationSchemas }, } cli-1.39.0/internal/cmd/location/location.go000066400000000000000000000010731451614444200207070ustar00rootroot00000000000000package location import ( "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" ) func NewCommand(cli *state.State, client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "location", Short: "Manage locations", Args: cobra.NoArgs, TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.AddCommand( ListCmd.CobraCommand(cli.Context, client, cli), DescribeCmd.CobraCommand(cli.Context, client, cli), ) return cmd } cli-1.39.0/internal/cmd/network/000077500000000000000000000000001451614444200164305ustar00rootroot00000000000000cli-1.39.0/internal/cmd/network/add_route.go000066400000000000000000000034401451614444200207260ustar00rootroot00000000000000package network import ( "context" "fmt" "net" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var AddRouteCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "add-route NETWORK FLAGS", Short: "Add a route to a network", Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.Network().Names)), TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.Flags().IPNet("destination", net.IPNet{}, "Destination network or host (required)") cmd.MarkFlagRequired("destination") cmd.Flags().IP("gateway", net.IP{}, "Gateway IP address (required)") cmd.MarkFlagRequired("gateway") return cmd }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { gateway, _ := cmd.Flags().GetIP("gateway") destination, _ := cmd.Flags().GetIPNet("destination") idOrName := args[0] network, _, err := client.Network().Get(ctx, idOrName) if err != nil { return err } if network == nil { return fmt.Errorf("network not found: %s", idOrName) } opts := hcloud.NetworkAddRouteOpts{ Route: hcloud.NetworkRoute{ Gateway: gateway, Destination: &destination, }, } action, _, err := client.Network().AddRoute(ctx, network, opts) if err != nil { return err } if err := waiter.ActionProgress(ctx, action); err != nil { return err } fmt.Printf("Route added to network %d\n", network.ID) return nil }, } cli-1.39.0/internal/cmd/network/add_subnet.go000066400000000000000000000046371451614444200211010ustar00rootroot00000000000000package network import ( "context" "fmt" "net" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var AddSubnetCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "add-subnet NETWORK FLAGS", Short: "Add a subnet to a network", Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.Network().Names)), TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.Flags().String("type", "", "Type of subnet (required)") cmd.RegisterFlagCompletionFunc("type", cmpl.SuggestCandidates("cloud", "server", "vswitch")) cmd.MarkFlagRequired("type") cmd.Flags().String("network-zone", "", "Name of network zone (required)") cmd.RegisterFlagCompletionFunc("network-zone", cmpl.SuggestCandidatesF(client.Location().NetworkZones)) cmd.MarkFlagRequired("network-zone") cmd.Flags().IPNet("ip-range", net.IPNet{}, "Range to allocate IPs from") cmd.Flags().Int64("vswitch-id", 0, "ID of the vSwitch") return cmd }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { subnetType, _ := cmd.Flags().GetString("type") networkZone, _ := cmd.Flags().GetString("network-zone") ipRange, _ := cmd.Flags().GetIPNet("ip-range") vSwitchID, _ := cmd.Flags().GetInt64("vswitch-id") idOrName := args[0] network, _, err := client.Network().Get(ctx, idOrName) if err != nil { return err } if network == nil { return fmt.Errorf("network not found: %s", idOrName) } subnet := hcloud.NetworkSubnet{ Type: hcloud.NetworkSubnetType(subnetType), NetworkZone: hcloud.NetworkZone(networkZone), } if ipRange.IP != nil && ipRange.Mask != nil { subnet.IPRange = &ipRange } if subnetType == "vswitch" { subnet.VSwitchID = vSwitchID } opts := hcloud.NetworkAddSubnetOpts{ Subnet: subnet, } action, _, err := client.Network().AddSubnet(ctx, network, opts) if err != nil { return err } if err := waiter.ActionProgress(ctx, action); err != nil { return err } fmt.Printf("Subnet added to network %d\n", network.ID) return nil }, } cli-1.39.0/internal/cmd/network/change_ip_range.go000066400000000000000000000031111451614444200220440ustar00rootroot00000000000000package network import ( "context" "fmt" "net" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var ChangeIPRangeCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "change-ip-range [FLAGS] NETWORK", Short: "Change the IP range of a network", Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.Network().Names)), TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.Flags().IPNet("ip-range", net.IPNet{}, "New IP range (required)") cmd.MarkFlagRequired("ip-range") return cmd }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { idOrName := args[0] network, _, err := client.Network().Get(ctx, idOrName) if err != nil { return err } if network == nil { return fmt.Errorf("network not found: %s", idOrName) } ipRange, _ := cmd.Flags().GetIPNet("ip-range") opts := hcloud.NetworkChangeIPRangeOpts{ IPRange: &ipRange, } action, _, err := client.Network().ChangeIPRange(ctx, network, opts) if err != nil { return err } if err := waiter.ActionProgress(ctx, action); err != nil { return err } fmt.Printf("IP range of network %d changed\n", network.ID) return nil }, } cli-1.39.0/internal/cmd/network/create.go000066400000000000000000000042621451614444200202260ustar00rootroot00000000000000package network import ( "net" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) func newCreateCommand(cli *state.State) *cobra.Command { cmd := &cobra.Command{ Use: "create [FLAGS]", Short: "Create a network", Args: cobra.NoArgs, TraverseChildren: true, DisableFlagsInUseLine: true, PreRunE: cli.EnsureToken, RunE: cli.Wrap(runCreate), } cmd.Flags().String("name", "", "Network name (required)") cmd.MarkFlagRequired("name") cmd.Flags().IPNet("ip-range", net.IPNet{}, "Network IP range (required)") cmd.MarkFlagRequired("ip-range") cmd.Flags().Bool("expose-routes-to-vswitch", false, "Expose routes from this network to the vSwitch connection. It only takes effect if a vSwitch connection is active.") cmd.Flags().StringToString("label", nil, "User-defined labels ('key=value') (can be specified multiple times)") cmd.Flags().StringSlice("enable-protection", []string{}, "Enable protection (delete) (default: none)") cmd.RegisterFlagCompletionFunc("enable-protection", cmpl.SuggestCandidates("delete")) return cmd } func runCreate(cli *state.State, cmd *cobra.Command, args []string) error { name, _ := cmd.Flags().GetString("name") ipRange, _ := cmd.Flags().GetIPNet("ip-range") labels, _ := cmd.Flags().GetStringToString("label") exposeRoutesToVSwitch, _ := cmd.Flags().GetBool("expose-routes-to-vswitch") protection, _ := cmd.Flags().GetStringSlice("enable-protection") protectionOpts, err := getChangeProtectionOpts(true, protection) if err != nil { return err } createOpts := hcloud.NetworkCreateOpts{ Name: name, IPRange: &ipRange, Labels: labels, ExposeRoutesToVSwitch: exposeRoutesToVSwitch, } network, _, err := cli.Client().Network.Create(cli.Context, createOpts) if err != nil { return err } cmd.Printf("Network %d created\n", network.ID) return changeProtection(cli.Context, hcapi2.NewClient(cli.Client()), cli, network, true, protectionOpts) } cli-1.39.0/internal/cmd/network/delete.go000066400000000000000000000016211451614444200202210ustar00rootroot00000000000000package network import ( "context" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var deleteCmd = base.DeleteCmd{ ResourceNameSingular: "Network", ShortDescription: "Delete a network", NameSuggestions: func(c hcapi2.Client) func() []string { return c.Network().Names }, Fetch: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) { return client.Network().Get(ctx, idOrName) }, Delete: func(ctx context.Context, client hcapi2.Client, _ state.ActionWaiter, cmd *cobra.Command, resource interface{}) error { network := resource.(*hcloud.Network) if _, err := client.Network().Delete(ctx, network); err != nil { return err } return nil }, } cli-1.39.0/internal/cmd/network/describe.go000066400000000000000000000045721451614444200205470ustar00rootroot00000000000000package network import ( "context" "fmt" humanize "github.com/dustin/go-humanize" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) // DescribeCmd defines a command for describing a network. var DescribeCmd = base.DescribeCmd{ ResourceNameSingular: "network", ShortDescription: "Describe a network", JSONKeyGetByID: "network", JSONKeyGetByName: "networks", NameSuggestions: func(c hcapi2.Client) func() []string { return c.Network().Names }, Fetch: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) { return client.Network().Get(ctx, idOrName) }, PrintText: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, resource interface{}) error { network := resource.(*hcloud.Network) fmt.Printf("ID:\t\t%d\n", network.ID) fmt.Printf("Name:\t\t%s\n", network.Name) fmt.Printf("Created:\t%s (%s)\n", util.Datetime(network.Created), humanize.Time(network.Created)) fmt.Printf("IP Range:\t%s\n", network.IPRange.String()) fmt.Printf("Expose Routes to vSwitch: %s\n", util.YesNo(network.ExposeRoutesToVSwitch)) fmt.Printf("Subnets:\n") if len(network.Subnets) == 0 { fmt.Print(" No subnets\n") } else { for _, subnet := range network.Subnets { fmt.Printf(" - Type:\t\t%s\n", subnet.Type) fmt.Printf(" Network Zone:\t%s\n", subnet.NetworkZone) fmt.Printf(" IP Range:\t\t%s\n", subnet.IPRange.String()) fmt.Printf(" Gateway:\t\t%s\n", subnet.Gateway.String()) if subnet.Type == hcloud.NetworkSubnetTypeVSwitch { fmt.Printf(" vSwitch ID:\t\t%d\n", subnet.VSwitchID) } } } fmt.Printf("Routes:\n") if len(network.Routes) == 0 { fmt.Print(" No routes\n") } else { for _, route := range network.Routes { fmt.Printf(" - Destination:\t%s\n", route.Destination.String()) fmt.Printf(" Gateway:\t\t%s\n", route.Gateway.String()) } } fmt.Printf("Protection:\n") fmt.Printf(" Delete:\t%s\n", util.YesNo(network.Protection.Delete)) fmt.Print("Labels:\n") if len(network.Labels) == 0 { fmt.Print(" No labels\n") } else { for key, value := range network.Labels { fmt.Printf(" %s: %s\n", key, value) } } return nil }, } cli-1.39.0/internal/cmd/network/disable_protection.go000066400000000000000000000023631451614444200226340ustar00rootroot00000000000000package network import ( "context" "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" ) var DisableProtectionCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { return &cobra.Command{ Use: "disable-protection [FLAGS] NETWORK PROTECTIONLEVEL [PROTECTIONLEVEL...]", Short: "Disable resource protection for a network", Args: cobra.MinimumNArgs(2), ValidArgsFunction: cmpl.SuggestArgs( cmpl.SuggestCandidatesF(client.Network().Names), cmpl.SuggestCandidates("delete"), ), TraverseChildren: true, DisableFlagsInUseLine: true, } }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { idOrName := args[0] network, _, err := client.Network().Get(ctx, idOrName) if err != nil { return err } if network == nil { return fmt.Errorf("network not found: %s", idOrName) } opts, err := getChangeProtectionOpts(false, args[1:]) if err != nil { return err } return changeProtection(ctx, client, waiter, network, false, opts) }, } cli-1.39.0/internal/cmd/network/enable_protection.go000066400000000000000000000045251451614444200224610ustar00rootroot00000000000000package network import ( "context" "fmt" "strings" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) func getChangeProtectionOpts(enable bool, flags []string) (hcloud.NetworkChangeProtectionOpts, error) { opts := hcloud.NetworkChangeProtectionOpts{} var unknown []string for _, arg := range flags { switch strings.ToLower(arg) { case "delete": opts.Delete = hcloud.Ptr(enable) default: unknown = append(unknown, arg) } } if len(unknown) > 0 { return opts, fmt.Errorf("unknown protection level: %s", strings.Join(unknown, ", ")) } return opts, nil } func changeProtection(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, network *hcloud.Network, enable bool, opts hcloud.NetworkChangeProtectionOpts) error { if opts.Delete == nil { return nil } action, _, err := client.Network().ChangeProtection(ctx, network, opts) if err != nil { return err } if err := waiter.ActionProgress(ctx, action); err != nil { return err } if enable { fmt.Printf("Resource protection enabled for network %d\n", network.ID) } else { fmt.Printf("Resource protection disabled for network %d\n", network.ID) } return nil } var EnableProtectionCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { return &cobra.Command{ Use: "enable-protection [FLAGS] NETWORK PROTECTIONLEVEL [PROTECTIONLEVEL...]", Short: "Enable resource protection for a network", Args: cobra.MinimumNArgs(2), ValidArgsFunction: cmpl.SuggestArgs( cmpl.SuggestCandidatesF(client.Network().Names), cmpl.SuggestCandidates("delete"), ), TraverseChildren: true, DisableFlagsInUseLine: true, } }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { idOrName := args[0] network, _, err := client.Network().Get(ctx, idOrName) if err != nil { return err } if network == nil { return fmt.Errorf("network not found: %s", idOrName) } opts, err := getChangeProtectionOpts(true, args[1:]) if err != nil { return err } return changeProtection(ctx, client, waiter, network, true, opts) }, } cli-1.39.0/internal/cmd/network/expose-routes-to-vswitch.go000066400000000000000000000034441451614444200237130ustar00rootroot00000000000000package network import ( "context" "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var ExposeRoutesToVSwitchCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "expose-routes-to-vswitch [flags] network", Short: "Expose routes to connected vSwitch", Long: "Enabling this will expose routes to the connected vSwitch. Set the --disable flag to remove the exposed routes.", Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.Network().Names)), TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.Flags().Bool("disable", false, "Remove any exposed routes from the connected vSwitch") return cmd }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { idOrName := args[0] network, _, err := client.Network().Get(ctx, idOrName) if err != nil { return err } if network == nil { return fmt.Errorf("network not found: %s", idOrName) } disable, _ := cmd.Flags().GetBool("disable") opts := hcloud.NetworkUpdateOpts{ ExposeRoutesToVSwitch: hcloud.Ptr(!disable), } _, _, err = client.Network().Update(ctx, network, opts) if err != nil { return err } if disable { fmt.Printf("Exposing routes to connected vSwitch of network %s disabled\n", network.Name) } else { fmt.Printf("Exposing routes to connected vSwitch of network %s enabled\n", network.Name) } return nil }, } cli-1.39.0/internal/cmd/network/labels.go000066400000000000000000000022371451614444200202250ustar00rootroot00000000000000package network import ( "context" "fmt" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var labelCmds = base.LabelCmds{ ResourceNameSingular: "Network", ShortDescriptionAdd: "Add a label to a Network", ShortDescriptionRemove: "Remove a label from a Network", NameSuggestions: func(c hcapi2.Client) func() []string { return c.Network().Names }, LabelKeySuggestions: func(c hcapi2.Client) func(idOrName string) []string { return c.Network().LabelKeys }, FetchLabels: func(ctx context.Context, client hcapi2.Client, idOrName string) (map[string]string, int64, error) { network, _, err := client.Network().Get(ctx, idOrName) if err != nil { return nil, 0, err } if network == nil { return nil, 0, fmt.Errorf("network not found: %s", idOrName) } return network.Labels, network.ID, nil }, SetLabels: func(ctx context.Context, client hcapi2.Client, id int64, labels map[string]string) error { opts := hcloud.NetworkUpdateOpts{ Labels: labels, } _, _, err := client.Network().Update(ctx, &hcloud.Network{ID: id}, opts) return err }, } cli-1.39.0/internal/cmd/network/list.go000066400000000000000000000071101451614444200177310ustar00rootroot00000000000000package network import ( "context" "fmt" "strings" "time" "github.com/spf13/pflag" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/output" "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" "github.com/hetznercloud/hcloud-go/v2/hcloud/schema" ) var ListCmd = base.ListCmd{ ResourceNamePlural: "Networks", JSONKeyGetByName: "networks", DefaultColumns: []string{"id", "name", "ip_range", "servers", "age"}, Fetch: func(ctx context.Context, client hcapi2.Client, _ *pflag.FlagSet, listOpts hcloud.ListOpts, sorts []string) ([]interface{}, error) { opts := hcloud.NetworkListOpts{ListOpts: listOpts} if len(sorts) > 0 { opts.Sort = sorts } networks, err := client.Network().AllWithOpts(ctx, opts) var resources []interface{} for _, n := range networks { resources = append(resources, n) } return resources, err }, OutputTable: func(_ hcapi2.Client) *output.Table { return output.NewTable(). AddAllowedFields(hcloud.Network{}). AddFieldFn("servers", output.FieldFn(func(obj interface{}) string { network := obj.(*hcloud.Network) serverCount := len(network.Servers) if serverCount <= 1 { return fmt.Sprintf("%v server", serverCount) } return fmt.Sprintf("%v servers", serverCount) })). AddFieldFn("ip_range", output.FieldFn(func(obj interface{}) string { network := obj.(*hcloud.Network) return network.IPRange.String() })). AddFieldFn("labels", output.FieldFn(func(obj interface{}) string { network := obj.(*hcloud.Network) return util.LabelsToString(network.Labels) })). AddFieldFn("protection", output.FieldFn(func(obj interface{}) string { network := obj.(*hcloud.Network) var protection []string if network.Protection.Delete { protection = append(protection, "delete") } return strings.Join(protection, ", ") })). AddFieldFn("created", output.FieldFn(func(obj interface{}) string { network := obj.(*hcloud.Network) return util.Datetime(network.Created) })). AddFieldFn("age", output.FieldFn(func(obj interface{}) string { network := obj.(*hcloud.Network) return util.Age(network.Created, time.Now()) })) }, JSONSchema: func(resources []interface{}) interface{} { networkSchemas := make([]schema.Network, 0, len(resources)) for _, resource := range resources { network := resource.(*hcloud.Network) networkSchema := schema.Network{ ID: network.ID, Name: network.Name, IPRange: network.IPRange.String(), Protection: schema.NetworkProtection{Delete: network.Protection.Delete}, Created: network.Created, Labels: network.Labels, ExposeRoutesToVSwitch: network.ExposeRoutesToVSwitch, } for _, subnet := range network.Subnets { networkSchema.Subnets = append(networkSchema.Subnets, schema.NetworkSubnet{ Type: string(subnet.Type), IPRange: subnet.IPRange.String(), NetworkZone: string(subnet.NetworkZone), Gateway: subnet.Gateway.String(), }) } for _, route := range network.Routes { networkSchema.Routes = append(networkSchema.Routes, schema.NetworkRoute{ Destination: route.Destination.String(), Gateway: route.Gateway.String(), }) } for _, server := range network.Servers { networkSchema.Servers = append(networkSchema.Servers, server.ID) } networkSchemas = append(networkSchemas, networkSchema) } return networkSchemas }, } cli-1.39.0/internal/cmd/network/list_test.go000066400000000000000000000022701451614444200207720ustar00rootroot00000000000000package network_test import ( "context" "net" "testing" "time" "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" "github.com/hetznercloud/cli/internal/cmd/network" "github.com/hetznercloud/cli/internal/testutil" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) func TestList(t *testing.T) { fx := testutil.NewFixture(t) defer fx.Finish() cmd := network.ListCmd.CobraCommand(context.Background(), fx.Client, fx.TokenEnsurer) fx.ExpectEnsureToken() fx.Client.NetworkClient.EXPECT(). AllWithOpts( gomock.Any(), hcloud.NetworkListOpts{ ListOpts: hcloud.ListOpts{ PerPage: 50, LabelSelector: "foo=bar", }, Sort: []string{"id:asc"}, }, ). Return([]*hcloud.Network{ { ID: 123, Name: "test-net", IPRange: &net.IPNet{IP: net.ParseIP("192.0.2.1"), Mask: net.CIDRMask(24, 32)}, Servers: []*hcloud.Server{{ID: 3421}}, Created: time.Now().Add(-10 * time.Second), }, }, nil) out, err := fx.Run(cmd, []string{"--selector", "foo=bar"}) expOut := `ID NAME IP RANGE SERVERS AGE 123 test-net 192.0.2.1/24 1 server 10s ` assert.NoError(t, err) assert.Equal(t, expOut, out) } cli-1.39.0/internal/cmd/network/network.go000066400000000000000000000025221451614444200204510ustar00rootroot00000000000000package network import ( "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" ) func NewCommand(cli *state.State, client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "network", Short: "Manage networks", Args: cobra.NoArgs, TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.AddCommand( ListCmd.CobraCommand(cli.Context, client, cli), DescribeCmd.CobraCommand(cli.Context, client, cli), newCreateCommand(cli), updateCmd.CobraCommand(cli.Context, client, cli), deleteCmd.CobraCommand(cli.Context, client, cli, cli), ChangeIPRangeCommand.CobraCommand(cli.Context, client, cli, cli), AddRouteCommand.CobraCommand(cli.Context, client, cli, cli), RemoveRouteCommand.CobraCommand(cli.Context, client, cli, cli), AddSubnetCommand.CobraCommand(cli.Context, client, cli, cli), RemoveSubnetCommand.CobraCommand(cli.Context, client, cli, cli), labelCmds.AddCobraCommand(cli.Context, client, cli), labelCmds.RemoveCobraCommand(cli.Context, client, cli), EnableProtectionCommand.CobraCommand(cli.Context, client, cli, cli), DisableProtectionCommand.CobraCommand(cli.Context, client, cli, cli), ExposeRoutesToVSwitchCommand.CobraCommand(cli.Context, client, cli, cli), ) return cmd } cli-1.39.0/internal/cmd/network/remove_route.go000066400000000000000000000034641451614444200215010ustar00rootroot00000000000000package network import ( "context" "fmt" "net" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var RemoveRouteCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "remove-route NETWORK FLAGS", Short: "Remove a route from a network", Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.Network().Names)), TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.Flags().IPNet("destination", net.IPNet{}, "Destination network or host (required)") cmd.MarkFlagRequired("destination") cmd.Flags().IP("gateway", net.IP{}, "Gateway IP address (required)") cmd.MarkFlagRequired("gateway") return cmd }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { gateway, _ := cmd.Flags().GetIP("gateway") destination, _ := cmd.Flags().GetIPNet("destination") idOrName := args[0] network, _, err := client.Network().Get(ctx, idOrName) if err != nil { return err } if network == nil { return fmt.Errorf("network not found: %s", idOrName) } opts := hcloud.NetworkDeleteRouteOpts{ Route: hcloud.NetworkRoute{ Gateway: gateway, Destination: &destination, }, } action, _, err := client.Network().DeleteRoute(ctx, network, opts) if err != nil { return err } if err := waiter.ActionProgress(ctx, action); err != nil { return err } fmt.Printf("Route removed from network %d\n", network.ID) return nil }, } cli-1.39.0/internal/cmd/network/remove_subnet.go000066400000000000000000000031751451614444200216420ustar00rootroot00000000000000package network import ( "context" "fmt" "net" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var RemoveSubnetCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "remove-subnet NETWORK FLAGS", Short: "Remove a subnet from a network", Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.Network().Names)), TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.Flags().IPNet("ip-range", net.IPNet{}, "Subnet IP range (required)") cmd.MarkFlagRequired("ip-range") return cmd }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { ipRange, _ := cmd.Flags().GetIPNet("ip-range") idOrName := args[0] network, _, err := client.Network().Get(ctx, idOrName) if err != nil { return err } if network == nil { return fmt.Errorf("network not found: %s", idOrName) } opts := hcloud.NetworkDeleteSubnetOpts{ Subnet: hcloud.NetworkSubnet{ IPRange: &ipRange, }, } action, _, err := client.Network().DeleteSubnet(ctx, network, opts) if err != nil { return err } if err := waiter.ActionProgress(ctx, action); err != nil { return err } fmt.Printf("Subnet %s removed from network %d\n", ipRange.String(), network.ID) return nil }, } cli-1.39.0/internal/cmd/network/update.go000066400000000000000000000023151451614444200202420ustar00rootroot00000000000000package network import ( "context" "github.com/spf13/cobra" "github.com/spf13/pflag" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var updateCmd = base.UpdateCmd{ ResourceNameSingular: "Network", ShortDescription: "Update a Network.\n\nTo enable or disable exposing routes to the vSwitch connection you can use the subcommand \"hcloud network expose-routes-to-vswitch\".", NameSuggestions: func(c hcapi2.Client) func() []string { return c.Network().Names }, Fetch: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) { return client.Network().Get(ctx, idOrName) }, DefineFlags: func(cmd *cobra.Command) { cmd.Flags().String("name", "", "Network name") }, Update: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, resource interface{}, flags map[string]pflag.Value) error { floatingIP := resource.(*hcloud.Network) updOpts := hcloud.NetworkUpdateOpts{ Name: flags["name"].String(), } _, _, err := client.Network().Update(ctx, floatingIP, updOpts) if err != nil { return err } return nil }, } cli-1.39.0/internal/cmd/output/000077500000000000000000000000001451614444200162775ustar00rootroot00000000000000cli-1.39.0/internal/cmd/output/output.go000066400000000000000000000170261451614444200201740ustar00rootroot00000000000000package output import ( "fmt" "io" "os" "reflect" "sort" "strings" "text/tabwriter" "unicode" "github.com/fatih/structs" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/cmd/util" ) const flagName = "output" type outputOption struct { Name string Values []string } func OptionNoHeader() outputOption { return outputOption{Name: "noheader"} } func OptionJSON() outputOption { return outputOption{Name: "json"} } func OptionFormat() outputOption { return outputOption{Name: "format"} } func OptionColumns(columns []string) outputOption { return outputOption{Name: "columns", Values: columns} } func AddFlag(cmd *cobra.Command, options ...outputOption) { var ( names []string values []string ) for _, option := range options { name := option.Name if option.Values != nil { name += "=..." values = append(values, option.Values...) } names = append(names, name) } cmd.Flags().StringArrayP( flagName, "o", []string{}, fmt.Sprintf("output options: %s", strings.Join(names, "|")), ) cmd.RegisterFlagCompletionFunc(flagName, cmpl.SuggestCandidates(values...)) cmd.PreRunE = util.ChainRunE(cmd.PreRunE, validateOutputFlag(options)) } func validateOutputFlag(options []outputOption) func(cmd *cobra.Command, args []string) error { return func(cmd *cobra.Command, args []string) error { validOptions := map[string]map[string]bool{} for _, option := range options { if option.Values == nil { // all values allowed validOptions[option.Name] = nil } else { // only discrete values allowed validOptions[option.Name] = map[string]bool{} for _, value := range option.Values { validOptions[option.Name][value] = true } } } flagValues, err := cmd.Flags().GetStringArray(flagName) if err != nil { return err } for _, flagValue := range flagValues { parts := strings.SplitN(flagValue, "=", 2) if strings.HasPrefix(parts[0], "columns") && len(parts) != 2 { return fmt.Errorf("invalid output option format") } if _, ok := validOptions[parts[0]]; !ok { return fmt.Errorf("invalid output option: %s", parts[0]) } if len(parts) > 1 && validOptions[parts[0]] != nil { parts[1] = strings.ToLower(strings.TrimSpace(parts[1])) for _, v := range strings.Split(parts[1], ",") { if !validOptions[parts[0]][v] { return fmt.Errorf("invalid value for output option %s: %s", parts[0], v) } } } } return nil } } func FlagsForCommand(cmd *cobra.Command) outputOpts { opts, _ := cmd.Flags().GetStringArray(flagName) return parseOutputFlags(opts) } type outputOpts map[string][]string // Set sets the key to value. It replaces any existing // values. func (o outputOpts) Set(key, value string) { o[key] = []string{value} } // Add adds the value to key. It appends to any existing // values associated with key. func (o outputOpts) Add(key, value string) { o[key] = append(o[key], value) } func (o outputOpts) IsSet(key string) bool { if values, ok := o[key]; ok && len(values) > 0 { return true } return false } func parseOutputFlags(in []string) outputOpts { o := outputOpts{} for _, param := range in { parts := strings.SplitN(param, "=", 2) if len(parts) == 2 { o[parts[0]] = strings.Split(parts[1], ",") } else { o[parts[0]] = []string{""} } } return o } // NewTable creates a new Table. func NewTable() *Table { return &Table{ w: tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0), columns: map[string]bool{}, fieldMapping: map[string]FieldFn{}, fieldAlias: map[string]string{}, allowedFields: map[string]bool{}, } } type FieldFn func(obj interface{}) string type writerFlusher interface { io.Writer Flush() error } // Table is a generic way to format object as a table. type Table struct { w writerFlusher columns map[string]bool fieldMapping map[string]FieldFn fieldAlias map[string]string allowedFields map[string]bool } // Columns returns a list of known output columns. func (o *Table) Columns() (cols []string) { for c := range o.columns { cols = append(cols, c) } sort.Strings(cols) return } // AddFieldAlias overrides the field name to allow custom column headers. func (o *Table) AddFieldAlias(field, alias string) *Table { o.fieldAlias[field] = alias return o } // AddFieldFn adds a function which handles the output of the specified field. func (o *Table) AddFieldFn(field string, fn FieldFn) *Table { o.fieldMapping[field] = fn o.allowedFields[field] = true o.columns[field] = true return o } // AddAllowedFields reads all first level fieldnames of the struct and allows them to be used. func (o *Table) AddAllowedFields(obj interface{}) *Table { v := reflect.ValueOf(obj) if v.Kind() != reflect.Struct { panic("AddAllowedFields input must be a struct") } t := v.Type() for i := 0; i < v.NumField(); i++ { k := t.Field(i).Type.Kind() if k != reflect.Bool && k != reflect.Float32 && k != reflect.Float64 && k != reflect.String && k != reflect.Int && k != reflect.Int64 { // only allow simple values // complex values need to be mapped via a FieldFn continue } o.allowedFields[strings.ToLower(t.Field(i).Name)] = true o.allowedFields[fieldName(t.Field(i).Name)] = true o.columns[fieldName(t.Field(i).Name)] = true } return o } // RemoveAllowedField removes fields from the allowed list. func (o *Table) RemoveAllowedField(fields ...string) *Table { for _, field := range fields { delete(o.allowedFields, field) delete(o.columns, field) } return o } // ValidateColumns returns an error if invalid columns are specified. func (o *Table) ValidateColumns(cols []string) error { var invalidCols []string for _, col := range cols { if _, ok := o.allowedFields[strings.ToLower(col)]; !ok { invalidCols = append(invalidCols, col) } } if len(invalidCols) > 0 { return fmt.Errorf("invalid table columns: %s", strings.Join(invalidCols, ",")) } return nil } // WriteHeader writes the table header. func (o *Table) WriteHeader(columns []string) { var header []string for _, col := range columns { if alias, ok := o.fieldAlias[col]; ok { col = alias } header = append(header, strings.Replace(strings.ToUpper(col), "_", " ", -1)) } fmt.Fprintln(o.w, strings.Join(header, "\t")) } func (o *Table) Flush() error { return o.w.Flush() } // Write writes a table line. func (o *Table) Write(columns []string, obj interface{}) { data := structs.Map(obj) dataL := map[string]interface{}{} for key, value := range data { dataL[strings.ToLower(key)] = value } var out []string for _, col := range columns { colName := strings.ToLower(col) if alias, ok := o.fieldAlias[colName]; ok { if fn, ok := o.fieldMapping[alias]; ok { out = append(out, fn(obj)) continue } } if fn, ok := o.fieldMapping[colName]; ok { out = append(out, fn(obj)) continue } if value, ok := dataL[strings.Replace(colName, "_", "", -1)]; ok { if value == nil { out = append(out, util.NA("")) continue } if b, ok := value.(bool); ok { out = append(out, util.YesNo(b)) continue } if s, ok := value.(string); ok { out = append(out, util.NA(s)) continue } out = append(out, fmt.Sprintf("%v", value)) } } fmt.Fprintln(o.w, strings.Join(out, "\t")) } func fieldName(name string) string { r := []rune(name) var out []rune for i := range r { if i > 0 && (unicode.IsUpper(r[i])) && (i+1 < len(r) && unicode.IsLower(r[i+1]) || unicode.IsLower(r[i-1])) { out = append(out, '_') } out = append(out, unicode.ToLower(r[i])) } return string(out) } cli-1.39.0/internal/cmd/output/output_test.go000066400000000000000000000046301451614444200212300ustar00rootroot00000000000000package output import ( "bytes" "strings" "testing" ) type writerFlusherStub struct { bytes.Buffer } func (s writerFlusherStub) Flush() error { return nil } type testFieldsStruct struct { Name string Number int } func TestTableOutput(t *testing.T) { var wfs writerFlusherStub to := NewTable() to.w = &wfs t.Run("AddAllowedFields", func(t *testing.T) { to.AddAllowedFields(testFieldsStruct{}) if _, ok := to.allowedFields["name"]; !ok { t.Error("name should be a allowed field") } }) t.Run("AddFieldAlias", func(t *testing.T) { to.AddFieldAlias("leeroy_jenkins", "leeroy jenkins") if alias, ok := to.fieldAlias["leeroy_jenkins"]; !ok || alias != "leeroy jenkins" { t.Errorf("leeroy_jenkins alias should be 'leeroy jenkins', is: %v", alias) } }) t.Run("AddFieldOutputFn", func(t *testing.T) { to.AddFieldFn("leeroy jenkins", FieldFn(func(obj interface{}) string { return "LEEROY JENKINS!!!" })) if _, ok := to.fieldMapping["leeroy jenkins"]; !ok { t.Errorf("'leeroy jenkins' field output fn should be set") } }) t.Run("ValidateColumns", func(t *testing.T) { err := to.ValidateColumns([]string{"non-existent", "NAME"}) if err == nil || strings.Contains(err.Error(), "name") || !strings.Contains(err.Error(), "non-existent") { t.Errorf("error should contain 'non-existent' but not 'name': %v", err) } }) t.Run("WriteHeader", func(t *testing.T) { to.WriteHeader([]string{"leeroy_jenkins", "name"}) if wfs.String() != "LEEROY JENKINS\tNAME\n" { t.Errorf("written header should be 'LEEROY JENKINS\\tNAME\\n', is: %q", wfs.String()) } wfs.Reset() }) t.Run("WriteLine", func(t *testing.T) { to.Write([]string{"leeroy_jenkins", "name", "number"}, &testFieldsStruct{"test123", 1000000000}) if wfs.String() != "LEEROY JENKINS!!!\ttest123\t1000000000\n" { t.Errorf("written line should be 'LEEROY JENKINS!!!\\ttest123\\t1000000000\\n', is: %q", wfs.String()) } wfs.Reset() }) t.Run("Columns", func(t *testing.T) { if len(to.Columns()) != 3 { t.Errorf("unexpected number of columns: %v", to.Columns()) } }) } func TestFieldName(t *testing.T) { type fixture struct { in, out string } tests := []fixture{ {"test", "test"}, {"t", "t"}, {"T", "t"}, {"Server", "server"}, {"BoundTo", "bound_to"}, } for _, test := range tests { if f := fieldName(test.in); f != test.out { t.Errorf("Unexpected output expected %q, is %q", test.out, f) } } } cli-1.39.0/internal/cmd/placementgroup/000077500000000000000000000000001451614444200177645ustar00rootroot00000000000000cli-1.39.0/internal/cmd/placementgroup/create.go000066400000000000000000000025321451614444200215600ustar00rootroot00000000000000package placementgroup import ( "context" "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var CreateCmd = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "create FLAGS", Short: "Create a placement group", } cmd.Flags().String("name", "", "Name") cmd.MarkFlagRequired("name") cmd.Flags().StringToString("label", nil, "User-defined labels ('key=value') (can be specified multiple times)") cmd.Flags().String("type", "", "Type of the placement group") cmd.MarkFlagRequired("type") return cmd }, Run: func(ctx context.Context, client hcapi2.Client, actionWaiter state.ActionWaiter, cmd *cobra.Command, args []string) error { name, _ := cmd.Flags().GetString("name") labels, _ := cmd.Flags().GetStringToString("label") placementGroupType, _ := cmd.Flags().GetString("type") opts := hcloud.PlacementGroupCreateOpts{ Name: name, Labels: labels, Type: hcloud.PlacementGroupType(placementGroupType), } result, _, err := client.PlacementGroup().Create(ctx, opts) if err != nil { return err } fmt.Printf("Placement group %d created\n", result.PlacementGroup.ID) return nil }, } cli-1.39.0/internal/cmd/placementgroup/create_test.go000066400000000000000000000022731451614444200226210ustar00rootroot00000000000000package placementgroup_test import ( "context" "testing" "time" "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" "github.com/hetznercloud/cli/internal/cmd/placementgroup" "github.com/hetznercloud/cli/internal/testutil" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) func TestCreate(t *testing.T) { fx := testutil.NewFixture(t) defer fx.Finish() cmd := placementgroup.CreateCmd.CobraCommand( context.Background(), fx.Client, fx.TokenEnsurer, fx.ActionWaiter) fx.ExpectEnsureToken() opts := hcloud.PlacementGroupCreateOpts{ Name: "my Placement Group", Labels: map[string]string{}, Type: hcloud.PlacementGroupTypeSpread, } placementGroup := hcloud.PlacementGroup{ ID: 897, Name: opts.Name, Created: time.Now(), Labels: opts.Labels, Type: opts.Type, } fx.Client.PlacementGroupClient.EXPECT(). Create(gomock.Any(), opts). Return(hcloud.PlacementGroupCreateResult{PlacementGroup: &placementGroup, Action: nil}, nil, nil) out, err := fx.Run(cmd, []string{"--name", placementGroup.Name, "--type", string(placementGroup.Type)}) expOut := `Placement group 897 created ` assert.NoError(t, err) assert.Equal(t, expOut, out) } cli-1.39.0/internal/cmd/placementgroup/delete.go000066400000000000000000000017221451614444200215570ustar00rootroot00000000000000package placementgroup import ( "context" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var DeleteCmd = base.DeleteCmd{ ResourceNameSingular: "placement group", ShortDescription: "Delete a placement group", NameSuggestions: func(c hcapi2.Client) func() []string { return c.PlacementGroup().Names }, Fetch: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) { return client.PlacementGroup().Get(ctx, idOrName) }, Delete: func(ctx context.Context, client hcapi2.Client, _ state.ActionWaiter, cmd *cobra.Command, resource interface{}) error { placementGroup := resource.(*hcloud.PlacementGroup) if _, err := client.PlacementGroup().Delete(ctx, placementGroup); err != nil { return err } return nil }, } cli-1.39.0/internal/cmd/placementgroup/delete_test.go000066400000000000000000000020341451614444200226130ustar00rootroot00000000000000package placementgroup_test import ( "context" "testing" "time" "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" "github.com/hetznercloud/cli/internal/cmd/placementgroup" "github.com/hetznercloud/cli/internal/testutil" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) func TestDelete(t *testing.T) { fx := testutil.NewFixture(t) defer fx.Finish() cmd := placementgroup.DeleteCmd.CobraCommand( context.Background(), fx.Client, fx.TokenEnsurer, fx.ActionWaiter) fx.ExpectEnsureToken() placementGroup := hcloud.PlacementGroup{ ID: 897, Name: "my Placement Group", Created: time.Now(), Labels: map[string]string{"key": "value"}, Servers: []int64{4711, 4712}, Type: hcloud.PlacementGroupTypeSpread, } fx.Client.PlacementGroupClient.EXPECT(). Get(gomock.Any(), placementGroup.Name). Return(&placementGroup, nil, nil) fx.Client.PlacementGroupClient.EXPECT(). Delete(gomock.Any(), &placementGroup) _, err := fx.Run(cmd, []string{placementGroup.Name}) assert.NoError(t, err) } cli-1.39.0/internal/cmd/placementgroup/describe.go000066400000000000000000000032131451614444200220720ustar00rootroot00000000000000package placementgroup import ( "context" "fmt" "github.com/dustin/go-humanize" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var DescribeCmd = base.DescribeCmd{ ResourceNameSingular: "placement group", ShortDescription: "Describe a placement group", JSONKeyGetByID: "placement_group", JSONKeyGetByName: "placement_groups", NameSuggestions: func(c hcapi2.Client) func() []string { return c.PlacementGroup().Names }, Fetch: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) { return client.PlacementGroup().Get(ctx, idOrName) }, PrintText: func(_ context.Context, client hcapi2.Client, cmd *cobra.Command, resource interface{}) error { placementGroup := resource.(*hcloud.PlacementGroup) fmt.Printf("ID:\t\t%d\n", placementGroup.ID) fmt.Printf("Name:\t\t%s\n", placementGroup.Name) fmt.Printf("Created:\t%s (%s)\n", util.Datetime(placementGroup.Created), humanize.Time(placementGroup.Created)) fmt.Print("Labels:\n") if len(placementGroup.Labels) == 0 { fmt.Print(" No labels\n") } else { for key, value := range placementGroup.Labels { fmt.Printf(" %s: %s\n", key, value) } } fmt.Print("Servers:\n") for _, serverID := range placementGroup.Servers { fmt.Printf(" - Server ID:\t\t%d\n", serverID) fmt.Printf(" Server Name:\t%s\n", client.Server().ServerName(serverID)) } fmt.Printf("Type:\t\t%s\n", placementGroup.Type) return nil }, } cli-1.39.0/internal/cmd/placementgroup/describe_test.go000066400000000000000000000030451451614444200231340ustar00rootroot00000000000000package placementgroup_test import ( "context" "fmt" "testing" "time" "github.com/dustin/go-humanize" "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" "github.com/hetznercloud/cli/internal/cmd/placementgroup" "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/testutil" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) func TestDescribe(t *testing.T) { fx := testutil.NewFixture(t) defer fx.Finish() cmd := placementgroup.DescribeCmd.CobraCommand( context.Background(), fx.Client, fx.TokenEnsurer) fx.ExpectEnsureToken() placementGroup := hcloud.PlacementGroup{ ID: 897, Name: "my Placement Group", Created: time.Date(2021, 07, 23, 10, 0, 0, 0, time.UTC), Labels: map[string]string{"key": "value"}, Servers: []int64{4711, 4712}, Type: hcloud.PlacementGroupTypeSpread, } fx.Client.PlacementGroupClient.EXPECT(). Get(gomock.Any(), placementGroup.Name). Return(&placementGroup, nil, nil) fx.Client.ServerClient.EXPECT(). ServerName(int64(4711)). Return("server1") fx.Client.ServerClient.EXPECT(). ServerName(int64(4712)). Return("server2") out, err := fx.Run(cmd, []string{placementGroup.Name}) expOut := fmt.Sprintf(`ID: 897 Name: my Placement Group Created: %s (%s) Labels: key: value Servers: - Server ID: 4711 Server Name: server1 - Server ID: 4712 Server Name: server2 Type: spread `, util.Datetime(placementGroup.Created), humanize.Time(placementGroup.Created), ) assert.NoError(t, err) assert.Equal(t, expOut, out) } cli-1.39.0/internal/cmd/placementgroup/labels.go000066400000000000000000000024141451614444200215560ustar00rootroot00000000000000package placementgroup import ( "context" "fmt" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var LabelCmds = base.LabelCmds{ ResourceNameSingular: "placement group", ShortDescriptionAdd: "Add a label to a placement group", ShortDescriptionRemove: "Remove a label from a placement group", NameSuggestions: func(c hcapi2.Client) func() []string { return c.PlacementGroup().Names }, LabelKeySuggestions: func(c hcapi2.Client) func(idOrName string) []string { return c.PlacementGroup().LabelKeys }, FetchLabels: func(ctx context.Context, client hcapi2.Client, idOrName string) (map[string]string, int64, error) { placementGroup, _, err := client.PlacementGroup().Get(ctx, idOrName) if err != nil { return nil, 0, err } if placementGroup == nil { return nil, 0, fmt.Errorf("placement group not found: %s", idOrName) } return placementGroup.Labels, placementGroup.ID, nil }, SetLabels: func(ctx context.Context, client hcapi2.Client, id int64, labels map[string]string) error { opts := hcloud.PlacementGroupUpdateOpts{ Labels: labels, } _, _, err := client.PlacementGroup().Update(ctx, &hcloud.PlacementGroup{ID: id}, opts) return err }, } cli-1.39.0/internal/cmd/placementgroup/labels_test.go000066400000000000000000000041221451614444200226130ustar00rootroot00000000000000package placementgroup_test import ( "context" "testing" "time" "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" "github.com/hetznercloud/cli/internal/cmd/placementgroup" "github.com/hetznercloud/cli/internal/testutil" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) func TestAddLabel(t *testing.T) { fx := testutil.NewFixture(t) defer fx.Finish() cmd := placementgroup.LabelCmds.AddCobraCommand( context.Background(), fx.Client, fx.TokenEnsurer) fx.ExpectEnsureToken() placementGroup := hcloud.PlacementGroup{ ID: 897, Name: "my Placement Group", Created: time.Now(), Labels: map[string]string{"key": "value"}, Servers: []int64{4711, 4712}, Type: hcloud.PlacementGroupTypeSpread, } opts := hcloud.PlacementGroupUpdateOpts{ Labels: map[string]string{"key": "value", "foo": "bar"}, } fx.Client.PlacementGroupClient.EXPECT(). Get(gomock.Any(), placementGroup.Name). Return(&placementGroup, nil, nil) fx.Client.PlacementGroupClient.EXPECT(). Update(gomock.Any(), &hcloud.PlacementGroup{ID: placementGroup.ID}, opts). Return(&placementGroup, nil, nil) _, err := fx.Run(cmd, []string{placementGroup.Name, "foo=bar"}) assert.NoError(t, err) } func TestRemoveLabel(t *testing.T) { fx := testutil.NewFixture(t) defer fx.Finish() cmd := placementgroup.LabelCmds.RemoveCobraCommand( context.Background(), fx.Client, fx.TokenEnsurer) fx.ExpectEnsureToken() placementGroup := hcloud.PlacementGroup{ ID: 897, Name: "my Placement Group", Created: time.Now(), Labels: map[string]string{"key": "value"}, Servers: []int64{4711, 4712}, Type: hcloud.PlacementGroupTypeSpread, } opts := hcloud.PlacementGroupUpdateOpts{ Labels: map[string]string{}, } fx.Client.PlacementGroupClient.EXPECT(). Get(gomock.Any(), placementGroup.Name). Return(&placementGroup, nil, nil) fx.Client.PlacementGroupClient.EXPECT(). Update(gomock.Any(), &hcloud.PlacementGroup{ID: placementGroup.ID}, opts). Return(&placementGroup, nil, nil) _, err := fx.Run(cmd, []string{placementGroup.Name, "key"}) assert.NoError(t, err) } cli-1.39.0/internal/cmd/placementgroup/list.go000066400000000000000000000045761451614444200213020ustar00rootroot00000000000000package placementgroup import ( "context" "fmt" "time" "github.com/spf13/pflag" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/output" "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" "github.com/hetznercloud/hcloud-go/v2/hcloud/schema" ) var ListCmd = base.ListCmd{ ResourceNamePlural: "Placement Groups", JSONKeyGetByName: "placement_groups", DefaultColumns: []string{"id", "name", "servers", "type", "age"}, Fetch: func(ctx context.Context, client hcapi2.Client, _ *pflag.FlagSet, listOpts hcloud.ListOpts, sorts []string) ([]interface{}, error) { opts := hcloud.PlacementGroupListOpts{ListOpts: listOpts} if len(sorts) > 0 { opts.Sort = sorts } placementGroups, err := client.PlacementGroup().AllWithOpts(ctx, opts) var resources []interface{} for _, n := range placementGroups { resources = append(resources, n) } return resources, err }, OutputTable: func(client hcapi2.Client) *output.Table { return output.NewTable(). AddAllowedFields(hcloud.PlacementGroup{}). AddFieldFn("servers", output.FieldFn(func(obj interface{}) string { placementGroup := obj.(*hcloud.PlacementGroup) count := len(placementGroup.Servers) if count == 1 { return fmt.Sprintf("%d server", count) } return fmt.Sprintf("%d servers", count) })). AddFieldFn("created", output.FieldFn(func(obj interface{}) string { placementGroup := obj.(*hcloud.PlacementGroup) return util.Datetime(placementGroup.Created) })). AddFieldFn("age", output.FieldFn(func(obj interface{}) string { placementGroup := obj.(*hcloud.PlacementGroup) return util.Age(placementGroup.Created, time.Now()) })) }, JSONSchema: func(resources []interface{}) interface{} { placementGroupSchemas := make([]schema.PlacementGroup, 0, len(resources)) for _, resource := range resources { placementGroup := resource.(*hcloud.PlacementGroup) placementGroupSchema := schema.PlacementGroup{ ID: placementGroup.ID, Name: placementGroup.Name, Labels: placementGroup.Labels, Created: placementGroup.Created, Servers: placementGroup.Servers, Type: string(placementGroup.Type), } placementGroupSchemas = append(placementGroupSchemas, placementGroupSchema) } return placementGroupSchemas }, } cli-1.39.0/internal/cmd/placementgroup/list_test.go000066400000000000000000000023651451614444200223330ustar00rootroot00000000000000package placementgroup_test import ( "context" "testing" "time" "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" "github.com/hetznercloud/cli/internal/cmd/placementgroup" "github.com/hetznercloud/cli/internal/testutil" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) func TestList(t *testing.T) { fx := testutil.NewFixture(t) defer fx.Finish() cmd := placementgroup.ListCmd.CobraCommand( context.Background(), fx.Client, fx.TokenEnsurer) fx.ExpectEnsureToken() fx.Client.PlacementGroupClient.EXPECT(). AllWithOpts( gomock.Any(), hcloud.PlacementGroupListOpts{ ListOpts: hcloud.ListOpts{ PerPage: 50, LabelSelector: "foo=bar", }, Sort: []string{"id:asc"}, }, ). Return([]*hcloud.PlacementGroup{ { ID: 897, Name: "my Placement Group", Labels: map[string]string{"key": "value"}, Servers: []int64{4711, 4712}, Type: hcloud.PlacementGroupTypeSpread, Created: time.Now().Add(-10 * time.Second), }, }, nil) out, err := fx.Run(cmd, []string{"--selector", "foo=bar"}) expOut := `ID NAME SERVERS TYPE AGE 897 my Placement Group 2 servers spread 10s ` assert.NoError(t, err) assert.Equal(t, expOut, out) } cli-1.39.0/internal/cmd/placementgroup/placementgroup.go000066400000000000000000000015461451614444200233460ustar00rootroot00000000000000package placementgroup import ( "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" ) func NewCommand(cli *state.State, client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "placement-group", Short: "Manage Placement Groups", Args: cobra.NoArgs, TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.AddCommand( CreateCmd.CobraCommand(cli.Context, client, cli, cli), ListCmd.CobraCommand(cli.Context, client, cli), DescribeCmd.CobraCommand(cli.Context, client, cli), UpdateCmd.CobraCommand(cli.Context, client, cli), DeleteCmd.CobraCommand(cli.Context, client, cli, cli), LabelCmds.AddCobraCommand(cli.Context, client, cli), LabelCmds.RemoveCobraCommand(cli.Context, client, cli), ) return cmd } cli-1.39.0/internal/cmd/placementgroup/update.go000066400000000000000000000022141451614444200215740ustar00rootroot00000000000000package placementgroup import ( "context" "github.com/spf13/cobra" "github.com/spf13/pflag" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var UpdateCmd = base.UpdateCmd{ ResourceNameSingular: "placement group", ShortDescription: "Update a placement group", NameSuggestions: func(c hcapi2.Client) func() []string { return c.PlacementGroup().Names }, Fetch: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) { return client.PlacementGroup().Get(ctx, idOrName) }, DefineFlags: func(cmd *cobra.Command) { cmd.Flags().String("name", "", "Placement group name") }, Update: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, resource interface{}, flags map[string]pflag.Value) error { placementGroup := resource.(*hcloud.PlacementGroup) updOpts := hcloud.PlacementGroupUpdateOpts{ Name: flags["name"].String(), } _, _, err := client.PlacementGroup().Update(ctx, placementGroup, updOpts) if err != nil { return err } return nil }, } cli-1.39.0/internal/cmd/placementgroup/update_test.go000066400000000000000000000022371451614444200226400ustar00rootroot00000000000000package placementgroup_test import ( "context" "testing" "time" "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" "github.com/hetznercloud/cli/internal/cmd/placementgroup" "github.com/hetznercloud/cli/internal/testutil" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) func TestUpdateName(t *testing.T) { fx := testutil.NewFixture(t) defer fx.Finish() cmd := placementgroup.UpdateCmd.CobraCommand( context.Background(), fx.Client, fx.TokenEnsurer) fx.ExpectEnsureToken() placementGroup := hcloud.PlacementGroup{ ID: 897, Name: "my Placement Group", Created: time.Now(), Labels: map[string]string{"key": "value"}, Servers: []int64{4711, 4712}, Type: hcloud.PlacementGroupTypeSpread, } opts := hcloud.PlacementGroupUpdateOpts{ Name: "new placement group name", } fx.Client.PlacementGroupClient.EXPECT(). Get(gomock.Any(), placementGroup.Name). Return(&placementGroup, nil, nil) fx.Client.PlacementGroupClient.EXPECT(). Update(gomock.Any(), &placementGroup, opts). Return(&placementGroup, nil, nil) _, err := fx.Run(cmd, []string{placementGroup.Name, "--name", opts.Name}) assert.NoError(t, err) } cli-1.39.0/internal/cmd/primaryip/000077500000000000000000000000001451614444200167535ustar00rootroot00000000000000cli-1.39.0/internal/cmd/primaryip/assign.go000066400000000000000000000036201451614444200205670ustar00rootroot00000000000000package primaryip import ( "context" "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var AssignCmd = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "assign [FLAGS] PRIMARYIP", Short: "Assign a Primary IP to an assignee (usually a server)", Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs( cmpl.SuggestCandidatesF(client.PrimaryIP().Names), ), TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.Flags().String("server", "", "Name or ID of the server") cmd.RegisterFlagCompletionFunc("server", cmpl.SuggestCandidatesF(client.Server().Names)) cmd.MarkFlagRequired("server") return cmd }, Run: func(ctx context.Context, client hcapi2.Client, actionWaiter state.ActionWaiter, cmd *cobra.Command, args []string) error { idOrName := args[0] primaryIP, _, err := client.PrimaryIP().Get(ctx, idOrName) if err != nil { return err } if primaryIP == nil { return fmt.Errorf("Primary IP not found: %v", idOrName) } serverIDOrName, _ := cmd.Flags().GetString("server") server, _, err := client.Server().Get(ctx, serverIDOrName) if err != nil { return err } if server == nil { return fmt.Errorf("server not found: %s", serverIDOrName) } opts := hcloud.PrimaryIPAssignOpts{ ID: primaryIP.ID, AssigneeType: "server", AssigneeID: server.ID, } action, _, err := client.PrimaryIP().Assign(ctx, opts) if err != nil { return err } if err := actionWaiter.ActionProgress(ctx, action); err != nil { return err } fmt.Printf("Primary IP %d assigned to %s %d\n", opts.ID, opts.AssigneeType, opts.AssigneeID) return nil }, } cli-1.39.0/internal/cmd/primaryip/assign_test.go000066400000000000000000000024041451614444200216250ustar00rootroot00000000000000package primaryip import ( "context" "fmt" "testing" "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" "github.com/hetznercloud/cli/internal/testutil" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) func TestAssign(t *testing.T) { fx := testutil.NewFixture(t) defer fx.Finish() cmd := AssignCmd.CobraCommand(context.Background(), fx.Client, fx.TokenEnsurer, fx.ActionWaiter) action := &hcloud.Action{ID: 1} fx.ExpectEnsureToken() var ( server = hcloud.Server{ ID: 15, Name: "my server", } ) fx.Client.ServerClient.EXPECT(). Get(gomock.Any(), fmt.Sprintf("%d", server.ID)). Return(&server, nil, nil) fx.Client.PrimaryIPClient.EXPECT(). Get( gomock.Any(), "13", ). Return( &hcloud.PrimaryIP{ID: 13}, &hcloud.Response{}, nil, ) fx.Client.PrimaryIPClient.EXPECT(). Assign( gomock.Any(), hcloud.PrimaryIPAssignOpts{ ID: 13, AssigneeType: "server", AssigneeID: 15, }, ). Return( action, &hcloud.Response{}, nil, ) fx.ActionWaiter.EXPECT().ActionProgress(gomock.Any(), action).Return(nil) out, err := fx.Run(cmd, []string{"13", "--server", "15"}) expOut := "Primary IP 13 assigned to server 15\n" assert.NoError(t, err) assert.Equal(t, expOut, out) } cli-1.39.0/internal/cmd/primaryip/changedns.go000066400000000000000000000035101451614444200212330ustar00rootroot00000000000000package primaryip import ( "context" "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var ChangeDNSCmd = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "set-rdns [FLAGS] PRIMARYIP", Short: "Change the reverse DNS from a Primary IP", Args: cobra.ExactArgs(1), TraverseChildren: true, ValidArgsFunction: cmpl.SuggestArgs( cmpl.SuggestCandidatesF(client.PrimaryIP().Names), ), DisableFlagsInUseLine: true, } cmd.Flags().String("hostname", "", "Hostname to set as a reverse DNS PTR entry (required)") cmd.MarkFlagRequired("hostname") cmd.Flags().String("ip", "", "IP address for which the reverse DNS entry should be set (required)") cmd.MarkFlagRequired("ip") return cmd }, Run: func(ctx context.Context, client hcapi2.Client, actionWaiter state.ActionWaiter, cmd *cobra.Command, args []string) error { idOrName := args[0] primaryIP, _, err := client.PrimaryIP().Get(ctx, idOrName) if err != nil { return err } if primaryIP == nil { return fmt.Errorf("Primary IP not found: %v", idOrName) } DNSPtr, _ := cmd.Flags().GetString("hostname") ip, _ := cmd.Flags().GetString("ip") opts := hcloud.PrimaryIPChangeDNSPtrOpts{ ID: primaryIP.ID, DNSPtr: DNSPtr, IP: ip, } action, _, err := client.PrimaryIP().ChangeDNSPtr(ctx, opts) if err != nil { return err } if err := actionWaiter.ActionProgress(ctx, action); err != nil { return err } fmt.Printf("Primary IP %d DNS pointer: %s associated to %s\n", opts.ID, opts.DNSPtr, opts.IP) return nil }, } cli-1.39.0/internal/cmd/primaryip/changedns_test.go000066400000000000000000000022411451614444200222720ustar00rootroot00000000000000package primaryip import ( "context" "testing" "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" "github.com/hetznercloud/cli/internal/testutil" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) func TestChangeDNS(t *testing.T) { fx := testutil.NewFixture(t) defer fx.Finish() cmd := ChangeDNSCmd.CobraCommand(context.Background(), fx.Client, fx.TokenEnsurer, fx.ActionWaiter) action := &hcloud.Action{ID: 1} fx.ExpectEnsureToken() fx.Client.PrimaryIPClient.EXPECT(). Get( gomock.Any(), "13", ). Return( &hcloud.PrimaryIP{ID: 13}, &hcloud.Response{}, nil, ) fx.Client.PrimaryIPClient.EXPECT(). ChangeDNSPtr( gomock.Any(), hcloud.PrimaryIPChangeDNSPtrOpts{ ID: 13, DNSPtr: "server.your-host.de", IP: "192.168.0.1", }, ). Return( action, &hcloud.Response{}, nil, ) fx.ActionWaiter.EXPECT().ActionProgress(gomock.Any(), action).Return(nil) out, err := fx.Run(cmd, []string{"--hostname=server.your-host.de", "--ip=192.168.0.1", "13"}) expOut := "Primary IP 13 DNS pointer: server.your-host.de associated to 192.168.0.1\n" assert.NoError(t, err) assert.Equal(t, expOut, out) } cli-1.39.0/internal/cmd/primaryip/create.go000066400000000000000000000047751451614444200205620ustar00rootroot00000000000000package primaryip import ( "context" "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var CreateCmd = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "create FLAGS", Short: "Create a Primary IP", Args: cobra.NoArgs, TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.Flags().String("type", "", "Type (ipv4 or ipv6) (required)") cmd.RegisterFlagCompletionFunc("type", cmpl.SuggestCandidates("ipv4", "ipv6")) cmd.MarkFlagRequired("type") cmd.Flags().String("name", "", "Name (required)") cmd.MarkFlagRequired("name") cmd.Flags().Int64("assignee-id", 0, "Assignee (usually a server) to assign Primary IP to") cmd.Flags().String("datacenter", "", "Datacenter (ID or name)") cmd.RegisterFlagCompletionFunc("datacenter", cmpl.SuggestCandidatesF(client.Datacenter().Names)) cmd.Flags().StringToString("label", nil, "User-defined labels ('key=value') (can be specified multiple times)") cmd.Flags().StringSlice("enable-protection", []string{}, "Enable protection (delete) (default: none)") cmd.RegisterFlagCompletionFunc("enable-protection", cmpl.SuggestCandidates("delete")) return cmd }, Run: func(ctx context.Context, client hcapi2.Client, actionWaiter state.ActionWaiter, cmd *cobra.Command, args []string) error { typ, _ := cmd.Flags().GetString("type") name, _ := cmd.Flags().GetString("name") assigneeID, _ := cmd.Flags().GetInt64("assignee-id") datacenter, _ := cmd.Flags().GetString("datacenter") protection, _ := cmd.Flags().GetStringSlice("enable-protection") protectionOpts, err := getChangeProtectionOpts(true, protection) if err != nil { return err } createOpts := hcloud.PrimaryIPCreateOpts{ Type: hcloud.PrimaryIPType(typ), Name: name, AssigneeType: "server", Datacenter: datacenter, } if assigneeID != 0 { createOpts.AssigneeID = &assigneeID } result, _, err := client.PrimaryIP().Create(ctx, createOpts) if err != nil { return err } fmt.Printf("Primary IP %d created\n", result.PrimaryIP.ID) if len(protection) > 0 { if err := changeProtection(ctx, client, actionWaiter, result.PrimaryIP, true, protectionOpts); err != nil { return err } } return nil }, } cli-1.39.0/internal/cmd/primaryip/create_test.go000066400000000000000000000016751451614444200216150ustar00rootroot00000000000000package primaryip import ( "context" "testing" "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" "github.com/hetznercloud/cli/internal/testutil" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) func TestCreate(t *testing.T) { fx := testutil.NewFixture(t) defer fx.Finish() cmd := CreateCmd.CobraCommand(context.Background(), fx.Client, fx.TokenEnsurer, fx.ActionWaiter) fx.ExpectEnsureToken() fx.Client.PrimaryIPClient.EXPECT(). Create( gomock.Any(), hcloud.PrimaryIPCreateOpts{ Name: "my-ip", Type: "ipv4", Datacenter: "fsn1-dc14", AssigneeType: "server", }, ). Return( &hcloud.PrimaryIPCreateResult{ PrimaryIP: &hcloud.PrimaryIP{ID: 1}, }, &hcloud.Response{}, nil, ) out, err := fx.Run(cmd, []string{"--name=my-ip", "--type=ipv4", "--datacenter=fsn1-dc14"}) expOut := "Primary IP 1 created\n" assert.NoError(t, err) assert.Equal(t, expOut, out) } cli-1.39.0/internal/cmd/primaryip/delete.go000066400000000000000000000016451451614444200205520ustar00rootroot00000000000000package primaryip import ( "context" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var deleteCmd = base.DeleteCmd{ ResourceNameSingular: "Primary IP", ShortDescription: "Delete a Primary IP", NameSuggestions: func(c hcapi2.Client) func() []string { return c.PrimaryIP().Names }, Fetch: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) { return client.PrimaryIP().Get(ctx, idOrName) }, Delete: func(ctx context.Context, client hcapi2.Client, _ state.ActionWaiter, cmd *cobra.Command, resource interface{}) error { primaryIP := resource.(*hcloud.PrimaryIP) if _, err := client.PrimaryIP().Delete(ctx, primaryIP); err != nil { return err } return nil }, } cli-1.39.0/internal/cmd/primaryip/delete_test.go000066400000000000000000000015411451614444200216040ustar00rootroot00000000000000package primaryip import ( "context" "testing" "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" "github.com/hetznercloud/cli/internal/testutil" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) func TestDelete(t *testing.T) { fx := testutil.NewFixture(t) defer fx.Finish() cmd := deleteCmd.CobraCommand(context.Background(), fx.Client, fx.TokenEnsurer, fx.ActionWaiter) primaryip := &hcloud.PrimaryIP{ID: 13} fx.ExpectEnsureToken() fx.Client.PrimaryIPClient.EXPECT(). Get( gomock.Any(), "13", ). Return( primaryip, &hcloud.Response{}, nil, ) fx.Client.PrimaryIPClient.EXPECT(). Delete( gomock.Any(), primaryip, ). Return( &hcloud.Response{}, nil, ) out, err := fx.Run(cmd, []string{"13"}) expOut := "Primary IP 13 deleted\n" assert.NoError(t, err) assert.Equal(t, expOut, out) } cli-1.39.0/internal/cmd/primaryip/describe.go000066400000000000000000000053561451614444200210730ustar00rootroot00000000000000package primaryip import ( "context" "fmt" "github.com/dustin/go-humanize" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var describeCmd = base.DescribeCmd{ ResourceNameSingular: "Primary IP", ShortDescription: "Describe an Primary IP", JSONKeyGetByID: "primary_ip", JSONKeyGetByName: "primary_ips", NameSuggestions: func(c hcapi2.Client) func() []string { return c.PrimaryIP().Names }, Fetch: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) { return client.PrimaryIP().Get(ctx, idOrName) }, PrintText: func(_ context.Context, client hcapi2.Client, cmd *cobra.Command, resource interface{}) error { primaryIP := resource.(*hcloud.PrimaryIP) fmt.Printf("ID:\t\t%d\n", primaryIP.ID) fmt.Printf("Name:\t\t%s\n", primaryIP.Name) fmt.Printf("Created:\t%s (%s)\n", util.Datetime(primaryIP.Created), humanize.Time(primaryIP.Created)) fmt.Printf("Type:\t\t%s\n", primaryIP.Type) fmt.Printf("IP:\t\t%s\n", primaryIP.IP.String()) fmt.Printf("Blocked:\t%s\n", util.YesNo(primaryIP.Blocked)) fmt.Printf("Auto delete:\t%s\n", util.YesNo(primaryIP.AutoDelete)) if primaryIP.AssigneeID != 0 { fmt.Printf("Assignee:\n") fmt.Printf(" ID:\t%d\n", primaryIP.AssigneeID) fmt.Printf(" Type:\t%s\n", primaryIP.AssigneeType) } else { fmt.Print("Assignee:\n Not assigned\n") } fmt.Print("DNS:\n") if len(primaryIP.DNSPtr) == 0 { fmt.Print(" No reverse DNS entries\n") } else { for ip, dns := range primaryIP.DNSPtr { fmt.Printf(" %s: %s\n", ip, dns) } } fmt.Printf("Protection:\n") fmt.Printf(" Delete:\t%s\n", util.YesNo(primaryIP.Protection.Delete)) fmt.Print("Labels:\n") if len(primaryIP.Labels) == 0 { fmt.Print(" No labels\n") } else { for key, value := range primaryIP.Labels { fmt.Printf(" %s: %s\n", key, value) } } fmt.Printf("Datacenter:\n") fmt.Printf(" ID:\t\t%d\n", primaryIP.Datacenter.ID) fmt.Printf(" Name:\t\t%s\n", primaryIP.Datacenter.Name) fmt.Printf(" Description:\t%s\n", primaryIP.Datacenter.Description) fmt.Printf(" Location:\n") fmt.Printf(" Name:\t\t%s\n", primaryIP.Datacenter.Location.Name) fmt.Printf(" Description:\t%s\n", primaryIP.Datacenter.Location.Description) fmt.Printf(" Country:\t\t%s\n", primaryIP.Datacenter.Location.Country) fmt.Printf(" City:\t\t%s\n", primaryIP.Datacenter.Location.City) fmt.Printf(" Latitude:\t\t%f\n", primaryIP.Datacenter.Location.Latitude) fmt.Printf(" Longitude:\t\t%f\n", primaryIP.Datacenter.Location.Longitude) return nil }, } cli-1.39.0/internal/cmd/primaryip/describe_test.go000066400000000000000000000030151451614444200221200ustar00rootroot00000000000000package primaryip import ( "context" "fmt" "net" "testing" "time" "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/testutil" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) func TestDescribe(t *testing.T) { fx := testutil.NewFixture(t) defer fx.Finish() cmd := describeCmd.CobraCommand(context.Background(), fx.Client, fx.TokenEnsurer) created := time.Date(1, time.Month(1), 1, 0, 0, 0, 0, time.UTC) ip := net.ParseIP("192.168.0.1") fx.ExpectEnsureToken() fx.Client.PrimaryIPClient.EXPECT(). Get( gomock.Any(), "10", ). Return(&hcloud.PrimaryIP{ ID: 10, Name: "test-net", Type: "ipv4", Created: created, IP: ip, Blocked: true, AutoDelete: false, AssigneeType: "server", Datacenter: &hcloud.Datacenter{ID: 0, Location: &hcloud.Location{ID: 0}}, }, &hcloud.Response{}, nil) out, err := fx.Run(cmd, []string{"10"}) expOut := `ID: 10 Name: test-net Created: %s (a long while ago) Type: ipv4 IP: 192.168.0.1 Blocked: yes Auto delete: no Assignee: Not assigned DNS: No reverse DNS entries Protection: Delete: no Labels: No labels Datacenter: ID: 0 Name: Description: Location: Name: Description: Country: City: Latitude: 0.000000 Longitude: 0.000000 ` expOutFmt := fmt.Sprintf(expOut, util.Datetime(created)) assert.NoError(t, err) assert.Equal(t, expOutFmt, out) } cli-1.39.0/internal/cmd/primaryip/disable_protecion_test.go000066400000000000000000000021121451614444200240220ustar00rootroot00000000000000package primaryip import ( "context" "testing" "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" "github.com/hetznercloud/cli/internal/testutil" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) func TestEnable(t *testing.T) { fx := testutil.NewFixture(t) defer fx.Finish() cmd := DisableProtectionCmd.CobraCommand(context.Background(), fx.Client, fx.TokenEnsurer, fx.ActionWaiter) action := &hcloud.Action{ID: 1} primaryip := &hcloud.PrimaryIP{ID: 13} fx.ExpectEnsureToken() fx.Client.PrimaryIPClient.EXPECT(). Get( gomock.Any(), "13", ). Return( primaryip, &hcloud.Response{}, nil, ) fx.Client.PrimaryIPClient.EXPECT(). ChangeProtection( gomock.Any(), hcloud.PrimaryIPChangeProtectionOpts{ ID: 13, Delete: false, }, ). Return( action, &hcloud.Response{}, nil, ) fx.ActionWaiter.EXPECT().ActionProgress(gomock.Any(), action).Return(nil) out, err := fx.Run(cmd, []string{"13"}) expOut := "Resource protection disabled for primary IP 13\n" assert.NoError(t, err) assert.Equal(t, expOut, out) } cli-1.39.0/internal/cmd/primaryip/disable_protection.go000066400000000000000000000027121451614444200231550ustar00rootroot00000000000000package primaryip import ( "context" "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" ) var DisableProtectionCmd = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "disable-protection PRIMARYIP [PROTECTIONLEVEL...]", Short: "Disable Protection for a Primary IP", Args: cobra.MinimumNArgs(1), ValidArgsFunction: cmpl.SuggestArgs( cmpl.SuggestCandidatesF(client.PrimaryIP().Names), cmpl.SuggestCandidates("delete"), ), TraverseChildren: true, DisableFlagsInUseLine: true, } return cmd }, Run: func(ctx context.Context, client hcapi2.Client, actionWaiter state.ActionWaiter, cmd *cobra.Command, args []string) error { idOrName := args[0] primaryIP, _, err := client.PrimaryIP().Get(ctx, idOrName) if err != nil { return err } if primaryIP == nil { return fmt.Errorf("Primary IP not found: %v", idOrName) } // This command used to have the "delete" protection level as the default. // To avoid a breaking change, we now add it if no level is defined. if len(args) < 2 { args = append(args, "delete") } opts, err := getChangeProtectionOpts(false, args[1:]) if err != nil { return err } return changeProtection(ctx, client, actionWaiter, primaryIP, false, opts) }, } cli-1.39.0/internal/cmd/primaryip/enable_protecion_test.go000066400000000000000000000021211451614444200236450ustar00rootroot00000000000000package primaryip import ( "context" "testing" "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" "github.com/hetznercloud/cli/internal/testutil" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) func TestEnableProtection(t *testing.T) { fx := testutil.NewFixture(t) defer fx.Finish() cmd := EnableProtectionCmd.CobraCommand(context.Background(), fx.Client, fx.TokenEnsurer, fx.ActionWaiter) action := &hcloud.Action{ID: 1} primaryip := &hcloud.PrimaryIP{ID: 13} fx.ExpectEnsureToken() fx.Client.PrimaryIPClient.EXPECT(). Get( gomock.Any(), "13", ). Return( primaryip, &hcloud.Response{}, nil, ) fx.Client.PrimaryIPClient.EXPECT(). ChangeProtection( gomock.Any(), hcloud.PrimaryIPChangeProtectionOpts{ ID: 13, Delete: true, }, ). Return( action, &hcloud.Response{}, nil, ) fx.ActionWaiter.EXPECT().ActionProgress(gomock.Any(), action).Return(nil) out, err := fx.Run(cmd, []string{"13"}) expOut := "Resource protection enabled for primary IP 13\n" assert.NoError(t, err) assert.Equal(t, expOut, out) } cli-1.39.0/internal/cmd/primaryip/enable_protection.go000066400000000000000000000050221451614444200227750ustar00rootroot00000000000000package primaryip import ( "context" "fmt" "strings" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) func getChangeProtectionOpts(enable bool, flags []string) (hcloud.PrimaryIPChangeProtectionOpts, error) { opts := hcloud.PrimaryIPChangeProtectionOpts{} var unknown []string for _, arg := range flags { switch strings.ToLower(arg) { case "delete": opts.Delete = enable default: unknown = append(unknown, arg) } } if len(unknown) > 0 { return opts, fmt.Errorf("unknown protection level: %s", strings.Join(unknown, ", ")) } return opts, nil } func changeProtection(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, primaryIp *hcloud.PrimaryIP, enable bool, opts hcloud.PrimaryIPChangeProtectionOpts) error { opts.ID = primaryIp.ID action, _, err := client.PrimaryIP().ChangeProtection(ctx, opts) if err != nil { return err } if err := waiter.ActionProgress(ctx, action); err != nil { return err } if enable { fmt.Printf("Resource protection enabled for primary IP %d\n", opts.ID) } else { fmt.Printf("Resource protection disabled for primary IP %d\n", opts.ID) } return nil } var EnableProtectionCmd = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "enable-protection PRIMARYIP [PROTECTIONLEVEL...]", Short: "Enable Protection for a Primary IP", Args: cobra.MinimumNArgs(1), ValidArgsFunction: cmpl.SuggestArgs( cmpl.SuggestCandidatesF(client.PrimaryIP().Names), cmpl.SuggestCandidates("delete"), ), TraverseChildren: true, DisableFlagsInUseLine: true, } return cmd }, Run: func(ctx context.Context, client hcapi2.Client, actionWaiter state.ActionWaiter, cmd *cobra.Command, args []string) error { idOrName := args[0] primaryIP, _, err := client.PrimaryIP().Get(ctx, idOrName) if err != nil { return err } if primaryIP == nil { return fmt.Errorf("Primary IP not found: %v", idOrName) } // This command used to have the "delete" protection level as the default. // To avoid a breaking change, we now add it if no level is defined. if len(args) < 2 { args = append(args, "delete") } opts, err := getChangeProtectionOpts(true, args[1:]) if err != nil { return err } return changeProtection(ctx, client, actionWaiter, primaryIP, true, opts) }, } cli-1.39.0/internal/cmd/primaryip/labels.go000066400000000000000000000023011451614444200205400ustar00rootroot00000000000000package primaryip import ( "context" "fmt" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var labelCmds = base.LabelCmds{ ResourceNameSingular: "primary-ip", ShortDescriptionAdd: "Add a label to a Primary IP", ShortDescriptionRemove: "Remove a label from a Primary IP", NameSuggestions: func(c hcapi2.Client) func() []string { return c.PrimaryIP().Names }, LabelKeySuggestions: func(c hcapi2.Client) func(idOrName string) []string { return c.PrimaryIP().LabelKeys }, FetchLabels: func(ctx context.Context, client hcapi2.Client, idOrName string) (map[string]string, int64, error) { primaryIP, _, err := client.PrimaryIP().Get(ctx, idOrName) if err != nil { return nil, 0, err } if primaryIP == nil { return nil, 0, fmt.Errorf("primaryIP not found: %s", idOrName) } return primaryIP.Labels, primaryIP.ID, nil }, SetLabels: func(ctx context.Context, client hcapi2.Client, id int64, labels map[string]string) error { opts := hcloud.PrimaryIPUpdateOpts{ Labels: &labels, } _, _, err := client.PrimaryIP().Update(ctx, &hcloud.PrimaryIP{ID: id}, opts) return err }, } cli-1.39.0/internal/cmd/primaryip/list.go000066400000000000000000000074431451614444200202650ustar00rootroot00000000000000package primaryip import ( "context" "fmt" "strings" "time" "github.com/spf13/pflag" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/output" "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" "github.com/hetznercloud/hcloud-go/v2/hcloud/schema" ) var ListCmd = base.ListCmd{ ResourceNamePlural: "Primary IPs", JSONKeyGetByName: "primary_ips", DefaultColumns: []string{"id", "type", "name", "ip", "assignee", "dns", "auto_delete", "age"}, Fetch: func(ctx context.Context, client hcapi2.Client, _ *pflag.FlagSet, listOpts hcloud.ListOpts, sorts []string) ([]interface{}, error) { opts := hcloud.PrimaryIPListOpts{ListOpts: listOpts} if len(sorts) > 0 { opts.Sort = sorts } primaryips, err := client.PrimaryIP().AllWithOpts(ctx, opts) var resources []interface{} for _, n := range primaryips { resources = append(resources, n) } return resources, err }, OutputTable: func(client hcapi2.Client) *output.Table { return output.NewTable(). AddAllowedFields(hcloud.PrimaryIP{}). AddFieldFn("dns", output.FieldFn(func(obj interface{}) string { primaryIP := obj.(*hcloud.PrimaryIP) var dns string if len(primaryIP.DNSPtr) == 1 { for _, v := range primaryIP.DNSPtr { dns = v } } if len(primaryIP.DNSPtr) > 1 { dns = fmt.Sprintf("%d entries", len(primaryIP.DNSPtr)) } return util.NA(dns) })). AddFieldFn("assignee", output.FieldFn(func(obj interface{}) string { primaryIP := obj.(*hcloud.PrimaryIP) assignee := "" if primaryIP.AssigneeID != 0 { switch primaryIP.AssigneeType { case "server": assignee = fmt.Sprintf("Server %s", client.Server().ServerName(primaryIP.AssigneeID)) } } return util.NA(assignee) })). AddFieldFn("protection", output.FieldFn(func(obj interface{}) string { primaryIP := obj.(*hcloud.PrimaryIP) var protection []string if primaryIP.Protection.Delete { protection = append(protection, "delete") } return strings.Join(protection, ", ") })). AddFieldFn("auto_delete", output.FieldFn(func(obj interface{}) string { primaryIP := obj.(*hcloud.PrimaryIP) return util.YesNo(primaryIP.AutoDelete) })). AddFieldFn("labels", output.FieldFn(func(obj interface{}) string { primaryIP := obj.(*hcloud.PrimaryIP) return util.LabelsToString(primaryIP.Labels) })). AddFieldFn("created", output.FieldFn(func(obj interface{}) string { primaryIP := obj.(*hcloud.PrimaryIP) return util.Datetime(primaryIP.Created) })). AddFieldFn("age", output.FieldFn(func(obj interface{}) string { primaryIP := obj.(*hcloud.PrimaryIP) return util.Age(primaryIP.Created, time.Now()) })) }, JSONSchema: func(resources []interface{}) interface{} { primaryIPsSchema := make([]schema.PrimaryIP, 0, len(resources)) for _, resource := range resources { primaryIP := resource.(*hcloud.PrimaryIP) var dnsPtrs []hcloud.PrimaryIPDNSPTR for i, d := range primaryIP.DNSPtr { dnsPtrs = append(dnsPtrs, hcloud.PrimaryIPDNSPTR{ DNSPtr: d, IP: i, }) } var primaryIPSchema = schema.PrimaryIP{ ID: primaryIP.ID, Name: primaryIP.Name, IP: primaryIP.IP.String(), Type: string(primaryIP.Type), AssigneeID: primaryIP.AssigneeID, AssigneeType: primaryIP.AssigneeType, AutoDelete: primaryIP.AutoDelete, Created: primaryIP.Created, Datacenter: util.DatacenterToSchema(*primaryIP.Datacenter), Protection: schema.PrimaryIPProtection{ Delete: primaryIP.Protection.Delete, }, Labels: primaryIP.Labels, } primaryIPsSchema = append(primaryIPsSchema, primaryIPSchema) } return primaryIPsSchema }, } cli-1.39.0/internal/cmd/primaryip/list_test.go000066400000000000000000000022441451614444200213160ustar00rootroot00000000000000package primaryip import ( "context" "net" "testing" "time" "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" "github.com/hetznercloud/cli/internal/testutil" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) func TestList(t *testing.T) { fx := testutil.NewFixture(t) defer fx.Finish() cmd := ListCmd.CobraCommand(context.Background(), fx.Client, fx.TokenEnsurer) fx.ExpectEnsureToken() fx.Client.PrimaryIPClient.EXPECT(). AllWithOpts( gomock.Any(), hcloud.PrimaryIPListOpts{ ListOpts: hcloud.ListOpts{ PerPage: 50, LabelSelector: "foo=bar", }, Sort: []string{"id:asc"}, }, ). Return([]*hcloud.PrimaryIP{ { ID: 123, Name: "test-net", AutoDelete: true, Type: hcloud.PrimaryIPTypeIPv4, IP: net.ParseIP("127.0.0.1"), Created: time.Now().Add(-10 * time.Second), }, }, nil) out, err := fx.Run(cmd, []string{"--selector", "foo=bar"}) expOut := `ID TYPE NAME IP ASSIGNEE DNS AUTO DELETE AGE 123 ipv4 test-net 127.0.0.1 - - yes 10s ` assert.NoError(t, err) assert.Equal(t, expOut, out) } cli-1.39.0/internal/cmd/primaryip/primaryip.go000066400000000000000000000022161451614444200213170ustar00rootroot00000000000000package primaryip import ( "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" ) func NewCommand(cli *state.State, client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "primary-ip", Short: "Manage Primary IPs", Args: cobra.NoArgs, TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.AddCommand( ListCmd.CobraCommand(cli.Context, client, cli), describeCmd.CobraCommand(cli.Context, client, cli), CreateCmd.CobraCommand(cli.Context, client, cli, cli), updateCmd.CobraCommand(cli.Context, client, cli), deleteCmd.CobraCommand(cli.Context, client, cli, cli), AssignCmd.CobraCommand(cli.Context, client, cli, cli), UnAssignCmd.CobraCommand(cli.Context, client, cli, cli), ChangeDNSCmd.CobraCommand(cli.Context, client, cli, cli), EnableProtectionCmd.CobraCommand(cli.Context, client, cli, cli), DisableProtectionCmd.CobraCommand(cli.Context, client, cli, cli), labelCmds.AddCobraCommand(cli.Context, client, cli), labelCmds.RemoveCobraCommand(cli.Context, client, cli), ) return cmd } cli-1.39.0/internal/cmd/primaryip/unassign.go000066400000000000000000000024631451614444200211360ustar00rootroot00000000000000package primaryip import ( "context" "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" ) var UnAssignCmd = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "unassign [FLAGS] PRIMARYIP", Short: "Unassign a Primary IP from an assignee (usually a server)", Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs( cmpl.SuggestCandidatesF(client.PrimaryIP().Names), ), TraverseChildren: true, DisableFlagsInUseLine: true, } return cmd }, Run: func(ctx context.Context, client hcapi2.Client, actionWaiter state.ActionWaiter, cmd *cobra.Command, args []string) error { idOrName := args[0] primaryIP, _, err := client.PrimaryIP().Get(ctx, idOrName) if err != nil { return err } if primaryIP == nil { return fmt.Errorf("Primary IP not found: %v", idOrName) } action, _, err := client.PrimaryIP().Unassign(ctx, primaryIP.ID) if err != nil { return err } if err := actionWaiter.ActionProgress(ctx, action); err != nil { return err } fmt.Printf("Primary IP %d was unassigned successfully\n", primaryIP.ID) return nil }, } cli-1.39.0/internal/cmd/primaryip/unassign_test.go000066400000000000000000000017331451614444200221740ustar00rootroot00000000000000package primaryip import ( "context" "testing" "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" "github.com/hetznercloud/cli/internal/testutil" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) func TestUnAssign(t *testing.T) { fx := testutil.NewFixture(t) defer fx.Finish() cmd := UnAssignCmd.CobraCommand(context.Background(), fx.Client, fx.TokenEnsurer, fx.ActionWaiter) action := &hcloud.Action{ID: 1} fx.ExpectEnsureToken() fx.Client.PrimaryIPClient.EXPECT(). Get( gomock.Any(), "13", ). Return( &hcloud.PrimaryIP{ID: 13}, &hcloud.Response{}, nil, ) fx.Client.PrimaryIPClient.EXPECT(). Unassign( gomock.Any(), int64(13), ). Return( action, &hcloud.Response{}, nil, ) fx.ActionWaiter.EXPECT().ActionProgress(gomock.Any(), action).Return(nil) out, err := fx.Run(cmd, []string{"13"}) expOut := "Primary IP 13 was unassigned successfully\n" assert.NoError(t, err) assert.Equal(t, expOut, out) } cli-1.39.0/internal/cmd/primaryip/update.go000066400000000000000000000025331451614444200205670ustar00rootroot00000000000000package primaryip import ( "context" "github.com/spf13/cobra" "github.com/spf13/pflag" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var updateCmd = base.UpdateCmd{ ResourceNameSingular: "Primary IP", ShortDescription: "Update a Primary IP", NameSuggestions: func(c hcapi2.Client) func() []string { return c.PrimaryIP().Names }, Fetch: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) { return client.PrimaryIP().Get(ctx, idOrName) }, DefineFlags: func(cmd *cobra.Command) { cmd.Flags().String("name", "", "Primary IP name") cmd.Flags().Bool("auto-delete", false, "Delete this Primary IP when the resource it is assigned to is deleted") }, Update: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, resource interface{}, flags map[string]pflag.Value) error { primaryIP := resource.(*hcloud.PrimaryIP) updOpts := hcloud.PrimaryIPUpdateOpts{ Name: flags["name"].String(), } autoDelete, _ := cmd.Flags().GetBool("auto-delete") if primaryIP.AutoDelete != autoDelete { updOpts.AutoDelete = hcloud.Bool(autoDelete) } _, _, err := client.PrimaryIP().Update(ctx, primaryIP, updOpts) if err != nil { return err } return nil }, } cli-1.39.0/internal/cmd/primaryip/update_test.go000066400000000000000000000017101451614444200216220ustar00rootroot00000000000000package primaryip import ( "context" "testing" "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" "github.com/hetznercloud/cli/internal/testutil" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) func TestUpdate(t *testing.T) { fx := testutil.NewFixture(t) defer fx.Finish() cmd := updateCmd.CobraCommand(context.Background(), fx.Client, fx.TokenEnsurer) primaryip := &hcloud.PrimaryIP{ID: 13} fx.ExpectEnsureToken() fx.Client.PrimaryIPClient.EXPECT(). Get( gomock.Any(), "13", ). Return( primaryip, &hcloud.Response{}, nil, ) fx.Client.PrimaryIPClient.EXPECT(). Update( gomock.Any(), primaryip, hcloud.PrimaryIPUpdateOpts{ Name: "foobar", }, ). Return( &hcloud.PrimaryIP{ID: 13, Name: "foobar"}, &hcloud.Response{}, nil, ) out, err := fx.Run(cmd, []string{"13", "--name=foobar"}) expOut := "Primary IP 13 updated\n" assert.NoError(t, err) assert.Equal(t, expOut, out) } cli-1.39.0/internal/cmd/server/000077500000000000000000000000001451614444200162455ustar00rootroot00000000000000cli-1.39.0/internal/cmd/server/add_to_placement_group.go000066400000000000000000000035051451614444200232750ustar00rootroot00000000000000package server import ( "context" "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" ) var AddToPlacementGroupCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "add-to-placement-group [FLAGS] SERVER", Short: "Add a server to a placement group", Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.Server().Names)), } cmd.Flags().StringP("placement-group", "g", "", "Placement Group (ID or name) (required)") cmd.RegisterFlagCompletionFunc("placement-group", cmpl.SuggestCandidatesF(client.PlacementGroup().Names)) cmd.MarkFlagRequired(("placement-group")) return cmd }, Run: func(ctx context.Context, client hcapi2.Client, actionWaiter state.ActionWaiter, cmd *cobra.Command, args []string) error { idOrName := args[0] server, _, err := client.Server().Get(ctx, idOrName) if err != nil { return err } if server == nil { return fmt.Errorf("server not found %s", idOrName) } placementGroupIDOrName, _ := cmd.Flags().GetString("placement-group") placementGroup, _, err := client.PlacementGroup().Get(ctx, placementGroupIDOrName) if err != nil { return err } if placementGroup == nil { return fmt.Errorf("placement group not found %s", placementGroupIDOrName) } action, _, err := client.Server().AddToPlacementGroup(ctx, server, placementGroup) if err != nil { return err } if err := actionWaiter.ActionProgress(ctx, action); err != nil { return err } fmt.Printf("Server %d added to placement group %s\n", server.ID, placementGroupIDOrName) return nil }, } cli-1.39.0/internal/cmd/server/add_to_placement_group_test.go000066400000000000000000000023631451614444200243350ustar00rootroot00000000000000package server_test import ( "context" "testing" "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" "github.com/hetznercloud/cli/internal/cmd/server" "github.com/hetznercloud/cli/internal/testutil" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) func TestAddToPlacementGroup(t *testing.T) { fx := testutil.NewFixture(t) defer fx.Finish() cmd := server.AddToPlacementGroupCommand.CobraCommand( context.Background(), fx.Client, fx.TokenEnsurer, fx.ActionWaiter) fx.ExpectEnsureToken() var ( server = hcloud.Server{ ID: 42, Name: "my server", } placementGroup = hcloud.PlacementGroup{ ID: 897, Name: "my Placement Group", } ) fx.Client.ServerClient.EXPECT(). Get(gomock.Any(), server.Name). Return(&server, nil, nil) fx.Client.PlacementGroupClient.EXPECT(). Get(gomock.Any(), placementGroup.Name). Return(&placementGroup, nil, nil) fx.Client.ServerClient.EXPECT(). AddToPlacementGroup(gomock.Any(), &server, &placementGroup) fx.ActionWaiter.EXPECT().ActionProgress(gomock.Any(), nil) out, err := fx.Run(cmd, []string{"-g", placementGroup.Name, server.Name}) expOut := `Server 42 added to placement group my Placement Group ` assert.NoError(t, err) assert.Equal(t, expOut, out) } cli-1.39.0/internal/cmd/server/attach_iso.go000066400000000000000000000035021451614444200207120ustar00rootroot00000000000000package server import ( "context" "errors" "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" ) var AttachISOCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { return &cobra.Command{ Use: "attach-iso [FLAGS] SERVER ISO", Short: "Attach an ISO to a server", Args: cobra.ExactArgs(2), TraverseChildren: true, ValidArgsFunction: cmpl.SuggestArgs( cmpl.SuggestCandidatesF(client.Server().Names), cmpl.SuggestCandidatesF(client.ISO().Names), ), DisableFlagsInUseLine: true, } }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, command *cobra.Command, args []string) error { idOrName := args[0] server, _, err := client.Server().Get(ctx, idOrName) if err != nil { return err } if server == nil { return fmt.Errorf("server not found: %s", idOrName) } isoIDOrName := args[1] iso, _, err := client.ISO().Get(ctx, isoIDOrName) if err != nil { return err } if iso == nil { return fmt.Errorf("ISO not found: %s", isoIDOrName) } // If ISO architecture is empty -> wildcard/unknown --> allow // If ISO architecture is set and does not match server --> deny if iso.Architecture != nil && *iso.Architecture != server.ServerType.Architecture { return errors.New("failed to attach iso: iso has a different architecture than the server") } action, _, err := client.Server().AttachISO(ctx, server, iso) if err != nil { return err } if err := waiter.ActionProgress(ctx, action); err != nil { return err } fmt.Printf("ISO %s attached to server %d\n", iso.Name, server.ID) return nil }, } cli-1.39.0/internal/cmd/server/attach_to_network.go000066400000000000000000000044001451614444200223110ustar00rootroot00000000000000package server import ( "context" "fmt" "net" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var AttachToNetworkCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "attach-to-network [FLAGS] SERVER", Short: "Attach a server to a network", Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.Server().Names)), TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.Flags().StringP("network", "n", "", "Network (ID or name) (required)") cmd.RegisterFlagCompletionFunc("network", cmpl.SuggestCandidatesF(client.Network().Names)) cmd.MarkFlagRequired("network") cmd.Flags().IP("ip", nil, "IP address to assign to the server (auto-assigned if omitted)") cmd.Flags().IPSlice("alias-ips", []net.IP{}, "Additional IP addresses to be assigned to the server") return cmd }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { idOrName := args[0] server, _, err := client.Server().Get(ctx, idOrName) if err != nil { return err } if server == nil { return fmt.Errorf("server not found: %s", idOrName) } networkIDOrName, _ := cmd.Flags().GetString("network") network, _, err := client.Network().Get(ctx, networkIDOrName) if err != nil { return err } if network == nil { return fmt.Errorf("network not found: %s", networkIDOrName) } ip, _ := cmd.Flags().GetIP("ip") aliasIPs, _ := cmd.Flags().GetIPSlice("alias-ips") opts := hcloud.ServerAttachToNetworkOpts{ Network: network, IP: ip, } for _, aliasIP := range aliasIPs { opts.AliasIPs = append(opts.AliasIPs, aliasIP) } action, _, err := client.Server().AttachToNetwork(ctx, server, opts) if err != nil { return err } if err := waiter.ActionProgress(ctx, action); err != nil { return err } fmt.Printf("Server %d attached to network %d\n", server.ID, network.ID) return nil }, } cli-1.39.0/internal/cmd/server/change_alias_ips.go000066400000000000000000000044171451614444200220530ustar00rootroot00000000000000package server import ( "context" "fmt" "net" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var ChangeAliasIPsCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "change-alias-ips [FLAGS] SERVER", Short: "Change a server's alias IPs in a network", Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.Server().Names)), TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.Flags().StringP("network", "n", "", "Network (ID or name) (required)") cmd.RegisterFlagCompletionFunc("network", cmpl.SuggestCandidatesF(client.Network().Names)) cmd.MarkFlagRequired("network") cmd.Flags().StringSlice("alias-ips", nil, "New alias IPs") cmd.Flags().Bool("clear", false, "Remove all alias IPs") return cmd }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { clear, _ := cmd.Flags().GetBool("clear") idOrName := args[0] server, _, err := client.Server().Get(ctx, idOrName) if err != nil { return err } if server == nil { return fmt.Errorf("server not found: %s", idOrName) } networkIDOrName, _ := cmd.Flags().GetString("network") network, _, err := client.Network().Get(ctx, networkIDOrName) if err != nil { return err } if network == nil { return fmt.Errorf("network not found: %s", networkIDOrName) } aliasIPs, _ := cmd.Flags().GetStringSlice("alias-ips") opts := hcloud.ServerChangeAliasIPsOpts{ Network: network, } if clear { opts.AliasIPs = []net.IP{} } else { for _, aliasIP := range aliasIPs { opts.AliasIPs = append(opts.AliasIPs, net.ParseIP(aliasIP)) } } action, _, err := client.Server().ChangeAliasIPs(ctx, server, opts) if err != nil { return err } if err := waiter.ActionProgress(ctx, action); err != nil { return err } fmt.Printf("Alias IPs changed for server %d in network %d\n", server.ID, network.ID) return nil }, } cli-1.39.0/internal/cmd/server/change_type.go000066400000000000000000000041201451614444200210570ustar00rootroot00000000000000package server import ( "context" "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var ChangeTypeCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "change-type [FLAGS] SERVER SERVERTYPE", Short: "Change type of a server", Args: cobra.ExactArgs(2), ValidArgsFunction: cmpl.SuggestArgs( cmpl.SuggestCandidatesF(client.Server().Names), cmpl.SuggestCandidatesF(client.ServerType().Names), ), TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.Flags().Bool("keep-disk", false, "Keep disk size of current server type. This enables downgrading the server.") return cmd }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { idOrName := args[0] server, _, err := client.Server().Get(ctx, idOrName) if err != nil { return err } if server == nil { return fmt.Errorf("server not found: %s", idOrName) } serverTypeIDOrName := args[1] serverType, _, err := client.ServerType().Get(ctx, serverTypeIDOrName) if err != nil { return err } if serverType == nil { return fmt.Errorf("server type not found: %s", serverTypeIDOrName) } if serverType.IsDeprecated() { fmt.Print(warningDeprecatedServerType(serverType)) } keepDisk, _ := cmd.Flags().GetBool("keep-disk") opts := hcloud.ServerChangeTypeOpts{ ServerType: serverType, UpgradeDisk: !keepDisk, } action, _, err := client.Server().ChangeType(ctx, server, opts) if err != nil { return err } if err := waiter.ActionProgress(ctx, action); err != nil { return err } if opts.UpgradeDisk { fmt.Printf("Server %d changed to type %s\n", server.ID, serverType.Name) } else { fmt.Printf("Server %d changed to type %s (disk size was unchanged)\n", server.ID, serverType.Name) } return nil }, } cli-1.39.0/internal/cmd/server/create.go000066400000000000000000000342721451614444200200470ustar00rootroot00000000000000package server import ( "bytes" "context" "encoding/base64" "fmt" "io/ioutil" "mime/multipart" "net/textproto" "os" "strings" "time" "github.com/spf13/cobra" "github.com/spf13/pflag" "golang.org/x/crypto/ssh" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) // CreateCmd defines a command for creating a server. var CreateCmd = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "create FLAGS", Short: "Create a server", } cmd.Flags().String("name", "", "Server name (required)") cmd.MarkFlagRequired("name") cmd.Flags().String("type", "", "Server type (ID or name) (required)") cmd.RegisterFlagCompletionFunc("type", cmpl.SuggestCandidatesF(client.ServerType().Names)) cmd.MarkFlagRequired("type") cmd.Flags().String("image", "", "Image (ID or name) (required)") cmd.RegisterFlagCompletionFunc("image", cmpl.SuggestCandidatesF(client.Image().Names)) cmd.MarkFlagRequired("image") cmd.Flags().String("location", "", "Location (ID or name)") cmd.RegisterFlagCompletionFunc("location", cmpl.SuggestCandidatesF(client.Location().Names)) cmd.Flags().String("datacenter", "", "Datacenter (ID or name)") cmd.RegisterFlagCompletionFunc("datacenter", cmpl.SuggestCandidatesF(client.Datacenter().Names)) cmd.Flags().StringSlice("ssh-key", nil, "ID or name of SSH key to inject (can be specified multiple times)") cmd.RegisterFlagCompletionFunc("ssh-key", cmpl.SuggestCandidatesF(client.SSHKey().Names)) cmd.Flags().StringToString("label", nil, "User-defined labels ('key=value') (can be specified multiple times)") cmd.Flags().StringArray("user-data-from-file", []string{}, "Read user data from specified file (use - to read from stdin)") cmd.Flags().Bool("start-after-create", true, "Start server right after creation") cmd.Flags().StringSlice("volume", nil, "ID or name of volume to attach (can be specified multiple times)") cmd.RegisterFlagCompletionFunc("volume", cmpl.SuggestCandidatesF(client.Volume().Names)) cmd.Flags().StringSlice("network", nil, "ID or name of network to attach the server to (can be specified multiple times)") cmd.RegisterFlagCompletionFunc("network", cmpl.SuggestCandidatesF(client.Network().Names)) cmd.Flags().StringSlice("firewall", nil, "ID or name of Firewall to attach the server to (can be specified multiple times)") cmd.RegisterFlagCompletionFunc("firewall", cmpl.SuggestCandidatesF(client.Firewall().Names)) cmd.Flags().Bool("automount", false, "Automount volumes after attach (default: false)") cmd.Flags().Bool("allow-deprecated-image", false, "Enable the use of deprecated images (default: false)") cmd.Flags().String("placement-group", "", "Placement Group (ID of name)") cmd.RegisterFlagCompletionFunc("placement-group", cmpl.SuggestCandidatesF(client.PlacementGroup().Names)) cmd.Flags().String("primary-ipv4", "", "Primary IPv4 (ID of name)") cmd.RegisterFlagCompletionFunc("primary-ipv4", cmpl.SuggestCandidatesF(client.PrimaryIP().IPv4Names)) cmd.Flags().String("primary-ipv6", "", "Primary IPv6 (ID of name)") cmd.RegisterFlagCompletionFunc("primary-ipv6", cmpl.SuggestCandidatesF(client.PrimaryIP().IPv6Names)) cmd.Flags().Bool("without-ipv4", false, "Creates the server without an IPv4 (default: false)") cmd.Flags().Bool("without-ipv6", false, "Creates the server without an IPv6 (default: false)") cmd.Flags().StringSlice("enable-protection", []string{}, "Enable protection (delete, rebuild) (default: none)") cmd.RegisterFlagCompletionFunc("enable-protection", cmpl.SuggestCandidates("delete", "rebuild")) cmd.Flags().Bool("enable-backup", false, "Enable automatic backups") return cmd }, Run: func(ctx context.Context, client hcapi2.Client, actionWaiter state.ActionWaiter, cmd *cobra.Command, args []string) error { createOpts, protectionOpts, err := createOptsFromFlags(ctx, client, cmd.Flags()) if err != nil { return err } result, _, err := client.Server().Create(ctx, createOpts) if err != nil { return err } if err := actionWaiter.ActionProgress(ctx, result.Action); err != nil { return err } if err := actionWaiter.WaitForActions(ctx, result.NextActions); err != nil { return err } server, _, err := client.Server().GetByID(ctx, result.Server.ID) if err != nil { return err } fmt.Printf("Server %d created\n", result.Server.ID) if err := changeProtection(ctx, client, actionWaiter, server, true, protectionOpts); err != nil { return err } enableBackup, _ := cmd.Flags().GetBool("enable-backup") if enableBackup { action, _, err := client.Server().EnableBackup(ctx, server, "") if err != nil { return err } if err := actionWaiter.ActionProgress(ctx, action); err != nil { return err } fmt.Printf("Backups enabled for server %d\n", server.ID) } if !server.PublicNet.IPv4.IsUnspecified() { fmt.Printf("IPv4: %s\n", server.PublicNet.IPv4.IP.String()) } if !server.PublicNet.IPv6.IsUnspecified() { fmt.Printf("IPv6: %s1\n", server.PublicNet.IPv6.Network.IP.String()) fmt.Printf("IPv6 Network: %s\n", server.PublicNet.IPv6.Network.String()) } if len(server.PrivateNet) > 0 { var networks []string for _, network := range server.PrivateNet { networks = append(networks, fmt.Sprintf("- %s (%s)", network.IP.String(), client.Network().Name(network.Network.ID))) } fmt.Printf("Private Networks:\n\t%s\n", strings.Join(networks, "\n")) } // Only print the root password if it's not empty, // which is only the case if it wasn't created with an SSH key. if result.RootPassword != "" { fmt.Printf("Root password: %s\n", result.RootPassword) } return nil }, } var userDataContentTypes = map[string]string{ "#!": "text/x-shellscript", "#include": "text/x-include-url", "#cloud-config": "text/cloud-config", "#upstart-job": "text/upstart-job", "#cloud-boothook": "text/cloud-boothook", "#part-handler": "text/part-handler", } func detectContentType(data string) string { for prefix, contentType := range userDataContentTypes { if strings.HasPrefix(data, prefix) { return contentType } } return "" } func buildUserData(files []string) (string, error) { var ( buf = new(bytes.Buffer) mp = multipart.NewWriter(buf) ) fmt.Fprint(buf, "MIME-Version: 1.0\r\n") fmt.Fprint(buf, "Content-Type: multipart/mixed; boundary="+mp.Boundary()+"\r\n\r\n") for _, file := range files { var ( data []byte err error ) if file == "-" { data, err = ioutil.ReadAll(os.Stdin) } else { data, err = ioutil.ReadFile(file) } if err != nil { return "", err } contentType := detectContentType(string(data)) if contentType == "" { return "", fmt.Errorf("cannot detect user data type of file %q", file) } header := textproto.MIMEHeader{} header.Set("Content-Type", contentType) header.Set("Content-Transfer-Encoding", "base64") w, err := mp.CreatePart(header) if err != nil { return "", fmt.Errorf("failed to create multipart for file %q: %s", file, err) } if _, err := base64.NewEncoder(base64.StdEncoding, w).Write(data); err != nil { return "", fmt.Errorf("failed to encode data for file %q: %s", file, err) } } if err := mp.Close(); err != nil { return "", err } return buf.String(), nil } func createOptsFromFlags( ctx context.Context, client hcapi2.Client, flags *pflag.FlagSet, ) (createOpts hcloud.ServerCreateOpts, protectionOps hcloud.ServerChangeProtectionOpts, err error) { name, _ := flags.GetString("name") serverTypeName, _ := flags.GetString("type") imageIDorName, _ := flags.GetString("image") location, _ := flags.GetString("location") datacenter, _ := flags.GetString("datacenter") userDataFiles, _ := flags.GetStringArray("user-data-from-file") startAfterCreate, _ := flags.GetBool("start-after-create") sshKeys, _ := flags.GetStringSlice("ssh-key") labels, _ := flags.GetStringToString("label") volumes, _ := flags.GetStringSlice("volume") networks, _ := flags.GetStringSlice("network") firewalls, _ := flags.GetStringSlice("firewall") automount, _ := flags.GetBool("automount") allowDeprecatedImage, _ := flags.GetBool("allow-deprecated-image") placementGroupIDorName, _ := flags.GetString("placement-group") withoutIPv4, _ := flags.GetBool("without-ipv4") withoutIPv6, _ := flags.GetBool("without-ipv6") primaryIPv4IDorName, _ := flags.GetString("primary-ipv4") primaryIPv6IDorName, _ := flags.GetString("primary-ipv6") protection, _ := flags.GetStringSlice("enable-protection") serverType, _, err := client.ServerType().Get(ctx, serverTypeName) if err != nil { return } if serverType == nil { err = fmt.Errorf("server type not found: %s", serverTypeName) return } if serverType.IsDeprecated() { fmt.Print(warningDeprecatedServerType(serverType)) } // Select correct image based on server type architecture image, _, err := client.Image().GetForArchitecture(ctx, imageIDorName, serverType.Architecture) if err != nil { return } if image == nil { err = fmt.Errorf("image %s for architecture %s not found", imageIDorName, serverType.Architecture) return } if !image.Deprecated.IsZero() { if allowDeprecatedImage { fmt.Printf("Attention: image %s is deprecated. It will continue to be available until %s.\n", image.Name, image.Deprecated.AddDate(0, 3, 0).Format(time.DateOnly)) } else { err = fmt.Errorf("image %s is deprecated, please use --allow-deprecated-image to create a server with this image. It will continue to be available until %s", image.Name, image.Deprecated.AddDate(0, 3, 0).Format(time.DateOnly)) return } } if withoutIPv4 && withoutIPv6 && len(networks) == 0 { err = fmt.Errorf("a server can not be created without IPv4, IPv6 and a private network. Choose at least one of those options to create the server") return } createOpts = hcloud.ServerCreateOpts{ Name: name, ServerType: serverType, Image: image, Labels: labels, StartAfterCreate: &startAfterCreate, Automount: &automount, } publicNetConfiguration := &hcloud.ServerCreatePublicNet{} if !withoutIPv4 { publicNetConfiguration.EnableIPv4 = true } if !withoutIPv6 { publicNetConfiguration.EnableIPv6 = true } if primaryIPv4IDorName != "" { var primaryIPv4 *hcloud.PrimaryIP primaryIPv4, _, err = client.PrimaryIP().Get(ctx, primaryIPv4IDorName) if err != nil { return } if primaryIPv4 == nil { err = fmt.Errorf("primary ipv4 not found: %s", primaryIPv4IDorName) return } publicNetConfiguration.IPv4 = primaryIPv4 } if primaryIPv6IDorName != "" { var primaryIPv6 *hcloud.PrimaryIP primaryIPv6, _, err = client.PrimaryIP().Get(ctx, primaryIPv6IDorName) if err != nil { return } if primaryIPv6 == nil { err = fmt.Errorf("primary ipv6 not found: %s", primaryIPv6IDorName) return } publicNetConfiguration.IPv6 = primaryIPv6 } createOpts.PublicNet = publicNetConfiguration if len(userDataFiles) == 1 { var data []byte if userDataFiles[0] == "-" { data, err = ioutil.ReadAll(os.Stdin) } else { data, err = ioutil.ReadFile(userDataFiles[0]) } if err != nil { return } createOpts.UserData = string(data) } else if len(userDataFiles) > 1 { createOpts.UserData, err = buildUserData(userDataFiles) if err != nil { return } } for _, sshKeyIDOrName := range sshKeys { var sshKey *hcloud.SSHKey sshKey, _, err = client.SSHKey().Get(ctx, sshKeyIDOrName) if err != nil { return } if sshKey == nil { sshKey, err = getSSHKeyForFingerprint(ctx, client, sshKeyIDOrName) if err != nil { return } } if sshKey == nil { err = fmt.Errorf("SSH key not found: %s", sshKeyIDOrName) return } createOpts.SSHKeys = append(createOpts.SSHKeys, sshKey) } for _, volumeIDOrName := range volumes { var volume *hcloud.Volume volume, _, err = client.Volume().Get(ctx, volumeIDOrName) if err != nil { return } if volume == nil { err = fmt.Errorf("volume not found: %s", volumeIDOrName) return } createOpts.Volumes = append(createOpts.Volumes, volume) } for _, networkIDOrName := range networks { var network *hcloud.Network network, _, err = client.Network().Get(ctx, networkIDOrName) if err != nil { return } if network == nil { err = fmt.Errorf("network not found: %s", networkIDOrName) return } createOpts.Networks = append(createOpts.Networks, network) } for _, firewallIDOrName := range firewalls { var firewall *hcloud.Firewall firewall, _, err = client.Firewall().Get(ctx, firewallIDOrName) if err != nil { return } if firewall == nil { err = fmt.Errorf("firewall not found: %s", firewallIDOrName) return } createOpts.Firewalls = append(createOpts.Firewalls, &hcloud.ServerCreateFirewall{Firewall: *firewall}) } if datacenter != "" { createOpts.Datacenter = &hcloud.Datacenter{Name: datacenter} } if location != "" { createOpts.Location = &hcloud.Location{Name: location} } if placementGroupIDorName != "" { var placementGroup *hcloud.PlacementGroup placementGroup, _, err = client.PlacementGroup().Get(ctx, placementGroupIDorName) if err != nil { return } if placementGroup == nil { err = fmt.Errorf("placement group not found: %s", placementGroupIDorName) return } createOpts.PlacementGroup = placementGroup } protectionOps, err = getChangeProtectionOpts(true, protection) return } func getSSHKeyForFingerprint( ctx context.Context, client hcapi2.Client, file string, ) (sshKey *hcloud.SSHKey, err error) { var ( fileContent []byte publicKey ssh.PublicKey ) if fileContent, err = ioutil.ReadFile(file); err == os.ErrNotExist { err = nil return } else if err != nil { err = fmt.Errorf("lookup SSH key by fingerprint: %v", err) return } if publicKey, _, _, _, err = ssh.ParseAuthorizedKey(fileContent); err != nil { err = fmt.Errorf("lookup SSH key by fingerprint: %v", err) return } sshKey, _, err = client.SSHKey().GetByFingerprint(ctx, ssh.FingerprintLegacyMD5(publicKey)) if err != nil { err = fmt.Errorf("lookup SSH key by fingerprint: %v", err) return } if sshKey == nil { err = fmt.Errorf("SSH key not found by using fingerprint of public key: %s", file) return } return } cli-1.39.0/internal/cmd/server/create_image.go000066400000000000000000000043051451614444200212030ustar00rootroot00000000000000package server import ( "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) func newCreateImageCommand(cli *state.State) *cobra.Command { cmd := &cobra.Command{ Use: "create-image [FLAGS] SERVER", Short: "Create an image from a server", Args: cobra.ExactArgs(1), TraverseChildren: true, DisableFlagsInUseLine: true, PreRunE: util.ChainRunE(validateCreateImage, cli.EnsureToken), RunE: cli.Wrap(runCreateImage), } cmd.Flags().String("type", "", "Image type (required)") cmd.RegisterFlagCompletionFunc("type", cmpl.SuggestCandidates("backup", "snapshot")) cmd.MarkFlagRequired("type") cmd.Flags().String("description", "", "Image description") cmd.Flags().StringToString("label", nil, "User-defined labels ('key=value') (can be specified multiple times)") return cmd } func validateCreateImage(cmd *cobra.Command, args []string) error { imageType, _ := cmd.Flags().GetString("type") switch hcloud.ImageType(imageType) { case hcloud.ImageTypeBackup, hcloud.ImageTypeSnapshot: break default: return fmt.Errorf("invalid image type: %v", imageType) } return nil } func runCreateImage(cli *state.State, cmd *cobra.Command, args []string) error { idOrName := args[0] server, _, err := cli.Client().Server.Get(cli.Context, idOrName) if err != nil { return err } if server == nil { return fmt.Errorf("server not found: %s", idOrName) } imageType, _ := cmd.Flags().GetString("type") description, _ := cmd.Flags().GetString("description") labels, _ := cmd.Flags().GetStringToString("label") opts := &hcloud.ServerCreateImageOpts{ Type: hcloud.ImageType(imageType), Description: hcloud.String(description), Labels: labels, } result, _, err := cli.Client().Server.CreateImage(cli.Context, server, opts) if err != nil { return err } if err := cli.ActionProgress(cli.Context, result.Action); err != nil { return err } fmt.Printf("Image %d created from server %d\n", result.Image.ID, server.ID) return nil } cli-1.39.0/internal/cmd/server/create_test.go000066400000000000000000000104641451614444200211030ustar00rootroot00000000000000package server_test import ( "context" "net" "testing" "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" "github.com/hetznercloud/cli/internal/cmd/server" "github.com/hetznercloud/cli/internal/testutil" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) func TestCreate(t *testing.T) { fx := testutil.NewFixture(t) defer fx.Finish() cmd := server.CreateCmd.CobraCommand( context.Background(), fx.Client, fx.TokenEnsurer, fx.ActionWaiter, ) fx.ExpectEnsureToken() fx.Client.ServerTypeClient.EXPECT(). Get(gomock.Any(), "cx11"). Return(&hcloud.ServerType{Architecture: hcloud.ArchitectureX86}, nil, nil) fx.Client.ImageClient.EXPECT(). GetForArchitecture(gomock.Any(), "ubuntu-20.04", hcloud.ArchitectureX86). Return(&hcloud.Image{}, nil, nil) fx.Client.ServerClient.EXPECT(). Create(gomock.Any(), gomock.Any()). Do(func(_ context.Context, opts hcloud.ServerCreateOpts) { assert.Equal(t, "cli-test", opts.Name) }). Return(hcloud.ServerCreateResult{ Server: &hcloud.Server{ ID: 1234, PublicNet: hcloud.ServerPublicNet{ IPv4: hcloud.ServerPublicNetIPv4{ IP: net.ParseIP("192.0.2.1"), }, }, }, Action: &hcloud.Action{ID: 123}, NextActions: []*hcloud.Action{{ID: 234}}, }, nil, nil) fx.Client.ServerClient.EXPECT(). GetByID(gomock.Any(), int64(1234)). Return(&hcloud.Server{ ID: 1234, PublicNet: hcloud.ServerPublicNet{ IPv4: hcloud.ServerPublicNetIPv4{ IP: net.ParseIP("192.0.2.1"), }, }, }, nil, nil) fx.ActionWaiter.EXPECT().ActionProgress(gomock.Any(), &hcloud.Action{ID: 123}).Return(nil) fx.ActionWaiter.EXPECT().WaitForActions(gomock.Any(), []*hcloud.Action{{ID: 234}}).Return(nil) args := []string{"--name", "cli-test", "--type", "cx11", "--image", "ubuntu-20.04"} out, err := fx.Run(cmd, args) assert.NoError(t, err) expOut := `Server 1234 created IPv4: 192.0.2.1 ` assert.Equal(t, expOut, out) } func TestCreateProtectionBackup(t *testing.T) { fx := testutil.NewFixture(t) defer fx.Finish() cmd := server.CreateCmd.CobraCommand( context.Background(), fx.Client, fx.TokenEnsurer, fx.ActionWaiter, ) fx.ExpectEnsureToken() fx.Client.ServerTypeClient.EXPECT(). Get(gomock.Any(), "cx11"). Return(&hcloud.ServerType{Architecture: hcloud.ArchitectureX86}, nil, nil) fx.Client.ImageClient.EXPECT(). GetForArchitecture(gomock.Any(), "ubuntu-20.04", hcloud.ArchitectureX86). Return(&hcloud.Image{}, nil, nil) fx.Client.ServerClient.EXPECT(). Create(gomock.Any(), gomock.Any()). Do(func(_ context.Context, opts hcloud.ServerCreateOpts) { assert.Equal(t, "cli-test", opts.Name) }). Return(hcloud.ServerCreateResult{ Server: &hcloud.Server{ ID: 1234, PublicNet: hcloud.ServerPublicNet{ IPv4: hcloud.ServerPublicNetIPv4{ IP: net.ParseIP("192.0.2.1"), }, }, }, Action: &hcloud.Action{ID: 123}, NextActions: []*hcloud.Action{{ID: 234}}, }, nil, nil) server := &hcloud.Server{ ID: 1234, PublicNet: hcloud.ServerPublicNet{ IPv4: hcloud.ServerPublicNetIPv4{ IP: net.ParseIP("192.0.2.1"), }, }, Protection: hcloud.ServerProtection{ Delete: true, Rebuild: true, }, } fx.Client.ServerClient.EXPECT(). GetByID(gomock.Any(), int64(1234)). Return(server, nil, nil) fx.ActionWaiter.EXPECT().ActionProgress(gomock.Any(), &hcloud.Action{ID: 123}).Return(nil) fx.ActionWaiter.EXPECT().WaitForActions(gomock.Any(), []*hcloud.Action{{ID: 234}}).Return(nil) fx.Client.ServerClient.EXPECT(). ChangeProtection(gomock.Any(), server, hcloud.ServerChangeProtectionOpts{ Rebuild: hcloud.Ptr(true), Delete: hcloud.Ptr(true), }). Return(&hcloud.Action{ ID: 1337, }, nil, nil) fx.ActionWaiter.EXPECT().ActionProgress(gomock.Any(), &hcloud.Action{ID: 1337}).Return(nil) fx.Client.ServerClient.EXPECT(). EnableBackup(gomock.Any(), server, ""). Return(&hcloud.Action{ ID: 42, }, nil, nil) fx.ActionWaiter.EXPECT().ActionProgress(gomock.Any(), &hcloud.Action{ID: 42}).Return(nil) args := []string{"--name", "cli-test", "--type", "cx11", "--image", "ubuntu-20.04", "--enable-protection", "rebuild,delete", "--enable-backup"} out, err := fx.Run(cmd, args) assert.NoError(t, err) expOut := `Server 1234 created Resource protection enabled for server 1234 Backups enabled for server 1234 IPv4: 192.0.2.1 ` assert.Equal(t, expOut, out) } cli-1.39.0/internal/cmd/server/delete.go000066400000000000000000000020041451614444200200320ustar00rootroot00000000000000package server import ( "context" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var deleteCmd = base.DeleteCmd{ ResourceNameSingular: "Server", ShortDescription: "Delete a server", NameSuggestions: func(c hcapi2.Client) func() []string { return c.Server().Names }, Fetch: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) { return client.Server().Get(ctx, idOrName) }, Delete: func(ctx context.Context, client hcapi2.Client, actionWaiter state.ActionWaiter, cmd *cobra.Command, resource interface{}) error { server := resource.(*hcloud.Server) result, _, err := client.Server().DeleteWithResult(ctx, server) if err != nil { return err } if err := actionWaiter.ActionProgress(ctx, result.Action); err != nil { return err } return nil }, } cli-1.39.0/internal/cmd/server/describe.go000066400000000000000000000162741451614444200203660ustar00rootroot00000000000000package server import ( "context" "fmt" humanize "github.com/dustin/go-humanize" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var describeCmd = base.DescribeCmd{ ResourceNameSingular: "server", ShortDescription: "Describe a server", JSONKeyGetByID: "server", JSONKeyGetByName: "servers", NameSuggestions: func(c hcapi2.Client) func() []string { return c.Server().Names }, Fetch: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) { return client.Server().Get(ctx, idOrName) }, PrintText: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, resource interface{}) error { server := resource.(*hcloud.Server) fmt.Printf("ID:\t\t%d\n", server.ID) fmt.Printf("Name:\t\t%s\n", server.Name) fmt.Printf("Status:\t\t%s\n", server.Status) fmt.Printf("Created:\t%s (%s)\n", util.Datetime(server.Created), humanize.Time(server.Created)) fmt.Printf("Server Type:\t%s (ID: %d)\n", server.ServerType.Name, server.ServerType.ID) fmt.Printf(" ID:\t\t%d\n", server.ServerType.ID) fmt.Printf(" Name:\t\t%s\n", server.ServerType.Name) fmt.Printf(" Description:\t%s\n", server.ServerType.Description) fmt.Printf(" Cores:\t%d\n", server.ServerType.Cores) fmt.Printf(" CPU Type:\t%s\n", server.ServerType.CPUType) fmt.Printf(" Memory:\t%v GB\n", server.ServerType.Memory) fmt.Printf(" Disk:\t\t%d GB\n", server.PrimaryDiskSize) fmt.Printf(" Storage Type:\t%s\n", server.ServerType.StorageType) fmt.Printf(util.PrefixLines(util.DescribeDeprecation(server.ServerType), " ")) fmt.Printf("Public Net:\n") fmt.Printf(" IPv4:\n") if server.PublicNet.IPv4.IsUnspecified() { fmt.Printf(" No Primary IPv4\n") } else { fmt.Printf(" ID:\t\t%d\n", server.PublicNet.IPv4.ID) fmt.Printf(" IP:\t\t%s\n", server.PublicNet.IPv4.IP) fmt.Printf(" Blocked:\t%s\n", util.YesNo(server.PublicNet.IPv4.Blocked)) fmt.Printf(" DNS:\t%s\n", server.PublicNet.IPv4.DNSPtr) } fmt.Printf(" IPv6:\n") if server.PublicNet.IPv6.IsUnspecified() { fmt.Printf(" No Primary IPv6\n") } else { fmt.Printf(" ID:\t\t%d\n", server.PublicNet.IPv6.ID) fmt.Printf(" IP:\t\t%s\n", server.PublicNet.IPv6.Network.String()) fmt.Printf(" Blocked:\t%s\n", util.YesNo(server.PublicNet.IPv6.Blocked)) } fmt.Printf(" Floating IPs:\n") if len(server.PublicNet.FloatingIPs) > 0 { for _, f := range server.PublicNet.FloatingIPs { floatingIP, _, err := client.FloatingIP().GetByID(ctx, f.ID) if err != nil { return fmt.Errorf("error fetching Floating IP: %v", err) } fmt.Printf(" - ID:\t\t\t%d\n", floatingIP.ID) fmt.Printf(" Description:\t%s\n", util.NA(floatingIP.Description)) fmt.Printf(" IP:\t\t\t%s\n", floatingIP.IP) } } else { fmt.Printf(" No Floating IPs\n") } fmt.Printf("Private Net:\n") if len(server.PrivateNet) > 0 { for _, n := range server.PrivateNet { network, _, err := client.Network().GetByID(ctx, n.Network.ID) if err != nil { return fmt.Errorf("error fetching network: %v", err) } fmt.Printf(" - ID:\t\t\t%d\n", network.ID) fmt.Printf(" Name:\t\t%s\n", network.Name) fmt.Printf(" IP:\t\t\t%s\n", n.IP.String()) fmt.Printf(" MAC Address:\t%s\n", n.MACAddress) if len(n.Aliases) > 0 { fmt.Printf(" Alias IPs:\n") for _, a := range n.Aliases { fmt.Printf(" -\t\t\t%s\n", a) } } else { fmt.Printf(" Alias IPs:\t\t%s\n", util.NA("")) } } } else { fmt.Printf(" No Private Networks\n") } fmt.Printf("Volumes:\n") if len(server.Volumes) > 0 { for _, v := range server.Volumes { volume, _, err := client.Volume().GetByID(ctx, v.ID) if err != nil { return fmt.Errorf("error fetching Volume: %v", err) } fmt.Printf(" - ID:\t\t%d\n", volume.ID) fmt.Printf(" Name:\t%s\n", volume.Name) fmt.Printf(" Size:\t%s\n", humanize.Bytes(uint64(volume.Size*humanize.GByte))) } } else { fmt.Printf(" No Volumes\n") } fmt.Printf("Image:\n") if server.Image != nil { image := server.Image fmt.Printf(" ID:\t\t%d\n", image.ID) fmt.Printf(" Type:\t\t%s\n", image.Type) fmt.Printf(" Status:\t%s\n", image.Status) fmt.Printf(" Name:\t\t%s\n", util.NA(image.Name)) fmt.Printf(" Description:\t%s\n", image.Description) if image.ImageSize != 0 { fmt.Printf(" Image size:\t%.2f GB\n", image.ImageSize) } else { fmt.Printf(" Image size:\t%s\n", util.NA("")) } fmt.Printf(" Disk size:\t%.0f GB\n", image.DiskSize) fmt.Printf(" Created:\t%s (%s)\n", util.Datetime(image.Created), humanize.Time(image.Created)) fmt.Printf(" OS flavor:\t%s\n", image.OSFlavor) fmt.Printf(" OS version:\t%s\n", util.NA(image.OSVersion)) fmt.Printf(" Rapid deploy:\t%s\n", util.YesNo(image.RapidDeploy)) } else { fmt.Printf(" No Image\n") } fmt.Printf("Datacenter:\n") fmt.Printf(" ID:\t\t%d\n", server.Datacenter.ID) fmt.Printf(" Name:\t\t%s\n", server.Datacenter.Name) fmt.Printf(" Description:\t%s\n", server.Datacenter.Description) fmt.Printf(" Location:\n") fmt.Printf(" Name:\t\t%s\n", server.Datacenter.Location.Name) fmt.Printf(" Description:\t%s\n", server.Datacenter.Location.Description) fmt.Printf(" Country:\t\t%s\n", server.Datacenter.Location.Country) fmt.Printf(" City:\t\t%s\n", server.Datacenter.Location.City) fmt.Printf(" Latitude:\t\t%f\n", server.Datacenter.Location.Latitude) fmt.Printf(" Longitude:\t\t%f\n", server.Datacenter.Location.Longitude) fmt.Printf("Traffic:\n") fmt.Printf(" Outgoing:\t%v\n", humanize.IBytes(server.OutgoingTraffic)) fmt.Printf(" Ingoing:\t%v\n", humanize.IBytes(server.IngoingTraffic)) fmt.Printf(" Included:\t%v\n", humanize.IBytes(server.IncludedTraffic)) if server.BackupWindow != "" { fmt.Printf("Backup Window:\t%s\n", server.BackupWindow) } else { fmt.Printf("Backup Window:\tBackups disabled\n") } if server.RescueEnabled { fmt.Printf("Rescue System:\tenabled\n") } else { fmt.Printf("Rescue System:\tdisabled\n") } fmt.Printf("ISO:\n") if server.ISO != nil { fmt.Printf(" ID:\t\t%d\n", server.ISO.ID) fmt.Printf(" Name:\t\t%s\n", server.ISO.Name) fmt.Printf(" Description:\t%s\n", server.ISO.Description) fmt.Printf(" Type:\t\t%s\n", server.ISO.Type) } else { fmt.Printf(" No ISO attached\n") } fmt.Printf("Protection:\n") fmt.Printf(" Delete:\t%s\n", util.YesNo(server.Protection.Delete)) fmt.Printf(" Rebuild:\t%s\n", util.YesNo(server.Protection.Rebuild)) fmt.Print("Labels:\n") if len(server.Labels) == 0 { fmt.Print(" No labels\n") } else { for key, value := range server.Labels { fmt.Printf(" %s: %s\n", key, value) } } fmt.Print("Placement Group:\n") if server.PlacementGroup != nil { fmt.Printf(" ID:\t\t%d\n", server.PlacementGroup.ID) fmt.Printf(" Name:\t\t%s\n", server.PlacementGroup.Name) fmt.Printf(" Type:\t\t%s\n", server.PlacementGroup.Type) } else { fmt.Print(" No Placement Group set\n") } return nil }, } cli-1.39.0/internal/cmd/server/detach_from_network.go000066400000000000000000000035711451614444200226260ustar00rootroot00000000000000package server import ( "context" "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var DetachFromNetworkCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "detach-from-network [FLAGS] SERVER", Short: "Detach a server from a network", Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.Server().Names)), TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.Flags().StringP("network", "n", "", "Network (ID or name) (required)") cmd.RegisterFlagCompletionFunc("network", cmpl.SuggestCandidatesF(client.Network().Names)) cmd.MarkFlagRequired("network") return cmd }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { idOrName := args[0] server, _, err := client.Server().Get(ctx, idOrName) if err != nil { return err } if server == nil { return fmt.Errorf("server not found: %s", idOrName) } networkIDOrName, _ := cmd.Flags().GetString("network") network, _, err := client.Network().Get(ctx, networkIDOrName) if err != nil { return err } if network == nil { return fmt.Errorf("network not found: %s", networkIDOrName) } opts := hcloud.ServerDetachFromNetworkOpts{ Network: network, } action, _, err := client.Server().DetachFromNetwork(ctx, server, opts) if err != nil { return err } if err := waiter.ActionProgress(ctx, action); err != nil { return err } fmt.Printf("Server %d detached from network %d\n", server.ID, network.ID) return nil }, } cli-1.39.0/internal/cmd/server/detach_iso.go000066400000000000000000000023761451614444200207060ustar00rootroot00000000000000package server import ( "context" "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" ) var DetachISOCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { return &cobra.Command{ Use: "detach-iso [FLAGS] SERVER", Short: "Detach an ISO from a server", Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.Server().Names)), TraverseChildren: true, DisableFlagsInUseLine: true, } }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { idOrName := args[0] server, _, err := client.Server().Get(ctx, idOrName) if err != nil { return err } if server == nil { return fmt.Errorf("server not found: %s", idOrName) } action, _, err := client.Server().DetachISO(ctx, server) if err != nil { return err } if err := waiter.ActionProgress(ctx, action); err != nil { return err } fmt.Printf("ISO detached from server %d\n", server.ID) return nil }, } cli-1.39.0/internal/cmd/server/disable_backup.go000066400000000000000000000024141451614444200215250ustar00rootroot00000000000000package server import ( "context" "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" ) var DisableBackupCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { return &cobra.Command{ Use: "disable-backup [FLAGS] SERVER", Short: "Disable backup for a server", Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.Server().Names)), TraverseChildren: true, DisableFlagsInUseLine: true, } }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { idOrName := args[0] server, _, err := client.Server().Get(ctx, idOrName) if err != nil { return err } if server == nil { return fmt.Errorf("server not found: %s", idOrName) } action, _, err := client.Server().DisableBackup(ctx, server) if err != nil { return err } if err := waiter.ActionProgress(ctx, action); err != nil { return err } fmt.Printf("Backup disabled for server %d\n", server.ID) return nil }, } cli-1.39.0/internal/cmd/server/disable_protection.go000066400000000000000000000023651451614444200224530ustar00rootroot00000000000000package server import ( "context" "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" ) var DisableProtectionCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { return &cobra.Command{ Use: "disable-protection [FLAGS] SERVER PROTECTIONLEVEL [PROTECTIONLEVEL...]", Short: "Disable resource protection for a server", Args: cobra.MinimumNArgs(2), ValidArgsFunction: cmpl.SuggestArgs( cmpl.SuggestCandidatesF(client.Server().Names), cmpl.SuggestCandidates("delete", "rebuild"), ), TraverseChildren: true, DisableFlagsInUseLine: true, } }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { idOrName := args[0] server, _, err := client.Server().Get(ctx, idOrName) if err != nil { return err } if server == nil { return fmt.Errorf("server not found: %s", idOrName) } opts, err := getChangeProtectionOpts(false, args[1:]) if err != nil { return err } return changeProtection(ctx, client, waiter, server, false, opts) }, } cli-1.39.0/internal/cmd/server/disable_rescue.go000066400000000000000000000024141451614444200215460ustar00rootroot00000000000000package server import ( "context" "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" ) var DisableRescueCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { return &cobra.Command{ Use: "disable-rescue [FLAGS] SERVER", Short: "Disable rescue for a server", Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.Server().Names)), TraverseChildren: true, DisableFlagsInUseLine: true, } }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { idOrName := args[0] server, _, err := client.Server().Get(ctx, idOrName) if err != nil { return err } if server == nil { return fmt.Errorf("server not found: %s", idOrName) } action, _, err := client.Server().DisableRescue(ctx, server) if err != nil { return err } if err := waiter.ActionProgress(ctx, action); err != nil { return err } fmt.Printf("Rescue disabled for server %d\n", server.ID) return nil }, } cli-1.39.0/internal/cmd/server/enable_backup.go000066400000000000000000000032301451614444200213450ustar00rootroot00000000000000package server import ( "context" "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" ) var EnableBackupCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "enable-backup [FLAGS] SERVER", Short: "Enable backup for a server", Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.Server().Names)), TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.Flags().String( "window", "", "(deprecated) The time window for the daily backup to run. All times are in UTC. 22-02 means that the backup will be started between 10 PM and 2 AM.") return cmd }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { idOrName := args[0] server, _, err := client.Server().Get(ctx, idOrName) if err != nil { return err } if server == nil { return fmt.Errorf("server not found: %s", idOrName) } window, _ := cmd.Flags().GetString("window") if window != "" { fmt.Print("[WARN] The ability to specify a backup window when enabling backups has been removed. Ignoring flag.\n") } action, _, err := client.Server().EnableBackup(ctx, server, "") if err != nil { return err } if err := waiter.ActionProgress(ctx, action); err != nil { return err } fmt.Printf("Backup enabled for server %d\n", server.ID) return nil }, } cli-1.39.0/internal/cmd/server/enable_protection.go000066400000000000000000000046321451614444200222750ustar00rootroot00000000000000package server import ( "context" "fmt" "strings" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) func getChangeProtectionOpts(enable bool, flags []string) (hcloud.ServerChangeProtectionOpts, error) { opts := hcloud.ServerChangeProtectionOpts{} var unknown []string for _, arg := range flags { switch strings.ToLower(arg) { case "delete": opts.Delete = hcloud.Ptr(enable) case "rebuild": opts.Rebuild = hcloud.Ptr(enable) default: unknown = append(unknown, arg) } } if len(unknown) > 0 { return opts, fmt.Errorf("unknown protection level: %s", strings.Join(unknown, ", ")) } return opts, nil } func changeProtection(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, server *hcloud.Server, enable bool, opts hcloud.ServerChangeProtectionOpts) error { if opts.Delete == nil && opts.Rebuild == nil { return nil } action, _, err := client.Server().ChangeProtection(ctx, server, opts) if err != nil { return err } if err := waiter.ActionProgress(ctx, action); err != nil { return err } if enable { fmt.Printf("Resource protection enabled for server %d\n", server.ID) } else { fmt.Printf("Resource protection disabled for server %d\n", server.ID) } return nil } var EnableProtectionCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { return &cobra.Command{ Use: "enable-protection [FLAGS] SERVER PROTECTIONLEVEL [PROTECTIONLEVEL...]", Short: "Enable resource protection for a server", Args: cobra.MinimumNArgs(2), ValidArgsFunction: cmpl.SuggestArgs( cmpl.SuggestCandidatesF(client.Server().Names), cmpl.SuggestCandidates("delete", "rebuild"), ), TraverseChildren: true, DisableFlagsInUseLine: true, } }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { idOrName := args[0] server, _, err := client.Server().Get(ctx, idOrName) if err != nil { return err } if server == nil { return fmt.Errorf("server not found: %s", idOrName) } opts, err := getChangeProtectionOpts(true, args[1:]) if err != nil { return err } return changeProtection(ctx, client, waiter, server, true, opts) }, } cli-1.39.0/internal/cmd/server/enable_rescue.go000066400000000000000000000043001451614444200213650ustar00rootroot00000000000000package server import ( "context" "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var EnableRescueCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "enable-rescue [FLAGS] SERVER", Short: "Enable rescue for a server", Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.Server().Names)), TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.Flags().String("type", "linux64", "Rescue type") cmd.RegisterFlagCompletionFunc("type", cmpl.SuggestCandidates("linux64", "linux32")) cmd.Flags().StringSlice("ssh-key", nil, "ID or name of SSH key to inject (can be specified multiple times)") cmd.RegisterFlagCompletionFunc("ssh-key", cmpl.SuggestCandidatesF(client.SSHKey().Names)) return cmd }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { idOrName := args[0] server, _, err := client.Server().Get(ctx, idOrName) if err != nil { return err } if server == nil { return fmt.Errorf("server not found: %s", idOrName) } var ( opts hcloud.ServerEnableRescueOpts ) rescueType, _ := cmd.Flags().GetString("type") opts.Type = hcloud.ServerRescueType(rescueType) sshKeys, _ := cmd.Flags().GetStringSlice("ssh-key") for _, sshKeyIDOrName := range sshKeys { sshKey, _, err := client.SSHKey().Get(ctx, sshKeyIDOrName) if err != nil { return err } if sshKey == nil { return fmt.Errorf("SSH key not found: %s", sshKeyIDOrName) } opts.SSHKeys = append(opts.SSHKeys, sshKey) } result, _, err := client.Server().EnableRescue(ctx, server, opts) if err != nil { return err } if err := waiter.ActionProgress(ctx, result.Action); err != nil { return err } fmt.Printf("Rescue enabled for server %d with root password: %s\n", server.ID, result.RootPassword) return nil }, } cli-1.39.0/internal/cmd/server/ip.go000066400000000000000000000030171451614444200172050ustar00rootroot00000000000000package server import ( "context" "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" ) var IPCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "ip SERVER FLAGS", Short: "Print a server's IP address", Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.Server().Names)), TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.Flags().BoolP("ipv6", "6", false, "Print the first address of the IPv6 public server network") return cmd }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { ipv6, err := cmd.Flags().GetBool("ipv6") idOrName := args[0] server, _, err := client.Server().Get(ctx, idOrName) if err != nil { return err } if server == nil { return fmt.Errorf("server not found: %s", idOrName) } if ipv6 { if server.PublicNet.IPv6.IsUnspecified() { return fmt.Errorf("server %s has not primary IPv6", idOrName) } fmt.Println(server.PublicNet.IPv6.IP.String() + "1") } else { if server.PublicNet.IPv4.IsUnspecified() { return fmt.Errorf("server %s has not primary IPv4", idOrName) } fmt.Println(server.PublicNet.IPv4.IP.String()) } return nil }, } cli-1.39.0/internal/cmd/server/labels.go000066400000000000000000000022201451614444200200320ustar00rootroot00000000000000package server import ( "context" "fmt" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var labelCmds = base.LabelCmds{ ResourceNameSingular: "server", ShortDescriptionAdd: "Add a label to a server", ShortDescriptionRemove: "Remove a label from a server", NameSuggestions: func(c hcapi2.Client) func() []string { return c.Server().Names }, LabelKeySuggestions: func(c hcapi2.Client) func(idOrName string) []string { return c.Server().LabelKeys }, FetchLabels: func(ctx context.Context, client hcapi2.Client, idOrName string) (map[string]string, int64, error) { server, _, err := client.Server().Get(ctx, idOrName) if err != nil { return nil, 0, err } if server == nil { return nil, 0, fmt.Errorf("server not found: %s", idOrName) } return server.Labels, server.ID, nil }, SetLabels: func(ctx context.Context, client hcapi2.Client, id int64, labels map[string]string) error { opts := hcloud.ServerUpdateOpts{ Labels: labels, } _, _, err := client.Server().Update(ctx, &hcloud.Server{ID: id}, opts) return err }, } cli-1.39.0/internal/cmd/server/list.go000066400000000000000000000157331451614444200175600ustar00rootroot00000000000000package server import ( "context" "fmt" "strconv" "strings" "time" humanize "github.com/dustin/go-humanize" "github.com/spf13/pflag" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/output" "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" "github.com/hetznercloud/hcloud-go/v2/hcloud/schema" ) var ListCmd = base.ListCmd{ ResourceNamePlural: "Servers", JSONKeyGetByName: "servers", DefaultColumns: []string{"id", "name", "status", "ipv4", "ipv6", "private_net", "datacenter", "age"}, Fetch: func(ctx context.Context, client hcapi2.Client, _ *pflag.FlagSet, listOpts hcloud.ListOpts, sorts []string) ([]interface{}, error) { opts := hcloud.ServerListOpts{ListOpts: listOpts} if len(sorts) > 0 { opts.Sort = sorts } servers, err := client.Server().AllWithOpts(ctx, opts) var resources []interface{} for _, r := range servers { resources = append(resources, r) } return resources, err }, OutputTable: func(client hcapi2.Client) *output.Table { return output.NewTable(). AddAllowedFields(hcloud.Server{}). AddFieldFn("ipv4", output.FieldFn(func(obj interface{}) string { server := obj.(*hcloud.Server) if server.PublicNet.IPv4.IsUnspecified() { return "-" } return server.PublicNet.IPv4.IP.String() })). AddFieldFn("ipv6", output.FieldFn(func(obj interface{}) string { server := obj.(*hcloud.Server) if server.PublicNet.IPv6.IsUnspecified() { return "-" } return server.PublicNet.IPv6.Network.String() })). AddFieldFn("included_traffic", output.FieldFn(func(obj interface{}) string { server := obj.(*hcloud.Server) return humanize.IBytes(server.IncludedTraffic) })). AddFieldFn("ingoing_traffic", output.FieldFn(func(obj interface{}) string { server := obj.(*hcloud.Server) return humanize.IBytes(server.IngoingTraffic) })). AddFieldFn("outgoing_traffic", output.FieldFn(func(obj interface{}) string { server := obj.(*hcloud.Server) return humanize.IBytes(server.OutgoingTraffic) })). AddFieldFn("datacenter", output.FieldFn(func(obj interface{}) string { server := obj.(*hcloud.Server) return server.Datacenter.Name })). AddFieldFn("location", output.FieldFn(func(obj interface{}) string { server := obj.(*hcloud.Server) return server.Datacenter.Location.Name })). AddFieldFn("labels", output.FieldFn(func(obj interface{}) string { server := obj.(*hcloud.Server) return util.LabelsToString(server.Labels) })). AddFieldFn("type", output.FieldFn(func(obj interface{}) string { server := obj.(*hcloud.Server) return server.ServerType.Name })). AddFieldFn("volumes", output.FieldFn(func(obj interface{}) string { server := obj.(*hcloud.Server) var volumes []string for _, volume := range server.Volumes { volumeID := strconv.FormatInt(volume.ID, 10) volumes = append(volumes, volumeID) } return strings.Join(volumes, ", ") })). AddFieldFn("private_net", output.FieldFn(func(obj interface{}) string { server := obj.(*hcloud.Server) var networks []string for _, network := range server.PrivateNet { networks = append(networks, fmt.Sprintf("%s (%s)", network.IP.String(), client.Network().Name(network.Network.ID))) } return util.NA(strings.Join(networks, ", ")) })). AddFieldFn("protection", output.FieldFn(func(obj interface{}) string { server := obj.(*hcloud.Server) var protection []string if server.Protection.Delete { protection = append(protection, "delete") } if server.Protection.Rebuild { protection = append(protection, "rebuild") } return strings.Join(protection, ", ") })). AddFieldFn("created", output.FieldFn(func(obj interface{}) string { server := obj.(*hcloud.Server) return util.Datetime(server.Created) })). AddFieldFn("age", output.FieldFn(func(obj interface{}) string { server := obj.(*hcloud.Server) return util.Age(server.Created, time.Now()) })). AddFieldFn("placement_group", output.FieldFn(func(obj interface{}) string { server := obj.(*hcloud.Server) if server.PlacementGroup == nil { return "-" } return server.PlacementGroup.Name })) }, JSONSchema: func(resources []interface{}) interface{} { serversSchema := make([]schema.Server, 0, len(resources)) for _, resource := range resources { server := resource.(*hcloud.Server) serverSchema := schema.Server{ ID: server.ID, Name: server.Name, Status: string(server.Status), Created: server.Created, Datacenter: util.DatacenterToSchema(*server.Datacenter), ServerType: util.ServerTypeToSchema(*server.ServerType), PublicNet: schema.ServerPublicNet{ IPv4: schema.ServerPublicNetIPv4{ IP: server.PublicNet.IPv4.IP.String(), Blocked: server.PublicNet.IPv4.Blocked, DNSPtr: server.PublicNet.IPv4.DNSPtr, }, IPv6: schema.ServerPublicNetIPv6{ IP: server.PublicNet.IPv6.IP.String(), Blocked: server.PublicNet.IPv6.Blocked, }, }, RescueEnabled: server.RescueEnabled, BackupWindow: hcloud.String(server.BackupWindow), OutgoingTraffic: &server.OutgoingTraffic, IngoingTraffic: &server.IngoingTraffic, IncludedTraffic: server.IncludedTraffic, Protection: schema.ServerProtection{ Delete: server.Protection.Delete, Rebuild: server.Protection.Rebuild, }, Labels: server.Labels, PrimaryDiskSize: server.PrimaryDiskSize, } if server.PlacementGroup != nil { serverPlacementGroup := util.PlacementGroupToSchema(*server.PlacementGroup) serverSchema.PlacementGroup = &serverPlacementGroup } if server.Image != nil { serverImage := util.ImageToSchema(*server.Image) serverSchema.Image = &serverImage } if server.ISO != nil { serverISO := util.ISOToSchema(*server.ISO) serverSchema.ISO = &serverISO } for ip, dnsPTR := range server.PublicNet.IPv6.DNSPtr { serverSchema.PublicNet.IPv6.DNSPtr = append(serverSchema.PublicNet.IPv6.DNSPtr, schema.ServerPublicNetIPv6DNSPtr{ IP: ip, DNSPtr: dnsPTR, }) } for _, floatingIP := range server.PublicNet.FloatingIPs { serverSchema.PublicNet.FloatingIPs = append(serverSchema.PublicNet.FloatingIPs, floatingIP.ID) } for _, volume := range server.Volumes { serverSchema.Volumes = append(serverSchema.Volumes, volume.ID) } for _, privateNet := range server.PrivateNet { privateNetSchema := schema.ServerPrivateNet{ Network: privateNet.Network.ID, IP: privateNet.IP.String(), MACAddress: privateNet.MACAddress, } for _, aliasIP := range privateNet.Aliases { privateNetSchema.AliasIPs = append(privateNetSchema.AliasIPs, aliasIP.String()) } serverSchema.PrivateNet = append(serverSchema.PrivateNet, privateNetSchema) } serversSchema = append(serversSchema, serverSchema) } return serversSchema }, } cli-1.39.0/internal/cmd/server/metrics.go000066400000000000000000000066021451614444200202460ustar00rootroot00000000000000package server import ( "context" "encoding/json" "fmt" "sort" "strconv" "time" "github.com/guptarohit/asciigraph" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/cmd/output" "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var MetricsCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "metrics [FLAGS] SERVER", Short: "[ALPHA] Metrics from a Server", Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.Server().Names)), TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.Flags().String("type", "", "Type of metrics you want to show") cmd.MarkFlagRequired("type") cmd.RegisterFlagCompletionFunc("type", cmpl.SuggestCandidates("cpu", "disk", "network")) cmd.Flags().String("start", "", "ISO 8601 timestamp") cmd.Flags().String("end", "", "ISO 8601 timestamp") output.AddFlag(cmd, output.OptionJSON()) return cmd }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { outputFlags := output.FlagsForCommand(cmd) idOrName := args[0] server, _, err := client.Server().Get(ctx, idOrName) if err != nil { return err } if server == nil { return fmt.Errorf("server not found: %s", idOrName) } metricType, _ := cmd.Flags().GetString("type") start, _ := cmd.Flags().GetString("start") startTime := time.Now().Add(-30 * time.Minute) if start != "" { startTime, err = time.Parse(time.RFC3339, start) if err != nil { return fmt.Errorf("start date has an invalid format. It should be ISO 8601, like: %s", time.Now().Format(time.RFC3339)) } } end, _ := cmd.Flags().GetString("end") endTime := time.Now() if end != "" { endTime, err = time.Parse(time.RFC3339, end) if err != nil { return fmt.Errorf("end date has an invalid format. It should be ISO 8601, like: %s", time.Now().Format(time.RFC3339)) } } m, resp, err := client.Server().GetMetrics(ctx, server, hcloud.ServerGetMetricsOpts{ Types: []hcloud.ServerMetricType{hcloud.ServerMetricType(metricType)}, Start: startTime, End: endTime, }) if err != nil { return err } switch { case outputFlags.IsSet("json"): var data map[string]interface{} if err := json.NewDecoder(resp.Body).Decode(&data); err != nil { return err } return util.DescribeJSON(data) default: var keys []string for k := range m.TimeSeries { keys = append(keys, k) } sort.Strings(keys) for _, k := range keys { if len(m.TimeSeries[k]) == 0 { fmt.Printf("Currently there are now metrics available. Please try it again later.") return nil } fmt.Printf("Server: %s \t Metric: %s \t Start: %s \t End: %s\n", server.Name, k, m.Start.String(), m.End.String()) var data []float64 for _, m := range m.TimeSeries[k] { d, _ := strconv.ParseFloat(m.Value, 64) data = append(data, d) } graph := asciigraph.Plot(data, asciigraph.Height(20), asciigraph.Width(100)) fmt.Println(graph) fmt.Printf("\n\n") } } return nil }, } cli-1.39.0/internal/cmd/server/poweroff.go000066400000000000000000000023461451614444200204300ustar00rootroot00000000000000package server import ( "context" "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" ) var PoweroffCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { return &cobra.Command{ Use: "poweroff [FLAGS] SERVER", Short: "Poweroff a server", Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.Server().Names)), TraverseChildren: true, DisableFlagsInUseLine: true, } }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { idOrName := args[0] server, _, err := client.Server().Get(ctx, idOrName) if err != nil { return err } if server == nil { return fmt.Errorf("server not found: %s", idOrName) } action, _, err := client.Server().Poweroff(ctx, server) if err != nil { return err } if err := waiter.ActionProgress(ctx, action); err != nil { return err } fmt.Printf("Server %d stopped\n", server.ID) return nil }, } cli-1.39.0/internal/cmd/server/poweron.go000066400000000000000000000023421451614444200202660ustar00rootroot00000000000000package server import ( "context" "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" ) var PoweronCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { return &cobra.Command{ Use: "poweron [FLAGS] SERVER", Short: "Poweron a server", Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.Server().Names)), TraverseChildren: true, DisableFlagsInUseLine: true, } }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { idOrName := args[0] server, _, err := client.Server().Get(ctx, idOrName) if err != nil { return err } if server == nil { return fmt.Errorf("server not found: %s", idOrName) } action, _, err := client.Server().Poweron(ctx, server) if err != nil { return err } if err := waiter.ActionProgress(ctx, action); err != nil { return err } fmt.Printf("Server %d started\n", server.ID) return nil }, } cli-1.39.0/internal/cmd/server/reboot.go000066400000000000000000000023371451614444200200730ustar00rootroot00000000000000package server import ( "context" "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" ) var RebootCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { return &cobra.Command{ Use: "reboot [FLAGS] SERVER", Short: "Reboot a server", Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.Server().Names)), TraverseChildren: true, DisableFlagsInUseLine: true, } }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { idOrName := args[0] server, _, err := client.Server().Get(ctx, idOrName) if err != nil { return err } if server == nil { return fmt.Errorf("server not found: %s", idOrName) } action, _, err := client.Server().Reboot(ctx, server) if err != nil { return err } if err := waiter.ActionProgress(ctx, action); err != nil { return err } fmt.Printf("Server %d rebooted\n", server.ID) return nil }, } cli-1.39.0/internal/cmd/server/rebuild.go000066400000000000000000000055521451614444200202310ustar00rootroot00000000000000package server import ( "context" "fmt" "time" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var RebuildCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "rebuild [FLAGS] SERVER", Short: "Rebuild a server", Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.Server().Names)), TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.Flags().String("image", "", "ID or name of image to rebuild from (required)") cmd.RegisterFlagCompletionFunc("image", cmpl.SuggestCandidatesF(client.Image().Names)) cmd.MarkFlagRequired("image") cmd.Flags().Bool("allow-deprecated-image", false, "Enable the use of deprecated images (default: false)") return cmd }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { serverIDOrName := args[0] server, _, err := client.Server().Get(ctx, serverIDOrName) if err != nil { return err } if server == nil { return fmt.Errorf("server not found: %s", serverIDOrName) } imageIDOrName, _ := cmd.Flags().GetString("image") // Select correct image based on server type architecture image, _, err := client.Image().GetForArchitecture(ctx, imageIDOrName, server.ServerType.Architecture) if err != nil { return err } if image == nil { return fmt.Errorf("image %s for architecture %s not found", imageIDOrName, server.ServerType.Architecture) } allowDeprecatedImage, _ := cmd.Flags().GetBool("allow-deprecated-image") if !image.Deprecated.IsZero() { if allowDeprecatedImage { fmt.Printf("Attention: image %s is deprecated. It will continue to be available until %s.\n", image.Name, image.Deprecated.AddDate(0, 3, 0).Format(time.DateOnly)) } else { return fmt.Errorf("image %s is deprecated, please use --allow-deprecated-image to create a server with this image. It will continue to be available until %s", image.Name, image.Deprecated.AddDate(0, 3, 0).Format(time.DateOnly)) } } opts := hcloud.ServerRebuildOpts{ Image: image, } result, _, err := client.Server().RebuildWithResult(ctx, server, opts) if err != nil { return err } if err := waiter.ActionProgress(ctx, result.Action); err != nil { return err } fmt.Printf("Server %d rebuilt with image %s\n", server.ID, image.Name) // Only print the root password if it's not empty, // which is only the case if it wasn't created with an SSH key. if result.RootPassword != "" { fmt.Printf("Root password: %s\n", result.RootPassword) } return nil }, } cli-1.39.0/internal/cmd/server/remove_from_placement_group.go000066400000000000000000000024001451614444200243540ustar00rootroot00000000000000package server import ( "context" "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" ) var RemoveFromPlacementGroup = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "remove-from-placement-group SERVER", Short: "Removes a server from a placement group", Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.Server().Names)), } return cmd }, Run: func(ctx context.Context, client hcapi2.Client, actionWaiter state.ActionWaiter, cmd *cobra.Command, args []string) error { idOrName := args[0] server, _, err := client.Server().Get(ctx, idOrName) if err != nil { return err } if server == nil { return fmt.Errorf("server not found: %s", idOrName) } action, _, err := client.Server().RemoveFromPlacementGroup(ctx, server) if err != nil { return err } if err := actionWaiter.ActionProgress(ctx, action); err != nil { return err } fmt.Printf("Server %d removed from placement group\n", server.ID) return nil }, } cli-1.39.0/internal/cmd/server/remove_from_placement_group_test.go000066400000000000000000000017401451614444200254210ustar00rootroot00000000000000package server_test import ( "context" "testing" "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" "github.com/hetznercloud/cli/internal/cmd/server" "github.com/hetznercloud/cli/internal/testutil" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) func TestRemoveFromPlacementGroup(t *testing.T) { fx := testutil.NewFixture(t) defer fx.Finish() cmd := server.RemoveFromPlacementGroup.CobraCommand( context.Background(), fx.Client, fx.TokenEnsurer, fx.ActionWaiter) fx.ExpectEnsureToken() server := hcloud.Server{ ID: 42, Name: "my server", } fx.Client.ServerClient.EXPECT(). Get(gomock.Any(), server.Name). Return(&server, nil, nil) fx.Client.ServerClient.EXPECT(). RemoveFromPlacementGroup(gomock.Any(), &server) fx.ActionWaiter.EXPECT().ActionProgress(gomock.Any(), nil) out, err := fx.Run(cmd, []string{server.Name}) expOut := `Server 42 removed from placement group ` assert.NoError(t, err) assert.Equal(t, expOut, out) } cli-1.39.0/internal/cmd/server/request_console.go000066400000000000000000000034031451614444200220060ustar00rootroot00000000000000package server import ( "context" "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/cmd/output" "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" ) var RequestConsoleCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "request-console [FLAGS] SERVER", Short: "Request a WebSocket VNC console for a server", Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.Server().Names)), TraverseChildren: true, DisableFlagsInUseLine: true, } output.AddFlag(cmd, output.OptionJSON()) return cmd }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { outOpts := output.FlagsForCommand(cmd) idOrName := args[0] server, _, err := client.Server().Get(ctx, idOrName) if err != nil { return err } if server == nil { return fmt.Errorf("server not found: %s", idOrName) } result, _, err := client.Server().RequestConsole(ctx, server) if err != nil { return err } if err := waiter.ActionProgress(ctx, result.Action); err != nil { return err } if outOpts.IsSet("json") { return util.DescribeJSON(struct { WSSURL string Password string }{ WSSURL: result.WSSURL, Password: result.Password, }) } fmt.Printf("Console for server %d:\n", server.ID) fmt.Printf("WebSocket URL: %s\n", result.WSSURL) fmt.Printf("VNC Password: %s\n", result.Password) return nil }, } cli-1.39.0/internal/cmd/server/reset.go000066400000000000000000000023301451614444200177140ustar00rootroot00000000000000package server import ( "context" "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" ) var ResetCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { return &cobra.Command{ Use: "reset [FLAGS] SERVER", Short: "Reset a server", Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.Server().Names)), TraverseChildren: true, DisableFlagsInUseLine: true, } }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { idOrName := args[0] server, _, err := client.Server().Get(ctx, idOrName) if err != nil { return err } if server == nil { return fmt.Errorf("server not found: %s", idOrName) } action, _, err := client.Server().Reset(ctx, server) if err != nil { return err } if err := waiter.ActionProgress(ctx, action); err != nil { return err } fmt.Printf("Server %d reset\n", server.ID) return nil }, } cli-1.39.0/internal/cmd/server/reset_password.go000066400000000000000000000024651451614444200216470ustar00rootroot00000000000000package server import ( "context" "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" ) var ResetPasswordCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { return &cobra.Command{ Use: "reset-password [FLAGS] SERVER", Short: "Reset the root password of a server", Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.Server().Names)), TraverseChildren: true, DisableFlagsInUseLine: true, } }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { idOrName := args[0] server, _, err := client.Server().Get(ctx, idOrName) if err != nil { return err } if server == nil { return fmt.Errorf("server not found: %s", idOrName) } result, _, err := client.Server().ResetPassword(ctx, server) if err != nil { return err } if err := waiter.ActionProgress(ctx, result.Action); err != nil { return err } fmt.Printf("Password of server %d reset to: %s\n", server.ID, result.RootPassword) return nil }, } cli-1.39.0/internal/cmd/server/server.go000066400000000000000000000050241451614444200201030ustar00rootroot00000000000000package server import ( "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" ) func NewCommand(cli *state.State, client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "server", Short: "Manage servers", Args: cobra.NoArgs, TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.AddCommand( ListCmd.CobraCommand(cli.Context, client, cli), describeCmd.CobraCommand(cli.Context, client, cli), CreateCmd.CobraCommand(cli.Context, client, cli, cli), deleteCmd.CobraCommand(cli.Context, client, cli, cli), RebootCommand.CobraCommand(cli.Context, client, cli, cli), PoweronCommand.CobraCommand(cli.Context, client, cli, cli), PoweroffCommand.CobraCommand(cli.Context, client, cli, cli), ResetCommand.CobraCommand(cli.Context, client, cli, cli), ShutdownCommand.CobraCommand(cli.Context, client, cli, cli), newCreateImageCommand(cli), ResetPasswordCommand.CobraCommand(cli.Context, client, cli, cli), EnableRescueCommand.CobraCommand(cli.Context, client, cli, cli), DisableRescueCommand.CobraCommand(cli.Context, client, cli, cli), AttachISOCommand.CobraCommand(cli.Context, client, cli, cli), DetachISOCommand.CobraCommand(cli.Context, client, cli, cli), updateCmd.CobraCommand(cli.Context, client, cli), ChangeTypeCommand.CobraCommand(cli.Context, client, cli, cli), RebuildCommand.CobraCommand(cli.Context, client, cli, cli), EnableBackupCommand.CobraCommand(cli.Context, client, cli, cli), DisableBackupCommand.CobraCommand(cli.Context, client, cli, cli), EnableProtectionCommand.CobraCommand(cli.Context, client, cli, cli), DisableProtectionCommand.CobraCommand(cli.Context, client, cli, cli), SSHCommand.CobraCommand(cli.Context, client, cli, cli), labelCmds.AddCobraCommand(cli.Context, client, cli), labelCmds.RemoveCobraCommand(cli.Context, client, cli), setRDNSCmd.CobraCommand(cli.Context, client, cli, cli), AttachToNetworkCommand.CobraCommand(cli.Context, client, cli, cli), DetachFromNetworkCommand.CobraCommand(cli.Context, client, cli, cli), ChangeAliasIPsCommand.CobraCommand(cli.Context, client, cli, cli), IPCommand.CobraCommand(cli.Context, client, cli, cli), RequestConsoleCommand.CobraCommand(cli.Context, client, cli, cli), MetricsCommand.CobraCommand(cli.Context, client, cli, cli), AddToPlacementGroupCommand.CobraCommand(cli.Context, client, cli, cli), RemoveFromPlacementGroup.CobraCommand(cli.Context, client, cli, cli), ) return cmd } cli-1.39.0/internal/cmd/server/set_rdns.go000066400000000000000000000013461451614444200204210ustar00rootroot00000000000000package server import ( "context" "net" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var setRDNSCmd = base.SetRdnsCmd{ ResourceNameSingular: "Server", ShortDescription: "Change reverse DNS of a Server", NameSuggestions: func(c hcapi2.Client) func() []string { return c.Server().Names }, Fetch: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) { return client.Server().Get(ctx, idOrName) }, GetDefaultIP: func(resource interface{}) net.IP { server := resource.(*hcloud.Server) return server.PublicNet.IPv4.IP }, } cli-1.39.0/internal/cmd/server/shutdown.go000066400000000000000000000053411451614444200204520ustar00rootroot00000000000000package server import ( "context" "errors" "fmt" "time" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var ShutdownCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { const description = "Shuts down a Server gracefully by sending an ACPI shutdown request. " + "The Server operating system must support ACPI and react to the request, " + "otherwise the Server will not shut down. Use the --wait flag to wait for the " + "server to shut down before returning." cmd := &cobra.Command{ Use: "shutdown [FLAGS] SERVER", Short: "Shutdown a server", Long: description, Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.Server().Names)), TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.Flags().Bool("wait", false, "Wait for the server to shut down before exiting") cmd.Flags().Duration("wait-timeout", 30*time.Second, "Timeout for waiting for off state after shutdown") return cmd }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { wait, _ := cmd.Flags().GetBool("wait") timeout, _ := cmd.Flags().GetDuration("wait-timeout") idOrName := args[0] server, _, err := client.Server().Get(ctx, idOrName) if err != nil { return err } if server == nil { return fmt.Errorf("server not found: %s", idOrName) } action, _, err := client.Server().Shutdown(ctx, server) if err != nil { return err } if err := waiter.ActionProgress(ctx, action); err != nil { return err } fmt.Printf("Sent shutdown signal to server %d\n", server.ID) if wait { start := time.Now() errCh := make(chan error) interval, _ := cmd.Flags().GetDuration("poll-interval") if interval < time.Second { interval = time.Second } go func() { defer close(errCh) ticker := time.NewTicker(interval) defer ticker.Stop() for server.Status != hcloud.ServerStatusOff { if now := <-ticker.C; now.Sub(start) >= timeout { errCh <- errors.New("failed to shut down server") return } server, _, err = client.Server().GetByID(ctx, server.ID) if err != nil { errCh <- err return } } errCh <- nil }() if err := state.DisplayProgressCircle(errCh, "Waiting for server to shut down"); err != nil { return err } fmt.Printf("Server %d shut down\n", server.ID) } return nil }, } cli-1.39.0/internal/cmd/server/shutdown_test.go000066400000000000000000000036651451614444200215200ustar00rootroot00000000000000package server import ( "context" "testing" "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" "github.com/hetznercloud/cli/internal/testutil" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) func TestShutdown(t *testing.T) { fx := testutil.NewFixture(t) defer fx.Finish() cmd := ShutdownCommand.CobraCommand( context.Background(), fx.Client, fx.TokenEnsurer, fx.ActionWaiter) fx.ExpectEnsureToken() var ( server = hcloud.Server{ ID: 42, Name: "my server", Status: hcloud.ServerStatusRunning, } ) fx.Client.ServerClient.EXPECT(). Get(gomock.Any(), server.Name). Return(&server, nil, nil) fx.Client.ServerClient.EXPECT(). Shutdown(gomock.Any(), &server) fx.ActionWaiter.EXPECT().ActionProgress(gomock.Any(), nil) out, err := fx.Run(cmd, []string{server.Name}) expOut := "Sent shutdown signal to server 42\n" assert.NoError(t, err) assert.Equal(t, expOut, out) } func TestShutdownWait(t *testing.T) { fx := testutil.NewFixture(t) defer fx.Finish() cmd := ShutdownCommand.CobraCommand( context.Background(), fx.Client, fx.TokenEnsurer, fx.ActionWaiter) fx.ExpectEnsureToken() var ( server = hcloud.Server{ ID: 42, Name: "my server", Status: hcloud.ServerStatusRunning, } ) fx.Client.ServerClient.EXPECT(). Get(gomock.Any(), server.Name). Return(&server, nil, nil) fx.Client.ServerClient.EXPECT(). Shutdown(gomock.Any(), &server) fx.ActionWaiter.EXPECT().ActionProgress(gomock.Any(), nil) fx.Client.ServerClient.EXPECT(). GetByID(gomock.Any(), server.ID). Return(&server, nil, nil). Return(&server, nil, nil). Return(&hcloud.Server{ID: server.ID, Name: server.Name, Status: hcloud.ServerStatusOff}, nil, nil) out, err := fx.Run(cmd, []string{server.Name, "--wait"}) expOut := "Sent shutdown signal to server 42\nWaiting for server to shut down ... done\nServer 42 shut down\n" assert.NoError(t, err) assert.Equal(t, expOut, out) } cli-1.39.0/internal/cmd/server/ssh.go000066400000000000000000000045351451614444200174000ustar00rootroot00000000000000package server import ( "context" "fmt" "os" "os/exec" "strconv" "syscall" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" ) var SSHCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "ssh [FLAGS] SERVER [COMMAND...]", Short: "Spawn an SSH connection for the server", Args: cobra.MinimumNArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.Server().Names)), TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.Flags().SetInterspersed(false) // To make "hcloud server ssh uname -a" execute "uname -a" cmd.Flags().Bool("ipv6", false, "Establish SSH connection to IPv6 address") cmd.Flags().StringP("user", "u", "root", "Username for SSH connection") cmd.Flags().IntP("port", "p", 22, "Port for SSH connection") return cmd }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { idOrName := args[0] server, _, err := client.Server().Get(ctx, idOrName) if err != nil { return err } if server == nil { return fmt.Errorf("server not found: %s", idOrName) } useIPv6, _ := cmd.Flags().GetBool("ipv6") user, _ := cmd.Flags().GetString("user") port, _ := cmd.Flags().GetInt("port") ipAddress := server.PublicNet.IPv4.IP if server.PublicNet.IPv4.IsUnspecified() || useIPv6 { if server.PublicNet.IPv6.IsUnspecified() { return fmt.Errorf("server %s does not have a assigned primary ipv4 or ipv6", idOrName) } ipAddress = server.PublicNet.IPv6.Network.IP // increment last byte to get the ::1 IP, which is routed ipAddress[15]++ } sshArgs := []string{"-l", user, "-p", strconv.Itoa(port), ipAddress.String()} sshCommand := exec.Command("ssh", append(sshArgs, args[1:]...)...) sshCommand.Stdin = os.Stdin sshCommand.Stdout = os.Stdout sshCommand.Stderr = os.Stderr if err := sshCommand.Run(); err != nil { if exitError, ok := err.(*exec.ExitError); ok { waitStatus := exitError.Sys().(syscall.WaitStatus) os.Exit(waitStatus.ExitStatus()) } else { return err } } return nil }, } cli-1.39.0/internal/cmd/server/texts.go000066400000000000000000000017671451614444200177560ustar00rootroot00000000000000package server import ( "fmt" "time" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) func warningDeprecatedServerType(serverType *hcloud.ServerType) string { if !serverType.IsDeprecated() { return "" } if time.Now().After(serverType.UnavailableAfter()) { return fmt.Sprintf("Attention: The server plan %q is deprecated and can no longer be ordered. Existing servers of that plan will continue to work as before and no action is required on your part. It is possible to migrate this server to another server plan by using the \"hcloud server change-type\" command.\n\n", serverType.Name) } return fmt.Sprintf("Attention: The server plan %q is deprecated and will no longer be available for order as of %s. Existing servers of that plan will continue to work as before and no action is required on your part. It is possible to migrate this server to another server plan by using the \"hcloud server change-type\" command.\n\n", serverType.Name, serverType.UnavailableAfter().Format(time.DateOnly)) } cli-1.39.0/internal/cmd/server/update.go000066400000000000000000000020711451614444200200560ustar00rootroot00000000000000package server import ( "context" "github.com/spf13/cobra" "github.com/spf13/pflag" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var updateCmd = base.UpdateCmd{ ResourceNameSingular: "Server", ShortDescription: "Update a Server", NameSuggestions: func(c hcapi2.Client) func() []string { return c.Server().Names }, Fetch: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) { return client.Server().Get(ctx, idOrName) }, DefineFlags: func(cmd *cobra.Command) { cmd.Flags().String("name", "", "Server name") }, Update: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, resource interface{}, flags map[string]pflag.Value) error { floatingIP := resource.(*hcloud.Server) updOpts := hcloud.ServerUpdateOpts{ Name: flags["name"].String(), } _, _, err := client.Server().Update(ctx, floatingIP, updOpts) if err != nil { return err } return nil }, } cli-1.39.0/internal/cmd/servertype/000077500000000000000000000000001451614444200171475ustar00rootroot00000000000000cli-1.39.0/internal/cmd/servertype/describe.go000066400000000000000000000034321451614444200212600ustar00rootroot00000000000000package servertype import ( "context" "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var describeCmd = base.DescribeCmd{ ResourceNameSingular: "serverType", ShortDescription: "Describe a server type", JSONKeyGetByID: "server_type", JSONKeyGetByName: "server_types", NameSuggestions: func(c hcapi2.Client) func() []string { return c.ServerType().Names }, Fetch: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) { return client.ServerType().Get(ctx, idOrName) }, PrintText: func(_ context.Context, _ hcapi2.Client, _ *cobra.Command, resource interface{}) error { serverType := resource.(*hcloud.ServerType) fmt.Printf("ID:\t\t\t%d\n", serverType.ID) fmt.Printf("Name:\t\t\t%s\n", serverType.Name) fmt.Printf("Description:\t\t%s\n", serverType.Description) fmt.Printf("Cores:\t\t\t%d\n", serverType.Cores) fmt.Printf("CPU Type:\t\t%s\n", serverType.CPUType) fmt.Printf("Architecture:\t\t%s\n", serverType.Architecture) fmt.Printf("Memory:\t\t\t%.1f GB\n", serverType.Memory) fmt.Printf("Disk:\t\t\t%d GB\n", serverType.Disk) fmt.Printf("Storage Type:\t\t%s\n", serverType.StorageType) fmt.Printf("Included Traffic:\t%d TB\n", serverType.IncludedTraffic/util.Tebibyte) fmt.Printf(util.DescribeDeprecation(serverType)) fmt.Printf("Pricings per Location:\n") for _, price := range serverType.Pricings { fmt.Printf(" - Location:\t%s:\n", price.Location.Name) fmt.Printf(" Hourly:\t€ %s\n", price.Hourly.Gross) fmt.Printf(" Monthly:\t€ %s\n", price.Monthly.Gross) } return nil }, } cli-1.39.0/internal/cmd/servertype/list.go000066400000000000000000000040261451614444200204530ustar00rootroot00000000000000package servertype import ( "context" "fmt" "github.com/spf13/pflag" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/output" "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" "github.com/hetznercloud/hcloud-go/v2/hcloud/schema" ) var ListCmd = base.ListCmd{ ResourceNamePlural: "Server Types", JSONKeyGetByName: "server_types", DefaultColumns: []string{"id", "name", "cores", "cpu_type", "architecture", "memory", "disk", "storage_type", "traffic"}, Fetch: func(ctx context.Context, client hcapi2.Client, _ *pflag.FlagSet, listOpts hcloud.ListOpts, sorts []string) ([]interface{}, error) { opts := hcloud.ServerTypeListOpts{ListOpts: listOpts} if len(sorts) > 0 { opts.Sort = sorts } servers, _, err := client.ServerType().List(ctx, opts) var resources []interface{} for _, r := range servers { resources = append(resources, r) } return resources, err }, OutputTable: func(client hcapi2.Client) *output.Table { return output.NewTable(). AddAllowedFields(hcloud.ServerType{}). AddFieldAlias("storagetype", "storage type"). AddFieldFn("memory", output.FieldFn(func(obj interface{}) string { serverType := obj.(*hcloud.ServerType) return fmt.Sprintf("%.1f GB", serverType.Memory) })). AddFieldFn("disk", output.FieldFn(func(obj interface{}) string { serverType := obj.(*hcloud.ServerType) return fmt.Sprintf("%d GB", serverType.Disk) })). AddFieldFn("traffic", func(obj interface{}) string { serverType := obj.(*hcloud.ServerType) return fmt.Sprintf("%d TB", serverType.IncludedTraffic/util.Tebibyte) }) }, JSONSchema: func(resources []interface{}) interface{} { serverTypeSchemas := make([]schema.ServerType, 0, len(resources)) for _, resource := range resources { serverType := resource.(*hcloud.ServerType) serverTypeSchemas = append(serverTypeSchemas, util.ServerTypeToSchema(*serverType)) } return serverTypeSchemas }, } cli-1.39.0/internal/cmd/servertype/server_type.go000066400000000000000000000011031451614444200220400ustar00rootroot00000000000000package servertype import ( "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" ) func NewCommand(cli *state.State, client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "server-type", Short: "Manage server types", Args: cobra.NoArgs, TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.AddCommand( ListCmd.CobraCommand(cli.Context, client, cli), describeCmd.CobraCommand(cli.Context, client, cli), ) return cmd } cli-1.39.0/internal/cmd/sshkey/000077500000000000000000000000001451614444200162455ustar00rootroot00000000000000cli-1.39.0/internal/cmd/sshkey/create.go000066400000000000000000000042441451614444200200430ustar00rootroot00000000000000package sshkey import ( "errors" "fmt" "io/ioutil" "os" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) func newCreateCommand(cli *state.State) *cobra.Command { cmd := &cobra.Command{ Use: "create FLAGS", Short: "Create a SSH key", Args: cobra.NoArgs, TraverseChildren: true, DisableFlagsInUseLine: true, PreRunE: util.ChainRunE(validateCreate, cli.EnsureToken), RunE: cli.Wrap(runCreate), } cmd.Flags().String("name", "", "Key name (required)") cmd.Flags().String("public-key", "", "Public key") cmd.Flags().String("public-key-from-file", "", "Path to file containing public key") cmd.Flags().StringToString("label", nil, "User-defined labels ('key=value') (can be specified multiple times)") return cmd } func validateCreate(cmd *cobra.Command, args []string) error { if name, _ := cmd.Flags().GetString("name"); name == "" { return errors.New("flag --name is required") } publicKey, _ := cmd.Flags().GetString("public-key") publicKeyFile, _ := cmd.Flags().GetString("public-key-from-file") if publicKey != "" && publicKeyFile != "" { return errors.New("flags --public-key and --public-key-from-file are mutually exclusive") } return nil } func runCreate(cli *state.State, cmd *cobra.Command, args []string) error { name, _ := cmd.Flags().GetString("name") publicKey, _ := cmd.Flags().GetString("public-key") publicKeyFile, _ := cmd.Flags().GetString("public-key-from-file") labels, _ := cmd.Flags().GetStringToString("label") if publicKeyFile != "" { var ( data []byte err error ) if publicKeyFile == "-" { data, err = ioutil.ReadAll(os.Stdin) } else { data, err = ioutil.ReadFile(publicKeyFile) } if err != nil { return err } publicKey = string(data) } opts := hcloud.SSHKeyCreateOpts{ Name: name, PublicKey: publicKey, Labels: labels, } sshKey, _, err := cli.Client().SSHKey.Create(cli.Context, opts) if err != nil { return err } fmt.Printf("SSH key %d created\n", sshKey.ID) return nil } cli-1.39.0/internal/cmd/sshkey/delete.go000066400000000000000000000016121451614444200200360ustar00rootroot00000000000000package sshkey import ( "context" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var deleteCmd = base.DeleteCmd{ ResourceNameSingular: "SSH Key", ShortDescription: "Delete a SSH Key", NameSuggestions: func(c hcapi2.Client) func() []string { return c.SSHKey().Names }, Fetch: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) { return client.SSHKey().Get(ctx, idOrName) }, Delete: func(ctx context.Context, client hcapi2.Client, _ state.ActionWaiter, cmd *cobra.Command, resource interface{}) error { sshKey := resource.(*hcloud.SSHKey) if _, err := client.SSHKey().Delete(ctx, sshKey); err != nil { return err } return nil }, } cli-1.39.0/internal/cmd/sshkey/describe.go000066400000000000000000000026151451614444200203600ustar00rootroot00000000000000package sshkey import ( "context" "fmt" "strings" "github.com/dustin/go-humanize" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var describeCmd = base.DescribeCmd{ ResourceNameSingular: "SSH Key", ShortDescription: "Describe a SSH Key", JSONKeyGetByID: "ssh_key", JSONKeyGetByName: "ssh_keys", NameSuggestions: func(c hcapi2.Client) func() []string { return c.SSHKey().Names }, Fetch: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) { return client.SSHKey().Get(ctx, idOrName) }, PrintText: func(_ context.Context, _ hcapi2.Client, _ *cobra.Command, resource interface{}) error { sshKey := resource.(*hcloud.SSHKey) fmt.Printf("ID:\t\t%d\n", sshKey.ID) fmt.Printf("Name:\t\t%s\n", sshKey.Name) fmt.Printf("Created:\t%s (%s)\n", util.Datetime(sshKey.Created), humanize.Time(sshKey.Created)) fmt.Printf("Fingerprint:\t%s\n", sshKey.Fingerprint) fmt.Printf("Public Key:\n%s\n", strings.TrimSpace(sshKey.PublicKey)) fmt.Print("Labels:\n") if len(sshKey.Labels) == 0 { fmt.Print(" No labels\n") } else { for key, value := range sshKey.Labels { fmt.Printf(" %s: %s\n", key, value) } } return nil }, } cli-1.39.0/internal/cmd/sshkey/labels.go000066400000000000000000000022241451614444200200360ustar00rootroot00000000000000package sshkey import ( "context" "fmt" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var labelCmds = base.LabelCmds{ ResourceNameSingular: "SSH Key", ShortDescriptionAdd: "Add a label to a SSH Key", ShortDescriptionRemove: "Remove a label from a SSH Key", NameSuggestions: func(c hcapi2.Client) func() []string { return c.SSHKey().Names }, LabelKeySuggestions: func(c hcapi2.Client) func(idOrName string) []string { return c.SSHKey().LabelKeys }, FetchLabels: func(ctx context.Context, client hcapi2.Client, idOrName string) (map[string]string, int64, error) { sshKey, _, err := client.SSHKey().Get(ctx, idOrName) if err != nil { return nil, 0, err } if sshKey == nil { return nil, 0, fmt.Errorf("ssh key not found: %s", idOrName) } return sshKey.Labels, sshKey.ID, nil }, SetLabels: func(ctx context.Context, client hcapi2.Client, id int64, labels map[string]string) error { opts := hcloud.SSHKeyUpdateOpts{ Labels: labels, } _, _, err := client.SSHKey().Update(ctx, &hcloud.SSHKey{ID: id}, opts) return err }, } cli-1.39.0/internal/cmd/sshkey/list.go000066400000000000000000000040301451614444200175440ustar00rootroot00000000000000package sshkey import ( "context" "time" "github.com/spf13/pflag" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/output" "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" "github.com/hetznercloud/hcloud-go/v2/hcloud/schema" ) var ListCmd = base.ListCmd{ ResourceNamePlural: "SSH keys", JSONKeyGetByName: "ssh_keys", DefaultColumns: []string{"id", "name", "fingerprint", "age"}, Fetch: func(ctx context.Context, client hcapi2.Client, _ *pflag.FlagSet, listOpts hcloud.ListOpts, sorts []string) ([]interface{}, error) { opts := hcloud.SSHKeyListOpts{ListOpts: listOpts} if len(sorts) > 0 { opts.Sort = sorts } sshKeys, err := client.SSHKey().AllWithOpts(ctx, opts) var resources []interface{} for _, n := range sshKeys { resources = append(resources, n) } return resources, err }, OutputTable: func(_ hcapi2.Client) *output.Table { return output.NewTable(). AddAllowedFields(hcloud.SSHKey{}). AddFieldFn("labels", output.FieldFn(func(obj interface{}) string { sshKey := obj.(*hcloud.SSHKey) return util.LabelsToString(sshKey.Labels) })). AddFieldFn("created", output.FieldFn(func(obj interface{}) string { sshKey := obj.(*hcloud.SSHKey) return util.Datetime(sshKey.Created) })). AddFieldFn("age", output.FieldFn(func(obj interface{}) string { sshKey := obj.(*hcloud.SSHKey) return util.Age(sshKey.Created, time.Now()) })) }, JSONSchema: func(resources []interface{}) interface{} { sshKeySchemas := make([]schema.SSHKey, 0, len(resources)) for _, resource := range resources { sshKey := resource.(*hcloud.SSHKey) sshKeySchema := schema.SSHKey{ ID: sshKey.ID, Name: sshKey.Name, Fingerprint: sshKey.Fingerprint, PublicKey: sshKey.PublicKey, Labels: sshKey.Labels, Created: sshKey.Created, } sshKeySchemas = append(sshKeySchemas, sshKeySchema) } return sshKeySchemas }, } cli-1.39.0/internal/cmd/sshkey/sshkey.go000066400000000000000000000014561451614444200201100ustar00rootroot00000000000000package sshkey import ( "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" ) func NewCommand(cli *state.State, client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "ssh-key", Short: "Manage SSH keys", Args: cobra.NoArgs, TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.AddCommand( ListCmd.CobraCommand(cli.Context, client, cli), newCreateCommand(cli), updateCmd.CobraCommand(cli.Context, client, cli), deleteCmd.CobraCommand(cli.Context, client, cli, cli), describeCmd.CobraCommand(cli.Context, client, cli), labelCmds.AddCobraCommand(cli.Context, client, cli), labelCmds.RemoveCobraCommand(cli.Context, client, cli), ) return cmd } cli-1.39.0/internal/cmd/sshkey/update.go000066400000000000000000000020721451614444200200570ustar00rootroot00000000000000package sshkey import ( "context" "github.com/spf13/cobra" "github.com/spf13/pflag" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var updateCmd = base.UpdateCmd{ ResourceNameSingular: "SSHKey", ShortDescription: "Update a SSHKey", NameSuggestions: func(c hcapi2.Client) func() []string { return c.SSHKey().Names }, Fetch: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) { return client.SSHKey().Get(ctx, idOrName) }, DefineFlags: func(cmd *cobra.Command) { cmd.Flags().String("name", "", "SSH Key name") }, Update: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, resource interface{}, flags map[string]pflag.Value) error { floatingIP := resource.(*hcloud.SSHKey) updOpts := hcloud.SSHKeyUpdateOpts{ Name: flags["name"].String(), } _, _, err := client.SSHKey().Update(ctx, floatingIP, updOpts) if err != nil { return err } return nil }, } cli-1.39.0/internal/cmd/util/000077500000000000000000000000001451614444200157145ustar00rootroot00000000000000cli-1.39.0/internal/cmd/util/byte_units.go000066400000000000000000000002221451614444200204240ustar00rootroot00000000000000package util const ( Byte = 1 Kibibyte = Byte * 1024 Mebibyte = Kibibyte * 1024 Gibibyte = Mebibyte * 1024 Tebibyte = Gibibyte * 1024 ) cli-1.39.0/internal/cmd/util/deprecation.go000066400000000000000000000010441451614444200205370ustar00rootroot00000000000000package util import ( "fmt" "github.com/dustin/go-humanize" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) func DescribeDeprecation(resource hcloud.Deprecatable) string { if !resource.IsDeprecated() { return "" } info := "Deprecation:\n" info += fmt.Sprintf(" Announced:\t\t%s (%s)\n", Datetime(resource.DeprecationAnnounced()), humanize.Time(resource.DeprecationAnnounced())) info += fmt.Sprintf(" Unavailable After:\t%s (%s)\n", Datetime(resource.UnavailableAfter()), humanize.Time(resource.UnavailableAfter())) return info } cli-1.39.0/internal/cmd/util/util.go000066400000000000000000000221771451614444200172310ustar00rootroot00000000000000package util import ( "encoding/json" "fmt" "os" "sort" "strings" "text/template" "time" "github.com/spf13/cobra" "github.com/spf13/pflag" "github.com/hetznercloud/hcloud-go/v2/hcloud" "github.com/hetznercloud/hcloud-go/v2/hcloud/schema" ) func YesNo(b bool) string { if b { return "yes" } return "no" } func NA(s string) string { if s == "" { return "-" } return s } func Datetime(t time.Time) string { return t.Local().Format(time.UnixDate) } func Age(t, currentTime time.Time) string { diff := currentTime.Sub(t) if int(diff.Hours()) >= 24 { days := int(diff.Hours()) / 24 return fmt.Sprintf("%dd", days) } if int(diff.Hours()) > 0 { return fmt.Sprintf("%dh", int(diff.Hours())) } if int(diff.Minutes()) > 0 { return fmt.Sprintf("%dm", int(diff.Minutes())) } if int(diff.Seconds()) > 0 { return fmt.Sprintf("%ds", int(diff.Seconds())) } return "just now" } func ChainRunE(fns ...func(cmd *cobra.Command, args []string) error) func(cmd *cobra.Command, args []string) error { return func(cmd *cobra.Command, args []string) error { for _, fn := range fns { if fn == nil { continue } if err := fn(cmd, args); err != nil { return err } } return nil } } func ExactlyOneSet(s string, ss ...string) bool { set := s != "" for _, s := range ss { if set && s != "" { return false } set = set || s != "" } return set } var outputDescription = `Output can be controlled with the -o flag. Use -o noheader to suppress the table header. Displayed columns and their order can be set with -o columns=%s (see available columns below).` func ListLongDescription(intro string, columns []string) string { var colExample []string if len(columns) > 2 { colExample = columns[0:2] } else { colExample = columns } return fmt.Sprintf( "%s\n\n%s\n\nColumns:\n - %s", intro, fmt.Sprintf(outputDescription, strings.Join(colExample, ",")), strings.Join(columns, "\n - "), ) } func SplitLabel(label string) []string { return strings.SplitN(label, "=", 2) } // SplitLabelVars splits up label into key and value and returns them as separate return values. // If label doesn't contain the `=` separator, SplitLabelVars returns the original string as key, // with an empty value. func SplitLabelVars(label string) (string, string) { parts := strings.SplitN(label, "=", 2) if len(parts) != 2 { return label, "" } return parts[0], parts[1] } func LabelsToString(labels map[string]string) string { var labelsString []string keys := make([]string, 0, len(labels)) for key := range labels { keys = append(keys, key) } sort.Strings(keys) for _, key := range keys { value := labels[key] if value == "" { labelsString = append(labelsString, key) } else { labelsString = append(labelsString, fmt.Sprintf("%s=%s", key, value)) } } return strings.Join(labelsString, ", ") } // PrefixLines will prefix all individual lines in the text with the passed prefix. func PrefixLines(text, prefix string) string { var lines []string for _, line := range strings.Split(text, "\n") { lines = append(lines, prefix+line) } return strings.Join(lines, "\n") } func DescribeFormat(object interface{}, format string) error { if !strings.HasSuffix(format, "\n") { format = format + "\n" } t, err := template.New("").Parse(format) if err != nil { return err } return t.Execute(os.Stdout, object) } func DescribeJSON(object interface{}) error { enc := json.NewEncoder(os.Stdout) return enc.Encode(object) } func LocationToSchema(location hcloud.Location) schema.Location { return schema.Location{ ID: location.ID, Name: location.Name, Description: location.Description, Country: location.Country, City: location.City, Latitude: location.Latitude, Longitude: location.Longitude, NetworkZone: string(location.NetworkZone), } } func DatacenterToSchema(datacenter hcloud.Datacenter) schema.Datacenter { datacenterSchema := schema.Datacenter{ ID: datacenter.ID, Name: datacenter.Name, Description: datacenter.Description, Location: LocationToSchema(*datacenter.Location), } for _, st := range datacenter.ServerTypes.Supported { datacenterSchema.ServerTypes.Supported = append(datacenterSchema.ServerTypes.Supported, st.ID) } for _, st := range datacenter.ServerTypes.Available { datacenterSchema.ServerTypes.Available = append(datacenterSchema.ServerTypes.Available, st.ID) } return datacenterSchema } func ServerTypeToSchema(serverType hcloud.ServerType) schema.ServerType { serverTypeSchema := schema.ServerType{ ID: serverType.ID, Name: serverType.Name, Description: serverType.Description, Cores: serverType.Cores, Memory: serverType.Memory, Disk: serverType.Disk, StorageType: string(serverType.StorageType), CPUType: string(serverType.CPUType), Architecture: string(serverType.Architecture), IncludedTraffic: serverType.IncludedTraffic, DeprecatableResource: DeprecatableResourceToSchema(serverType.DeprecatableResource), } for _, pricing := range serverType.Pricings { serverTypeSchema.Prices = append(serverTypeSchema.Prices, schema.PricingServerTypePrice{ Location: pricing.Location.Name, PriceHourly: schema.Price{ Net: pricing.Hourly.Net, Gross: pricing.Hourly.Gross, }, PriceMonthly: schema.Price{ Net: pricing.Monthly.Net, Gross: pricing.Monthly.Gross, }, }) } return serverTypeSchema } func ImageToSchema(image hcloud.Image) schema.Image { imageSchema := schema.Image{ ID: image.ID, Name: hcloud.String(image.Name), Description: image.Description, Status: string(image.Status), Type: string(image.Type), ImageSize: &image.ImageSize, DiskSize: image.DiskSize, Created: image.Created, OSFlavor: image.OSFlavor, OSVersion: hcloud.String(image.OSVersion), Architecture: string(image.Architecture), RapidDeploy: image.RapidDeploy, Protection: schema.ImageProtection{ Delete: image.Protection.Delete, }, Deprecated: image.Deprecated, Labels: image.Labels, } if image.CreatedFrom != nil { imageSchema.CreatedFrom = &schema.ImageCreatedFrom{ ID: image.CreatedFrom.ID, Name: image.CreatedFrom.Name, } } if image.BoundTo != nil { imageSchema.BoundTo = hcloud.Ptr(image.BoundTo.ID) } return imageSchema } func ISOToSchema(iso hcloud.ISO) schema.ISO { isoSchema := schema.ISO{ ID: iso.ID, Name: iso.Name, Description: iso.Description, Type: string(iso.Type), Deprecated: iso.Deprecated, } if iso.Architecture != nil { isoSchema.Architecture = hcloud.Ptr(string(*iso.Architecture)) } return isoSchema } func LoadBalancerTypeToSchema(loadBalancerType hcloud.LoadBalancerType) schema.LoadBalancerType { loadBalancerTypeSchema := schema.LoadBalancerType{ ID: loadBalancerType.ID, Name: loadBalancerType.Name, Description: loadBalancerType.Description, MaxConnections: loadBalancerType.MaxConnections, MaxServices: loadBalancerType.MaxServices, MaxTargets: loadBalancerType.MaxTargets, MaxAssignedCertificates: loadBalancerType.MaxAssignedCertificates, } for _, pricing := range loadBalancerType.Pricings { loadBalancerTypeSchema.Prices = append(loadBalancerTypeSchema.Prices, schema.PricingLoadBalancerTypePrice{ Location: pricing.Location.Name, PriceHourly: schema.Price{ Net: pricing.Hourly.Net, Gross: pricing.Hourly.Gross, }, PriceMonthly: schema.Price{ Net: pricing.Monthly.Net, Gross: pricing.Monthly.Gross, }, }) } return loadBalancerTypeSchema } func PlacementGroupToSchema(placementGroup hcloud.PlacementGroup) schema.PlacementGroup { return schema.PlacementGroup{ ID: placementGroup.ID, Name: placementGroup.Name, Labels: placementGroup.Labels, Created: placementGroup.Created, Type: string(placementGroup.Type), Servers: placementGroup.Servers, } } func DeprecatableResourceToSchema(deprecatableResource hcloud.DeprecatableResource) schema.DeprecatableResource { var deprecation *schema.DeprecationInfo if deprecatableResource.IsDeprecated() { deprecation = &schema.DeprecationInfo{ Announced: deprecatableResource.Deprecation.Announced, UnavailableAfter: deprecatableResource.Deprecation.UnavailableAfter, } } return schema.DeprecatableResource{ Deprecation: deprecation, } } // ValidateRequiredFlags ensures that flags has values for all flags with // the passed names. // // This function duplicates the functionality cobra provides when calling // MarkFlagRequired. However, in some cases a flag cannot be marked as required // in cobra, for example when it depends on other flags. In those cases this // function comes in handy. func ValidateRequiredFlags(flags *pflag.FlagSet, names ...string) error { var missingFlags []string for _, name := range names { if !flags.Changed(name) { missingFlags = append(missingFlags, `"`+name+`"`) } } if len(missingFlags) > 0 { return fmt.Errorf("hcloud: required flag(s) %s not set", strings.Join(missingFlags, ", ")) } return nil } cli-1.39.0/internal/cmd/util/util_internal_test.go000066400000000000000000000044341451614444200221600ustar00rootroot00000000000000package util import ( "testing" "time" ) func TestOnlyOneSet(t *testing.T) { tests := []struct { name string s string ss []string expected bool }{ { name: "only arg emtpy", expected: false, }, { name: "only arg non-empty", s: "s", expected: true, }, { name: "first arg non-empty, rest empty", s: "s", ss: []string{""}, expected: true, }, { name: "at least one other arg non-empty", s: "s", ss: []string{"", "s"}, }, { name: "only one arg non-empty", ss: []string{"", "s"}, expected: true, }, } for _, tt := range tests { tt := tt t.Run(tt.name, func(t *testing.T) { actual := ExactlyOneSet(tt.s, tt.ss...) if tt.expected != actual { t.Errorf("expected %t; got %t", tt.expected, actual) } }) } } func TestAge(t *testing.T) { tests := []struct { name string t time.Time now time.Time expected string }{ { name: "exactly now", t: time.Date(2022, 11, 17, 15, 22, 12, 11, time.UTC), now: time.Date(2022, 11, 17, 15, 22, 12, 11, time.UTC), expected: "just now", }, { name: "within a few milliseconds", t: time.Date(2022, 11, 17, 15, 22, 12, 11, time.UTC), now: time.Date(2022, 11, 17, 15, 22, 12, 21, time.UTC), expected: "just now", }, { name: "10 seconds", t: time.Date(2022, 11, 17, 15, 22, 12, 21, time.UTC), now: time.Date(2022, 11, 17, 15, 22, 22, 21, time.UTC), expected: "10s", }, { name: "10 minutes", t: time.Date(2022, 11, 17, 15, 22, 12, 21, time.UTC), now: time.Date(2022, 11, 17, 15, 32, 12, 21, time.UTC), expected: "10m", }, { name: "24 hours", t: time.Date(2022, 11, 17, 15, 22, 12, 21, time.UTC), now: time.Date(2022, 11, 18, 15, 22, 12, 21, time.UTC), expected: "1d", }, { name: "25 hours", t: time.Date(2022, 11, 17, 15, 22, 12, 21, time.UTC), now: time.Date(2022, 11, 18, 16, 22, 12, 21, time.UTC), expected: "1d", }, } for _, tt := range tests { tt := tt t.Run(tt.name, func(t *testing.T) { actual := Age(tt.t, tt.now) if tt.expected != actual { t.Errorf("expected %s; got %s", tt.expected, actual) } }) } } cli-1.39.0/internal/cmd/version/000077500000000000000000000000001451614444200164245ustar00rootroot00000000000000cli-1.39.0/internal/cmd/version/version.go000066400000000000000000000011211451614444200204330ustar00rootroot00000000000000package version import ( "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/cli/internal/version" ) func NewCommand(cli *state.State) *cobra.Command { cmd := &cobra.Command{ Use: "version", Short: "Print version information", Args: cobra.NoArgs, DisableFlagsInUseLine: true, RunE: cli.Wrap(runVersion), } return cmd } func runVersion(cli *state.State, cmd *cobra.Command, args []string) error { fmt.Printf("hcloud %s\n", version.Version) return nil } cli-1.39.0/internal/cmd/volume/000077500000000000000000000000001451614444200162465ustar00rootroot00000000000000cli-1.39.0/internal/cmd/volume/attach.go000066400000000000000000000036531451614444200200500ustar00rootroot00000000000000package volume import ( "context" "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var AttachCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "attach [FLAGS] VOLUME", Short: "Attach a volume to a server", Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.Volume().Names)), TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.Flags().String("server", "", "Server (ID or name) (required)") cmd.RegisterFlagCompletionFunc("server", cmpl.SuggestCandidatesF(client.Server().Names)) cmd.MarkFlagRequired("server") cmd.Flags().Bool("automount", false, "Automount volume after attach") return cmd }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { volume, _, err := client.Volume().Get(ctx, args[0]) if err != nil { return err } if volume == nil { return fmt.Errorf("volume not found: %s", args[0]) } serverIDOrName, _ := cmd.Flags().GetString("server") server, _, err := client.Server().Get(ctx, serverIDOrName) if err != nil { return err } if server == nil { return fmt.Errorf("server not found: %s", serverIDOrName) } automount, _ := cmd.Flags().GetBool("automount") action, _, err := client.Volume().AttachWithOpts(ctx, volume, hcloud.VolumeAttachOpts{ Server: server, Automount: &automount, }) if err != nil { return err } if err := waiter.ActionProgress(ctx, action); err != nil { return err } fmt.Printf("Volume %d attached to server %s\n", volume.ID, server.Name) return nil }, } cli-1.39.0/internal/cmd/volume/create.go000066400000000000000000000065731451614444200200530ustar00rootroot00000000000000package volume import ( "context" "fmt" "strconv" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var CreateCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "create FLAGS", Short: "Create a volume", Args: cobra.NoArgs, TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.Flags().String("name", "", "Volume name (required)") cmd.MarkFlagRequired("name") cmd.Flags().String("server", "", "Server (ID or name)") cmd.RegisterFlagCompletionFunc("server", cmpl.SuggestCandidatesF(client.Server().Names)) cmd.Flags().String("location", "", "Location (ID or name)") cmd.RegisterFlagCompletionFunc("location", cmpl.SuggestCandidatesF(client.Location().Names)) cmd.Flags().Int("size", 0, "Size (GB) (required)") cmd.MarkFlagRequired("size") cmd.Flags().Bool("automount", false, "Automount volume after attach (server must be provided)") cmd.Flags().String("format", "", "Format volume after creation (ext4 or xfs)") cmd.RegisterFlagCompletionFunc("format", cmpl.SuggestCandidates("ext4", "xfs")) cmd.Flags().StringToString("label", nil, "User-defined labels ('key=value') (can be specified multiple times)") cmd.Flags().StringSlice("enable-protection", []string{}, "Enable protection (delete) (default: none)") cmd.RegisterFlagCompletionFunc("enable-protection", cmpl.SuggestCandidates("delete")) return cmd }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { name, _ := cmd.Flags().GetString("name") serverIDOrName, _ := cmd.Flags().GetString("server") size, _ := cmd.Flags().GetInt("size") location, _ := cmd.Flags().GetString("location") automount, _ := cmd.Flags().GetBool("automount") format, _ := cmd.Flags().GetString("format") labels, _ := cmd.Flags().GetStringToString("label") protection, _ := cmd.Flags().GetStringSlice("enable-protection") protectionOpts, err := getChangeProtectionOpts(true, protection) if err != nil { return err } createOpts := hcloud.VolumeCreateOpts{ Name: name, Size: size, Labels: labels, } if location != "" { id, err := strconv.ParseInt(location, 10, 64) if err == nil { createOpts.Location = &hcloud.Location{ID: id} } else { createOpts.Location = &hcloud.Location{Name: location} } } if serverIDOrName != "" { server, _, err := client.Server().Get(ctx, serverIDOrName) if err != nil { return err } if server == nil { return fmt.Errorf("server not found: %s", serverIDOrName) } createOpts.Server = server } if automount { createOpts.Automount = &automount } if format != "" { createOpts.Format = &format } result, _, err := client.Volume().Create(ctx, createOpts) if err != nil { return err } if err := waiter.ActionProgress(ctx, result.Action); err != nil { return err } if err := waiter.WaitForActions(ctx, result.NextActions); err != nil { return err } fmt.Printf("Volume %d created\n", result.Volume.ID) return changeProtection(ctx, client, waiter, result.Volume, true, protectionOpts) }, } cli-1.39.0/internal/cmd/volume/delete.go000066400000000000000000000016101451614444200200350ustar00rootroot00000000000000package volume import ( "context" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var deleteCmd = base.DeleteCmd{ ResourceNameSingular: "Volume", ShortDescription: "Delete a Volume", NameSuggestions: func(c hcapi2.Client) func() []string { return c.Volume().Names }, Fetch: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) { return client.Volume().Get(ctx, idOrName) }, Delete: func(ctx context.Context, client hcapi2.Client, _ state.ActionWaiter, cmd *cobra.Command, resource interface{}) error { volume := resource.(*hcloud.Volume) if _, err := client.Volume().Delete(ctx, volume); err != nil { return err } return nil }, } cli-1.39.0/internal/cmd/volume/describe.go000066400000000000000000000041571451614444200203640ustar00rootroot00000000000000package volume import ( "context" "fmt" humanize "github.com/dustin/go-humanize" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var describeCmd = base.DescribeCmd{ ResourceNameSingular: "volume", ShortDescription: "Describe an Volume", JSONKeyGetByID: "volume", JSONKeyGetByName: "volumes", NameSuggestions: func(c hcapi2.Client) func() []string { return c.Volume().Names }, Fetch: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) { return client.Volume().Get(ctx, idOrName) }, PrintText: func(_ context.Context, client hcapi2.Client, cmd *cobra.Command, resource interface{}) error { volume := resource.(*hcloud.Volume) fmt.Printf("ID:\t\t%d\n", volume.ID) fmt.Printf("Name:\t\t%s\n", volume.Name) fmt.Printf("Created:\t%s (%s)\n", util.Datetime(volume.Created), humanize.Time(volume.Created)) fmt.Printf("Size:\t\t%s\n", humanize.Bytes(uint64(volume.Size*humanize.GByte))) fmt.Printf("Linux Device:\t%s\n", volume.LinuxDevice) fmt.Printf("Location:\n") fmt.Printf(" Name:\t\t%s\n", volume.Location.Name) fmt.Printf(" Description:\t%s\n", volume.Location.Description) fmt.Printf(" Country:\t%s\n", volume.Location.Country) fmt.Printf(" City:\t\t%s\n", volume.Location.City) fmt.Printf(" Latitude:\t%f\n", volume.Location.Latitude) fmt.Printf(" Longitude:\t%f\n", volume.Location.Longitude) if volume.Server != nil { fmt.Printf("Server:\n") fmt.Printf(" ID:\t\t%d\n", volume.Server.ID) fmt.Printf(" Name:\t\t%s\n", client.Server().ServerName(volume.Server.ID)) } else { fmt.Print("Server:\n Not attached\n") } fmt.Printf("Protection:\n") fmt.Printf(" Delete:\t%s\n", util.YesNo(volume.Protection.Delete)) fmt.Print("Labels:\n") if len(volume.Labels) == 0 { fmt.Print(" No labels\n") } else { for key, value := range volume.Labels { fmt.Printf(" %s: %s\n", key, value) } } return nil }, } cli-1.39.0/internal/cmd/volume/detach.go000066400000000000000000000023071451614444200200270ustar00rootroot00000000000000package volume import ( "context" "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" ) var DetachCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { return &cobra.Command{ Use: "detach [FLAGS] VOLUME", Short: "Detach a volume", Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.Volume().Names)), TraverseChildren: true, DisableFlagsInUseLine: true, } }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { volume, _, err := client.Volume().Get(ctx, args[0]) if err != nil { return err } if volume == nil { return fmt.Errorf("volume not found: %s", args[0]) } action, _, err := client.Volume().Detach(ctx, volume) if err != nil { return err } if err := waiter.ActionProgress(ctx, action); err != nil { return err } fmt.Printf("Volume %d detached\n", volume.ID) return nil }, } cli-1.39.0/internal/cmd/volume/disable_protection.go000066400000000000000000000023221451614444200224450ustar00rootroot00000000000000package volume import ( "context" "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" ) var DisableProtectionCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { return &cobra.Command{ Use: "disable-protection [FLAGS] VOLUME PROTECTIONLEVEL [PROTECTIONLEVEL...]", Short: "Disable resource protection for a volume", Args: cobra.MinimumNArgs(2), ValidArgsFunction: cmpl.SuggestArgs( cmpl.SuggestCandidatesF(client.Volume().Names), cmpl.SuggestCandidates("delete"), ), TraverseChildren: true, DisableFlagsInUseLine: true, } }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { volume, _, err := client.Volume().Get(ctx, args[0]) if err != nil { return err } if volume == nil { return fmt.Errorf("volume not found: %s", args[0]) } opts, err := getChangeProtectionOpts(false, args[1:]) if err != nil { return err } return changeProtection(ctx, client, waiter, volume, false, opts) }, } cli-1.39.0/internal/cmd/volume/enable_protection.go000066400000000000000000000044511451614444200222750ustar00rootroot00000000000000package volume import ( "context" "fmt" "strings" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) func getChangeProtectionOpts(enable bool, flags []string) (hcloud.VolumeChangeProtectionOpts, error) { opts := hcloud.VolumeChangeProtectionOpts{} var unknown []string for _, arg := range flags { switch strings.ToLower(arg) { case "delete": opts.Delete = hcloud.Ptr(enable) default: unknown = append(unknown, arg) } } if len(unknown) > 0 { return opts, fmt.Errorf("unknown protection level: %s", strings.Join(unknown, ", ")) } return opts, nil } func changeProtection(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, volume *hcloud.Volume, enable bool, opts hcloud.VolumeChangeProtectionOpts) error { if opts.Delete == nil { return nil } action, _, err := client.Volume().ChangeProtection(ctx, volume, opts) if err != nil { return err } if err := waiter.ActionProgress(ctx, action); err != nil { return err } if enable { fmt.Printf("Resource protection enabled for volume %d\n", volume.ID) } else { fmt.Printf("Resource protection disabled for volume %d\n", volume.ID) } return nil } var EnableProtectionCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { return &cobra.Command{ Use: "enable-protection [FLAGS] VOLUME PROTECTIONLEVEL [PROTECTIONLEVEL...]", Short: "Enable resource protection for a volume", Args: cobra.MinimumNArgs(2), ValidArgsFunction: cmpl.SuggestArgs( cmpl.SuggestCandidatesF(client.Volume().Names), cmpl.SuggestCandidates("delete"), ), TraverseChildren: true, DisableFlagsInUseLine: true, } }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { volume, _, err := client.Volume().Get(ctx, args[0]) if err != nil { return err } if volume == nil { return fmt.Errorf("volume not found: %s", args[0]) } opts, err := getChangeProtectionOpts(true, args[1:]) if err != nil { return err } return changeProtection(ctx, client, waiter, volume, true, opts) }, } cli-1.39.0/internal/cmd/volume/labels.go000066400000000000000000000022201451614444200200330ustar00rootroot00000000000000package volume import ( "context" "fmt" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var labelCmds = base.LabelCmds{ ResourceNameSingular: "Volume", ShortDescriptionAdd: "Add a label to a Volume", ShortDescriptionRemove: "Remove a label from a Volume", NameSuggestions: func(c hcapi2.Client) func() []string { return c.Volume().Names }, LabelKeySuggestions: func(c hcapi2.Client) func(idOrName string) []string { return c.Volume().LabelKeys }, FetchLabels: func(ctx context.Context, client hcapi2.Client, idOrName string) (map[string]string, int64, error) { volume, _, err := client.Volume().Get(ctx, idOrName) if err != nil { return nil, 0, err } if volume == nil { return nil, 0, fmt.Errorf("volume not found: %s", idOrName) } return volume.Labels, volume.ID, nil }, SetLabels: func(ctx context.Context, client hcapi2.Client, id int64, labels map[string]string) error { opts := hcloud.VolumeUpdateOpts{ Labels: labels, } _, _, err := client.Volume().Update(ctx, &hcloud.Volume{ID: id}, opts) return err }, } cli-1.39.0/internal/cmd/volume/list.go000066400000000000000000000062141451614444200175530ustar00rootroot00000000000000package volume import ( "context" "strings" "time" humanize "github.com/dustin/go-humanize" "github.com/spf13/pflag" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/output" "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" "github.com/hetznercloud/hcloud-go/v2/hcloud/schema" ) var ListCmd = base.ListCmd{ ResourceNamePlural: "Volumes", JSONKeyGetByName: "volumes", DefaultColumns: []string{"id", "name", "size", "server", "location", "age"}, Fetch: func(ctx context.Context, client hcapi2.Client, _ *pflag.FlagSet, listOpts hcloud.ListOpts, sorts []string) ([]interface{}, error) { opts := hcloud.VolumeListOpts{ListOpts: listOpts} if len(sorts) > 0 { opts.Sort = sorts } volumes, err := client.Volume().AllWithOpts(ctx, opts) var resources []interface{} for _, n := range volumes { resources = append(resources, n) } return resources, err }, OutputTable: func(client hcapi2.Client) *output.Table { return output.NewTable(). AddAllowedFields(hcloud.Volume{}). AddFieldFn("server", output.FieldFn(func(obj interface{}) string { volume := obj.(*hcloud.Volume) var server string if volume.Server != nil { return client.Server().ServerName(volume.Server.ID) } return util.NA(server) })). AddFieldFn("size", output.FieldFn(func(obj interface{}) string { volume := obj.(*hcloud.Volume) return humanize.Bytes(uint64(volume.Size * humanize.GByte)) })). AddFieldFn("location", output.FieldFn(func(obj interface{}) string { volume := obj.(*hcloud.Volume) return volume.Location.Name })). AddFieldFn("protection", output.FieldFn(func(obj interface{}) string { volume := obj.(*hcloud.Volume) var protection []string if volume.Protection.Delete { protection = append(protection, "delete") } return strings.Join(protection, ", ") })). AddFieldFn("labels", output.FieldFn(func(obj interface{}) string { volume := obj.(*hcloud.Volume) return util.LabelsToString(volume.Labels) })). AddFieldFn("created", output.FieldFn(func(obj interface{}) string { volume := obj.(*hcloud.Volume) return util.Datetime(volume.Created) })). AddFieldFn("age", output.FieldFn(func(obj interface{}) string { volume := obj.(*hcloud.Volume) return util.Age(volume.Created, time.Now()) })) }, JSONSchema: func(resources []interface{}) interface{} { volumesSchema := make([]schema.Volume, 0, len(resources)) for _, resource := range resources { volume := resource.(*hcloud.Volume) volumeSchema := schema.Volume{ ID: volume.ID, Name: volume.Name, Location: util.LocationToSchema(*volume.Location), Size: volume.Size, LinuxDevice: volume.LinuxDevice, Labels: volume.Labels, Created: volume.Created, Protection: schema.VolumeProtection{Delete: volume.Protection.Delete}, } if volume.Server != nil { volumeSchema.Server = hcloud.Ptr(volume.Server.ID) } volumesSchema = append(volumesSchema, volumeSchema) } return volumesSchema }, } cli-1.39.0/internal/cmd/volume/resize.go000066400000000000000000000026701451614444200201030ustar00rootroot00000000000000package volume import ( "context" "fmt" "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/cmpl" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" ) var ResizeCommand = base.Cmd{ BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "resize [FLAGS] VOLUME", Short: "Resize a volume", Args: cobra.ExactArgs(1), ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.Volume().Names)), TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.Flags().Int("size", 0, "New size (GB) of the volume (required)") cmd.MarkFlagRequired("size") return cmd }, Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error { volume, _, err := client.Volume().Get(ctx, args[0]) if err != nil { return err } if volume == nil { return fmt.Errorf("volume not found: %s", args[0]) } size, _ := cmd.Flags().GetInt("size") action, _, err := client.Volume().Resize(ctx, volume, size) if err != nil { return err } if err := waiter.ActionProgress(ctx, action); err != nil { return err } fmt.Printf("Volume %d resized\n", volume.ID) fmt.Printf("You might need to adjust the filesystem size on the server too\n") return nil }, } cli-1.39.0/internal/cmd/volume/update.go000066400000000000000000000020711451614444200200570ustar00rootroot00000000000000package volume import ( "context" "github.com/spf13/cobra" "github.com/spf13/pflag" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) var updateCmd = base.UpdateCmd{ ResourceNameSingular: "Volume", ShortDescription: "Update a Volume", NameSuggestions: func(c hcapi2.Client) func() []string { return c.Volume().Names }, Fetch: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) { return client.Volume().Get(ctx, idOrName) }, DefineFlags: func(cmd *cobra.Command) { cmd.Flags().String("name", "", "Volume name") }, Update: func(ctx context.Context, client hcapi2.Client, cmd *cobra.Command, resource interface{}, flags map[string]pflag.Value) error { floatingIP := resource.(*hcloud.Volume) updOpts := hcloud.VolumeUpdateOpts{ Name: flags["name"].String(), } _, _, err := client.Volume().Update(ctx, floatingIP, updOpts) if err != nil { return err } return nil }, } cli-1.39.0/internal/cmd/volume/volume.go000066400000000000000000000022261451614444200201060ustar00rootroot00000000000000package volume import ( "github.com/spf13/cobra" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" ) func NewCommand(cli *state.State, client hcapi2.Client) *cobra.Command { cmd := &cobra.Command{ Use: "volume", Short: "Manage Volumes", Args: cobra.NoArgs, TraverseChildren: true, DisableFlagsInUseLine: true, } cmd.AddCommand( ListCmd.CobraCommand(cli.Context, client, cli), CreateCommand.CobraCommand(cli.Context, client, cli, cli), updateCmd.CobraCommand(cli.Context, client, cli), deleteCmd.CobraCommand(cli.Context, client, cli, cli), describeCmd.CobraCommand(cli.Context, client, cli), AttachCommand.CobraCommand(cli.Context, client, cli, cli), DetachCommand.CobraCommand(cli.Context, client, cli, cli), ResizeCommand.CobraCommand(cli.Context, client, cli, cli), EnableProtectionCommand.CobraCommand(cli.Context, client, cli, cli), DisableProtectionCommand.CobraCommand(cli.Context, client, cli, cli), labelCmds.AddCobraCommand(cli.Context, client, cli), labelCmds.RemoveCobraCommand(cli.Context, client, cli), ) return cmd } cli-1.39.0/internal/hcapi2/000077500000000000000000000000001451614444200153425ustar00rootroot00000000000000cli-1.39.0/internal/hcapi2/certificate.go000066400000000000000000000023741451614444200201610ustar00rootroot00000000000000package hcapi2 import ( "context" "strconv" ) // CertificateClient embeds the Hetzner Cloud Certificate client and provides some // additional helper functions. type CertificateClient interface { CertificateClientBase Names() []string LabelKeys(string) []string } func NewCertificateClient(client CertificateClientBase) CertificateClient { return &certificateClient{ CertificateClientBase: client, } } type certificateClient struct { CertificateClientBase } // Names obtains a list of available data centers. It returns nil if // data center names could not be fetched. func (c *certificateClient) Names() []string { dcs, err := c.All(context.Background()) if err != nil || len(dcs) == 0 { return nil } names := make([]string, len(dcs)) for i, dc := range dcs { name := dc.Name if name == "" { name = strconv.FormatInt(dc.ID, 10) } names[i] = name } return names } // LabelKeys returns a slice containing the keys of all labels // assigned to the certificate with the passed idOrName. func (c *certificateClient) LabelKeys(idOrName string) []string { certificate, _, err := c.Get(context.Background(), idOrName) if err != nil || certificate == nil || len(certificate.Labels) == 0 { return nil } return labelKeys(certificate.Labels) } cli-1.39.0/internal/hcapi2/client.go000066400000000000000000000116001451614444200171450ustar00rootroot00000000000000package hcapi2 import ( "sync" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) // Client makes all API clients accessible via a single interface. type Client interface { Datacenter() DatacenterClient Firewall() FirewallClient FloatingIP() FloatingIPClient Image() ImageClient Location() LocationClient Network() NetworkClient Server() ServerClient ServerType() ServerTypeClient SSHKey() SSHKeyClient Volume() VolumeClient Certificate() CertificateClient LoadBalancer() LoadBalancerClient LoadBalancerType() LoadBalancerTypeClient ISO() ISOClient PlacementGroup() PlacementGroupClient RDNS() RDNSClient PrimaryIP() PrimaryIPClient } type client struct { client *hcloud.Client certificateClient CertificateClient datacenterClient DatacenterClient serverClient ServerClient serverTypeClient ServerTypeClient locationClient LocationClient loadBalancerClient LoadBalancerClient loadBalancerTypeClient LoadBalancerTypeClient networkClient NetworkClient firewallClient FirewallClient floatingIPClient FloatingIPClient imageClient ImageClient isoClient ISOClient sshKeyClient SSHKeyClient volumeClient VolumeClient placementGroupClient PlacementGroupClient rdnsClient RDNSClient primaryIPClient PrimaryIPClient mu sync.Mutex } // NewClient creates a new CLI API client extending hcloud.Client. func NewClient(c *hcloud.Client) Client { return &client{ client: c, } } func (c *client) Certificate() CertificateClient { c.mu.Lock() if c.certificateClient == nil { c.certificateClient = NewCertificateClient(&c.client.Certificate) } defer c.mu.Unlock() return c.certificateClient } func (c *client) Datacenter() DatacenterClient { c.mu.Lock() if c.datacenterClient == nil { c.datacenterClient = NewDatacenterClient(&c.client.Datacenter) } defer c.mu.Unlock() return c.datacenterClient } func (c *client) Firewall() FirewallClient { c.mu.Lock() if c.firewallClient == nil { c.firewallClient = NewFirewallClient(&c.client.Firewall) } defer c.mu.Unlock() return c.firewallClient } func (c *client) FloatingIP() FloatingIPClient { c.mu.Lock() if c.floatingIPClient == nil { c.floatingIPClient = NewFloatingIPClient(&c.client.FloatingIP) } defer c.mu.Unlock() return c.floatingIPClient } func (c *client) PrimaryIP() PrimaryIPClient { c.mu.Lock() if c.primaryIPClient == nil { c.primaryIPClient = NewPrimaryIPClient(&c.client.PrimaryIP) } defer c.mu.Unlock() return c.primaryIPClient } func (c *client) Image() ImageClient { c.mu.Lock() if c.imageClient == nil { c.imageClient = NewImageClient(&c.client.Image) } defer c.mu.Unlock() return c.imageClient } func (c *client) ISO() ISOClient { c.mu.Lock() if c.isoClient == nil { c.isoClient = NewISOClient(&c.client.ISO) } defer c.mu.Unlock() return c.isoClient } func (c *client) Location() LocationClient { c.mu.Lock() if c.locationClient == nil { c.locationClient = NewLocationClient(&c.client.Location) } defer c.mu.Unlock() return c.locationClient } func (c *client) LoadBalancer() LoadBalancerClient { c.mu.Lock() if c.loadBalancerClient == nil { c.loadBalancerClient = NewLoadBalancerClient(&c.client.LoadBalancer) } defer c.mu.Unlock() return c.loadBalancerClient } func (c *client) LoadBalancerType() LoadBalancerTypeClient { c.mu.Lock() if c.loadBalancerTypeClient == nil { c.loadBalancerTypeClient = NewLoadBalancerTypeClient(&c.client.LoadBalancerType) } defer c.mu.Unlock() return c.loadBalancerTypeClient } func (c *client) Network() NetworkClient { c.mu.Lock() if c.networkClient == nil { c.networkClient = NewNetworkClient(&c.client.Network) } defer c.mu.Unlock() return c.networkClient } func (c *client) Server() ServerClient { c.mu.Lock() if c.serverClient == nil { c.serverClient = NewServerClient(&c.client.Server) } defer c.mu.Unlock() return c.serverClient } func (c *client) ServerType() ServerTypeClient { c.mu.Lock() if c.serverTypeClient == nil { c.serverTypeClient = NewServerTypeClient(&c.client.ServerType) } defer c.mu.Unlock() return c.serverTypeClient } func (c *client) SSHKey() SSHKeyClient { c.mu.Lock() if c.sshKeyClient == nil { c.sshKeyClient = NewSSHKeyClient(&c.client.SSHKey) } defer c.mu.Unlock() return c.sshKeyClient } func (c *client) RDNS() RDNSClient { c.mu.Lock() if c.rdnsClient == nil { c.rdnsClient = NewRDNSClient(&c.client.RDNS) } defer c.mu.Unlock() return c.rdnsClient } func (c *client) Volume() VolumeClient { c.mu.Lock() if c.volumeClient == nil { c.volumeClient = NewVolumeClient(&c.client.Volume) } defer c.mu.Unlock() return c.volumeClient } func (c *client) PlacementGroup() PlacementGroupClient { c.mu.Lock() if c.placementGroupClient == nil { c.placementGroupClient = NewPlacementGroupClient(&c.client.PlacementGroup) } defer c.mu.Unlock() return c.placementGroupClient } cli-1.39.0/internal/hcapi2/datacenter.go000066400000000000000000000015341451614444200200060ustar00rootroot00000000000000package hcapi2 import ( "context" "strconv" ) // DatacenterClient embeds the Hetzner Cloud DataCenter client and provides some // additional helper functions. type DatacenterClient interface { DatacenterClientBase Names() []string } func NewDatacenterClient(client DatacenterClientBase) DatacenterClient { return &datacenterClient{ DatacenterClientBase: client, } } type datacenterClient struct { DatacenterClientBase } // Names obtains a list of available data centers. It returns nil if // data center names could not be fetched. func (c *datacenterClient) Names() []string { dcs, err := c.All(context.Background()) if err != nil || len(dcs) == 0 { return nil } names := make([]string, len(dcs)) for i, dc := range dcs { name := dc.Name if name == "" { name = strconv.FormatInt(dc.ID, 10) } names[i] = name } return names } cli-1.39.0/internal/hcapi2/firewall.go000066400000000000000000000024111451614444200174740ustar00rootroot00000000000000package hcapi2 import ( "context" "strconv" ) type FirewallClient interface { FirewallClientBase Names() []string LabelKeys(string) []string } func NewFirewallClient(client FirewallClientBase) FirewallClient { return &firewallClient{ FirewallClientBase: client, } } // FirewallClient embeds the Hetzner Cloud Firewall client and provides // some additional helper functions. type firewallClient struct { FirewallClientBase } // Names obtains a list of available firewalls. It returns nil if // the firewall names could not be fetched or there were no firewalls. func (c *firewallClient) Names() []string { firewalls, err := c.All(context.Background()) if err != nil || len(firewalls) == 0 { return nil } names := make([]string, len(firewalls)) for i, firewall := range firewalls { name := firewall.Name if name == "" { name = strconv.FormatInt(firewall.ID, 10) } names[i] = name } return names } // LabelKeys returns a slice containing the keys of all labels // assigned to the firewall with the passed idOrName. func (c *firewallClient) LabelKeys(idOrName string) []string { firewall, _, err := c.Get(context.Background(), idOrName) if err != nil || firewall == nil || len(firewall.Labels) == 0 { return nil } return labelKeys(firewall.Labels) } cli-1.39.0/internal/hcapi2/floatingip.go000066400000000000000000000026521451614444200200320ustar00rootroot00000000000000package hcapi2 import ( "context" "strconv" ) // FloatingIPClient embeds the hcloud FloatingIPClient (via an interface) and provides // some additional helper functions. type FloatingIPClient interface { FloatingIPClientBase Names() []string LabelKeys(idOrName string) []string } // NewFloatingIPClient creates a new floating IP client. func NewFloatingIPClient(client FloatingIPClientBase) FloatingIPClient { return &floatingIPClient{ FloatingIPClientBase: client, } } // FloatingIPClient embeds the Hetzner Cloud FloatingIP client and provides some // additional helper functions. type floatingIPClient struct { FloatingIPClientBase } // Names obtains a list of available floating IPs. It returns nil if // no floating IP names could be fetched or none were available. func (c *floatingIPClient) Names() []string { fips, err := c.All(context.Background()) if err != nil || len(fips) == 0 { return nil } names := make([]string, len(fips)) for i, fip := range fips { name := fip.Name if name == "" { name = strconv.FormatInt(fip.ID, 10) } names[i] = name } return names } // LabelKeys returns a slice containing the keys of all labels // assigned to the Floating IP with the passed idOrName. func (c *floatingIPClient) LabelKeys(idOrName string) []string { fip, _, err := c.Get(context.Background(), idOrName) if err != nil || fip == nil || len(fip.Labels) == 0 { return nil } return labelKeys(fip.Labels) } cli-1.39.0/internal/hcapi2/image.go000066400000000000000000000023571451614444200167620ustar00rootroot00000000000000package hcapi2 import ( "context" "strconv" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) // ImageClient embeds the Hetzner Cloud Image client and provides some // additional helper functions. type ImageClient interface { ImageClientBase Names() []string LabelKeys(string) []string } func NewImageClient(client ImageClientBase) ImageClient { return &imageClient{ ImageClientBase: client, } } type imageClient struct { ImageClientBase } // Names obtains a list of available images. It returns nil if image names // could not be fetched. func (c *imageClient) Names() []string { imgs, err := c.AllWithOpts(context.Background(), hcloud.ImageListOpts{IncludeDeprecated: true}) if err != nil || len(imgs) == 0 { return nil } names := make([]string, len(imgs)) for i, img := range imgs { name := img.Name if name == "" { name = strconv.FormatInt(img.ID, 10) } names[i] = name } return names } // ImageLabelKeys returns a slice containing the keys of all labels assigned to // the Image with the passed idOrName. func (c *imageClient) LabelKeys(idOrName string) []string { img, _, err := c.Get(context.Background(), idOrName) if err != nil || img == nil || len(img.Labels) == 0 { return nil } return labelKeys(img.Labels) } cli-1.39.0/internal/hcapi2/interface_gen.go000066400000000000000000000050261451614444200204650ustar00rootroot00000000000000package hcapi2 //go:generate interfacer -for github.com/hetznercloud/hcloud-go/v2/hcloud.CertificateClient -as hcapi2.CertificateClientBase -o zz_certificate_client_base.go //go:generate interfacer -for github.com/hetznercloud/hcloud-go/v2/hcloud.DatacenterClient -as hcapi2.DatacenterClientBase -o zz_datacenter_client_base.go //go:generate interfacer -for github.com/hetznercloud/hcloud-go/v2/hcloud.ImageClient -as hcapi2.ImageClientBase -o zz_image_client_base.go //go:generate interfacer -for github.com/hetznercloud/hcloud-go/v2/hcloud.ISOClient -as hcapi2.ISOClientBase -o zz_iso_client_base.go //go:generate interfacer -for github.com/hetznercloud/hcloud-go/v2/hcloud.FirewallClient -as hcapi2.FirewallClientBase -o zz_firewall_client_base.go //go:generate interfacer -for github.com/hetznercloud/hcloud-go/v2/hcloud.FloatingIPClient -as hcapi2.FloatingIPClientBase -o zz_floating_ip_client_base.go //go:generate interfacer -for github.com/hetznercloud/hcloud-go/v2/hcloud.LocationClient -as hcapi2.LocationClientBase -o zz_location_client_base.go //go:generate interfacer -for github.com/hetznercloud/hcloud-go/v2/hcloud.LoadBalancerClient -as hcapi2.LoadBalancerClientBase -o zz_loadbalancer_client_base.go //go:generate interfacer -for github.com/hetznercloud/hcloud-go/v2/hcloud.LoadBalancerTypeClient -as hcapi2.LoadBalancerTypeClientBase -o zz_loadbalancer_type_client_base.go //go:generate interfacer -for github.com/hetznercloud/hcloud-go/v2/hcloud.NetworkClient -as hcapi2.NetworkClientBase -o zz_network_client_base.go //go:generate interfacer -for github.com/hetznercloud/hcloud-go/v2/hcloud.ServerClient -as hcapi2.ServerClientBase -o zz_server_client_base.go //go:generate interfacer -for github.com/hetznercloud/hcloud-go/v2/hcloud.ServerTypeClient -as hcapi2.ServerTypeClientBase -o zz_server_type_client_base.go //go:generate interfacer -for github.com/hetznercloud/hcloud-go/v2/hcloud.SSHKeyClient -as hcapi2.SSHKeyClientBase -o zz_ssh_key_client_base.go //go:generate interfacer -for github.com/hetznercloud/hcloud-go/v2/hcloud.VolumeClient -as hcapi2.VolumeClientBase -o zz_volume_client_base.go //go:generate interfacer -for github.com/hetznercloud/hcloud-go/v2/hcloud.PlacementGroupClient -as hcapi2.PlacementGroupClientBase -o zz_placement_group_client_base.go //go:generate interfacer -for github.com/hetznercloud/hcloud-go/v2/hcloud.RDNSClient -as hcapi2.RDNSClientBase -o zz_rdns_client_base.go //go:generate interfacer -for github.com/hetznercloud/hcloud-go/v2/hcloud.PrimaryIPClient -as hcapi2.PrimaryIPClientBase -o zz_primary_ip_client_base.go cli-1.39.0/internal/hcapi2/iso.go000066400000000000000000000014071451614444200164650ustar00rootroot00000000000000package hcapi2 import ( "context" "strconv" ) // ISOClient embeds the Hetzner Cloud iso client and provides some // additional helper functions. type ISOClient interface { ISOClientBase Names() []string } func NewISOClient(client ISOClientBase) ISOClient { return &isoClient{ ISOClientBase: client, } } type isoClient struct { ISOClientBase } // Names obtains a list of available data centers. It returns nil if // iso names could not be fetched. func (c *isoClient) Names() []string { isos, err := c.All(context.Background()) if err != nil || len(isos) == 0 { return nil } names := make([]string, len(isos)) for i, iso := range isos { name := iso.Name if name == "" { name = strconv.FormatInt(iso.ID, 10) } names[i] = name } return names } cli-1.39.0/internal/hcapi2/labels.go000066400000000000000000000002331451614444200171310ustar00rootroot00000000000000package hcapi2 func labelKeys(m map[string]string) []string { ks := make([]string, len(m)) i := 0 for k := range m { ks[i] = k i++ } return ks } cli-1.39.0/internal/hcapi2/load_balancer_type.go000066400000000000000000000043321451614444200215020ustar00rootroot00000000000000package hcapi2 import ( "context" "strconv" "sync" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) type LoadBalancerTypeClient interface { LoadBalancerTypeClientBase Names() []string LoadBalancerTypeName(id int64) string LoadBalancerTypeDescription(id int64) string } func NewLoadBalancerTypeClient(client LoadBalancerTypeClientBase) LoadBalancerTypeClient { return &loadBalancerTypeClient{ LoadBalancerTypeClientBase: client, } } type loadBalancerTypeClient struct { LoadBalancerTypeClientBase lbTypeByID map[int64]*hcloud.LoadBalancerType once sync.Once err error } // LoadBalancerTypeName obtains the name of the loadBalancer type with id. If the name could not // be fetched it returns the value id converted to a string. func (c *loadBalancerTypeClient) LoadBalancerTypeName(id int64) string { if err := c.init(); err != nil { return strconv.FormatInt(id, 10) } loadBalancerType, ok := c.lbTypeByID[id] if !ok || loadBalancerType.Name == "" { return strconv.FormatInt(id, 10) } return loadBalancerType.Name } // LoadBalancerTypeDescription obtains the description of the loadBalancer type with id. If the name could not // be fetched it returns the value id converted to a string. func (c *loadBalancerTypeClient) LoadBalancerTypeDescription(id int64) string { if err := c.init(); err != nil { return strconv.FormatInt(id, 10) } loadBalancerType, ok := c.lbTypeByID[id] if !ok || loadBalancerType.Description == "" { return strconv.FormatInt(id, 10) } return loadBalancerType.Description } // Names returns a slice of all available loadBalancer types. func (c *loadBalancerTypeClient) Names() []string { sts, err := c.All(context.Background()) if err != nil || len(sts) == 0 { return nil } names := make([]string, len(sts)) for i, st := range sts { names[i] = st.Name } return names } func (c *loadBalancerTypeClient) init() error { c.once.Do(func() { loadBalancerTypes, err := c.All(context.Background()) if err != nil { c.err = err } if c.err != nil || len(loadBalancerTypes) == 0 { return } c.lbTypeByID = make(map[int64]*hcloud.LoadBalancerType, len(loadBalancerTypes)) for _, srv := range loadBalancerTypes { c.lbTypeByID[srv.ID] = srv } }) return c.err } cli-1.39.0/internal/hcapi2/loadbalancer.go000066400000000000000000000042041451614444200203000ustar00rootroot00000000000000package hcapi2 import ( "context" "strconv" "sync" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) // LoadBalancerClient embeds the Hetzner Cloud LoadBalancer client and provides some // additional helper functions. type LoadBalancerClient interface { LoadBalancerClientBase LoadBalancerName(id int64) string Names() []string LabelKeys(string) []string } func NewLoadBalancerClient(client LoadBalancerClientBase) LoadBalancerClient { return &loadBalancerClient{ LoadBalancerClientBase: client, } } type loadBalancerClient struct { LoadBalancerClientBase lbByID map[int64]*hcloud.LoadBalancer once sync.Once err error } // LoadBalancerName obtains the name of the server with id. If the name could not // be fetched it returns the value id converted to a string. func (c *loadBalancerClient) LoadBalancerName(id int64) string { if err := c.init(); err != nil { return strconv.FormatInt(id, 10) } lb, ok := c.lbByID[id] if !ok || lb.Name == "" { return strconv.FormatInt(id, 10) } return lb.Name } // Names obtains a list of available data centers. It returns nil if // data center names could not be fetched. func (c *loadBalancerClient) Names() []string { dcs, err := c.All(context.Background()) if err != nil || len(dcs) == 0 { return nil } names := make([]string, len(dcs)) for i, dc := range dcs { name := dc.Name if name == "" { name = strconv.FormatInt(dc.ID, 10) } names[i] = name } return names } // LabelKeys returns a slice containing the keys of all labels // assigned to the loadBalancer with the passed idOrName. func (c *loadBalancerClient) LabelKeys(idOrName string) []string { loadBalancer, _, err := c.Get(context.Background(), idOrName) if err != nil || loadBalancer == nil || len(loadBalancer.Labels) == 0 { return nil } return labelKeys(loadBalancer.Labels) } func (c *loadBalancerClient) init() error { c.once.Do(func() { srvs, err := c.All(context.Background()) if err != nil { c.err = err } if c.err != nil || len(srvs) == 0 { return } c.lbByID = make(map[int64]*hcloud.LoadBalancer, len(srvs)) for _, srv := range srvs { c.lbByID[srv.ID] = srv } }) return c.err } cli-1.39.0/internal/hcapi2/location.go000066400000000000000000000025321451614444200175030ustar00rootroot00000000000000package hcapi2 import ( "context" "strconv" ) // LocationClient embeds the Hetzner Cloud Location client and provides some // additional helper functions. type LocationClient interface { LocationClientBase Names() []string NetworkZones() []string } func NewLocationClient(client LocationClientBase) LocationClient { return &locationClient{ LocationClientBase: client, } } type locationClient struct { LocationClientBase } // Names obtains a list of available locations. It returns nil if // location names could not be fetched. func (c *locationClient) Names() []string { locs, err := c.All(context.Background()) if err != nil || len(locs) == 0 { return nil } names := make([]string, len(locs)) for i, loc := range locs { name := loc.Name if name == "" { name = strconv.FormatInt(loc.ID, 10) } names[i] = name } return names } // NetworkZones obtains a list of available network zones. It returns nil if // location data could not be fetched. func (c *locationClient) NetworkZones() []string { locs, err := c.All(context.Background()) if err != nil || len(locs) == 0 { return nil } zones := make(map[string]bool) for _, loc := range locs { if loc.NetworkZone != "" { zones[string(loc.NetworkZone)] = true } } var zoneList []string for zone := range zones { zoneList = append(zoneList, zone) } return zoneList } cli-1.39.0/internal/hcapi2/mock/000077500000000000000000000000001451614444200162735ustar00rootroot00000000000000cli-1.39.0/internal/hcapi2/mock/client.go000066400000000000000000000064631451614444200201110ustar00rootroot00000000000000package hcapi2_mock import ( "github.com/golang/mock/gomock" "github.com/hetznercloud/cli/internal/hcapi2" ) type MockClient struct { CertificateClient *MockCertificateClient DatacenterClient *MockDatacenterClient FirewallClient *MockFirewallClient FloatingIPClient *MockFloatingIPClient PrimaryIPClient *MockPrimaryIPClient ImageClient *MockImageClient LocationClient *MockLocationClient LoadBalancerClient *MockLoadBalancerClient LoadBalancerTypeClient *MockLoadBalancerTypeClient NetworkClient *MockNetworkClient ServerClient *MockServerClient ServerTypeClient *MockServerTypeClient SSHKeyClient *MockSSHKeyClient VolumeClient *MockVolumeClient ISOClient *MockISOClient PlacementGroupClient *MockPlacementGroupClient RDNSClient *MockRDNSClient } func NewMockClient(ctrl *gomock.Controller) *MockClient { return &MockClient{ CertificateClient: NewMockCertificateClient(ctrl), DatacenterClient: NewMockDatacenterClient(ctrl), FirewallClient: NewMockFirewallClient(ctrl), FloatingIPClient: NewMockFloatingIPClient(ctrl), PrimaryIPClient: NewMockPrimaryIPClient(ctrl), ImageClient: NewMockImageClient(ctrl), LocationClient: NewMockLocationClient(ctrl), LoadBalancerClient: NewMockLoadBalancerClient(ctrl), LoadBalancerTypeClient: NewMockLoadBalancerTypeClient(ctrl), NetworkClient: NewMockNetworkClient(ctrl), ServerClient: NewMockServerClient(ctrl), ServerTypeClient: NewMockServerTypeClient(ctrl), SSHKeyClient: NewMockSSHKeyClient(ctrl), VolumeClient: NewMockVolumeClient(ctrl), ISOClient: NewMockISOClient(ctrl), PlacementGroupClient: NewMockPlacementGroupClient(ctrl), RDNSClient: NewMockRDNSClient(ctrl), } } func (c *MockClient) Certificate() hcapi2.CertificateClient { return c.CertificateClient } func (c *MockClient) Datacenter() hcapi2.DatacenterClient { return c.DatacenterClient } func (c *MockClient) Firewall() hcapi2.FirewallClient { return c.FirewallClient } func (c *MockClient) FloatingIP() hcapi2.FloatingIPClient { return c.FloatingIPClient } func (c *MockClient) PrimaryIP() hcapi2.PrimaryIPClient { return c.PrimaryIPClient } func (c *MockClient) Image() hcapi2.ImageClient { return c.ImageClient } func (c *MockClient) ISO() hcapi2.ISOClient { return c.ISOClient } func (c *MockClient) Location() hcapi2.LocationClient { return c.LocationClient } func (c *MockClient) LoadBalancer() hcapi2.LoadBalancerClient { return c.LoadBalancerClient } func (c *MockClient) LoadBalancerType() hcapi2.LoadBalancerTypeClient { return c.LoadBalancerTypeClient } func (c *MockClient) Network() hcapi2.NetworkClient { return c.NetworkClient } func (c *MockClient) Server() hcapi2.ServerClient { return c.ServerClient } func (c *MockClient) ServerType() hcapi2.ServerTypeClient { return c.ServerTypeClient } func (c *MockClient) SSHKey() hcapi2.SSHKeyClient { return c.SSHKeyClient } func (c *MockClient) Volume() hcapi2.VolumeClient { return c.VolumeClient } func (c *MockClient) RDNS() hcapi2.RDNSClient { return c.RDNSClient } func (c *MockClient) PlacementGroup() hcapi2.PlacementGroupClient { return c.PlacementGroupClient } cli-1.39.0/internal/hcapi2/mock/mock_gen.go000066400000000000000000000046331451614444200204120ustar00rootroot00000000000000package hcapi2_mock //go:generate mockgen -package hcapi2_mock -destination zz_certificate_client_mock.go github.com/hetznercloud/cli/internal/hcapi2 CertificateClient //go:generate mockgen -package hcapi2_mock -destination zz_datacenter_client_mock.go github.com/hetznercloud/cli/internal/hcapi2 DatacenterClient //go:generate mockgen -package hcapi2_mock -destination zz_image_client_mock.go github.com/hetznercloud/cli/internal/hcapi2 ImageClient //go:generate mockgen -package hcapi2_mock -destination zz_iso_client_mock.go github.com/hetznercloud/cli/internal/hcapi2 ISOClient //go:generate mockgen -package hcapi2_mock -destination zz_firewall_client_mock.go github.com/hetznercloud/cli/internal/hcapi2 FirewallClient //go:generate mockgen -package hcapi2_mock -destination zz_floating_ip_client_mock.go github.com/hetznercloud/cli/internal/hcapi2 FloatingIPClient //go:generate mockgen -package hcapi2_mock -destination zz_primary_ip_client_mock.go github.com/hetznercloud/cli/internal/hcapi2 PrimaryIPClient //go:generate mockgen -package hcapi2_mock -destination zz_location_client_mock.go github.com/hetznercloud/cli/internal/hcapi2 LocationClient //go:generate mockgen -package hcapi2_mock -destination zz_loadbalancer_client_mock.go github.com/hetznercloud/cli/internal/hcapi2 LoadBalancerClient //go:generate mockgen -package hcapi2_mock -destination zz_loadbalancer_type_client_mock.go github.com/hetznercloud/cli/internal/hcapi2 LoadBalancerTypeClient //go:generate mockgen -package hcapi2_mock -destination zz_network_client_mock.go github.com/hetznercloud/cli/internal/hcapi2 NetworkClient //go:generate mockgen -package hcapi2_mock -destination zz_server_client_mock.go github.com/hetznercloud/cli/internal/hcapi2 ServerClient //go:generate mockgen -package hcapi2_mock -destination zz_server_type_client_mock.go github.com/hetznercloud/cli/internal/hcapi2 ServerTypeClient //go:generate mockgen -package hcapi2_mock -destination zz_ssh_key_client_mock.go github.com/hetznercloud/cli/internal/hcapi2 SSHKeyClient //go:generate mockgen -package hcapi2_mock -destination zz_volume_client_mock.go github.com/hetznercloud/cli/internal/hcapi2 VolumeClient //go:generate mockgen -package hcapi2_mock -destination zz_placement_group_client_mock.go github.com/hetznercloud/cli/internal/hcapi2 PlacementGroupClient //go:generate mockgen -package hcapi2_mock -destination zz_rdns_client_mock.go github.com/hetznercloud/cli/internal/hcapi2 RDNSClient cli-1.39.0/internal/hcapi2/mock/zz_certificate_client_mock.go000066400000000000000000000221541451614444200242020ustar00rootroot00000000000000// Code generated by MockGen. DO NOT EDIT. // Source: github.com/hetznercloud/cli/internal/hcapi2 (interfaces: CertificateClient) // Package hcapi2_mock is a generated GoMock package. package hcapi2_mock import ( context "context" reflect "reflect" gomock "github.com/golang/mock/gomock" hcloud "github.com/hetznercloud/hcloud-go/v2/hcloud" ) // MockCertificateClient is a mock of CertificateClient interface. type MockCertificateClient struct { ctrl *gomock.Controller recorder *MockCertificateClientMockRecorder } // MockCertificateClientMockRecorder is the mock recorder for MockCertificateClient. type MockCertificateClientMockRecorder struct { mock *MockCertificateClient } // NewMockCertificateClient creates a new mock instance. func NewMockCertificateClient(ctrl *gomock.Controller) *MockCertificateClient { mock := &MockCertificateClient{ctrl: ctrl} mock.recorder = &MockCertificateClientMockRecorder{mock} return mock } // EXPECT returns an object that allows the caller to indicate expected use. func (m *MockCertificateClient) EXPECT() *MockCertificateClientMockRecorder { return m.recorder } // All mocks base method. func (m *MockCertificateClient) All(arg0 context.Context) ([]*hcloud.Certificate, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "All", arg0) ret0, _ := ret[0].([]*hcloud.Certificate) ret1, _ := ret[1].(error) return ret0, ret1 } // All indicates an expected call of All. func (mr *MockCertificateClientMockRecorder) All(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "All", reflect.TypeOf((*MockCertificateClient)(nil).All), arg0) } // AllWithOpts mocks base method. func (m *MockCertificateClient) AllWithOpts(arg0 context.Context, arg1 hcloud.CertificateListOpts) ([]*hcloud.Certificate, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "AllWithOpts", arg0, arg1) ret0, _ := ret[0].([]*hcloud.Certificate) ret1, _ := ret[1].(error) return ret0, ret1 } // AllWithOpts indicates an expected call of AllWithOpts. func (mr *MockCertificateClientMockRecorder) AllWithOpts(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AllWithOpts", reflect.TypeOf((*MockCertificateClient)(nil).AllWithOpts), arg0, arg1) } // Create mocks base method. func (m *MockCertificateClient) Create(arg0 context.Context, arg1 hcloud.CertificateCreateOpts) (*hcloud.Certificate, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Create", arg0, arg1) ret0, _ := ret[0].(*hcloud.Certificate) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // Create indicates an expected call of Create. func (mr *MockCertificateClientMockRecorder) Create(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Create", reflect.TypeOf((*MockCertificateClient)(nil).Create), arg0, arg1) } // CreateCertificate mocks base method. func (m *MockCertificateClient) CreateCertificate(arg0 context.Context, arg1 hcloud.CertificateCreateOpts) (hcloud.CertificateCreateResult, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "CreateCertificate", arg0, arg1) ret0, _ := ret[0].(hcloud.CertificateCreateResult) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // CreateCertificate indicates an expected call of CreateCertificate. func (mr *MockCertificateClientMockRecorder) CreateCertificate(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateCertificate", reflect.TypeOf((*MockCertificateClient)(nil).CreateCertificate), arg0, arg1) } // Delete mocks base method. func (m *MockCertificateClient) Delete(arg0 context.Context, arg1 *hcloud.Certificate) (*hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Delete", arg0, arg1) ret0, _ := ret[0].(*hcloud.Response) ret1, _ := ret[1].(error) return ret0, ret1 } // Delete indicates an expected call of Delete. func (mr *MockCertificateClientMockRecorder) Delete(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockCertificateClient)(nil).Delete), arg0, arg1) } // Get mocks base method. func (m *MockCertificateClient) Get(arg0 context.Context, arg1 string) (*hcloud.Certificate, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Get", arg0, arg1) ret0, _ := ret[0].(*hcloud.Certificate) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // Get indicates an expected call of Get. func (mr *MockCertificateClientMockRecorder) Get(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockCertificateClient)(nil).Get), arg0, arg1) } // GetByID mocks base method. func (m *MockCertificateClient) GetByID(arg0 context.Context, arg1 int64) (*hcloud.Certificate, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetByID", arg0, arg1) ret0, _ := ret[0].(*hcloud.Certificate) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // GetByID indicates an expected call of GetByID. func (mr *MockCertificateClientMockRecorder) GetByID(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByID", reflect.TypeOf((*MockCertificateClient)(nil).GetByID), arg0, arg1) } // GetByName mocks base method. func (m *MockCertificateClient) GetByName(arg0 context.Context, arg1 string) (*hcloud.Certificate, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetByName", arg0, arg1) ret0, _ := ret[0].(*hcloud.Certificate) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // GetByName indicates an expected call of GetByName. func (mr *MockCertificateClientMockRecorder) GetByName(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByName", reflect.TypeOf((*MockCertificateClient)(nil).GetByName), arg0, arg1) } // LabelKeys mocks base method. func (m *MockCertificateClient) LabelKeys(arg0 string) []string { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "LabelKeys", arg0) ret0, _ := ret[0].([]string) return ret0 } // LabelKeys indicates an expected call of LabelKeys. func (mr *MockCertificateClientMockRecorder) LabelKeys(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LabelKeys", reflect.TypeOf((*MockCertificateClient)(nil).LabelKeys), arg0) } // List mocks base method. func (m *MockCertificateClient) List(arg0 context.Context, arg1 hcloud.CertificateListOpts) ([]*hcloud.Certificate, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "List", arg0, arg1) ret0, _ := ret[0].([]*hcloud.Certificate) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // List indicates an expected call of List. func (mr *MockCertificateClientMockRecorder) List(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockCertificateClient)(nil).List), arg0, arg1) } // Names mocks base method. func (m *MockCertificateClient) Names() []string { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Names") ret0, _ := ret[0].([]string) return ret0 } // Names indicates an expected call of Names. func (mr *MockCertificateClientMockRecorder) Names() *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Names", reflect.TypeOf((*MockCertificateClient)(nil).Names)) } // RetryIssuance mocks base method. func (m *MockCertificateClient) RetryIssuance(arg0 context.Context, arg1 *hcloud.Certificate) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "RetryIssuance", arg0, arg1) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // RetryIssuance indicates an expected call of RetryIssuance. func (mr *MockCertificateClientMockRecorder) RetryIssuance(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetryIssuance", reflect.TypeOf((*MockCertificateClient)(nil).RetryIssuance), arg0, arg1) } // Update mocks base method. func (m *MockCertificateClient) Update(arg0 context.Context, arg1 *hcloud.Certificate, arg2 hcloud.CertificateUpdateOpts) (*hcloud.Certificate, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Update", arg0, arg1, arg2) ret0, _ := ret[0].(*hcloud.Certificate) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // Update indicates an expected call of Update. func (mr *MockCertificateClientMockRecorder) Update(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockCertificateClient)(nil).Update), arg0, arg1, arg2) } cli-1.39.0/internal/hcapi2/mock/zz_datacenter_client_mock.go000066400000000000000000000122671451614444200240360ustar00rootroot00000000000000// Code generated by MockGen. DO NOT EDIT. // Source: github.com/hetznercloud/cli/internal/hcapi2 (interfaces: DatacenterClient) // Package hcapi2_mock is a generated GoMock package. package hcapi2_mock import ( context "context" reflect "reflect" gomock "github.com/golang/mock/gomock" hcloud "github.com/hetznercloud/hcloud-go/v2/hcloud" ) // MockDatacenterClient is a mock of DatacenterClient interface. type MockDatacenterClient struct { ctrl *gomock.Controller recorder *MockDatacenterClientMockRecorder } // MockDatacenterClientMockRecorder is the mock recorder for MockDatacenterClient. type MockDatacenterClientMockRecorder struct { mock *MockDatacenterClient } // NewMockDatacenterClient creates a new mock instance. func NewMockDatacenterClient(ctrl *gomock.Controller) *MockDatacenterClient { mock := &MockDatacenterClient{ctrl: ctrl} mock.recorder = &MockDatacenterClientMockRecorder{mock} return mock } // EXPECT returns an object that allows the caller to indicate expected use. func (m *MockDatacenterClient) EXPECT() *MockDatacenterClientMockRecorder { return m.recorder } // All mocks base method. func (m *MockDatacenterClient) All(arg0 context.Context) ([]*hcloud.Datacenter, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "All", arg0) ret0, _ := ret[0].([]*hcloud.Datacenter) ret1, _ := ret[1].(error) return ret0, ret1 } // All indicates an expected call of All. func (mr *MockDatacenterClientMockRecorder) All(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "All", reflect.TypeOf((*MockDatacenterClient)(nil).All), arg0) } // AllWithOpts mocks base method. func (m *MockDatacenterClient) AllWithOpts(arg0 context.Context, arg1 hcloud.DatacenterListOpts) ([]*hcloud.Datacenter, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "AllWithOpts", arg0, arg1) ret0, _ := ret[0].([]*hcloud.Datacenter) ret1, _ := ret[1].(error) return ret0, ret1 } // AllWithOpts indicates an expected call of AllWithOpts. func (mr *MockDatacenterClientMockRecorder) AllWithOpts(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AllWithOpts", reflect.TypeOf((*MockDatacenterClient)(nil).AllWithOpts), arg0, arg1) } // Get mocks base method. func (m *MockDatacenterClient) Get(arg0 context.Context, arg1 string) (*hcloud.Datacenter, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Get", arg0, arg1) ret0, _ := ret[0].(*hcloud.Datacenter) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // Get indicates an expected call of Get. func (mr *MockDatacenterClientMockRecorder) Get(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockDatacenterClient)(nil).Get), arg0, arg1) } // GetByID mocks base method. func (m *MockDatacenterClient) GetByID(arg0 context.Context, arg1 int64) (*hcloud.Datacenter, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetByID", arg0, arg1) ret0, _ := ret[0].(*hcloud.Datacenter) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // GetByID indicates an expected call of GetByID. func (mr *MockDatacenterClientMockRecorder) GetByID(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByID", reflect.TypeOf((*MockDatacenterClient)(nil).GetByID), arg0, arg1) } // GetByName mocks base method. func (m *MockDatacenterClient) GetByName(arg0 context.Context, arg1 string) (*hcloud.Datacenter, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetByName", arg0, arg1) ret0, _ := ret[0].(*hcloud.Datacenter) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // GetByName indicates an expected call of GetByName. func (mr *MockDatacenterClientMockRecorder) GetByName(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByName", reflect.TypeOf((*MockDatacenterClient)(nil).GetByName), arg0, arg1) } // List mocks base method. func (m *MockDatacenterClient) List(arg0 context.Context, arg1 hcloud.DatacenterListOpts) ([]*hcloud.Datacenter, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "List", arg0, arg1) ret0, _ := ret[0].([]*hcloud.Datacenter) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // List indicates an expected call of List. func (mr *MockDatacenterClientMockRecorder) List(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockDatacenterClient)(nil).List), arg0, arg1) } // Names mocks base method. func (m *MockDatacenterClient) Names() []string { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Names") ret0, _ := ret[0].([]string) return ret0 } // Names indicates an expected call of Names. func (mr *MockDatacenterClientMockRecorder) Names() *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Names", reflect.TypeOf((*MockDatacenterClient)(nil).Names)) } cli-1.39.0/internal/hcapi2/mock/zz_firewall_client_mock.go000066400000000000000000000232271451614444200235270ustar00rootroot00000000000000// Code generated by MockGen. DO NOT EDIT. // Source: github.com/hetznercloud/cli/internal/hcapi2 (interfaces: FirewallClient) // Package hcapi2_mock is a generated GoMock package. package hcapi2_mock import ( context "context" reflect "reflect" gomock "github.com/golang/mock/gomock" hcloud "github.com/hetznercloud/hcloud-go/v2/hcloud" ) // MockFirewallClient is a mock of FirewallClient interface. type MockFirewallClient struct { ctrl *gomock.Controller recorder *MockFirewallClientMockRecorder } // MockFirewallClientMockRecorder is the mock recorder for MockFirewallClient. type MockFirewallClientMockRecorder struct { mock *MockFirewallClient } // NewMockFirewallClient creates a new mock instance. func NewMockFirewallClient(ctrl *gomock.Controller) *MockFirewallClient { mock := &MockFirewallClient{ctrl: ctrl} mock.recorder = &MockFirewallClientMockRecorder{mock} return mock } // EXPECT returns an object that allows the caller to indicate expected use. func (m *MockFirewallClient) EXPECT() *MockFirewallClientMockRecorder { return m.recorder } // All mocks base method. func (m *MockFirewallClient) All(arg0 context.Context) ([]*hcloud.Firewall, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "All", arg0) ret0, _ := ret[0].([]*hcloud.Firewall) ret1, _ := ret[1].(error) return ret0, ret1 } // All indicates an expected call of All. func (mr *MockFirewallClientMockRecorder) All(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "All", reflect.TypeOf((*MockFirewallClient)(nil).All), arg0) } // AllWithOpts mocks base method. func (m *MockFirewallClient) AllWithOpts(arg0 context.Context, arg1 hcloud.FirewallListOpts) ([]*hcloud.Firewall, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "AllWithOpts", arg0, arg1) ret0, _ := ret[0].([]*hcloud.Firewall) ret1, _ := ret[1].(error) return ret0, ret1 } // AllWithOpts indicates an expected call of AllWithOpts. func (mr *MockFirewallClientMockRecorder) AllWithOpts(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AllWithOpts", reflect.TypeOf((*MockFirewallClient)(nil).AllWithOpts), arg0, arg1) } // ApplyResources mocks base method. func (m *MockFirewallClient) ApplyResources(arg0 context.Context, arg1 *hcloud.Firewall, arg2 []hcloud.FirewallResource) ([]*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ApplyResources", arg0, arg1, arg2) ret0, _ := ret[0].([]*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // ApplyResources indicates an expected call of ApplyResources. func (mr *MockFirewallClientMockRecorder) ApplyResources(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ApplyResources", reflect.TypeOf((*MockFirewallClient)(nil).ApplyResources), arg0, arg1, arg2) } // Create mocks base method. func (m *MockFirewallClient) Create(arg0 context.Context, arg1 hcloud.FirewallCreateOpts) (hcloud.FirewallCreateResult, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Create", arg0, arg1) ret0, _ := ret[0].(hcloud.FirewallCreateResult) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // Create indicates an expected call of Create. func (mr *MockFirewallClientMockRecorder) Create(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Create", reflect.TypeOf((*MockFirewallClient)(nil).Create), arg0, arg1) } // Delete mocks base method. func (m *MockFirewallClient) Delete(arg0 context.Context, arg1 *hcloud.Firewall) (*hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Delete", arg0, arg1) ret0, _ := ret[0].(*hcloud.Response) ret1, _ := ret[1].(error) return ret0, ret1 } // Delete indicates an expected call of Delete. func (mr *MockFirewallClientMockRecorder) Delete(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockFirewallClient)(nil).Delete), arg0, arg1) } // Get mocks base method. func (m *MockFirewallClient) Get(arg0 context.Context, arg1 string) (*hcloud.Firewall, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Get", arg0, arg1) ret0, _ := ret[0].(*hcloud.Firewall) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // Get indicates an expected call of Get. func (mr *MockFirewallClientMockRecorder) Get(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockFirewallClient)(nil).Get), arg0, arg1) } // GetByID mocks base method. func (m *MockFirewallClient) GetByID(arg0 context.Context, arg1 int64) (*hcloud.Firewall, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetByID", arg0, arg1) ret0, _ := ret[0].(*hcloud.Firewall) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // GetByID indicates an expected call of GetByID. func (mr *MockFirewallClientMockRecorder) GetByID(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByID", reflect.TypeOf((*MockFirewallClient)(nil).GetByID), arg0, arg1) } // GetByName mocks base method. func (m *MockFirewallClient) GetByName(arg0 context.Context, arg1 string) (*hcloud.Firewall, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetByName", arg0, arg1) ret0, _ := ret[0].(*hcloud.Firewall) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // GetByName indicates an expected call of GetByName. func (mr *MockFirewallClientMockRecorder) GetByName(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByName", reflect.TypeOf((*MockFirewallClient)(nil).GetByName), arg0, arg1) } // LabelKeys mocks base method. func (m *MockFirewallClient) LabelKeys(arg0 string) []string { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "LabelKeys", arg0) ret0, _ := ret[0].([]string) return ret0 } // LabelKeys indicates an expected call of LabelKeys. func (mr *MockFirewallClientMockRecorder) LabelKeys(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LabelKeys", reflect.TypeOf((*MockFirewallClient)(nil).LabelKeys), arg0) } // List mocks base method. func (m *MockFirewallClient) List(arg0 context.Context, arg1 hcloud.FirewallListOpts) ([]*hcloud.Firewall, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "List", arg0, arg1) ret0, _ := ret[0].([]*hcloud.Firewall) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // List indicates an expected call of List. func (mr *MockFirewallClientMockRecorder) List(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockFirewallClient)(nil).List), arg0, arg1) } // Names mocks base method. func (m *MockFirewallClient) Names() []string { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Names") ret0, _ := ret[0].([]string) return ret0 } // Names indicates an expected call of Names. func (mr *MockFirewallClientMockRecorder) Names() *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Names", reflect.TypeOf((*MockFirewallClient)(nil).Names)) } // RemoveResources mocks base method. func (m *MockFirewallClient) RemoveResources(arg0 context.Context, arg1 *hcloud.Firewall, arg2 []hcloud.FirewallResource) ([]*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "RemoveResources", arg0, arg1, arg2) ret0, _ := ret[0].([]*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // RemoveResources indicates an expected call of RemoveResources. func (mr *MockFirewallClientMockRecorder) RemoveResources(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveResources", reflect.TypeOf((*MockFirewallClient)(nil).RemoveResources), arg0, arg1, arg2) } // SetRules mocks base method. func (m *MockFirewallClient) SetRules(arg0 context.Context, arg1 *hcloud.Firewall, arg2 hcloud.FirewallSetRulesOpts) ([]*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "SetRules", arg0, arg1, arg2) ret0, _ := ret[0].([]*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // SetRules indicates an expected call of SetRules. func (mr *MockFirewallClientMockRecorder) SetRules(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetRules", reflect.TypeOf((*MockFirewallClient)(nil).SetRules), arg0, arg1, arg2) } // Update mocks base method. func (m *MockFirewallClient) Update(arg0 context.Context, arg1 *hcloud.Firewall, arg2 hcloud.FirewallUpdateOpts) (*hcloud.Firewall, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Update", arg0, arg1, arg2) ret0, _ := ret[0].(*hcloud.Firewall) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // Update indicates an expected call of Update. func (mr *MockFirewallClientMockRecorder) Update(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockFirewallClient)(nil).Update), arg0, arg1, arg2) } cli-1.39.0/internal/hcapi2/mock/zz_floating_ip_client_mock.go000066400000000000000000000246741451614444200242240ustar00rootroot00000000000000// Code generated by MockGen. DO NOT EDIT. // Source: github.com/hetznercloud/cli/internal/hcapi2 (interfaces: FloatingIPClient) // Package hcapi2_mock is a generated GoMock package. package hcapi2_mock import ( context "context" reflect "reflect" gomock "github.com/golang/mock/gomock" hcloud "github.com/hetznercloud/hcloud-go/v2/hcloud" ) // MockFloatingIPClient is a mock of FloatingIPClient interface. type MockFloatingIPClient struct { ctrl *gomock.Controller recorder *MockFloatingIPClientMockRecorder } // MockFloatingIPClientMockRecorder is the mock recorder for MockFloatingIPClient. type MockFloatingIPClientMockRecorder struct { mock *MockFloatingIPClient } // NewMockFloatingIPClient creates a new mock instance. func NewMockFloatingIPClient(ctrl *gomock.Controller) *MockFloatingIPClient { mock := &MockFloatingIPClient{ctrl: ctrl} mock.recorder = &MockFloatingIPClientMockRecorder{mock} return mock } // EXPECT returns an object that allows the caller to indicate expected use. func (m *MockFloatingIPClient) EXPECT() *MockFloatingIPClientMockRecorder { return m.recorder } // All mocks base method. func (m *MockFloatingIPClient) All(arg0 context.Context) ([]*hcloud.FloatingIP, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "All", arg0) ret0, _ := ret[0].([]*hcloud.FloatingIP) ret1, _ := ret[1].(error) return ret0, ret1 } // All indicates an expected call of All. func (mr *MockFloatingIPClientMockRecorder) All(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "All", reflect.TypeOf((*MockFloatingIPClient)(nil).All), arg0) } // AllWithOpts mocks base method. func (m *MockFloatingIPClient) AllWithOpts(arg0 context.Context, arg1 hcloud.FloatingIPListOpts) ([]*hcloud.FloatingIP, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "AllWithOpts", arg0, arg1) ret0, _ := ret[0].([]*hcloud.FloatingIP) ret1, _ := ret[1].(error) return ret0, ret1 } // AllWithOpts indicates an expected call of AllWithOpts. func (mr *MockFloatingIPClientMockRecorder) AllWithOpts(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AllWithOpts", reflect.TypeOf((*MockFloatingIPClient)(nil).AllWithOpts), arg0, arg1) } // Assign mocks base method. func (m *MockFloatingIPClient) Assign(arg0 context.Context, arg1 *hcloud.FloatingIP, arg2 *hcloud.Server) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Assign", arg0, arg1, arg2) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // Assign indicates an expected call of Assign. func (mr *MockFloatingIPClientMockRecorder) Assign(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Assign", reflect.TypeOf((*MockFloatingIPClient)(nil).Assign), arg0, arg1, arg2) } // ChangeDNSPtr mocks base method. func (m *MockFloatingIPClient) ChangeDNSPtr(arg0 context.Context, arg1 *hcloud.FloatingIP, arg2 string, arg3 *string) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ChangeDNSPtr", arg0, arg1, arg2, arg3) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // ChangeDNSPtr indicates an expected call of ChangeDNSPtr. func (mr *MockFloatingIPClientMockRecorder) ChangeDNSPtr(arg0, arg1, arg2, arg3 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChangeDNSPtr", reflect.TypeOf((*MockFloatingIPClient)(nil).ChangeDNSPtr), arg0, arg1, arg2, arg3) } // ChangeProtection mocks base method. func (m *MockFloatingIPClient) ChangeProtection(arg0 context.Context, arg1 *hcloud.FloatingIP, arg2 hcloud.FloatingIPChangeProtectionOpts) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ChangeProtection", arg0, arg1, arg2) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // ChangeProtection indicates an expected call of ChangeProtection. func (mr *MockFloatingIPClientMockRecorder) ChangeProtection(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChangeProtection", reflect.TypeOf((*MockFloatingIPClient)(nil).ChangeProtection), arg0, arg1, arg2) } // Create mocks base method. func (m *MockFloatingIPClient) Create(arg0 context.Context, arg1 hcloud.FloatingIPCreateOpts) (hcloud.FloatingIPCreateResult, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Create", arg0, arg1) ret0, _ := ret[0].(hcloud.FloatingIPCreateResult) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // Create indicates an expected call of Create. func (mr *MockFloatingIPClientMockRecorder) Create(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Create", reflect.TypeOf((*MockFloatingIPClient)(nil).Create), arg0, arg1) } // Delete mocks base method. func (m *MockFloatingIPClient) Delete(arg0 context.Context, arg1 *hcloud.FloatingIP) (*hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Delete", arg0, arg1) ret0, _ := ret[0].(*hcloud.Response) ret1, _ := ret[1].(error) return ret0, ret1 } // Delete indicates an expected call of Delete. func (mr *MockFloatingIPClientMockRecorder) Delete(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockFloatingIPClient)(nil).Delete), arg0, arg1) } // Get mocks base method. func (m *MockFloatingIPClient) Get(arg0 context.Context, arg1 string) (*hcloud.FloatingIP, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Get", arg0, arg1) ret0, _ := ret[0].(*hcloud.FloatingIP) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // Get indicates an expected call of Get. func (mr *MockFloatingIPClientMockRecorder) Get(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockFloatingIPClient)(nil).Get), arg0, arg1) } // GetByID mocks base method. func (m *MockFloatingIPClient) GetByID(arg0 context.Context, arg1 int64) (*hcloud.FloatingIP, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetByID", arg0, arg1) ret0, _ := ret[0].(*hcloud.FloatingIP) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // GetByID indicates an expected call of GetByID. func (mr *MockFloatingIPClientMockRecorder) GetByID(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByID", reflect.TypeOf((*MockFloatingIPClient)(nil).GetByID), arg0, arg1) } // GetByName mocks base method. func (m *MockFloatingIPClient) GetByName(arg0 context.Context, arg1 string) (*hcloud.FloatingIP, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetByName", arg0, arg1) ret0, _ := ret[0].(*hcloud.FloatingIP) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // GetByName indicates an expected call of GetByName. func (mr *MockFloatingIPClientMockRecorder) GetByName(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByName", reflect.TypeOf((*MockFloatingIPClient)(nil).GetByName), arg0, arg1) } // LabelKeys mocks base method. func (m *MockFloatingIPClient) LabelKeys(arg0 string) []string { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "LabelKeys", arg0) ret0, _ := ret[0].([]string) return ret0 } // LabelKeys indicates an expected call of LabelKeys. func (mr *MockFloatingIPClientMockRecorder) LabelKeys(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LabelKeys", reflect.TypeOf((*MockFloatingIPClient)(nil).LabelKeys), arg0) } // List mocks base method. func (m *MockFloatingIPClient) List(arg0 context.Context, arg1 hcloud.FloatingIPListOpts) ([]*hcloud.FloatingIP, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "List", arg0, arg1) ret0, _ := ret[0].([]*hcloud.FloatingIP) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // List indicates an expected call of List. func (mr *MockFloatingIPClientMockRecorder) List(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockFloatingIPClient)(nil).List), arg0, arg1) } // Names mocks base method. func (m *MockFloatingIPClient) Names() []string { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Names") ret0, _ := ret[0].([]string) return ret0 } // Names indicates an expected call of Names. func (mr *MockFloatingIPClientMockRecorder) Names() *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Names", reflect.TypeOf((*MockFloatingIPClient)(nil).Names)) } // Unassign mocks base method. func (m *MockFloatingIPClient) Unassign(arg0 context.Context, arg1 *hcloud.FloatingIP) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Unassign", arg0, arg1) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // Unassign indicates an expected call of Unassign. func (mr *MockFloatingIPClientMockRecorder) Unassign(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Unassign", reflect.TypeOf((*MockFloatingIPClient)(nil).Unassign), arg0, arg1) } // Update mocks base method. func (m *MockFloatingIPClient) Update(arg0 context.Context, arg1 *hcloud.FloatingIP, arg2 hcloud.FloatingIPUpdateOpts) (*hcloud.FloatingIP, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Update", arg0, arg1, arg2) ret0, _ := ret[0].(*hcloud.FloatingIP) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // Update indicates an expected call of Update. func (mr *MockFloatingIPClientMockRecorder) Update(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockFloatingIPClient)(nil).Update), arg0, arg1, arg2) } cli-1.39.0/internal/hcapi2/mock/zz_image_client_mock.go000066400000000000000000000216211451614444200230000ustar00rootroot00000000000000// Code generated by MockGen. DO NOT EDIT. // Source: github.com/hetznercloud/cli/internal/hcapi2 (interfaces: ImageClient) // Package hcapi2_mock is a generated GoMock package. package hcapi2_mock import ( context "context" reflect "reflect" gomock "github.com/golang/mock/gomock" hcloud "github.com/hetznercloud/hcloud-go/v2/hcloud" ) // MockImageClient is a mock of ImageClient interface. type MockImageClient struct { ctrl *gomock.Controller recorder *MockImageClientMockRecorder } // MockImageClientMockRecorder is the mock recorder for MockImageClient. type MockImageClientMockRecorder struct { mock *MockImageClient } // NewMockImageClient creates a new mock instance. func NewMockImageClient(ctrl *gomock.Controller) *MockImageClient { mock := &MockImageClient{ctrl: ctrl} mock.recorder = &MockImageClientMockRecorder{mock} return mock } // EXPECT returns an object that allows the caller to indicate expected use. func (m *MockImageClient) EXPECT() *MockImageClientMockRecorder { return m.recorder } // All mocks base method. func (m *MockImageClient) All(arg0 context.Context) ([]*hcloud.Image, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "All", arg0) ret0, _ := ret[0].([]*hcloud.Image) ret1, _ := ret[1].(error) return ret0, ret1 } // All indicates an expected call of All. func (mr *MockImageClientMockRecorder) All(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "All", reflect.TypeOf((*MockImageClient)(nil).All), arg0) } // AllWithOpts mocks base method. func (m *MockImageClient) AllWithOpts(arg0 context.Context, arg1 hcloud.ImageListOpts) ([]*hcloud.Image, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "AllWithOpts", arg0, arg1) ret0, _ := ret[0].([]*hcloud.Image) ret1, _ := ret[1].(error) return ret0, ret1 } // AllWithOpts indicates an expected call of AllWithOpts. func (mr *MockImageClientMockRecorder) AllWithOpts(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AllWithOpts", reflect.TypeOf((*MockImageClient)(nil).AllWithOpts), arg0, arg1) } // ChangeProtection mocks base method. func (m *MockImageClient) ChangeProtection(arg0 context.Context, arg1 *hcloud.Image, arg2 hcloud.ImageChangeProtectionOpts) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ChangeProtection", arg0, arg1, arg2) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // ChangeProtection indicates an expected call of ChangeProtection. func (mr *MockImageClientMockRecorder) ChangeProtection(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChangeProtection", reflect.TypeOf((*MockImageClient)(nil).ChangeProtection), arg0, arg1, arg2) } // Delete mocks base method. func (m *MockImageClient) Delete(arg0 context.Context, arg1 *hcloud.Image) (*hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Delete", arg0, arg1) ret0, _ := ret[0].(*hcloud.Response) ret1, _ := ret[1].(error) return ret0, ret1 } // Delete indicates an expected call of Delete. func (mr *MockImageClientMockRecorder) Delete(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockImageClient)(nil).Delete), arg0, arg1) } // Get mocks base method. func (m *MockImageClient) Get(arg0 context.Context, arg1 string) (*hcloud.Image, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Get", arg0, arg1) ret0, _ := ret[0].(*hcloud.Image) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // Get indicates an expected call of Get. func (mr *MockImageClientMockRecorder) Get(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockImageClient)(nil).Get), arg0, arg1) } // GetByID mocks base method. func (m *MockImageClient) GetByID(arg0 context.Context, arg1 int64) (*hcloud.Image, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetByID", arg0, arg1) ret0, _ := ret[0].(*hcloud.Image) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // GetByID indicates an expected call of GetByID. func (mr *MockImageClientMockRecorder) GetByID(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByID", reflect.TypeOf((*MockImageClient)(nil).GetByID), arg0, arg1) } // GetByName mocks base method. func (m *MockImageClient) GetByName(arg0 context.Context, arg1 string) (*hcloud.Image, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetByName", arg0, arg1) ret0, _ := ret[0].(*hcloud.Image) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // GetByName indicates an expected call of GetByName. func (mr *MockImageClientMockRecorder) GetByName(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByName", reflect.TypeOf((*MockImageClient)(nil).GetByName), arg0, arg1) } // GetByNameAndArchitecture mocks base method. func (m *MockImageClient) GetByNameAndArchitecture(arg0 context.Context, arg1 string, arg2 hcloud.Architecture) (*hcloud.Image, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetByNameAndArchitecture", arg0, arg1, arg2) ret0, _ := ret[0].(*hcloud.Image) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // GetByNameAndArchitecture indicates an expected call of GetByNameAndArchitecture. func (mr *MockImageClientMockRecorder) GetByNameAndArchitecture(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByNameAndArchitecture", reflect.TypeOf((*MockImageClient)(nil).GetByNameAndArchitecture), arg0, arg1, arg2) } // GetForArchitecture mocks base method. func (m *MockImageClient) GetForArchitecture(arg0 context.Context, arg1 string, arg2 hcloud.Architecture) (*hcloud.Image, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetForArchitecture", arg0, arg1, arg2) ret0, _ := ret[0].(*hcloud.Image) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // GetForArchitecture indicates an expected call of GetForArchitecture. func (mr *MockImageClientMockRecorder) GetForArchitecture(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetForArchitecture", reflect.TypeOf((*MockImageClient)(nil).GetForArchitecture), arg0, arg1, arg2) } // LabelKeys mocks base method. func (m *MockImageClient) LabelKeys(arg0 string) []string { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "LabelKeys", arg0) ret0, _ := ret[0].([]string) return ret0 } // LabelKeys indicates an expected call of LabelKeys. func (mr *MockImageClientMockRecorder) LabelKeys(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LabelKeys", reflect.TypeOf((*MockImageClient)(nil).LabelKeys), arg0) } // List mocks base method. func (m *MockImageClient) List(arg0 context.Context, arg1 hcloud.ImageListOpts) ([]*hcloud.Image, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "List", arg0, arg1) ret0, _ := ret[0].([]*hcloud.Image) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // List indicates an expected call of List. func (mr *MockImageClientMockRecorder) List(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockImageClient)(nil).List), arg0, arg1) } // Names mocks base method. func (m *MockImageClient) Names() []string { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Names") ret0, _ := ret[0].([]string) return ret0 } // Names indicates an expected call of Names. func (mr *MockImageClientMockRecorder) Names() *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Names", reflect.TypeOf((*MockImageClient)(nil).Names)) } // Update mocks base method. func (m *MockImageClient) Update(arg0 context.Context, arg1 *hcloud.Image, arg2 hcloud.ImageUpdateOpts) (*hcloud.Image, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Update", arg0, arg1, arg2) ret0, _ := ret[0].(*hcloud.Image) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // Update indicates an expected call of Update. func (mr *MockImageClientMockRecorder) Update(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockImageClient)(nil).Update), arg0, arg1, arg2) } cli-1.39.0/internal/hcapi2/mock/zz_iso_client_mock.go000066400000000000000000000115221451614444200225070ustar00rootroot00000000000000// Code generated by MockGen. DO NOT EDIT. // Source: github.com/hetznercloud/cli/internal/hcapi2 (interfaces: ISOClient) // Package hcapi2_mock is a generated GoMock package. package hcapi2_mock import ( context "context" reflect "reflect" gomock "github.com/golang/mock/gomock" hcloud "github.com/hetznercloud/hcloud-go/v2/hcloud" ) // MockISOClient is a mock of ISOClient interface. type MockISOClient struct { ctrl *gomock.Controller recorder *MockISOClientMockRecorder } // MockISOClientMockRecorder is the mock recorder for MockISOClient. type MockISOClientMockRecorder struct { mock *MockISOClient } // NewMockISOClient creates a new mock instance. func NewMockISOClient(ctrl *gomock.Controller) *MockISOClient { mock := &MockISOClient{ctrl: ctrl} mock.recorder = &MockISOClientMockRecorder{mock} return mock } // EXPECT returns an object that allows the caller to indicate expected use. func (m *MockISOClient) EXPECT() *MockISOClientMockRecorder { return m.recorder } // All mocks base method. func (m *MockISOClient) All(arg0 context.Context) ([]*hcloud.ISO, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "All", arg0) ret0, _ := ret[0].([]*hcloud.ISO) ret1, _ := ret[1].(error) return ret0, ret1 } // All indicates an expected call of All. func (mr *MockISOClientMockRecorder) All(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "All", reflect.TypeOf((*MockISOClient)(nil).All), arg0) } // AllWithOpts mocks base method. func (m *MockISOClient) AllWithOpts(arg0 context.Context, arg1 hcloud.ISOListOpts) ([]*hcloud.ISO, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "AllWithOpts", arg0, arg1) ret0, _ := ret[0].([]*hcloud.ISO) ret1, _ := ret[1].(error) return ret0, ret1 } // AllWithOpts indicates an expected call of AllWithOpts. func (mr *MockISOClientMockRecorder) AllWithOpts(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AllWithOpts", reflect.TypeOf((*MockISOClient)(nil).AllWithOpts), arg0, arg1) } // Get mocks base method. func (m *MockISOClient) Get(arg0 context.Context, arg1 string) (*hcloud.ISO, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Get", arg0, arg1) ret0, _ := ret[0].(*hcloud.ISO) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // Get indicates an expected call of Get. func (mr *MockISOClientMockRecorder) Get(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockISOClient)(nil).Get), arg0, arg1) } // GetByID mocks base method. func (m *MockISOClient) GetByID(arg0 context.Context, arg1 int64) (*hcloud.ISO, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetByID", arg0, arg1) ret0, _ := ret[0].(*hcloud.ISO) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // GetByID indicates an expected call of GetByID. func (mr *MockISOClientMockRecorder) GetByID(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByID", reflect.TypeOf((*MockISOClient)(nil).GetByID), arg0, arg1) } // GetByName mocks base method. func (m *MockISOClient) GetByName(arg0 context.Context, arg1 string) (*hcloud.ISO, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetByName", arg0, arg1) ret0, _ := ret[0].(*hcloud.ISO) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // GetByName indicates an expected call of GetByName. func (mr *MockISOClientMockRecorder) GetByName(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByName", reflect.TypeOf((*MockISOClient)(nil).GetByName), arg0, arg1) } // List mocks base method. func (m *MockISOClient) List(arg0 context.Context, arg1 hcloud.ISOListOpts) ([]*hcloud.ISO, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "List", arg0, arg1) ret0, _ := ret[0].([]*hcloud.ISO) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // List indicates an expected call of List. func (mr *MockISOClientMockRecorder) List(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockISOClient)(nil).List), arg0, arg1) } // Names mocks base method. func (m *MockISOClient) Names() []string { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Names") ret0, _ := ret[0].([]string) return ret0 } // Names indicates an expected call of Names. func (mr *MockISOClientMockRecorder) Names() *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Names", reflect.TypeOf((*MockISOClient)(nil).Names)) } cli-1.39.0/internal/hcapi2/mock/zz_loadbalancer_client_mock.go000066400000000000000000000540731451614444200243340ustar00rootroot00000000000000// Code generated by MockGen. DO NOT EDIT. // Source: github.com/hetznercloud/cli/internal/hcapi2 (interfaces: LoadBalancerClient) // Package hcapi2_mock is a generated GoMock package. package hcapi2_mock import ( context "context" net "net" reflect "reflect" gomock "github.com/golang/mock/gomock" hcloud "github.com/hetznercloud/hcloud-go/v2/hcloud" ) // MockLoadBalancerClient is a mock of LoadBalancerClient interface. type MockLoadBalancerClient struct { ctrl *gomock.Controller recorder *MockLoadBalancerClientMockRecorder } // MockLoadBalancerClientMockRecorder is the mock recorder for MockLoadBalancerClient. type MockLoadBalancerClientMockRecorder struct { mock *MockLoadBalancerClient } // NewMockLoadBalancerClient creates a new mock instance. func NewMockLoadBalancerClient(ctrl *gomock.Controller) *MockLoadBalancerClient { mock := &MockLoadBalancerClient{ctrl: ctrl} mock.recorder = &MockLoadBalancerClientMockRecorder{mock} return mock } // EXPECT returns an object that allows the caller to indicate expected use. func (m *MockLoadBalancerClient) EXPECT() *MockLoadBalancerClientMockRecorder { return m.recorder } // AddIPTarget mocks base method. func (m *MockLoadBalancerClient) AddIPTarget(arg0 context.Context, arg1 *hcloud.LoadBalancer, arg2 hcloud.LoadBalancerAddIPTargetOpts) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "AddIPTarget", arg0, arg1, arg2) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // AddIPTarget indicates an expected call of AddIPTarget. func (mr *MockLoadBalancerClientMockRecorder) AddIPTarget(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddIPTarget", reflect.TypeOf((*MockLoadBalancerClient)(nil).AddIPTarget), arg0, arg1, arg2) } // AddLabelSelectorTarget mocks base method. func (m *MockLoadBalancerClient) AddLabelSelectorTarget(arg0 context.Context, arg1 *hcloud.LoadBalancer, arg2 hcloud.LoadBalancerAddLabelSelectorTargetOpts) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "AddLabelSelectorTarget", arg0, arg1, arg2) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // AddLabelSelectorTarget indicates an expected call of AddLabelSelectorTarget. func (mr *MockLoadBalancerClientMockRecorder) AddLabelSelectorTarget(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddLabelSelectorTarget", reflect.TypeOf((*MockLoadBalancerClient)(nil).AddLabelSelectorTarget), arg0, arg1, arg2) } // AddServerTarget mocks base method. func (m *MockLoadBalancerClient) AddServerTarget(arg0 context.Context, arg1 *hcloud.LoadBalancer, arg2 hcloud.LoadBalancerAddServerTargetOpts) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "AddServerTarget", arg0, arg1, arg2) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // AddServerTarget indicates an expected call of AddServerTarget. func (mr *MockLoadBalancerClientMockRecorder) AddServerTarget(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddServerTarget", reflect.TypeOf((*MockLoadBalancerClient)(nil).AddServerTarget), arg0, arg1, arg2) } // AddService mocks base method. func (m *MockLoadBalancerClient) AddService(arg0 context.Context, arg1 *hcloud.LoadBalancer, arg2 hcloud.LoadBalancerAddServiceOpts) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "AddService", arg0, arg1, arg2) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // AddService indicates an expected call of AddService. func (mr *MockLoadBalancerClientMockRecorder) AddService(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddService", reflect.TypeOf((*MockLoadBalancerClient)(nil).AddService), arg0, arg1, arg2) } // All mocks base method. func (m *MockLoadBalancerClient) All(arg0 context.Context) ([]*hcloud.LoadBalancer, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "All", arg0) ret0, _ := ret[0].([]*hcloud.LoadBalancer) ret1, _ := ret[1].(error) return ret0, ret1 } // All indicates an expected call of All. func (mr *MockLoadBalancerClientMockRecorder) All(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "All", reflect.TypeOf((*MockLoadBalancerClient)(nil).All), arg0) } // AllWithOpts mocks base method. func (m *MockLoadBalancerClient) AllWithOpts(arg0 context.Context, arg1 hcloud.LoadBalancerListOpts) ([]*hcloud.LoadBalancer, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "AllWithOpts", arg0, arg1) ret0, _ := ret[0].([]*hcloud.LoadBalancer) ret1, _ := ret[1].(error) return ret0, ret1 } // AllWithOpts indicates an expected call of AllWithOpts. func (mr *MockLoadBalancerClientMockRecorder) AllWithOpts(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AllWithOpts", reflect.TypeOf((*MockLoadBalancerClient)(nil).AllWithOpts), arg0, arg1) } // AttachToNetwork mocks base method. func (m *MockLoadBalancerClient) AttachToNetwork(arg0 context.Context, arg1 *hcloud.LoadBalancer, arg2 hcloud.LoadBalancerAttachToNetworkOpts) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "AttachToNetwork", arg0, arg1, arg2) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // AttachToNetwork indicates an expected call of AttachToNetwork. func (mr *MockLoadBalancerClientMockRecorder) AttachToNetwork(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AttachToNetwork", reflect.TypeOf((*MockLoadBalancerClient)(nil).AttachToNetwork), arg0, arg1, arg2) } // ChangeAlgorithm mocks base method. func (m *MockLoadBalancerClient) ChangeAlgorithm(arg0 context.Context, arg1 *hcloud.LoadBalancer, arg2 hcloud.LoadBalancerChangeAlgorithmOpts) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ChangeAlgorithm", arg0, arg1, arg2) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // ChangeAlgorithm indicates an expected call of ChangeAlgorithm. func (mr *MockLoadBalancerClientMockRecorder) ChangeAlgorithm(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChangeAlgorithm", reflect.TypeOf((*MockLoadBalancerClient)(nil).ChangeAlgorithm), arg0, arg1, arg2) } // ChangeDNSPtr mocks base method. func (m *MockLoadBalancerClient) ChangeDNSPtr(arg0 context.Context, arg1 *hcloud.LoadBalancer, arg2 string, arg3 *string) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ChangeDNSPtr", arg0, arg1, arg2, arg3) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // ChangeDNSPtr indicates an expected call of ChangeDNSPtr. func (mr *MockLoadBalancerClientMockRecorder) ChangeDNSPtr(arg0, arg1, arg2, arg3 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChangeDNSPtr", reflect.TypeOf((*MockLoadBalancerClient)(nil).ChangeDNSPtr), arg0, arg1, arg2, arg3) } // ChangeProtection mocks base method. func (m *MockLoadBalancerClient) ChangeProtection(arg0 context.Context, arg1 *hcloud.LoadBalancer, arg2 hcloud.LoadBalancerChangeProtectionOpts) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ChangeProtection", arg0, arg1, arg2) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // ChangeProtection indicates an expected call of ChangeProtection. func (mr *MockLoadBalancerClientMockRecorder) ChangeProtection(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChangeProtection", reflect.TypeOf((*MockLoadBalancerClient)(nil).ChangeProtection), arg0, arg1, arg2) } // ChangeType mocks base method. func (m *MockLoadBalancerClient) ChangeType(arg0 context.Context, arg1 *hcloud.LoadBalancer, arg2 hcloud.LoadBalancerChangeTypeOpts) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ChangeType", arg0, arg1, arg2) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // ChangeType indicates an expected call of ChangeType. func (mr *MockLoadBalancerClientMockRecorder) ChangeType(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChangeType", reflect.TypeOf((*MockLoadBalancerClient)(nil).ChangeType), arg0, arg1, arg2) } // Create mocks base method. func (m *MockLoadBalancerClient) Create(arg0 context.Context, arg1 hcloud.LoadBalancerCreateOpts) (hcloud.LoadBalancerCreateResult, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Create", arg0, arg1) ret0, _ := ret[0].(hcloud.LoadBalancerCreateResult) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // Create indicates an expected call of Create. func (mr *MockLoadBalancerClientMockRecorder) Create(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Create", reflect.TypeOf((*MockLoadBalancerClient)(nil).Create), arg0, arg1) } // Delete mocks base method. func (m *MockLoadBalancerClient) Delete(arg0 context.Context, arg1 *hcloud.LoadBalancer) (*hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Delete", arg0, arg1) ret0, _ := ret[0].(*hcloud.Response) ret1, _ := ret[1].(error) return ret0, ret1 } // Delete indicates an expected call of Delete. func (mr *MockLoadBalancerClientMockRecorder) Delete(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockLoadBalancerClient)(nil).Delete), arg0, arg1) } // DeleteService mocks base method. func (m *MockLoadBalancerClient) DeleteService(arg0 context.Context, arg1 *hcloud.LoadBalancer, arg2 int) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "DeleteService", arg0, arg1, arg2) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // DeleteService indicates an expected call of DeleteService. func (mr *MockLoadBalancerClientMockRecorder) DeleteService(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteService", reflect.TypeOf((*MockLoadBalancerClient)(nil).DeleteService), arg0, arg1, arg2) } // DetachFromNetwork mocks base method. func (m *MockLoadBalancerClient) DetachFromNetwork(arg0 context.Context, arg1 *hcloud.LoadBalancer, arg2 hcloud.LoadBalancerDetachFromNetworkOpts) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "DetachFromNetwork", arg0, arg1, arg2) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // DetachFromNetwork indicates an expected call of DetachFromNetwork. func (mr *MockLoadBalancerClientMockRecorder) DetachFromNetwork(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DetachFromNetwork", reflect.TypeOf((*MockLoadBalancerClient)(nil).DetachFromNetwork), arg0, arg1, arg2) } // DisablePublicInterface mocks base method. func (m *MockLoadBalancerClient) DisablePublicInterface(arg0 context.Context, arg1 *hcloud.LoadBalancer) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "DisablePublicInterface", arg0, arg1) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // DisablePublicInterface indicates an expected call of DisablePublicInterface. func (mr *MockLoadBalancerClientMockRecorder) DisablePublicInterface(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DisablePublicInterface", reflect.TypeOf((*MockLoadBalancerClient)(nil).DisablePublicInterface), arg0, arg1) } // EnablePublicInterface mocks base method. func (m *MockLoadBalancerClient) EnablePublicInterface(arg0 context.Context, arg1 *hcloud.LoadBalancer) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "EnablePublicInterface", arg0, arg1) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // EnablePublicInterface indicates an expected call of EnablePublicInterface. func (mr *MockLoadBalancerClientMockRecorder) EnablePublicInterface(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EnablePublicInterface", reflect.TypeOf((*MockLoadBalancerClient)(nil).EnablePublicInterface), arg0, arg1) } // Get mocks base method. func (m *MockLoadBalancerClient) Get(arg0 context.Context, arg1 string) (*hcloud.LoadBalancer, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Get", arg0, arg1) ret0, _ := ret[0].(*hcloud.LoadBalancer) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // Get indicates an expected call of Get. func (mr *MockLoadBalancerClientMockRecorder) Get(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockLoadBalancerClient)(nil).Get), arg0, arg1) } // GetByID mocks base method. func (m *MockLoadBalancerClient) GetByID(arg0 context.Context, arg1 int64) (*hcloud.LoadBalancer, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetByID", arg0, arg1) ret0, _ := ret[0].(*hcloud.LoadBalancer) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // GetByID indicates an expected call of GetByID. func (mr *MockLoadBalancerClientMockRecorder) GetByID(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByID", reflect.TypeOf((*MockLoadBalancerClient)(nil).GetByID), arg0, arg1) } // GetByName mocks base method. func (m *MockLoadBalancerClient) GetByName(arg0 context.Context, arg1 string) (*hcloud.LoadBalancer, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetByName", arg0, arg1) ret0, _ := ret[0].(*hcloud.LoadBalancer) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // GetByName indicates an expected call of GetByName. func (mr *MockLoadBalancerClientMockRecorder) GetByName(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByName", reflect.TypeOf((*MockLoadBalancerClient)(nil).GetByName), arg0, arg1) } // GetMetrics mocks base method. func (m *MockLoadBalancerClient) GetMetrics(arg0 context.Context, arg1 *hcloud.LoadBalancer, arg2 hcloud.LoadBalancerGetMetricsOpts) (*hcloud.LoadBalancerMetrics, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetMetrics", arg0, arg1, arg2) ret0, _ := ret[0].(*hcloud.LoadBalancerMetrics) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // GetMetrics indicates an expected call of GetMetrics. func (mr *MockLoadBalancerClientMockRecorder) GetMetrics(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMetrics", reflect.TypeOf((*MockLoadBalancerClient)(nil).GetMetrics), arg0, arg1, arg2) } // LabelKeys mocks base method. func (m *MockLoadBalancerClient) LabelKeys(arg0 string) []string { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "LabelKeys", arg0) ret0, _ := ret[0].([]string) return ret0 } // LabelKeys indicates an expected call of LabelKeys. func (mr *MockLoadBalancerClientMockRecorder) LabelKeys(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LabelKeys", reflect.TypeOf((*MockLoadBalancerClient)(nil).LabelKeys), arg0) } // List mocks base method. func (m *MockLoadBalancerClient) List(arg0 context.Context, arg1 hcloud.LoadBalancerListOpts) ([]*hcloud.LoadBalancer, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "List", arg0, arg1) ret0, _ := ret[0].([]*hcloud.LoadBalancer) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // List indicates an expected call of List. func (mr *MockLoadBalancerClientMockRecorder) List(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockLoadBalancerClient)(nil).List), arg0, arg1) } // LoadBalancerName mocks base method. func (m *MockLoadBalancerClient) LoadBalancerName(arg0 int64) string { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "LoadBalancerName", arg0) ret0, _ := ret[0].(string) return ret0 } // LoadBalancerName indicates an expected call of LoadBalancerName. func (mr *MockLoadBalancerClientMockRecorder) LoadBalancerName(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadBalancerName", reflect.TypeOf((*MockLoadBalancerClient)(nil).LoadBalancerName), arg0) } // Names mocks base method. func (m *MockLoadBalancerClient) Names() []string { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Names") ret0, _ := ret[0].([]string) return ret0 } // Names indicates an expected call of Names. func (mr *MockLoadBalancerClientMockRecorder) Names() *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Names", reflect.TypeOf((*MockLoadBalancerClient)(nil).Names)) } // RemoveIPTarget mocks base method. func (m *MockLoadBalancerClient) RemoveIPTarget(arg0 context.Context, arg1 *hcloud.LoadBalancer, arg2 net.IP) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "RemoveIPTarget", arg0, arg1, arg2) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // RemoveIPTarget indicates an expected call of RemoveIPTarget. func (mr *MockLoadBalancerClientMockRecorder) RemoveIPTarget(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveIPTarget", reflect.TypeOf((*MockLoadBalancerClient)(nil).RemoveIPTarget), arg0, arg1, arg2) } // RemoveLabelSelectorTarget mocks base method. func (m *MockLoadBalancerClient) RemoveLabelSelectorTarget(arg0 context.Context, arg1 *hcloud.LoadBalancer, arg2 string) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "RemoveLabelSelectorTarget", arg0, arg1, arg2) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // RemoveLabelSelectorTarget indicates an expected call of RemoveLabelSelectorTarget. func (mr *MockLoadBalancerClientMockRecorder) RemoveLabelSelectorTarget(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveLabelSelectorTarget", reflect.TypeOf((*MockLoadBalancerClient)(nil).RemoveLabelSelectorTarget), arg0, arg1, arg2) } // RemoveServerTarget mocks base method. func (m *MockLoadBalancerClient) RemoveServerTarget(arg0 context.Context, arg1 *hcloud.LoadBalancer, arg2 *hcloud.Server) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "RemoveServerTarget", arg0, arg1, arg2) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // RemoveServerTarget indicates an expected call of RemoveServerTarget. func (mr *MockLoadBalancerClientMockRecorder) RemoveServerTarget(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveServerTarget", reflect.TypeOf((*MockLoadBalancerClient)(nil).RemoveServerTarget), arg0, arg1, arg2) } // Update mocks base method. func (m *MockLoadBalancerClient) Update(arg0 context.Context, arg1 *hcloud.LoadBalancer, arg2 hcloud.LoadBalancerUpdateOpts) (*hcloud.LoadBalancer, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Update", arg0, arg1, arg2) ret0, _ := ret[0].(*hcloud.LoadBalancer) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // Update indicates an expected call of Update. func (mr *MockLoadBalancerClientMockRecorder) Update(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockLoadBalancerClient)(nil).Update), arg0, arg1, arg2) } // UpdateService mocks base method. func (m *MockLoadBalancerClient) UpdateService(arg0 context.Context, arg1 *hcloud.LoadBalancer, arg2 int, arg3 hcloud.LoadBalancerUpdateServiceOpts) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "UpdateService", arg0, arg1, arg2, arg3) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // UpdateService indicates an expected call of UpdateService. func (mr *MockLoadBalancerClientMockRecorder) UpdateService(arg0, arg1, arg2, arg3 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateService", reflect.TypeOf((*MockLoadBalancerClient)(nil).UpdateService), arg0, arg1, arg2, arg3) } cli-1.39.0/internal/hcapi2/mock/zz_loadbalancer_type_client_mock.go000066400000000000000000000153311451614444200253670ustar00rootroot00000000000000// Code generated by MockGen. DO NOT EDIT. // Source: github.com/hetznercloud/cli/internal/hcapi2 (interfaces: LoadBalancerTypeClient) // Package hcapi2_mock is a generated GoMock package. package hcapi2_mock import ( context "context" reflect "reflect" gomock "github.com/golang/mock/gomock" hcloud "github.com/hetznercloud/hcloud-go/v2/hcloud" ) // MockLoadBalancerTypeClient is a mock of LoadBalancerTypeClient interface. type MockLoadBalancerTypeClient struct { ctrl *gomock.Controller recorder *MockLoadBalancerTypeClientMockRecorder } // MockLoadBalancerTypeClientMockRecorder is the mock recorder for MockLoadBalancerTypeClient. type MockLoadBalancerTypeClientMockRecorder struct { mock *MockLoadBalancerTypeClient } // NewMockLoadBalancerTypeClient creates a new mock instance. func NewMockLoadBalancerTypeClient(ctrl *gomock.Controller) *MockLoadBalancerTypeClient { mock := &MockLoadBalancerTypeClient{ctrl: ctrl} mock.recorder = &MockLoadBalancerTypeClientMockRecorder{mock} return mock } // EXPECT returns an object that allows the caller to indicate expected use. func (m *MockLoadBalancerTypeClient) EXPECT() *MockLoadBalancerTypeClientMockRecorder { return m.recorder } // All mocks base method. func (m *MockLoadBalancerTypeClient) All(arg0 context.Context) ([]*hcloud.LoadBalancerType, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "All", arg0) ret0, _ := ret[0].([]*hcloud.LoadBalancerType) ret1, _ := ret[1].(error) return ret0, ret1 } // All indicates an expected call of All. func (mr *MockLoadBalancerTypeClientMockRecorder) All(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "All", reflect.TypeOf((*MockLoadBalancerTypeClient)(nil).All), arg0) } // AllWithOpts mocks base method. func (m *MockLoadBalancerTypeClient) AllWithOpts(arg0 context.Context, arg1 hcloud.LoadBalancerTypeListOpts) ([]*hcloud.LoadBalancerType, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "AllWithOpts", arg0, arg1) ret0, _ := ret[0].([]*hcloud.LoadBalancerType) ret1, _ := ret[1].(error) return ret0, ret1 } // AllWithOpts indicates an expected call of AllWithOpts. func (mr *MockLoadBalancerTypeClientMockRecorder) AllWithOpts(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AllWithOpts", reflect.TypeOf((*MockLoadBalancerTypeClient)(nil).AllWithOpts), arg0, arg1) } // Get mocks base method. func (m *MockLoadBalancerTypeClient) Get(arg0 context.Context, arg1 string) (*hcloud.LoadBalancerType, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Get", arg0, arg1) ret0, _ := ret[0].(*hcloud.LoadBalancerType) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // Get indicates an expected call of Get. func (mr *MockLoadBalancerTypeClientMockRecorder) Get(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockLoadBalancerTypeClient)(nil).Get), arg0, arg1) } // GetByID mocks base method. func (m *MockLoadBalancerTypeClient) GetByID(arg0 context.Context, arg1 int64) (*hcloud.LoadBalancerType, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetByID", arg0, arg1) ret0, _ := ret[0].(*hcloud.LoadBalancerType) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // GetByID indicates an expected call of GetByID. func (mr *MockLoadBalancerTypeClientMockRecorder) GetByID(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByID", reflect.TypeOf((*MockLoadBalancerTypeClient)(nil).GetByID), arg0, arg1) } // GetByName mocks base method. func (m *MockLoadBalancerTypeClient) GetByName(arg0 context.Context, arg1 string) (*hcloud.LoadBalancerType, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetByName", arg0, arg1) ret0, _ := ret[0].(*hcloud.LoadBalancerType) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // GetByName indicates an expected call of GetByName. func (mr *MockLoadBalancerTypeClientMockRecorder) GetByName(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByName", reflect.TypeOf((*MockLoadBalancerTypeClient)(nil).GetByName), arg0, arg1) } // List mocks base method. func (m *MockLoadBalancerTypeClient) List(arg0 context.Context, arg1 hcloud.LoadBalancerTypeListOpts) ([]*hcloud.LoadBalancerType, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "List", arg0, arg1) ret0, _ := ret[0].([]*hcloud.LoadBalancerType) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // List indicates an expected call of List. func (mr *MockLoadBalancerTypeClientMockRecorder) List(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockLoadBalancerTypeClient)(nil).List), arg0, arg1) } // LoadBalancerTypeDescription mocks base method. func (m *MockLoadBalancerTypeClient) LoadBalancerTypeDescription(arg0 int64) string { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "LoadBalancerTypeDescription", arg0) ret0, _ := ret[0].(string) return ret0 } // LoadBalancerTypeDescription indicates an expected call of LoadBalancerTypeDescription. func (mr *MockLoadBalancerTypeClientMockRecorder) LoadBalancerTypeDescription(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadBalancerTypeDescription", reflect.TypeOf((*MockLoadBalancerTypeClient)(nil).LoadBalancerTypeDescription), arg0) } // LoadBalancerTypeName mocks base method. func (m *MockLoadBalancerTypeClient) LoadBalancerTypeName(arg0 int64) string { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "LoadBalancerTypeName", arg0) ret0, _ := ret[0].(string) return ret0 } // LoadBalancerTypeName indicates an expected call of LoadBalancerTypeName. func (mr *MockLoadBalancerTypeClientMockRecorder) LoadBalancerTypeName(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadBalancerTypeName", reflect.TypeOf((*MockLoadBalancerTypeClient)(nil).LoadBalancerTypeName), arg0) } // Names mocks base method. func (m *MockLoadBalancerTypeClient) Names() []string { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Names") ret0, _ := ret[0].([]string) return ret0 } // Names indicates an expected call of Names. func (mr *MockLoadBalancerTypeClientMockRecorder) Names() *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Names", reflect.TypeOf((*MockLoadBalancerTypeClient)(nil).Names)) } cli-1.39.0/internal/hcapi2/mock/zz_location_client_mock.go000066400000000000000000000130631451614444200235270ustar00rootroot00000000000000// Code generated by MockGen. DO NOT EDIT. // Source: github.com/hetznercloud/cli/internal/hcapi2 (interfaces: LocationClient) // Package hcapi2_mock is a generated GoMock package. package hcapi2_mock import ( context "context" reflect "reflect" gomock "github.com/golang/mock/gomock" hcloud "github.com/hetznercloud/hcloud-go/v2/hcloud" ) // MockLocationClient is a mock of LocationClient interface. type MockLocationClient struct { ctrl *gomock.Controller recorder *MockLocationClientMockRecorder } // MockLocationClientMockRecorder is the mock recorder for MockLocationClient. type MockLocationClientMockRecorder struct { mock *MockLocationClient } // NewMockLocationClient creates a new mock instance. func NewMockLocationClient(ctrl *gomock.Controller) *MockLocationClient { mock := &MockLocationClient{ctrl: ctrl} mock.recorder = &MockLocationClientMockRecorder{mock} return mock } // EXPECT returns an object that allows the caller to indicate expected use. func (m *MockLocationClient) EXPECT() *MockLocationClientMockRecorder { return m.recorder } // All mocks base method. func (m *MockLocationClient) All(arg0 context.Context) ([]*hcloud.Location, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "All", arg0) ret0, _ := ret[0].([]*hcloud.Location) ret1, _ := ret[1].(error) return ret0, ret1 } // All indicates an expected call of All. func (mr *MockLocationClientMockRecorder) All(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "All", reflect.TypeOf((*MockLocationClient)(nil).All), arg0) } // AllWithOpts mocks base method. func (m *MockLocationClient) AllWithOpts(arg0 context.Context, arg1 hcloud.LocationListOpts) ([]*hcloud.Location, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "AllWithOpts", arg0, arg1) ret0, _ := ret[0].([]*hcloud.Location) ret1, _ := ret[1].(error) return ret0, ret1 } // AllWithOpts indicates an expected call of AllWithOpts. func (mr *MockLocationClientMockRecorder) AllWithOpts(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AllWithOpts", reflect.TypeOf((*MockLocationClient)(nil).AllWithOpts), arg0, arg1) } // Get mocks base method. func (m *MockLocationClient) Get(arg0 context.Context, arg1 string) (*hcloud.Location, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Get", arg0, arg1) ret0, _ := ret[0].(*hcloud.Location) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // Get indicates an expected call of Get. func (mr *MockLocationClientMockRecorder) Get(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockLocationClient)(nil).Get), arg0, arg1) } // GetByID mocks base method. func (m *MockLocationClient) GetByID(arg0 context.Context, arg1 int64) (*hcloud.Location, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetByID", arg0, arg1) ret0, _ := ret[0].(*hcloud.Location) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // GetByID indicates an expected call of GetByID. func (mr *MockLocationClientMockRecorder) GetByID(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByID", reflect.TypeOf((*MockLocationClient)(nil).GetByID), arg0, arg1) } // GetByName mocks base method. func (m *MockLocationClient) GetByName(arg0 context.Context, arg1 string) (*hcloud.Location, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetByName", arg0, arg1) ret0, _ := ret[0].(*hcloud.Location) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // GetByName indicates an expected call of GetByName. func (mr *MockLocationClientMockRecorder) GetByName(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByName", reflect.TypeOf((*MockLocationClient)(nil).GetByName), arg0, arg1) } // List mocks base method. func (m *MockLocationClient) List(arg0 context.Context, arg1 hcloud.LocationListOpts) ([]*hcloud.Location, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "List", arg0, arg1) ret0, _ := ret[0].([]*hcloud.Location) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // List indicates an expected call of List. func (mr *MockLocationClientMockRecorder) List(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockLocationClient)(nil).List), arg0, arg1) } // Names mocks base method. func (m *MockLocationClient) Names() []string { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Names") ret0, _ := ret[0].([]string) return ret0 } // Names indicates an expected call of Names. func (mr *MockLocationClientMockRecorder) Names() *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Names", reflect.TypeOf((*MockLocationClient)(nil).Names)) } // NetworkZones mocks base method. func (m *MockLocationClient) NetworkZones() []string { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "NetworkZones") ret0, _ := ret[0].([]string) return ret0 } // NetworkZones indicates an expected call of NetworkZones. func (mr *MockLocationClientMockRecorder) NetworkZones() *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NetworkZones", reflect.TypeOf((*MockLocationClient)(nil).NetworkZones)) } cli-1.39.0/internal/hcapi2/mock/zz_network_client_mock.go000066400000000000000000000301631451614444200234100ustar00rootroot00000000000000// Code generated by MockGen. DO NOT EDIT. // Source: github.com/hetznercloud/cli/internal/hcapi2 (interfaces: NetworkClient) // Package hcapi2_mock is a generated GoMock package. package hcapi2_mock import ( context "context" reflect "reflect" gomock "github.com/golang/mock/gomock" hcloud "github.com/hetznercloud/hcloud-go/v2/hcloud" ) // MockNetworkClient is a mock of NetworkClient interface. type MockNetworkClient struct { ctrl *gomock.Controller recorder *MockNetworkClientMockRecorder } // MockNetworkClientMockRecorder is the mock recorder for MockNetworkClient. type MockNetworkClientMockRecorder struct { mock *MockNetworkClient } // NewMockNetworkClient creates a new mock instance. func NewMockNetworkClient(ctrl *gomock.Controller) *MockNetworkClient { mock := &MockNetworkClient{ctrl: ctrl} mock.recorder = &MockNetworkClientMockRecorder{mock} return mock } // EXPECT returns an object that allows the caller to indicate expected use. func (m *MockNetworkClient) EXPECT() *MockNetworkClientMockRecorder { return m.recorder } // AddRoute mocks base method. func (m *MockNetworkClient) AddRoute(arg0 context.Context, arg1 *hcloud.Network, arg2 hcloud.NetworkAddRouteOpts) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "AddRoute", arg0, arg1, arg2) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // AddRoute indicates an expected call of AddRoute. func (mr *MockNetworkClientMockRecorder) AddRoute(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddRoute", reflect.TypeOf((*MockNetworkClient)(nil).AddRoute), arg0, arg1, arg2) } // AddSubnet mocks base method. func (m *MockNetworkClient) AddSubnet(arg0 context.Context, arg1 *hcloud.Network, arg2 hcloud.NetworkAddSubnetOpts) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "AddSubnet", arg0, arg1, arg2) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // AddSubnet indicates an expected call of AddSubnet. func (mr *MockNetworkClientMockRecorder) AddSubnet(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddSubnet", reflect.TypeOf((*MockNetworkClient)(nil).AddSubnet), arg0, arg1, arg2) } // All mocks base method. func (m *MockNetworkClient) All(arg0 context.Context) ([]*hcloud.Network, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "All", arg0) ret0, _ := ret[0].([]*hcloud.Network) ret1, _ := ret[1].(error) return ret0, ret1 } // All indicates an expected call of All. func (mr *MockNetworkClientMockRecorder) All(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "All", reflect.TypeOf((*MockNetworkClient)(nil).All), arg0) } // AllWithOpts mocks base method. func (m *MockNetworkClient) AllWithOpts(arg0 context.Context, arg1 hcloud.NetworkListOpts) ([]*hcloud.Network, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "AllWithOpts", arg0, arg1) ret0, _ := ret[0].([]*hcloud.Network) ret1, _ := ret[1].(error) return ret0, ret1 } // AllWithOpts indicates an expected call of AllWithOpts. func (mr *MockNetworkClientMockRecorder) AllWithOpts(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AllWithOpts", reflect.TypeOf((*MockNetworkClient)(nil).AllWithOpts), arg0, arg1) } // ChangeIPRange mocks base method. func (m *MockNetworkClient) ChangeIPRange(arg0 context.Context, arg1 *hcloud.Network, arg2 hcloud.NetworkChangeIPRangeOpts) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ChangeIPRange", arg0, arg1, arg2) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // ChangeIPRange indicates an expected call of ChangeIPRange. func (mr *MockNetworkClientMockRecorder) ChangeIPRange(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChangeIPRange", reflect.TypeOf((*MockNetworkClient)(nil).ChangeIPRange), arg0, arg1, arg2) } // ChangeProtection mocks base method. func (m *MockNetworkClient) ChangeProtection(arg0 context.Context, arg1 *hcloud.Network, arg2 hcloud.NetworkChangeProtectionOpts) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ChangeProtection", arg0, arg1, arg2) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // ChangeProtection indicates an expected call of ChangeProtection. func (mr *MockNetworkClientMockRecorder) ChangeProtection(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChangeProtection", reflect.TypeOf((*MockNetworkClient)(nil).ChangeProtection), arg0, arg1, arg2) } // Create mocks base method. func (m *MockNetworkClient) Create(arg0 context.Context, arg1 hcloud.NetworkCreateOpts) (*hcloud.Network, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Create", arg0, arg1) ret0, _ := ret[0].(*hcloud.Network) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // Create indicates an expected call of Create. func (mr *MockNetworkClientMockRecorder) Create(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Create", reflect.TypeOf((*MockNetworkClient)(nil).Create), arg0, arg1) } // Delete mocks base method. func (m *MockNetworkClient) Delete(arg0 context.Context, arg1 *hcloud.Network) (*hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Delete", arg0, arg1) ret0, _ := ret[0].(*hcloud.Response) ret1, _ := ret[1].(error) return ret0, ret1 } // Delete indicates an expected call of Delete. func (mr *MockNetworkClientMockRecorder) Delete(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockNetworkClient)(nil).Delete), arg0, arg1) } // DeleteRoute mocks base method. func (m *MockNetworkClient) DeleteRoute(arg0 context.Context, arg1 *hcloud.Network, arg2 hcloud.NetworkDeleteRouteOpts) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "DeleteRoute", arg0, arg1, arg2) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // DeleteRoute indicates an expected call of DeleteRoute. func (mr *MockNetworkClientMockRecorder) DeleteRoute(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteRoute", reflect.TypeOf((*MockNetworkClient)(nil).DeleteRoute), arg0, arg1, arg2) } // DeleteSubnet mocks base method. func (m *MockNetworkClient) DeleteSubnet(arg0 context.Context, arg1 *hcloud.Network, arg2 hcloud.NetworkDeleteSubnetOpts) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "DeleteSubnet", arg0, arg1, arg2) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // DeleteSubnet indicates an expected call of DeleteSubnet. func (mr *MockNetworkClientMockRecorder) DeleteSubnet(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteSubnet", reflect.TypeOf((*MockNetworkClient)(nil).DeleteSubnet), arg0, arg1, arg2) } // Get mocks base method. func (m *MockNetworkClient) Get(arg0 context.Context, arg1 string) (*hcloud.Network, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Get", arg0, arg1) ret0, _ := ret[0].(*hcloud.Network) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // Get indicates an expected call of Get. func (mr *MockNetworkClientMockRecorder) Get(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockNetworkClient)(nil).Get), arg0, arg1) } // GetByID mocks base method. func (m *MockNetworkClient) GetByID(arg0 context.Context, arg1 int64) (*hcloud.Network, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetByID", arg0, arg1) ret0, _ := ret[0].(*hcloud.Network) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // GetByID indicates an expected call of GetByID. func (mr *MockNetworkClientMockRecorder) GetByID(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByID", reflect.TypeOf((*MockNetworkClient)(nil).GetByID), arg0, arg1) } // GetByName mocks base method. func (m *MockNetworkClient) GetByName(arg0 context.Context, arg1 string) (*hcloud.Network, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetByName", arg0, arg1) ret0, _ := ret[0].(*hcloud.Network) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // GetByName indicates an expected call of GetByName. func (mr *MockNetworkClientMockRecorder) GetByName(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByName", reflect.TypeOf((*MockNetworkClient)(nil).GetByName), arg0, arg1) } // LabelKeys mocks base method. func (m *MockNetworkClient) LabelKeys(arg0 string) []string { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "LabelKeys", arg0) ret0, _ := ret[0].([]string) return ret0 } // LabelKeys indicates an expected call of LabelKeys. func (mr *MockNetworkClientMockRecorder) LabelKeys(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LabelKeys", reflect.TypeOf((*MockNetworkClient)(nil).LabelKeys), arg0) } // List mocks base method. func (m *MockNetworkClient) List(arg0 context.Context, arg1 hcloud.NetworkListOpts) ([]*hcloud.Network, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "List", arg0, arg1) ret0, _ := ret[0].([]*hcloud.Network) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // List indicates an expected call of List. func (mr *MockNetworkClientMockRecorder) List(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockNetworkClient)(nil).List), arg0, arg1) } // Name mocks base method. func (m *MockNetworkClient) Name(arg0 int64) string { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Name", arg0) ret0, _ := ret[0].(string) return ret0 } // Name indicates an expected call of Name. func (mr *MockNetworkClientMockRecorder) Name(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Name", reflect.TypeOf((*MockNetworkClient)(nil).Name), arg0) } // Names mocks base method. func (m *MockNetworkClient) Names() []string { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Names") ret0, _ := ret[0].([]string) return ret0 } // Names indicates an expected call of Names. func (mr *MockNetworkClientMockRecorder) Names() *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Names", reflect.TypeOf((*MockNetworkClient)(nil).Names)) } // Update mocks base method. func (m *MockNetworkClient) Update(arg0 context.Context, arg1 *hcloud.Network, arg2 hcloud.NetworkUpdateOpts) (*hcloud.Network, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Update", arg0, arg1, arg2) ret0, _ := ret[0].(*hcloud.Network) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // Update indicates an expected call of Update. func (mr *MockNetworkClientMockRecorder) Update(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockNetworkClient)(nil).Update), arg0, arg1, arg2) } cli-1.39.0/internal/hcapi2/mock/zz_placement_group_client_mock.go000066400000000000000000000176101451614444200251050ustar00rootroot00000000000000// Code generated by MockGen. DO NOT EDIT. // Source: github.com/hetznercloud/cli/internal/hcapi2 (interfaces: PlacementGroupClient) // Package hcapi2_mock is a generated GoMock package. package hcapi2_mock import ( context "context" reflect "reflect" gomock "github.com/golang/mock/gomock" hcloud "github.com/hetznercloud/hcloud-go/v2/hcloud" ) // MockPlacementGroupClient is a mock of PlacementGroupClient interface. type MockPlacementGroupClient struct { ctrl *gomock.Controller recorder *MockPlacementGroupClientMockRecorder } // MockPlacementGroupClientMockRecorder is the mock recorder for MockPlacementGroupClient. type MockPlacementGroupClientMockRecorder struct { mock *MockPlacementGroupClient } // NewMockPlacementGroupClient creates a new mock instance. func NewMockPlacementGroupClient(ctrl *gomock.Controller) *MockPlacementGroupClient { mock := &MockPlacementGroupClient{ctrl: ctrl} mock.recorder = &MockPlacementGroupClientMockRecorder{mock} return mock } // EXPECT returns an object that allows the caller to indicate expected use. func (m *MockPlacementGroupClient) EXPECT() *MockPlacementGroupClientMockRecorder { return m.recorder } // All mocks base method. func (m *MockPlacementGroupClient) All(arg0 context.Context) ([]*hcloud.PlacementGroup, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "All", arg0) ret0, _ := ret[0].([]*hcloud.PlacementGroup) ret1, _ := ret[1].(error) return ret0, ret1 } // All indicates an expected call of All. func (mr *MockPlacementGroupClientMockRecorder) All(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "All", reflect.TypeOf((*MockPlacementGroupClient)(nil).All), arg0) } // AllWithOpts mocks base method. func (m *MockPlacementGroupClient) AllWithOpts(arg0 context.Context, arg1 hcloud.PlacementGroupListOpts) ([]*hcloud.PlacementGroup, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "AllWithOpts", arg0, arg1) ret0, _ := ret[0].([]*hcloud.PlacementGroup) ret1, _ := ret[1].(error) return ret0, ret1 } // AllWithOpts indicates an expected call of AllWithOpts. func (mr *MockPlacementGroupClientMockRecorder) AllWithOpts(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AllWithOpts", reflect.TypeOf((*MockPlacementGroupClient)(nil).AllWithOpts), arg0, arg1) } // Create mocks base method. func (m *MockPlacementGroupClient) Create(arg0 context.Context, arg1 hcloud.PlacementGroupCreateOpts) (hcloud.PlacementGroupCreateResult, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Create", arg0, arg1) ret0, _ := ret[0].(hcloud.PlacementGroupCreateResult) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // Create indicates an expected call of Create. func (mr *MockPlacementGroupClientMockRecorder) Create(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Create", reflect.TypeOf((*MockPlacementGroupClient)(nil).Create), arg0, arg1) } // Delete mocks base method. func (m *MockPlacementGroupClient) Delete(arg0 context.Context, arg1 *hcloud.PlacementGroup) (*hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Delete", arg0, arg1) ret0, _ := ret[0].(*hcloud.Response) ret1, _ := ret[1].(error) return ret0, ret1 } // Delete indicates an expected call of Delete. func (mr *MockPlacementGroupClientMockRecorder) Delete(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockPlacementGroupClient)(nil).Delete), arg0, arg1) } // Get mocks base method. func (m *MockPlacementGroupClient) Get(arg0 context.Context, arg1 string) (*hcloud.PlacementGroup, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Get", arg0, arg1) ret0, _ := ret[0].(*hcloud.PlacementGroup) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // Get indicates an expected call of Get. func (mr *MockPlacementGroupClientMockRecorder) Get(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockPlacementGroupClient)(nil).Get), arg0, arg1) } // GetByID mocks base method. func (m *MockPlacementGroupClient) GetByID(arg0 context.Context, arg1 int64) (*hcloud.PlacementGroup, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetByID", arg0, arg1) ret0, _ := ret[0].(*hcloud.PlacementGroup) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // GetByID indicates an expected call of GetByID. func (mr *MockPlacementGroupClientMockRecorder) GetByID(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByID", reflect.TypeOf((*MockPlacementGroupClient)(nil).GetByID), arg0, arg1) } // GetByName mocks base method. func (m *MockPlacementGroupClient) GetByName(arg0 context.Context, arg1 string) (*hcloud.PlacementGroup, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetByName", arg0, arg1) ret0, _ := ret[0].(*hcloud.PlacementGroup) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // GetByName indicates an expected call of GetByName. func (mr *MockPlacementGroupClientMockRecorder) GetByName(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByName", reflect.TypeOf((*MockPlacementGroupClient)(nil).GetByName), arg0, arg1) } // LabelKeys mocks base method. func (m *MockPlacementGroupClient) LabelKeys(arg0 string) []string { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "LabelKeys", arg0) ret0, _ := ret[0].([]string) return ret0 } // LabelKeys indicates an expected call of LabelKeys. func (mr *MockPlacementGroupClientMockRecorder) LabelKeys(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LabelKeys", reflect.TypeOf((*MockPlacementGroupClient)(nil).LabelKeys), arg0) } // List mocks base method. func (m *MockPlacementGroupClient) List(arg0 context.Context, arg1 hcloud.PlacementGroupListOpts) ([]*hcloud.PlacementGroup, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "List", arg0, arg1) ret0, _ := ret[0].([]*hcloud.PlacementGroup) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // List indicates an expected call of List. func (mr *MockPlacementGroupClientMockRecorder) List(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockPlacementGroupClient)(nil).List), arg0, arg1) } // Names mocks base method. func (m *MockPlacementGroupClient) Names() []string { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Names") ret0, _ := ret[0].([]string) return ret0 } // Names indicates an expected call of Names. func (mr *MockPlacementGroupClientMockRecorder) Names() *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Names", reflect.TypeOf((*MockPlacementGroupClient)(nil).Names)) } // Update mocks base method. func (m *MockPlacementGroupClient) Update(arg0 context.Context, arg1 *hcloud.PlacementGroup, arg2 hcloud.PlacementGroupUpdateOpts) (*hcloud.PlacementGroup, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Update", arg0, arg1, arg2) ret0, _ := ret[0].(*hcloud.PlacementGroup) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // Update indicates an expected call of Update. func (mr *MockPlacementGroupClientMockRecorder) Update(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockPlacementGroupClient)(nil).Update), arg0, arg1, arg2) } cli-1.39.0/internal/hcapi2/mock/zz_primary_ip_client_mock.go000066400000000000000000000274021451614444200240740ustar00rootroot00000000000000// Code generated by MockGen. DO NOT EDIT. // Source: github.com/hetznercloud/cli/internal/hcapi2 (interfaces: PrimaryIPClient) // Package hcapi2_mock is a generated GoMock package. package hcapi2_mock import ( context "context" reflect "reflect" gomock "github.com/golang/mock/gomock" hcloud "github.com/hetznercloud/hcloud-go/v2/hcloud" ) // MockPrimaryIPClient is a mock of PrimaryIPClient interface. type MockPrimaryIPClient struct { ctrl *gomock.Controller recorder *MockPrimaryIPClientMockRecorder } // MockPrimaryIPClientMockRecorder is the mock recorder for MockPrimaryIPClient. type MockPrimaryIPClientMockRecorder struct { mock *MockPrimaryIPClient } // NewMockPrimaryIPClient creates a new mock instance. func NewMockPrimaryIPClient(ctrl *gomock.Controller) *MockPrimaryIPClient { mock := &MockPrimaryIPClient{ctrl: ctrl} mock.recorder = &MockPrimaryIPClientMockRecorder{mock} return mock } // EXPECT returns an object that allows the caller to indicate expected use. func (m *MockPrimaryIPClient) EXPECT() *MockPrimaryIPClientMockRecorder { return m.recorder } // All mocks base method. func (m *MockPrimaryIPClient) All(arg0 context.Context) ([]*hcloud.PrimaryIP, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "All", arg0) ret0, _ := ret[0].([]*hcloud.PrimaryIP) ret1, _ := ret[1].(error) return ret0, ret1 } // All indicates an expected call of All. func (mr *MockPrimaryIPClientMockRecorder) All(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "All", reflect.TypeOf((*MockPrimaryIPClient)(nil).All), arg0) } // AllWithOpts mocks base method. func (m *MockPrimaryIPClient) AllWithOpts(arg0 context.Context, arg1 hcloud.PrimaryIPListOpts) ([]*hcloud.PrimaryIP, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "AllWithOpts", arg0, arg1) ret0, _ := ret[0].([]*hcloud.PrimaryIP) ret1, _ := ret[1].(error) return ret0, ret1 } // AllWithOpts indicates an expected call of AllWithOpts. func (mr *MockPrimaryIPClientMockRecorder) AllWithOpts(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AllWithOpts", reflect.TypeOf((*MockPrimaryIPClient)(nil).AllWithOpts), arg0, arg1) } // Assign mocks base method. func (m *MockPrimaryIPClient) Assign(arg0 context.Context, arg1 hcloud.PrimaryIPAssignOpts) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Assign", arg0, arg1) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // Assign indicates an expected call of Assign. func (mr *MockPrimaryIPClientMockRecorder) Assign(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Assign", reflect.TypeOf((*MockPrimaryIPClient)(nil).Assign), arg0, arg1) } // ChangeDNSPtr mocks base method. func (m *MockPrimaryIPClient) ChangeDNSPtr(arg0 context.Context, arg1 hcloud.PrimaryIPChangeDNSPtrOpts) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ChangeDNSPtr", arg0, arg1) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // ChangeDNSPtr indicates an expected call of ChangeDNSPtr. func (mr *MockPrimaryIPClientMockRecorder) ChangeDNSPtr(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChangeDNSPtr", reflect.TypeOf((*MockPrimaryIPClient)(nil).ChangeDNSPtr), arg0, arg1) } // ChangeProtection mocks base method. func (m *MockPrimaryIPClient) ChangeProtection(arg0 context.Context, arg1 hcloud.PrimaryIPChangeProtectionOpts) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ChangeProtection", arg0, arg1) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // ChangeProtection indicates an expected call of ChangeProtection. func (mr *MockPrimaryIPClientMockRecorder) ChangeProtection(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChangeProtection", reflect.TypeOf((*MockPrimaryIPClient)(nil).ChangeProtection), arg0, arg1) } // Create mocks base method. func (m *MockPrimaryIPClient) Create(arg0 context.Context, arg1 hcloud.PrimaryIPCreateOpts) (*hcloud.PrimaryIPCreateResult, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Create", arg0, arg1) ret0, _ := ret[0].(*hcloud.PrimaryIPCreateResult) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // Create indicates an expected call of Create. func (mr *MockPrimaryIPClientMockRecorder) Create(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Create", reflect.TypeOf((*MockPrimaryIPClient)(nil).Create), arg0, arg1) } // Delete mocks base method. func (m *MockPrimaryIPClient) Delete(arg0 context.Context, arg1 *hcloud.PrimaryIP) (*hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Delete", arg0, arg1) ret0, _ := ret[0].(*hcloud.Response) ret1, _ := ret[1].(error) return ret0, ret1 } // Delete indicates an expected call of Delete. func (mr *MockPrimaryIPClientMockRecorder) Delete(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockPrimaryIPClient)(nil).Delete), arg0, arg1) } // Get mocks base method. func (m *MockPrimaryIPClient) Get(arg0 context.Context, arg1 string) (*hcloud.PrimaryIP, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Get", arg0, arg1) ret0, _ := ret[0].(*hcloud.PrimaryIP) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // Get indicates an expected call of Get. func (mr *MockPrimaryIPClientMockRecorder) Get(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockPrimaryIPClient)(nil).Get), arg0, arg1) } // GetByID mocks base method. func (m *MockPrimaryIPClient) GetByID(arg0 context.Context, arg1 int64) (*hcloud.PrimaryIP, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetByID", arg0, arg1) ret0, _ := ret[0].(*hcloud.PrimaryIP) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // GetByID indicates an expected call of GetByID. func (mr *MockPrimaryIPClientMockRecorder) GetByID(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByID", reflect.TypeOf((*MockPrimaryIPClient)(nil).GetByID), arg0, arg1) } // GetByIP mocks base method. func (m *MockPrimaryIPClient) GetByIP(arg0 context.Context, arg1 string) (*hcloud.PrimaryIP, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetByIP", arg0, arg1) ret0, _ := ret[0].(*hcloud.PrimaryIP) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // GetByIP indicates an expected call of GetByIP. func (mr *MockPrimaryIPClientMockRecorder) GetByIP(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByIP", reflect.TypeOf((*MockPrimaryIPClient)(nil).GetByIP), arg0, arg1) } // GetByName mocks base method. func (m *MockPrimaryIPClient) GetByName(arg0 context.Context, arg1 string) (*hcloud.PrimaryIP, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetByName", arg0, arg1) ret0, _ := ret[0].(*hcloud.PrimaryIP) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // GetByName indicates an expected call of GetByName. func (mr *MockPrimaryIPClientMockRecorder) GetByName(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByName", reflect.TypeOf((*MockPrimaryIPClient)(nil).GetByName), arg0, arg1) } // IPv4Names mocks base method. func (m *MockPrimaryIPClient) IPv4Names() []string { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "IPv4Names") ret0, _ := ret[0].([]string) return ret0 } // IPv4Names indicates an expected call of IPv4Names. func (mr *MockPrimaryIPClientMockRecorder) IPv4Names() *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IPv4Names", reflect.TypeOf((*MockPrimaryIPClient)(nil).IPv4Names)) } // IPv6Names mocks base method. func (m *MockPrimaryIPClient) IPv6Names() []string { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "IPv6Names") ret0, _ := ret[0].([]string) return ret0 } // IPv6Names indicates an expected call of IPv6Names. func (mr *MockPrimaryIPClientMockRecorder) IPv6Names() *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IPv6Names", reflect.TypeOf((*MockPrimaryIPClient)(nil).IPv6Names)) } // LabelKeys mocks base method. func (m *MockPrimaryIPClient) LabelKeys(arg0 string) []string { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "LabelKeys", arg0) ret0, _ := ret[0].([]string) return ret0 } // LabelKeys indicates an expected call of LabelKeys. func (mr *MockPrimaryIPClientMockRecorder) LabelKeys(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LabelKeys", reflect.TypeOf((*MockPrimaryIPClient)(nil).LabelKeys), arg0) } // List mocks base method. func (m *MockPrimaryIPClient) List(arg0 context.Context, arg1 hcloud.PrimaryIPListOpts) ([]*hcloud.PrimaryIP, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "List", arg0, arg1) ret0, _ := ret[0].([]*hcloud.PrimaryIP) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // List indicates an expected call of List. func (mr *MockPrimaryIPClientMockRecorder) List(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockPrimaryIPClient)(nil).List), arg0, arg1) } // Names mocks base method. func (m *MockPrimaryIPClient) Names() []string { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Names") ret0, _ := ret[0].([]string) return ret0 } // Names indicates an expected call of Names. func (mr *MockPrimaryIPClientMockRecorder) Names() *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Names", reflect.TypeOf((*MockPrimaryIPClient)(nil).Names)) } // Unassign mocks base method. func (m *MockPrimaryIPClient) Unassign(arg0 context.Context, arg1 int64) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Unassign", arg0, arg1) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // Unassign indicates an expected call of Unassign. func (mr *MockPrimaryIPClientMockRecorder) Unassign(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Unassign", reflect.TypeOf((*MockPrimaryIPClient)(nil).Unassign), arg0, arg1) } // Update mocks base method. func (m *MockPrimaryIPClient) Update(arg0 context.Context, arg1 *hcloud.PrimaryIP, arg2 hcloud.PrimaryIPUpdateOpts) (*hcloud.PrimaryIP, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Update", arg0, arg1, arg2) ret0, _ := ret[0].(*hcloud.PrimaryIP) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // Update indicates an expected call of Update. func (mr *MockPrimaryIPClientMockRecorder) Update(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockPrimaryIPClient)(nil).Update), arg0, arg1, arg2) } cli-1.39.0/internal/hcapi2/mock/zz_rdns_client_mock.go000066400000000000000000000033501451614444200226630ustar00rootroot00000000000000// Code generated by MockGen. DO NOT EDIT. // Source: github.com/hetznercloud/cli/internal/hcapi2 (interfaces: RDNSClient) // Package hcapi2_mock is a generated GoMock package. package hcapi2_mock import ( context "context" net "net" reflect "reflect" gomock "github.com/golang/mock/gomock" hcloud "github.com/hetznercloud/hcloud-go/v2/hcloud" ) // MockRDNSClient is a mock of RDNSClient interface. type MockRDNSClient struct { ctrl *gomock.Controller recorder *MockRDNSClientMockRecorder } // MockRDNSClientMockRecorder is the mock recorder for MockRDNSClient. type MockRDNSClientMockRecorder struct { mock *MockRDNSClient } // NewMockRDNSClient creates a new mock instance. func NewMockRDNSClient(ctrl *gomock.Controller) *MockRDNSClient { mock := &MockRDNSClient{ctrl: ctrl} mock.recorder = &MockRDNSClientMockRecorder{mock} return mock } // EXPECT returns an object that allows the caller to indicate expected use. func (m *MockRDNSClient) EXPECT() *MockRDNSClientMockRecorder { return m.recorder } // ChangeDNSPtr mocks base method. func (m *MockRDNSClient) ChangeDNSPtr(arg0 context.Context, arg1 hcloud.RDNSSupporter, arg2 net.IP, arg3 *string) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ChangeDNSPtr", arg0, arg1, arg2, arg3) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // ChangeDNSPtr indicates an expected call of ChangeDNSPtr. func (mr *MockRDNSClientMockRecorder) ChangeDNSPtr(arg0, arg1, arg2, arg3 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChangeDNSPtr", reflect.TypeOf((*MockRDNSClient)(nil).ChangeDNSPtr), arg0, arg1, arg2, arg3) } cli-1.39.0/internal/hcapi2/mock/zz_server_client_mock.go000066400000000000000000000637631451614444200232410ustar00rootroot00000000000000// Code generated by MockGen. DO NOT EDIT. // Source: github.com/hetznercloud/cli/internal/hcapi2 (interfaces: ServerClient) // Package hcapi2_mock is a generated GoMock package. package hcapi2_mock import ( context "context" reflect "reflect" gomock "github.com/golang/mock/gomock" hcloud "github.com/hetznercloud/hcloud-go/v2/hcloud" ) // MockServerClient is a mock of ServerClient interface. type MockServerClient struct { ctrl *gomock.Controller recorder *MockServerClientMockRecorder } // MockServerClientMockRecorder is the mock recorder for MockServerClient. type MockServerClientMockRecorder struct { mock *MockServerClient } // NewMockServerClient creates a new mock instance. func NewMockServerClient(ctrl *gomock.Controller) *MockServerClient { mock := &MockServerClient{ctrl: ctrl} mock.recorder = &MockServerClientMockRecorder{mock} return mock } // EXPECT returns an object that allows the caller to indicate expected use. func (m *MockServerClient) EXPECT() *MockServerClientMockRecorder { return m.recorder } // AddToPlacementGroup mocks base method. func (m *MockServerClient) AddToPlacementGroup(arg0 context.Context, arg1 *hcloud.Server, arg2 *hcloud.PlacementGroup) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "AddToPlacementGroup", arg0, arg1, arg2) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // AddToPlacementGroup indicates an expected call of AddToPlacementGroup. func (mr *MockServerClientMockRecorder) AddToPlacementGroup(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddToPlacementGroup", reflect.TypeOf((*MockServerClient)(nil).AddToPlacementGroup), arg0, arg1, arg2) } // All mocks base method. func (m *MockServerClient) All(arg0 context.Context) ([]*hcloud.Server, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "All", arg0) ret0, _ := ret[0].([]*hcloud.Server) ret1, _ := ret[1].(error) return ret0, ret1 } // All indicates an expected call of All. func (mr *MockServerClientMockRecorder) All(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "All", reflect.TypeOf((*MockServerClient)(nil).All), arg0) } // AllWithOpts mocks base method. func (m *MockServerClient) AllWithOpts(arg0 context.Context, arg1 hcloud.ServerListOpts) ([]*hcloud.Server, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "AllWithOpts", arg0, arg1) ret0, _ := ret[0].([]*hcloud.Server) ret1, _ := ret[1].(error) return ret0, ret1 } // AllWithOpts indicates an expected call of AllWithOpts. func (mr *MockServerClientMockRecorder) AllWithOpts(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AllWithOpts", reflect.TypeOf((*MockServerClient)(nil).AllWithOpts), arg0, arg1) } // AttachISO mocks base method. func (m *MockServerClient) AttachISO(arg0 context.Context, arg1 *hcloud.Server, arg2 *hcloud.ISO) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "AttachISO", arg0, arg1, arg2) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // AttachISO indicates an expected call of AttachISO. func (mr *MockServerClientMockRecorder) AttachISO(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AttachISO", reflect.TypeOf((*MockServerClient)(nil).AttachISO), arg0, arg1, arg2) } // AttachToNetwork mocks base method. func (m *MockServerClient) AttachToNetwork(arg0 context.Context, arg1 *hcloud.Server, arg2 hcloud.ServerAttachToNetworkOpts) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "AttachToNetwork", arg0, arg1, arg2) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // AttachToNetwork indicates an expected call of AttachToNetwork. func (mr *MockServerClientMockRecorder) AttachToNetwork(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AttachToNetwork", reflect.TypeOf((*MockServerClient)(nil).AttachToNetwork), arg0, arg1, arg2) } // ChangeAliasIPs mocks base method. func (m *MockServerClient) ChangeAliasIPs(arg0 context.Context, arg1 *hcloud.Server, arg2 hcloud.ServerChangeAliasIPsOpts) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ChangeAliasIPs", arg0, arg1, arg2) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // ChangeAliasIPs indicates an expected call of ChangeAliasIPs. func (mr *MockServerClientMockRecorder) ChangeAliasIPs(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChangeAliasIPs", reflect.TypeOf((*MockServerClient)(nil).ChangeAliasIPs), arg0, arg1, arg2) } // ChangeDNSPtr mocks base method. func (m *MockServerClient) ChangeDNSPtr(arg0 context.Context, arg1 *hcloud.Server, arg2 string, arg3 *string) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ChangeDNSPtr", arg0, arg1, arg2, arg3) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // ChangeDNSPtr indicates an expected call of ChangeDNSPtr. func (mr *MockServerClientMockRecorder) ChangeDNSPtr(arg0, arg1, arg2, arg3 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChangeDNSPtr", reflect.TypeOf((*MockServerClient)(nil).ChangeDNSPtr), arg0, arg1, arg2, arg3) } // ChangeProtection mocks base method. func (m *MockServerClient) ChangeProtection(arg0 context.Context, arg1 *hcloud.Server, arg2 hcloud.ServerChangeProtectionOpts) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ChangeProtection", arg0, arg1, arg2) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // ChangeProtection indicates an expected call of ChangeProtection. func (mr *MockServerClientMockRecorder) ChangeProtection(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChangeProtection", reflect.TypeOf((*MockServerClient)(nil).ChangeProtection), arg0, arg1, arg2) } // ChangeType mocks base method. func (m *MockServerClient) ChangeType(arg0 context.Context, arg1 *hcloud.Server, arg2 hcloud.ServerChangeTypeOpts) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ChangeType", arg0, arg1, arg2) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // ChangeType indicates an expected call of ChangeType. func (mr *MockServerClientMockRecorder) ChangeType(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChangeType", reflect.TypeOf((*MockServerClient)(nil).ChangeType), arg0, arg1, arg2) } // Create mocks base method. func (m *MockServerClient) Create(arg0 context.Context, arg1 hcloud.ServerCreateOpts) (hcloud.ServerCreateResult, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Create", arg0, arg1) ret0, _ := ret[0].(hcloud.ServerCreateResult) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // Create indicates an expected call of Create. func (mr *MockServerClientMockRecorder) Create(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Create", reflect.TypeOf((*MockServerClient)(nil).Create), arg0, arg1) } // CreateImage mocks base method. func (m *MockServerClient) CreateImage(arg0 context.Context, arg1 *hcloud.Server, arg2 *hcloud.ServerCreateImageOpts) (hcloud.ServerCreateImageResult, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "CreateImage", arg0, arg1, arg2) ret0, _ := ret[0].(hcloud.ServerCreateImageResult) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // CreateImage indicates an expected call of CreateImage. func (mr *MockServerClientMockRecorder) CreateImage(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateImage", reflect.TypeOf((*MockServerClient)(nil).CreateImage), arg0, arg1, arg2) } // Delete mocks base method. func (m *MockServerClient) Delete(arg0 context.Context, arg1 *hcloud.Server) (*hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Delete", arg0, arg1) ret0, _ := ret[0].(*hcloud.Response) ret1, _ := ret[1].(error) return ret0, ret1 } // Delete indicates an expected call of Delete. func (mr *MockServerClientMockRecorder) Delete(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockServerClient)(nil).Delete), arg0, arg1) } // DeleteWithResult mocks base method. func (m *MockServerClient) DeleteWithResult(arg0 context.Context, arg1 *hcloud.Server) (*hcloud.ServerDeleteResult, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "DeleteWithResult", arg0, arg1) ret0, _ := ret[0].(*hcloud.ServerDeleteResult) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // DeleteWithResult indicates an expected call of DeleteWithResult. func (mr *MockServerClientMockRecorder) DeleteWithResult(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteWithResult", reflect.TypeOf((*MockServerClient)(nil).DeleteWithResult), arg0, arg1) } // DetachFromNetwork mocks base method. func (m *MockServerClient) DetachFromNetwork(arg0 context.Context, arg1 *hcloud.Server, arg2 hcloud.ServerDetachFromNetworkOpts) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "DetachFromNetwork", arg0, arg1, arg2) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // DetachFromNetwork indicates an expected call of DetachFromNetwork. func (mr *MockServerClientMockRecorder) DetachFromNetwork(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DetachFromNetwork", reflect.TypeOf((*MockServerClient)(nil).DetachFromNetwork), arg0, arg1, arg2) } // DetachISO mocks base method. func (m *MockServerClient) DetachISO(arg0 context.Context, arg1 *hcloud.Server) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "DetachISO", arg0, arg1) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // DetachISO indicates an expected call of DetachISO. func (mr *MockServerClientMockRecorder) DetachISO(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DetachISO", reflect.TypeOf((*MockServerClient)(nil).DetachISO), arg0, arg1) } // DisableBackup mocks base method. func (m *MockServerClient) DisableBackup(arg0 context.Context, arg1 *hcloud.Server) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "DisableBackup", arg0, arg1) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // DisableBackup indicates an expected call of DisableBackup. func (mr *MockServerClientMockRecorder) DisableBackup(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DisableBackup", reflect.TypeOf((*MockServerClient)(nil).DisableBackup), arg0, arg1) } // DisableRescue mocks base method. func (m *MockServerClient) DisableRescue(arg0 context.Context, arg1 *hcloud.Server) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "DisableRescue", arg0, arg1) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // DisableRescue indicates an expected call of DisableRescue. func (mr *MockServerClientMockRecorder) DisableRescue(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DisableRescue", reflect.TypeOf((*MockServerClient)(nil).DisableRescue), arg0, arg1) } // EnableBackup mocks base method. func (m *MockServerClient) EnableBackup(arg0 context.Context, arg1 *hcloud.Server, arg2 string) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "EnableBackup", arg0, arg1, arg2) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // EnableBackup indicates an expected call of EnableBackup. func (mr *MockServerClientMockRecorder) EnableBackup(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EnableBackup", reflect.TypeOf((*MockServerClient)(nil).EnableBackup), arg0, arg1, arg2) } // EnableRescue mocks base method. func (m *MockServerClient) EnableRescue(arg0 context.Context, arg1 *hcloud.Server, arg2 hcloud.ServerEnableRescueOpts) (hcloud.ServerEnableRescueResult, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "EnableRescue", arg0, arg1, arg2) ret0, _ := ret[0].(hcloud.ServerEnableRescueResult) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // EnableRescue indicates an expected call of EnableRescue. func (mr *MockServerClientMockRecorder) EnableRescue(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EnableRescue", reflect.TypeOf((*MockServerClient)(nil).EnableRescue), arg0, arg1, arg2) } // Get mocks base method. func (m *MockServerClient) Get(arg0 context.Context, arg1 string) (*hcloud.Server, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Get", arg0, arg1) ret0, _ := ret[0].(*hcloud.Server) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // Get indicates an expected call of Get. func (mr *MockServerClientMockRecorder) Get(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockServerClient)(nil).Get), arg0, arg1) } // GetByID mocks base method. func (m *MockServerClient) GetByID(arg0 context.Context, arg1 int64) (*hcloud.Server, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetByID", arg0, arg1) ret0, _ := ret[0].(*hcloud.Server) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // GetByID indicates an expected call of GetByID. func (mr *MockServerClientMockRecorder) GetByID(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByID", reflect.TypeOf((*MockServerClient)(nil).GetByID), arg0, arg1) } // GetByName mocks base method. func (m *MockServerClient) GetByName(arg0 context.Context, arg1 string) (*hcloud.Server, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetByName", arg0, arg1) ret0, _ := ret[0].(*hcloud.Server) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // GetByName indicates an expected call of GetByName. func (mr *MockServerClientMockRecorder) GetByName(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByName", reflect.TypeOf((*MockServerClient)(nil).GetByName), arg0, arg1) } // GetMetrics mocks base method. func (m *MockServerClient) GetMetrics(arg0 context.Context, arg1 *hcloud.Server, arg2 hcloud.ServerGetMetricsOpts) (*hcloud.ServerMetrics, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetMetrics", arg0, arg1, arg2) ret0, _ := ret[0].(*hcloud.ServerMetrics) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // GetMetrics indicates an expected call of GetMetrics. func (mr *MockServerClientMockRecorder) GetMetrics(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMetrics", reflect.TypeOf((*MockServerClient)(nil).GetMetrics), arg0, arg1, arg2) } // LabelKeys mocks base method. func (m *MockServerClient) LabelKeys(arg0 string) []string { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "LabelKeys", arg0) ret0, _ := ret[0].([]string) return ret0 } // LabelKeys indicates an expected call of LabelKeys. func (mr *MockServerClientMockRecorder) LabelKeys(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LabelKeys", reflect.TypeOf((*MockServerClient)(nil).LabelKeys), arg0) } // List mocks base method. func (m *MockServerClient) List(arg0 context.Context, arg1 hcloud.ServerListOpts) ([]*hcloud.Server, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "List", arg0, arg1) ret0, _ := ret[0].([]*hcloud.Server) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // List indicates an expected call of List. func (mr *MockServerClientMockRecorder) List(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockServerClient)(nil).List), arg0, arg1) } // Names mocks base method. func (m *MockServerClient) Names() []string { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Names") ret0, _ := ret[0].([]string) return ret0 } // Names indicates an expected call of Names. func (mr *MockServerClientMockRecorder) Names() *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Names", reflect.TypeOf((*MockServerClient)(nil).Names)) } // Poweroff mocks base method. func (m *MockServerClient) Poweroff(arg0 context.Context, arg1 *hcloud.Server) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Poweroff", arg0, arg1) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // Poweroff indicates an expected call of Poweroff. func (mr *MockServerClientMockRecorder) Poweroff(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Poweroff", reflect.TypeOf((*MockServerClient)(nil).Poweroff), arg0, arg1) } // Poweron mocks base method. func (m *MockServerClient) Poweron(arg0 context.Context, arg1 *hcloud.Server) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Poweron", arg0, arg1) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // Poweron indicates an expected call of Poweron. func (mr *MockServerClientMockRecorder) Poweron(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Poweron", reflect.TypeOf((*MockServerClient)(nil).Poweron), arg0, arg1) } // Reboot mocks base method. func (m *MockServerClient) Reboot(arg0 context.Context, arg1 *hcloud.Server) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Reboot", arg0, arg1) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // Reboot indicates an expected call of Reboot. func (mr *MockServerClientMockRecorder) Reboot(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Reboot", reflect.TypeOf((*MockServerClient)(nil).Reboot), arg0, arg1) } // Rebuild mocks base method. func (m *MockServerClient) Rebuild(arg0 context.Context, arg1 *hcloud.Server, arg2 hcloud.ServerRebuildOpts) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Rebuild", arg0, arg1, arg2) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // Rebuild indicates an expected call of Rebuild. func (mr *MockServerClientMockRecorder) Rebuild(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Rebuild", reflect.TypeOf((*MockServerClient)(nil).Rebuild), arg0, arg1, arg2) } // RebuildWithResult mocks base method. func (m *MockServerClient) RebuildWithResult(arg0 context.Context, arg1 *hcloud.Server, arg2 hcloud.ServerRebuildOpts) (hcloud.ServerRebuildResult, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "RebuildWithResult", arg0, arg1, arg2) ret0, _ := ret[0].(hcloud.ServerRebuildResult) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // RebuildWithResult indicates an expected call of RebuildWithResult. func (mr *MockServerClientMockRecorder) RebuildWithResult(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RebuildWithResult", reflect.TypeOf((*MockServerClient)(nil).RebuildWithResult), arg0, arg1, arg2) } // RemoveFromPlacementGroup mocks base method. func (m *MockServerClient) RemoveFromPlacementGroup(arg0 context.Context, arg1 *hcloud.Server) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "RemoveFromPlacementGroup", arg0, arg1) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // RemoveFromPlacementGroup indicates an expected call of RemoveFromPlacementGroup. func (mr *MockServerClientMockRecorder) RemoveFromPlacementGroup(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveFromPlacementGroup", reflect.TypeOf((*MockServerClient)(nil).RemoveFromPlacementGroup), arg0, arg1) } // RequestConsole mocks base method. func (m *MockServerClient) RequestConsole(arg0 context.Context, arg1 *hcloud.Server) (hcloud.ServerRequestConsoleResult, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "RequestConsole", arg0, arg1) ret0, _ := ret[0].(hcloud.ServerRequestConsoleResult) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // RequestConsole indicates an expected call of RequestConsole. func (mr *MockServerClientMockRecorder) RequestConsole(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RequestConsole", reflect.TypeOf((*MockServerClient)(nil).RequestConsole), arg0, arg1) } // Reset mocks base method. func (m *MockServerClient) Reset(arg0 context.Context, arg1 *hcloud.Server) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Reset", arg0, arg1) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // Reset indicates an expected call of Reset. func (mr *MockServerClientMockRecorder) Reset(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Reset", reflect.TypeOf((*MockServerClient)(nil).Reset), arg0, arg1) } // ResetPassword mocks base method. func (m *MockServerClient) ResetPassword(arg0 context.Context, arg1 *hcloud.Server) (hcloud.ServerResetPasswordResult, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ResetPassword", arg0, arg1) ret0, _ := ret[0].(hcloud.ServerResetPasswordResult) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // ResetPassword indicates an expected call of ResetPassword. func (mr *MockServerClientMockRecorder) ResetPassword(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ResetPassword", reflect.TypeOf((*MockServerClient)(nil).ResetPassword), arg0, arg1) } // ServerName mocks base method. func (m *MockServerClient) ServerName(arg0 int64) string { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ServerName", arg0) ret0, _ := ret[0].(string) return ret0 } // ServerName indicates an expected call of ServerName. func (mr *MockServerClientMockRecorder) ServerName(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ServerName", reflect.TypeOf((*MockServerClient)(nil).ServerName), arg0) } // Shutdown mocks base method. func (m *MockServerClient) Shutdown(arg0 context.Context, arg1 *hcloud.Server) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Shutdown", arg0, arg1) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // Shutdown indicates an expected call of Shutdown. func (mr *MockServerClientMockRecorder) Shutdown(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Shutdown", reflect.TypeOf((*MockServerClient)(nil).Shutdown), arg0, arg1) } // Update mocks base method. func (m *MockServerClient) Update(arg0 context.Context, arg1 *hcloud.Server, arg2 hcloud.ServerUpdateOpts) (*hcloud.Server, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Update", arg0, arg1, arg2) ret0, _ := ret[0].(*hcloud.Server) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // Update indicates an expected call of Update. func (mr *MockServerClientMockRecorder) Update(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockServerClient)(nil).Update), arg0, arg1, arg2) } cli-1.39.0/internal/hcapi2/mock/zz_server_type_client_mock.go000066400000000000000000000144431451614444200242710ustar00rootroot00000000000000// Code generated by MockGen. DO NOT EDIT. // Source: github.com/hetznercloud/cli/internal/hcapi2 (interfaces: ServerTypeClient) // Package hcapi2_mock is a generated GoMock package. package hcapi2_mock import ( context "context" reflect "reflect" gomock "github.com/golang/mock/gomock" hcloud "github.com/hetznercloud/hcloud-go/v2/hcloud" ) // MockServerTypeClient is a mock of ServerTypeClient interface. type MockServerTypeClient struct { ctrl *gomock.Controller recorder *MockServerTypeClientMockRecorder } // MockServerTypeClientMockRecorder is the mock recorder for MockServerTypeClient. type MockServerTypeClientMockRecorder struct { mock *MockServerTypeClient } // NewMockServerTypeClient creates a new mock instance. func NewMockServerTypeClient(ctrl *gomock.Controller) *MockServerTypeClient { mock := &MockServerTypeClient{ctrl: ctrl} mock.recorder = &MockServerTypeClientMockRecorder{mock} return mock } // EXPECT returns an object that allows the caller to indicate expected use. func (m *MockServerTypeClient) EXPECT() *MockServerTypeClientMockRecorder { return m.recorder } // All mocks base method. func (m *MockServerTypeClient) All(arg0 context.Context) ([]*hcloud.ServerType, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "All", arg0) ret0, _ := ret[0].([]*hcloud.ServerType) ret1, _ := ret[1].(error) return ret0, ret1 } // All indicates an expected call of All. func (mr *MockServerTypeClientMockRecorder) All(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "All", reflect.TypeOf((*MockServerTypeClient)(nil).All), arg0) } // AllWithOpts mocks base method. func (m *MockServerTypeClient) AllWithOpts(arg0 context.Context, arg1 hcloud.ServerTypeListOpts) ([]*hcloud.ServerType, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "AllWithOpts", arg0, arg1) ret0, _ := ret[0].([]*hcloud.ServerType) ret1, _ := ret[1].(error) return ret0, ret1 } // AllWithOpts indicates an expected call of AllWithOpts. func (mr *MockServerTypeClientMockRecorder) AllWithOpts(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AllWithOpts", reflect.TypeOf((*MockServerTypeClient)(nil).AllWithOpts), arg0, arg1) } // Get mocks base method. func (m *MockServerTypeClient) Get(arg0 context.Context, arg1 string) (*hcloud.ServerType, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Get", arg0, arg1) ret0, _ := ret[0].(*hcloud.ServerType) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // Get indicates an expected call of Get. func (mr *MockServerTypeClientMockRecorder) Get(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockServerTypeClient)(nil).Get), arg0, arg1) } // GetByID mocks base method. func (m *MockServerTypeClient) GetByID(arg0 context.Context, arg1 int64) (*hcloud.ServerType, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetByID", arg0, arg1) ret0, _ := ret[0].(*hcloud.ServerType) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // GetByID indicates an expected call of GetByID. func (mr *MockServerTypeClientMockRecorder) GetByID(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByID", reflect.TypeOf((*MockServerTypeClient)(nil).GetByID), arg0, arg1) } // GetByName mocks base method. func (m *MockServerTypeClient) GetByName(arg0 context.Context, arg1 string) (*hcloud.ServerType, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetByName", arg0, arg1) ret0, _ := ret[0].(*hcloud.ServerType) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // GetByName indicates an expected call of GetByName. func (mr *MockServerTypeClientMockRecorder) GetByName(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByName", reflect.TypeOf((*MockServerTypeClient)(nil).GetByName), arg0, arg1) } // List mocks base method. func (m *MockServerTypeClient) List(arg0 context.Context, arg1 hcloud.ServerTypeListOpts) ([]*hcloud.ServerType, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "List", arg0, arg1) ret0, _ := ret[0].([]*hcloud.ServerType) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // List indicates an expected call of List. func (mr *MockServerTypeClientMockRecorder) List(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockServerTypeClient)(nil).List), arg0, arg1) } // Names mocks base method. func (m *MockServerTypeClient) Names() []string { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Names") ret0, _ := ret[0].([]string) return ret0 } // Names indicates an expected call of Names. func (mr *MockServerTypeClientMockRecorder) Names() *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Names", reflect.TypeOf((*MockServerTypeClient)(nil).Names)) } // ServerTypeDescription mocks base method. func (m *MockServerTypeClient) ServerTypeDescription(arg0 int64) string { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ServerTypeDescription", arg0) ret0, _ := ret[0].(string) return ret0 } // ServerTypeDescription indicates an expected call of ServerTypeDescription. func (mr *MockServerTypeClientMockRecorder) ServerTypeDescription(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ServerTypeDescription", reflect.TypeOf((*MockServerTypeClient)(nil).ServerTypeDescription), arg0) } // ServerTypeName mocks base method. func (m *MockServerTypeClient) ServerTypeName(arg0 int64) string { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ServerTypeName", arg0) ret0, _ := ret[0].(string) return ret0 } // ServerTypeName indicates an expected call of ServerTypeName. func (mr *MockServerTypeClientMockRecorder) ServerTypeName(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ServerTypeName", reflect.TypeOf((*MockServerTypeClient)(nil).ServerTypeName), arg0) } cli-1.39.0/internal/hcapi2/mock/zz_ssh_key_client_mock.go000066400000000000000000000177711451614444200233760ustar00rootroot00000000000000// Code generated by MockGen. DO NOT EDIT. // Source: github.com/hetznercloud/cli/internal/hcapi2 (interfaces: SSHKeyClient) // Package hcapi2_mock is a generated GoMock package. package hcapi2_mock import ( context "context" reflect "reflect" gomock "github.com/golang/mock/gomock" hcloud "github.com/hetznercloud/hcloud-go/v2/hcloud" ) // MockSSHKeyClient is a mock of SSHKeyClient interface. type MockSSHKeyClient struct { ctrl *gomock.Controller recorder *MockSSHKeyClientMockRecorder } // MockSSHKeyClientMockRecorder is the mock recorder for MockSSHKeyClient. type MockSSHKeyClientMockRecorder struct { mock *MockSSHKeyClient } // NewMockSSHKeyClient creates a new mock instance. func NewMockSSHKeyClient(ctrl *gomock.Controller) *MockSSHKeyClient { mock := &MockSSHKeyClient{ctrl: ctrl} mock.recorder = &MockSSHKeyClientMockRecorder{mock} return mock } // EXPECT returns an object that allows the caller to indicate expected use. func (m *MockSSHKeyClient) EXPECT() *MockSSHKeyClientMockRecorder { return m.recorder } // All mocks base method. func (m *MockSSHKeyClient) All(arg0 context.Context) ([]*hcloud.SSHKey, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "All", arg0) ret0, _ := ret[0].([]*hcloud.SSHKey) ret1, _ := ret[1].(error) return ret0, ret1 } // All indicates an expected call of All. func (mr *MockSSHKeyClientMockRecorder) All(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "All", reflect.TypeOf((*MockSSHKeyClient)(nil).All), arg0) } // AllWithOpts mocks base method. func (m *MockSSHKeyClient) AllWithOpts(arg0 context.Context, arg1 hcloud.SSHKeyListOpts) ([]*hcloud.SSHKey, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "AllWithOpts", arg0, arg1) ret0, _ := ret[0].([]*hcloud.SSHKey) ret1, _ := ret[1].(error) return ret0, ret1 } // AllWithOpts indicates an expected call of AllWithOpts. func (mr *MockSSHKeyClientMockRecorder) AllWithOpts(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AllWithOpts", reflect.TypeOf((*MockSSHKeyClient)(nil).AllWithOpts), arg0, arg1) } // Create mocks base method. func (m *MockSSHKeyClient) Create(arg0 context.Context, arg1 hcloud.SSHKeyCreateOpts) (*hcloud.SSHKey, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Create", arg0, arg1) ret0, _ := ret[0].(*hcloud.SSHKey) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // Create indicates an expected call of Create. func (mr *MockSSHKeyClientMockRecorder) Create(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Create", reflect.TypeOf((*MockSSHKeyClient)(nil).Create), arg0, arg1) } // Delete mocks base method. func (m *MockSSHKeyClient) Delete(arg0 context.Context, arg1 *hcloud.SSHKey) (*hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Delete", arg0, arg1) ret0, _ := ret[0].(*hcloud.Response) ret1, _ := ret[1].(error) return ret0, ret1 } // Delete indicates an expected call of Delete. func (mr *MockSSHKeyClientMockRecorder) Delete(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockSSHKeyClient)(nil).Delete), arg0, arg1) } // Get mocks base method. func (m *MockSSHKeyClient) Get(arg0 context.Context, arg1 string) (*hcloud.SSHKey, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Get", arg0, arg1) ret0, _ := ret[0].(*hcloud.SSHKey) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // Get indicates an expected call of Get. func (mr *MockSSHKeyClientMockRecorder) Get(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockSSHKeyClient)(nil).Get), arg0, arg1) } // GetByFingerprint mocks base method. func (m *MockSSHKeyClient) GetByFingerprint(arg0 context.Context, arg1 string) (*hcloud.SSHKey, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetByFingerprint", arg0, arg1) ret0, _ := ret[0].(*hcloud.SSHKey) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // GetByFingerprint indicates an expected call of GetByFingerprint. func (mr *MockSSHKeyClientMockRecorder) GetByFingerprint(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByFingerprint", reflect.TypeOf((*MockSSHKeyClient)(nil).GetByFingerprint), arg0, arg1) } // GetByID mocks base method. func (m *MockSSHKeyClient) GetByID(arg0 context.Context, arg1 int64) (*hcloud.SSHKey, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetByID", arg0, arg1) ret0, _ := ret[0].(*hcloud.SSHKey) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // GetByID indicates an expected call of GetByID. func (mr *MockSSHKeyClientMockRecorder) GetByID(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByID", reflect.TypeOf((*MockSSHKeyClient)(nil).GetByID), arg0, arg1) } // GetByName mocks base method. func (m *MockSSHKeyClient) GetByName(arg0 context.Context, arg1 string) (*hcloud.SSHKey, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetByName", arg0, arg1) ret0, _ := ret[0].(*hcloud.SSHKey) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // GetByName indicates an expected call of GetByName. func (mr *MockSSHKeyClientMockRecorder) GetByName(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByName", reflect.TypeOf((*MockSSHKeyClient)(nil).GetByName), arg0, arg1) } // LabelKeys mocks base method. func (m *MockSSHKeyClient) LabelKeys(arg0 string) []string { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "LabelKeys", arg0) ret0, _ := ret[0].([]string) return ret0 } // LabelKeys indicates an expected call of LabelKeys. func (mr *MockSSHKeyClientMockRecorder) LabelKeys(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LabelKeys", reflect.TypeOf((*MockSSHKeyClient)(nil).LabelKeys), arg0) } // List mocks base method. func (m *MockSSHKeyClient) List(arg0 context.Context, arg1 hcloud.SSHKeyListOpts) ([]*hcloud.SSHKey, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "List", arg0, arg1) ret0, _ := ret[0].([]*hcloud.SSHKey) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // List indicates an expected call of List. func (mr *MockSSHKeyClientMockRecorder) List(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockSSHKeyClient)(nil).List), arg0, arg1) } // Names mocks base method. func (m *MockSSHKeyClient) Names() []string { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Names") ret0, _ := ret[0].([]string) return ret0 } // Names indicates an expected call of Names. func (mr *MockSSHKeyClientMockRecorder) Names() *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Names", reflect.TypeOf((*MockSSHKeyClient)(nil).Names)) } // Update mocks base method. func (m *MockSSHKeyClient) Update(arg0 context.Context, arg1 *hcloud.SSHKey, arg2 hcloud.SSHKeyUpdateOpts) (*hcloud.SSHKey, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Update", arg0, arg1, arg2) ret0, _ := ret[0].(*hcloud.SSHKey) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // Update indicates an expected call of Update. func (mr *MockSSHKeyClientMockRecorder) Update(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockSSHKeyClient)(nil).Update), arg0, arg1, arg2) } cli-1.39.0/internal/hcapi2/mock/zz_volume_client_mock.go000066400000000000000000000253401451614444200232270ustar00rootroot00000000000000// Code generated by MockGen. DO NOT EDIT. // Source: github.com/hetznercloud/cli/internal/hcapi2 (interfaces: VolumeClient) // Package hcapi2_mock is a generated GoMock package. package hcapi2_mock import ( context "context" reflect "reflect" gomock "github.com/golang/mock/gomock" hcloud "github.com/hetznercloud/hcloud-go/v2/hcloud" ) // MockVolumeClient is a mock of VolumeClient interface. type MockVolumeClient struct { ctrl *gomock.Controller recorder *MockVolumeClientMockRecorder } // MockVolumeClientMockRecorder is the mock recorder for MockVolumeClient. type MockVolumeClientMockRecorder struct { mock *MockVolumeClient } // NewMockVolumeClient creates a new mock instance. func NewMockVolumeClient(ctrl *gomock.Controller) *MockVolumeClient { mock := &MockVolumeClient{ctrl: ctrl} mock.recorder = &MockVolumeClientMockRecorder{mock} return mock } // EXPECT returns an object that allows the caller to indicate expected use. func (m *MockVolumeClient) EXPECT() *MockVolumeClientMockRecorder { return m.recorder } // All mocks base method. func (m *MockVolumeClient) All(arg0 context.Context) ([]*hcloud.Volume, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "All", arg0) ret0, _ := ret[0].([]*hcloud.Volume) ret1, _ := ret[1].(error) return ret0, ret1 } // All indicates an expected call of All. func (mr *MockVolumeClientMockRecorder) All(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "All", reflect.TypeOf((*MockVolumeClient)(nil).All), arg0) } // AllWithOpts mocks base method. func (m *MockVolumeClient) AllWithOpts(arg0 context.Context, arg1 hcloud.VolumeListOpts) ([]*hcloud.Volume, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "AllWithOpts", arg0, arg1) ret0, _ := ret[0].([]*hcloud.Volume) ret1, _ := ret[1].(error) return ret0, ret1 } // AllWithOpts indicates an expected call of AllWithOpts. func (mr *MockVolumeClientMockRecorder) AllWithOpts(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AllWithOpts", reflect.TypeOf((*MockVolumeClient)(nil).AllWithOpts), arg0, arg1) } // Attach mocks base method. func (m *MockVolumeClient) Attach(arg0 context.Context, arg1 *hcloud.Volume, arg2 *hcloud.Server) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Attach", arg0, arg1, arg2) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // Attach indicates an expected call of Attach. func (mr *MockVolumeClientMockRecorder) Attach(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Attach", reflect.TypeOf((*MockVolumeClient)(nil).Attach), arg0, arg1, arg2) } // AttachWithOpts mocks base method. func (m *MockVolumeClient) AttachWithOpts(arg0 context.Context, arg1 *hcloud.Volume, arg2 hcloud.VolumeAttachOpts) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "AttachWithOpts", arg0, arg1, arg2) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // AttachWithOpts indicates an expected call of AttachWithOpts. func (mr *MockVolumeClientMockRecorder) AttachWithOpts(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AttachWithOpts", reflect.TypeOf((*MockVolumeClient)(nil).AttachWithOpts), arg0, arg1, arg2) } // ChangeProtection mocks base method. func (m *MockVolumeClient) ChangeProtection(arg0 context.Context, arg1 *hcloud.Volume, arg2 hcloud.VolumeChangeProtectionOpts) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ChangeProtection", arg0, arg1, arg2) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // ChangeProtection indicates an expected call of ChangeProtection. func (mr *MockVolumeClientMockRecorder) ChangeProtection(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChangeProtection", reflect.TypeOf((*MockVolumeClient)(nil).ChangeProtection), arg0, arg1, arg2) } // Create mocks base method. func (m *MockVolumeClient) Create(arg0 context.Context, arg1 hcloud.VolumeCreateOpts) (hcloud.VolumeCreateResult, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Create", arg0, arg1) ret0, _ := ret[0].(hcloud.VolumeCreateResult) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // Create indicates an expected call of Create. func (mr *MockVolumeClientMockRecorder) Create(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Create", reflect.TypeOf((*MockVolumeClient)(nil).Create), arg0, arg1) } // Delete mocks base method. func (m *MockVolumeClient) Delete(arg0 context.Context, arg1 *hcloud.Volume) (*hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Delete", arg0, arg1) ret0, _ := ret[0].(*hcloud.Response) ret1, _ := ret[1].(error) return ret0, ret1 } // Delete indicates an expected call of Delete. func (mr *MockVolumeClientMockRecorder) Delete(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockVolumeClient)(nil).Delete), arg0, arg1) } // Detach mocks base method. func (m *MockVolumeClient) Detach(arg0 context.Context, arg1 *hcloud.Volume) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Detach", arg0, arg1) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // Detach indicates an expected call of Detach. func (mr *MockVolumeClientMockRecorder) Detach(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Detach", reflect.TypeOf((*MockVolumeClient)(nil).Detach), arg0, arg1) } // Get mocks base method. func (m *MockVolumeClient) Get(arg0 context.Context, arg1 string) (*hcloud.Volume, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Get", arg0, arg1) ret0, _ := ret[0].(*hcloud.Volume) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // Get indicates an expected call of Get. func (mr *MockVolumeClientMockRecorder) Get(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockVolumeClient)(nil).Get), arg0, arg1) } // GetByID mocks base method. func (m *MockVolumeClient) GetByID(arg0 context.Context, arg1 int64) (*hcloud.Volume, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetByID", arg0, arg1) ret0, _ := ret[0].(*hcloud.Volume) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // GetByID indicates an expected call of GetByID. func (mr *MockVolumeClientMockRecorder) GetByID(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByID", reflect.TypeOf((*MockVolumeClient)(nil).GetByID), arg0, arg1) } // GetByName mocks base method. func (m *MockVolumeClient) GetByName(arg0 context.Context, arg1 string) (*hcloud.Volume, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetByName", arg0, arg1) ret0, _ := ret[0].(*hcloud.Volume) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // GetByName indicates an expected call of GetByName. func (mr *MockVolumeClientMockRecorder) GetByName(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByName", reflect.TypeOf((*MockVolumeClient)(nil).GetByName), arg0, arg1) } // LabelKeys mocks base method. func (m *MockVolumeClient) LabelKeys(arg0 string) []string { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "LabelKeys", arg0) ret0, _ := ret[0].([]string) return ret0 } // LabelKeys indicates an expected call of LabelKeys. func (mr *MockVolumeClientMockRecorder) LabelKeys(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LabelKeys", reflect.TypeOf((*MockVolumeClient)(nil).LabelKeys), arg0) } // List mocks base method. func (m *MockVolumeClient) List(arg0 context.Context, arg1 hcloud.VolumeListOpts) ([]*hcloud.Volume, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "List", arg0, arg1) ret0, _ := ret[0].([]*hcloud.Volume) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // List indicates an expected call of List. func (mr *MockVolumeClientMockRecorder) List(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockVolumeClient)(nil).List), arg0, arg1) } // Names mocks base method. func (m *MockVolumeClient) Names() []string { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Names") ret0, _ := ret[0].([]string) return ret0 } // Names indicates an expected call of Names. func (mr *MockVolumeClientMockRecorder) Names() *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Names", reflect.TypeOf((*MockVolumeClient)(nil).Names)) } // Resize mocks base method. func (m *MockVolumeClient) Resize(arg0 context.Context, arg1 *hcloud.Volume, arg2 int) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Resize", arg0, arg1, arg2) ret0, _ := ret[0].(*hcloud.Action) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // Resize indicates an expected call of Resize. func (mr *MockVolumeClientMockRecorder) Resize(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Resize", reflect.TypeOf((*MockVolumeClient)(nil).Resize), arg0, arg1, arg2) } // Update mocks base method. func (m *MockVolumeClient) Update(arg0 context.Context, arg1 *hcloud.Volume, arg2 hcloud.VolumeUpdateOpts) (*hcloud.Volume, *hcloud.Response, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Update", arg0, arg1, arg2) ret0, _ := ret[0].(*hcloud.Volume) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // Update indicates an expected call of Update. func (mr *MockVolumeClientMockRecorder) Update(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockVolumeClient)(nil).Update), arg0, arg1, arg2) } cli-1.39.0/internal/hcapi2/network.go000066400000000000000000000045261451614444200173710ustar00rootroot00000000000000package hcapi2 import ( "context" "strconv" "sync" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) // NetworkClient embeds the Hetzner Cloud Network client and provides some // additional helper functions. type NetworkClient interface { NetworkClientBase Names() []string Name(int64) string LabelKeys(string) []string } func NewNetworkClient(client NetworkClientBase) NetworkClient { return &networkClient{ NetworkClientBase: client, } } type networkClient struct { NetworkClientBase netsByID map[int64]*hcloud.Network netsByName map[string]*hcloud.Network once sync.Once err error } // Name obtains the name of the network with id. If the name could not // be fetched it returns the value id converted to a string. func (c *networkClient) Name(id int64) string { if err := c.init(); err != nil { return strconv.FormatInt(id, 10) } net, ok := c.netsByID[id] if !ok || net.Name == "" { return strconv.FormatInt(id, 10) } return net.Name } // Names obtains a list of available networks. It returns nil if the // network names could not be fetched or if there are no networks. func (c *networkClient) Names() []string { if err := c.init(); err != nil || len(c.netsByID) == 0 { return nil } names := make([]string, len(c.netsByID)) i := 0 for _, net := range c.netsByID { name := net.Name if name == "" { name = strconv.FormatInt(net.ID, 10) } names[i] = name i++ } return names } // LabelKeys returns a slice containing the keys of all labels assigned // to the Network with the passed idOrName. func (c *networkClient) LabelKeys(idOrName string) []string { var net *hcloud.Network if err := c.init(); err != nil || len(c.netsByID) == 0 { return nil } if id, err := strconv.ParseInt(idOrName, 10, 64); err != nil { net = c.netsByID[id] } if v, ok := c.netsByName[idOrName]; ok && net == nil { net = v } if net == nil || len(net.Labels) == 0 { return nil } return labelKeys(net.Labels) } func (c *networkClient) init() error { c.once.Do(func() { nets, err := c.All(context.Background()) if err != nil { c.err = err } if c.err != nil || len(nets) == 0 { return } c.netsByID = make(map[int64]*hcloud.Network, len(nets)) c.netsByName = make(map[string]*hcloud.Network, len(nets)) for _, net := range nets { c.netsByID[net.ID] = net c.netsByName[net.Name] = net } }) return c.err } cli-1.39.0/internal/hcapi2/placement_group.go000066400000000000000000000020241451614444200210530ustar00rootroot00000000000000package hcapi2 import ( "context" "strconv" ) type PlacementGroupClient interface { PlacementGroupClientBase Names() []string LabelKeys(string) []string } func NewPlacementGroupClient(client PlacementGroupClientBase) PlacementGroupClient { return &placementGroupClient{ PlacementGroupClientBase: client, } } type placementGroupClient struct { PlacementGroupClientBase } func (c *placementGroupClient) Names() []string { placementGroups, err := c.All(context.Background()) if err != nil || len(placementGroups) == 0 { return nil } names := make([]string, len(placementGroups)) for i, firewall := range placementGroups { name := firewall.Name if name == "" { name = strconv.FormatInt(firewall.ID, 10) } names[i] = name } return names } func (c *placementGroupClient) LabelKeys(idOrName string) []string { placementGroups, _, err := c.Get(context.Background(), idOrName) if err != nil || placementGroups == nil || len(placementGroups.Labels) == 0 { return nil } return labelKeys(placementGroups.Labels) } cli-1.39.0/internal/hcapi2/primaryip.go000066400000000000000000000047641451614444200177200ustar00rootroot00000000000000package hcapi2 import ( "context" "strconv" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) // PrimaryIPClient embeds the hcloud PrimaryIPClient (via an interface) and provides // some additional helper functions. type PrimaryIPClient interface { PrimaryIPClientBase Names() []string IPv4Names() []string IPv6Names() []string LabelKeys(idOrName string) []string } // NewPrimaryIPClient creates a new primary IP client. func NewPrimaryIPClient(client PrimaryIPClientBase) PrimaryIPClient { return &primaryIPClient{ PrimaryIPClientBase: client, } } // PrimaryIPClient embeds the Hetzner Cloud PrimaryIP client and provides some // additional helper functions. type primaryIPClient struct { PrimaryIPClientBase } // Names obtains a list of available primary IPs. It returns nil if // no primary IP names could be fetched or none were available. func (c *primaryIPClient) Names() []string { fips, err := c.All(context.Background()) if err != nil || len(fips) == 0 { return nil } names := make([]string, len(fips)) for i, fip := range fips { name := fip.Name if name == "" { name = strconv.FormatInt(fip.ID, 10) } names[i] = name } return names } // IPv4Names obtains a list of available primary IPv4s. It returns nil if // no primary IP names could be fetched or none were available. func (c *primaryIPClient) IPv4Names() []string { fips, err := c.All(context.Background()) if err != nil || len(fips) == 0 { return nil } names := []string{} for _, fip := range fips { if fip.Type == hcloud.PrimaryIPTypeIPv4 { name := fip.Name if name == "" { name = strconv.FormatInt(fip.ID, 10) } names = append(names, name) } } return names } // IPv6Names obtains a list of available primary IPv6s. It returns nil if // no primary IP names could be fetched or none were available. func (c *primaryIPClient) IPv6Names() []string { fips, err := c.All(context.Background()) if err != nil || len(fips) == 0 { return nil } names := []string{} for _, fip := range fips { if fip.Type == hcloud.PrimaryIPTypeIPv6 { name := fip.Name if name == "" { name = strconv.FormatInt(fip.ID, 10) } names = append(names, name) } } return names } // LabelKeys returns a slice containing the keys of all labels // assigned to the Primary IP with the passed idOrName. func (c *primaryIPClient) LabelKeys(idOrName string) []string { fip, _, err := c.Get(context.Background(), idOrName) if err != nil || fip == nil || len(fip.Labels) == 0 { return nil } return labelKeys(fip.Labels) } cli-1.39.0/internal/hcapi2/rdns.go000066400000000000000000000004151451614444200166370ustar00rootroot00000000000000package hcapi2 // NewRDNSClient embeds the Hetzner Cloud rdns client. type RDNSClient interface { RDNSClientBase } func NewRDNSClient(client RDNSClientBase) RDNSClient { return &rdnsClient{ RDNSClientBase: client, } } type rdnsClient struct { RDNSClientBase } cli-1.39.0/internal/hcapi2/server.go000066400000000000000000000056501451614444200172050ustar00rootroot00000000000000package hcapi2 import ( "context" "strconv" "sync" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) type ServerClient interface { ServerClientBase ServerName(id int64) string Names() []string LabelKeys(idOrName string) []string } func NewServerClient(client *hcloud.ServerClient) ServerClient { return &serverClient{ ServerClientBase: client, } } // ServerClient embeds the Hetzner Cloud Server client and provides some // additional helper functions. type serverClient struct { ServerClientBase ServerTypes *hcloud.ServerTypeClient srvByID map[int64]*hcloud.Server srvByName map[string]*hcloud.Server once sync.Once err error } // ServerName obtains the name of the server with id. If the name could not // be fetched it returns the value id converted to a string. func (c *serverClient) ServerName(id int64) string { if err := c.init(); err != nil { return strconv.FormatInt(id, 10) } srv, ok := c.srvByID[id] if !ok || srv.Name == "" { return strconv.FormatInt(id, 10) } return srv.Name } // Names obtains a list of available servers. It returns nil if the // server names could not be fetched or if there are no servers. func (c *serverClient) Names() []string { if err := c.init(); err != nil || len(c.srvByID) == 0 { return nil } names := make([]string, len(c.srvByID)) i := 0 for _, srv := range c.srvByID { name := srv.Name if name == "" { name = strconv.FormatInt(srv.ID, 10) } names[i] = name i++ } return names } // LabelKeys returns a slice containing the keys of all labels assigned // to the Server with the passed idOrName. func (c *serverClient) LabelKeys(idOrName string) []string { var srv *hcloud.Server if err := c.init(); err != nil || len(c.srvByID) == 0 { return nil } // Try to get server by ID. if id, err := strconv.ParseInt(idOrName, 10, 64); err != nil { srv = c.srvByID[id] } // If the above failed idOrName might contain a server name. If srv is not // nil at this point and we found something in the map, someone gave their // server a name containing the ID of another server. if v, ok := c.srvByName[idOrName]; ok && srv == nil { srv = v } if srv == nil || len(srv.Labels) == 0 { return nil } return labelKeys(srv.Labels) } // ServerTypeNames returns a slice of all available server types. func (c *serverClient) ServerTypeNames() []string { sts, err := c.ServerTypes.All(context.Background()) if err != nil || len(sts) == 0 { return nil } names := make([]string, len(sts)) for i, st := range sts { names[i] = st.Name } return names } func (c *serverClient) init() error { c.once.Do(func() { srvs, err := c.All(context.Background()) if err != nil { c.err = err } if c.err != nil || len(srvs) == 0 { return } c.srvByID = make(map[int64]*hcloud.Server, len(srvs)) c.srvByName = make(map[string]*hcloud.Server, len(srvs)) for _, srv := range srvs { c.srvByID[srv.ID] = srv c.srvByName[srv.Name] = srv } }) return c.err } cli-1.39.0/internal/hcapi2/server_type.go000066400000000000000000000040251451614444200202410ustar00rootroot00000000000000package hcapi2 import ( "context" "strconv" "sync" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) type ServerTypeClient interface { ServerTypeClientBase Names() []string ServerTypeName(id int64) string ServerTypeDescription(id int64) string } func NewServerTypeClient(client ServerTypeClientBase) ServerTypeClient { return &serverTypeClient{ ServerTypeClientBase: client, } } type serverTypeClient struct { ServerTypeClientBase srvTypeByID map[int64]*hcloud.ServerType once sync.Once err error } // ServerTypeName obtains the name of the server type with id. If the name could not // be fetched it returns the value id converted to a string. func (c *serverTypeClient) ServerTypeName(id int64) string { if err := c.init(); err != nil { return strconv.FormatInt(id, 10) } serverType, ok := c.srvTypeByID[id] if !ok || serverType.Name == "" { return strconv.FormatInt(id, 10) } return serverType.Name } // ServerTypeDescription obtains the description of the server type with id. If the name could not // be fetched it returns the value id converted to a string. func (c *serverTypeClient) ServerTypeDescription(id int64) string { if err := c.init(); err != nil { return strconv.FormatInt(id, 10) } serverType, ok := c.srvTypeByID[id] if !ok || serverType.Description == "" { return strconv.FormatInt(id, 10) } return serverType.Description } // Names returns a slice of all available server types. func (c *serverTypeClient) Names() []string { sts, err := c.All(context.Background()) if err != nil || len(sts) == 0 { return nil } names := make([]string, len(sts)) for i, st := range sts { names[i] = st.Name } return names } func (c *serverTypeClient) init() error { c.once.Do(func() { serverTypes, err := c.All(context.Background()) if err != nil { c.err = err } if c.err != nil || len(serverTypes) == 0 { return } c.srvTypeByID = make(map[int64]*hcloud.ServerType, len(serverTypes)) for _, srv := range serverTypes { c.srvTypeByID[srv.ID] = srv } }) return c.err } cli-1.39.0/internal/hcapi2/sshkey.go000066400000000000000000000023151451614444200172000ustar00rootroot00000000000000package hcapi2 import ( "context" "strconv" ) // SSHKeyClient embeds the Hetzner Cloud SSHKey client and provides some // additional helper functions. type SSHKeyClient interface { SSHKeyClientBase Names() []string LabelKeys(idOrName string) []string } func NewSSHKeyClient(client SSHKeyClientBase) SSHKeyClient { return &sshKeyClient{ SSHKeyClientBase: client, } } type sshKeyClient struct { SSHKeyClientBase } // Names obtains a list of available SSH keys. It returns nil if SSH key // names could not be fetched or none are available. func (c *sshKeyClient) Names() []string { sshKeys, err := c.All(context.Background()) if err != nil || len(sshKeys) == 0 { return nil } names := make([]string, len(sshKeys)) for i, key := range sshKeys { name := key.Name if name == "" { name = strconv.FormatInt(key.ID, 10) } names[i] = name } return names } // LabelKeys returns a slice containing the keys of all labels // assigned to the SSH Key with the passed idOrName. func (c *sshKeyClient) LabelKeys(idOrName string) []string { sshKey, _, err := c.Get(context.Background(), idOrName) if err != nil || sshKey == nil || len(sshKey.Labels) == 0 { return nil } return labelKeys(sshKey.Labels) } cli-1.39.0/internal/hcapi2/volume.go000066400000000000000000000023411451614444200172000ustar00rootroot00000000000000package hcapi2 import ( "context" "strconv" ) // VolumeClient embeds the Hetzner Cloud Volume client and provides some additional // helper functions. type VolumeClient interface { VolumeClientBase Names() []string LabelKeys(idOrName string) []string } func NewVolumeClient(client VolumeClientBase) VolumeClient { return &volumeClient{ VolumeClientBase: client, } } type volumeClient struct { VolumeClientBase } // Names obtains a list of available volumes for the current account. It // returns nil if the current project has no volumes or the volume names could // not be fetched. func (c *volumeClient) Names() []string { vols, err := c.All(context.Background()) if err != nil || len(vols) == 0 { return nil } names := make([]string, len(vols)) for i, vol := range vols { name := vol.Name if name == "" { name = strconv.FormatInt(vol.ID, 10) } names[i] = name } return names } // LabelKeys returns a slice containing the keys of all labels assigned // to the Volume with the passed idOrName. func (c *volumeClient) LabelKeys(idOrName string) []string { vol, _, err := c.Get(context.Background(), idOrName) if err != nil || vol == nil || len(vol.Labels) == 0 { return nil } return labelKeys(vol.Labels) } cli-1.39.0/internal/hcapi2/zz_certificate_client_base.go000066400000000000000000000024131451614444200232260ustar00rootroot00000000000000// Code generated by interfacer; DO NOT EDIT package hcapi2 import ( "context" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) // CertificateClientBase is an interface generated for "github.com/hetznercloud/hcloud-go/v2/hcloud.CertificateClient". type CertificateClientBase interface { All(context.Context) ([]*hcloud.Certificate, error) AllWithOpts(context.Context, hcloud.CertificateListOpts) ([]*hcloud.Certificate, error) Create(context.Context, hcloud.CertificateCreateOpts) (*hcloud.Certificate, *hcloud.Response, error) CreateCertificate(context.Context, hcloud.CertificateCreateOpts) (hcloud.CertificateCreateResult, *hcloud.Response, error) Delete(context.Context, *hcloud.Certificate) (*hcloud.Response, error) Get(context.Context, string) (*hcloud.Certificate, *hcloud.Response, error) GetByID(context.Context, int64) (*hcloud.Certificate, *hcloud.Response, error) GetByName(context.Context, string) (*hcloud.Certificate, *hcloud.Response, error) List(context.Context, hcloud.CertificateListOpts) ([]*hcloud.Certificate, *hcloud.Response, error) RetryIssuance(context.Context, *hcloud.Certificate) (*hcloud.Action, *hcloud.Response, error) Update(context.Context, *hcloud.Certificate, hcloud.CertificateUpdateOpts) (*hcloud.Certificate, *hcloud.Response, error) } cli-1.39.0/internal/hcapi2/zz_datacenter_client_base.go000066400000000000000000000013741451614444200230630ustar00rootroot00000000000000// Code generated by interfacer; DO NOT EDIT package hcapi2 import ( "context" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) // DatacenterClientBase is an interface generated for "github.com/hetznercloud/hcloud-go/v2/hcloud.DatacenterClient". type DatacenterClientBase interface { All(context.Context) ([]*hcloud.Datacenter, error) AllWithOpts(context.Context, hcloud.DatacenterListOpts) ([]*hcloud.Datacenter, error) Get(context.Context, string) (*hcloud.Datacenter, *hcloud.Response, error) GetByID(context.Context, int64) (*hcloud.Datacenter, *hcloud.Response, error) GetByName(context.Context, string) (*hcloud.Datacenter, *hcloud.Response, error) List(context.Context, hcloud.DatacenterListOpts) ([]*hcloud.Datacenter, *hcloud.Response, error) } cli-1.39.0/internal/hcapi2/zz_firewall_client_base.go000066400000000000000000000025631451614444200225570ustar00rootroot00000000000000// Code generated by interfacer; DO NOT EDIT package hcapi2 import ( "context" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) // FirewallClientBase is an interface generated for "github.com/hetznercloud/hcloud-go/v2/hcloud.FirewallClient". type FirewallClientBase interface { All(context.Context) ([]*hcloud.Firewall, error) AllWithOpts(context.Context, hcloud.FirewallListOpts) ([]*hcloud.Firewall, error) ApplyResources(context.Context, *hcloud.Firewall, []hcloud.FirewallResource) ([]*hcloud.Action, *hcloud.Response, error) Create(context.Context, hcloud.FirewallCreateOpts) (hcloud.FirewallCreateResult, *hcloud.Response, error) Delete(context.Context, *hcloud.Firewall) (*hcloud.Response, error) Get(context.Context, string) (*hcloud.Firewall, *hcloud.Response, error) GetByID(context.Context, int64) (*hcloud.Firewall, *hcloud.Response, error) GetByName(context.Context, string) (*hcloud.Firewall, *hcloud.Response, error) List(context.Context, hcloud.FirewallListOpts) ([]*hcloud.Firewall, *hcloud.Response, error) RemoveResources(context.Context, *hcloud.Firewall, []hcloud.FirewallResource) ([]*hcloud.Action, *hcloud.Response, error) SetRules(context.Context, *hcloud.Firewall, hcloud.FirewallSetRulesOpts) ([]*hcloud.Action, *hcloud.Response, error) Update(context.Context, *hcloud.Firewall, hcloud.FirewallUpdateOpts) (*hcloud.Firewall, *hcloud.Response, error) } cli-1.39.0/internal/hcapi2/zz_floating_ip_client_base.go000066400000000000000000000027401451614444200232420ustar00rootroot00000000000000// Code generated by interfacer; DO NOT EDIT package hcapi2 import ( "context" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) // FloatingIPClientBase is an interface generated for "github.com/hetznercloud/hcloud-go/v2/hcloud.FloatingIPClient". type FloatingIPClientBase interface { All(context.Context) ([]*hcloud.FloatingIP, error) AllWithOpts(context.Context, hcloud.FloatingIPListOpts) ([]*hcloud.FloatingIP, error) Assign(context.Context, *hcloud.FloatingIP, *hcloud.Server) (*hcloud.Action, *hcloud.Response, error) ChangeDNSPtr(context.Context, *hcloud.FloatingIP, string, *string) (*hcloud.Action, *hcloud.Response, error) ChangeProtection(context.Context, *hcloud.FloatingIP, hcloud.FloatingIPChangeProtectionOpts) (*hcloud.Action, *hcloud.Response, error) Create(context.Context, hcloud.FloatingIPCreateOpts) (hcloud.FloatingIPCreateResult, *hcloud.Response, error) Delete(context.Context, *hcloud.FloatingIP) (*hcloud.Response, error) Get(context.Context, string) (*hcloud.FloatingIP, *hcloud.Response, error) GetByID(context.Context, int64) (*hcloud.FloatingIP, *hcloud.Response, error) GetByName(context.Context, string) (*hcloud.FloatingIP, *hcloud.Response, error) List(context.Context, hcloud.FloatingIPListOpts) ([]*hcloud.FloatingIP, *hcloud.Response, error) Unassign(context.Context, *hcloud.FloatingIP) (*hcloud.Action, *hcloud.Response, error) Update(context.Context, *hcloud.FloatingIP, hcloud.FloatingIPUpdateOpts) (*hcloud.FloatingIP, *hcloud.Response, error) } cli-1.39.0/internal/hcapi2/zz_image_client_base.go000066400000000000000000000023121451614444200220240ustar00rootroot00000000000000// Code generated by interfacer; DO NOT EDIT package hcapi2 import ( "context" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) // ImageClientBase is an interface generated for "github.com/hetznercloud/hcloud-go/v2/hcloud.ImageClient". type ImageClientBase interface { All(context.Context) ([]*hcloud.Image, error) AllWithOpts(context.Context, hcloud.ImageListOpts) ([]*hcloud.Image, error) ChangeProtection(context.Context, *hcloud.Image, hcloud.ImageChangeProtectionOpts) (*hcloud.Action, *hcloud.Response, error) Delete(context.Context, *hcloud.Image) (*hcloud.Response, error) Get(context.Context, string) (*hcloud.Image, *hcloud.Response, error) GetByID(context.Context, int64) (*hcloud.Image, *hcloud.Response, error) GetByName(context.Context, string) (*hcloud.Image, *hcloud.Response, error) GetByNameAndArchitecture(context.Context, string, hcloud.Architecture) (*hcloud.Image, *hcloud.Response, error) GetForArchitecture(context.Context, string, hcloud.Architecture) (*hcloud.Image, *hcloud.Response, error) List(context.Context, hcloud.ImageListOpts) ([]*hcloud.Image, *hcloud.Response, error) Update(context.Context, *hcloud.Image, hcloud.ImageUpdateOpts) (*hcloud.Image, *hcloud.Response, error) } cli-1.39.0/internal/hcapi2/zz_iso_client_base.go000066400000000000000000000012571451614444200215430ustar00rootroot00000000000000// Code generated by interfacer; DO NOT EDIT package hcapi2 import ( "context" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) // ISOClientBase is an interface generated for "github.com/hetznercloud/hcloud-go/v2/hcloud.ISOClient". type ISOClientBase interface { All(context.Context) ([]*hcloud.ISO, error) AllWithOpts(context.Context, hcloud.ISOListOpts) ([]*hcloud.ISO, error) Get(context.Context, string) (*hcloud.ISO, *hcloud.Response, error) GetByID(context.Context, int64) (*hcloud.ISO, *hcloud.Response, error) GetByName(context.Context, string) (*hcloud.ISO, *hcloud.Response, error) List(context.Context, hcloud.ISOListOpts) ([]*hcloud.ISO, *hcloud.Response, error) } cli-1.39.0/internal/hcapi2/zz_loadbalancer_client_base.go000066400000000000000000000064651451614444200233660ustar00rootroot00000000000000// Code generated by interfacer; DO NOT EDIT package hcapi2 import ( "context" "github.com/hetznercloud/hcloud-go/v2/hcloud" "net" ) // LoadBalancerClientBase is an interface generated for "github.com/hetznercloud/hcloud-go/v2/hcloud.LoadBalancerClient". type LoadBalancerClientBase interface { AddIPTarget(context.Context, *hcloud.LoadBalancer, hcloud.LoadBalancerAddIPTargetOpts) (*hcloud.Action, *hcloud.Response, error) AddLabelSelectorTarget(context.Context, *hcloud.LoadBalancer, hcloud.LoadBalancerAddLabelSelectorTargetOpts) (*hcloud.Action, *hcloud.Response, error) AddServerTarget(context.Context, *hcloud.LoadBalancer, hcloud.LoadBalancerAddServerTargetOpts) (*hcloud.Action, *hcloud.Response, error) AddService(context.Context, *hcloud.LoadBalancer, hcloud.LoadBalancerAddServiceOpts) (*hcloud.Action, *hcloud.Response, error) All(context.Context) ([]*hcloud.LoadBalancer, error) AllWithOpts(context.Context, hcloud.LoadBalancerListOpts) ([]*hcloud.LoadBalancer, error) AttachToNetwork(context.Context, *hcloud.LoadBalancer, hcloud.LoadBalancerAttachToNetworkOpts) (*hcloud.Action, *hcloud.Response, error) ChangeAlgorithm(context.Context, *hcloud.LoadBalancer, hcloud.LoadBalancerChangeAlgorithmOpts) (*hcloud.Action, *hcloud.Response, error) ChangeDNSPtr(context.Context, *hcloud.LoadBalancer, string, *string) (*hcloud.Action, *hcloud.Response, error) ChangeProtection(context.Context, *hcloud.LoadBalancer, hcloud.LoadBalancerChangeProtectionOpts) (*hcloud.Action, *hcloud.Response, error) ChangeType(context.Context, *hcloud.LoadBalancer, hcloud.LoadBalancerChangeTypeOpts) (*hcloud.Action, *hcloud.Response, error) Create(context.Context, hcloud.LoadBalancerCreateOpts) (hcloud.LoadBalancerCreateResult, *hcloud.Response, error) Delete(context.Context, *hcloud.LoadBalancer) (*hcloud.Response, error) DeleteService(context.Context, *hcloud.LoadBalancer, int) (*hcloud.Action, *hcloud.Response, error) DetachFromNetwork(context.Context, *hcloud.LoadBalancer, hcloud.LoadBalancerDetachFromNetworkOpts) (*hcloud.Action, *hcloud.Response, error) DisablePublicInterface(context.Context, *hcloud.LoadBalancer) (*hcloud.Action, *hcloud.Response, error) EnablePublicInterface(context.Context, *hcloud.LoadBalancer) (*hcloud.Action, *hcloud.Response, error) Get(context.Context, string) (*hcloud.LoadBalancer, *hcloud.Response, error) GetByID(context.Context, int64) (*hcloud.LoadBalancer, *hcloud.Response, error) GetByName(context.Context, string) (*hcloud.LoadBalancer, *hcloud.Response, error) GetMetrics(context.Context, *hcloud.LoadBalancer, hcloud.LoadBalancerGetMetricsOpts) (*hcloud.LoadBalancerMetrics, *hcloud.Response, error) List(context.Context, hcloud.LoadBalancerListOpts) ([]*hcloud.LoadBalancer, *hcloud.Response, error) RemoveIPTarget(context.Context, *hcloud.LoadBalancer, net.IP) (*hcloud.Action, *hcloud.Response, error) RemoveLabelSelectorTarget(context.Context, *hcloud.LoadBalancer, string) (*hcloud.Action, *hcloud.Response, error) RemoveServerTarget(context.Context, *hcloud.LoadBalancer, *hcloud.Server) (*hcloud.Action, *hcloud.Response, error) Update(context.Context, *hcloud.LoadBalancer, hcloud.LoadBalancerUpdateOpts) (*hcloud.LoadBalancer, *hcloud.Response, error) UpdateService(context.Context, *hcloud.LoadBalancer, int, hcloud.LoadBalancerUpdateServiceOpts) (*hcloud.Action, *hcloud.Response, error) } cli-1.39.0/internal/hcapi2/zz_loadbalancer_type_client_base.go000066400000000000000000000014761451614444200244240ustar00rootroot00000000000000// Code generated by interfacer; DO NOT EDIT package hcapi2 import ( "context" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) // LoadBalancerTypeClientBase is an interface generated for "github.com/hetznercloud/hcloud-go/v2/hcloud.LoadBalancerTypeClient". type LoadBalancerTypeClientBase interface { All(context.Context) ([]*hcloud.LoadBalancerType, error) AllWithOpts(context.Context, hcloud.LoadBalancerTypeListOpts) ([]*hcloud.LoadBalancerType, error) Get(context.Context, string) (*hcloud.LoadBalancerType, *hcloud.Response, error) GetByID(context.Context, int64) (*hcloud.LoadBalancerType, *hcloud.Response, error) GetByName(context.Context, string) (*hcloud.LoadBalancerType, *hcloud.Response, error) List(context.Context, hcloud.LoadBalancerTypeListOpts) ([]*hcloud.LoadBalancerType, *hcloud.Response, error) } cli-1.39.0/internal/hcapi2/zz_location_client_base.go000066400000000000000000000013461451614444200225600ustar00rootroot00000000000000// Code generated by interfacer; DO NOT EDIT package hcapi2 import ( "context" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) // LocationClientBase is an interface generated for "github.com/hetznercloud/hcloud-go/v2/hcloud.LocationClient". type LocationClientBase interface { All(context.Context) ([]*hcloud.Location, error) AllWithOpts(context.Context, hcloud.LocationListOpts) ([]*hcloud.Location, error) Get(context.Context, string) (*hcloud.Location, *hcloud.Response, error) GetByID(context.Context, int64) (*hcloud.Location, *hcloud.Response, error) GetByName(context.Context, string) (*hcloud.Location, *hcloud.Response, error) List(context.Context, hcloud.LocationListOpts) ([]*hcloud.Location, *hcloud.Response, error) } cli-1.39.0/internal/hcapi2/zz_network_client_base.go000066400000000000000000000033021451614444200224330ustar00rootroot00000000000000// Code generated by interfacer; DO NOT EDIT package hcapi2 import ( "context" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) // NetworkClientBase is an interface generated for "github.com/hetznercloud/hcloud-go/v2/hcloud.NetworkClient". type NetworkClientBase interface { AddRoute(context.Context, *hcloud.Network, hcloud.NetworkAddRouteOpts) (*hcloud.Action, *hcloud.Response, error) AddSubnet(context.Context, *hcloud.Network, hcloud.NetworkAddSubnetOpts) (*hcloud.Action, *hcloud.Response, error) All(context.Context) ([]*hcloud.Network, error) AllWithOpts(context.Context, hcloud.NetworkListOpts) ([]*hcloud.Network, error) ChangeIPRange(context.Context, *hcloud.Network, hcloud.NetworkChangeIPRangeOpts) (*hcloud.Action, *hcloud.Response, error) ChangeProtection(context.Context, *hcloud.Network, hcloud.NetworkChangeProtectionOpts) (*hcloud.Action, *hcloud.Response, error) Create(context.Context, hcloud.NetworkCreateOpts) (*hcloud.Network, *hcloud.Response, error) Delete(context.Context, *hcloud.Network) (*hcloud.Response, error) DeleteRoute(context.Context, *hcloud.Network, hcloud.NetworkDeleteRouteOpts) (*hcloud.Action, *hcloud.Response, error) DeleteSubnet(context.Context, *hcloud.Network, hcloud.NetworkDeleteSubnetOpts) (*hcloud.Action, *hcloud.Response, error) Get(context.Context, string) (*hcloud.Network, *hcloud.Response, error) GetByID(context.Context, int64) (*hcloud.Network, *hcloud.Response, error) GetByName(context.Context, string) (*hcloud.Network, *hcloud.Response, error) List(context.Context, hcloud.NetworkListOpts) ([]*hcloud.Network, *hcloud.Response, error) Update(context.Context, *hcloud.Network, hcloud.NetworkUpdateOpts) (*hcloud.Network, *hcloud.Response, error) } cli-1.39.0/internal/hcapi2/zz_placement_group_client_base.go000066400000000000000000000021561451614444200241340ustar00rootroot00000000000000// Code generated by interfacer; DO NOT EDIT package hcapi2 import ( "context" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) // PlacementGroupClientBase is an interface generated for "github.com/hetznercloud/hcloud-go/v2/hcloud.PlacementGroupClient". type PlacementGroupClientBase interface { All(context.Context) ([]*hcloud.PlacementGroup, error) AllWithOpts(context.Context, hcloud.PlacementGroupListOpts) ([]*hcloud.PlacementGroup, error) Create(context.Context, hcloud.PlacementGroupCreateOpts) (hcloud.PlacementGroupCreateResult, *hcloud.Response, error) Delete(context.Context, *hcloud.PlacementGroup) (*hcloud.Response, error) Get(context.Context, string) (*hcloud.PlacementGroup, *hcloud.Response, error) GetByID(context.Context, int64) (*hcloud.PlacementGroup, *hcloud.Response, error) GetByName(context.Context, string) (*hcloud.PlacementGroup, *hcloud.Response, error) List(context.Context, hcloud.PlacementGroupListOpts) ([]*hcloud.PlacementGroup, *hcloud.Response, error) Update(context.Context, *hcloud.PlacementGroup, hcloud.PlacementGroupUpdateOpts) (*hcloud.PlacementGroup, *hcloud.Response, error) } cli-1.39.0/internal/hcapi2/zz_primary_ip_client_base.go000066400000000000000000000027621451614444200231260ustar00rootroot00000000000000// Code generated by interfacer; DO NOT EDIT package hcapi2 import ( "context" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) // PrimaryIPClientBase is an interface generated for "github.com/hetznercloud/hcloud-go/v2/hcloud.PrimaryIPClient". type PrimaryIPClientBase interface { All(context.Context) ([]*hcloud.PrimaryIP, error) AllWithOpts(context.Context, hcloud.PrimaryIPListOpts) ([]*hcloud.PrimaryIP, error) Assign(context.Context, hcloud.PrimaryIPAssignOpts) (*hcloud.Action, *hcloud.Response, error) ChangeDNSPtr(context.Context, hcloud.PrimaryIPChangeDNSPtrOpts) (*hcloud.Action, *hcloud.Response, error) ChangeProtection(context.Context, hcloud.PrimaryIPChangeProtectionOpts) (*hcloud.Action, *hcloud.Response, error) Create(context.Context, hcloud.PrimaryIPCreateOpts) (*hcloud.PrimaryIPCreateResult, *hcloud.Response, error) Delete(context.Context, *hcloud.PrimaryIP) (*hcloud.Response, error) Get(context.Context, string) (*hcloud.PrimaryIP, *hcloud.Response, error) GetByID(context.Context, int64) (*hcloud.PrimaryIP, *hcloud.Response, error) GetByIP(context.Context, string) (*hcloud.PrimaryIP, *hcloud.Response, error) GetByName(context.Context, string) (*hcloud.PrimaryIP, *hcloud.Response, error) List(context.Context, hcloud.PrimaryIPListOpts) ([]*hcloud.PrimaryIP, *hcloud.Response, error) Unassign(context.Context, int64) (*hcloud.Action, *hcloud.Response, error) Update(context.Context, *hcloud.PrimaryIP, hcloud.PrimaryIPUpdateOpts) (*hcloud.PrimaryIP, *hcloud.Response, error) } cli-1.39.0/internal/hcapi2/zz_rdns_client_base.go000066400000000000000000000006071451614444200217150ustar00rootroot00000000000000// Code generated by interfacer; DO NOT EDIT package hcapi2 import ( "context" "github.com/hetznercloud/hcloud-go/v2/hcloud" "net" ) // RDNSClientBase is an interface generated for "github.com/hetznercloud/hcloud-go/v2/hcloud.RDNSClient". type RDNSClientBase interface { ChangeDNSPtr(context.Context, hcloud.RDNSSupporter, net.IP, *string) (*hcloud.Action, *hcloud.Response, error) } cli-1.39.0/internal/hcapi2/zz_server_client_base.go000066400000000000000000000073161451614444200222610ustar00rootroot00000000000000// Code generated by interfacer; DO NOT EDIT package hcapi2 import ( "context" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) // ServerClientBase is an interface generated for "github.com/hetznercloud/hcloud-go/v2/hcloud.ServerClient". type ServerClientBase interface { AddToPlacementGroup(context.Context, *hcloud.Server, *hcloud.PlacementGroup) (*hcloud.Action, *hcloud.Response, error) All(context.Context) ([]*hcloud.Server, error) AllWithOpts(context.Context, hcloud.ServerListOpts) ([]*hcloud.Server, error) AttachISO(context.Context, *hcloud.Server, *hcloud.ISO) (*hcloud.Action, *hcloud.Response, error) AttachToNetwork(context.Context, *hcloud.Server, hcloud.ServerAttachToNetworkOpts) (*hcloud.Action, *hcloud.Response, error) ChangeAliasIPs(context.Context, *hcloud.Server, hcloud.ServerChangeAliasIPsOpts) (*hcloud.Action, *hcloud.Response, error) ChangeDNSPtr(context.Context, *hcloud.Server, string, *string) (*hcloud.Action, *hcloud.Response, error) ChangeProtection(context.Context, *hcloud.Server, hcloud.ServerChangeProtectionOpts) (*hcloud.Action, *hcloud.Response, error) ChangeType(context.Context, *hcloud.Server, hcloud.ServerChangeTypeOpts) (*hcloud.Action, *hcloud.Response, error) Create(context.Context, hcloud.ServerCreateOpts) (hcloud.ServerCreateResult, *hcloud.Response, error) CreateImage(context.Context, *hcloud.Server, *hcloud.ServerCreateImageOpts) (hcloud.ServerCreateImageResult, *hcloud.Response, error) Delete(context.Context, *hcloud.Server) (*hcloud.Response, error) DeleteWithResult(context.Context, *hcloud.Server) (*hcloud.ServerDeleteResult, *hcloud.Response, error) DetachFromNetwork(context.Context, *hcloud.Server, hcloud.ServerDetachFromNetworkOpts) (*hcloud.Action, *hcloud.Response, error) DetachISO(context.Context, *hcloud.Server) (*hcloud.Action, *hcloud.Response, error) DisableBackup(context.Context, *hcloud.Server) (*hcloud.Action, *hcloud.Response, error) DisableRescue(context.Context, *hcloud.Server) (*hcloud.Action, *hcloud.Response, error) EnableBackup(context.Context, *hcloud.Server, string) (*hcloud.Action, *hcloud.Response, error) EnableRescue(context.Context, *hcloud.Server, hcloud.ServerEnableRescueOpts) (hcloud.ServerEnableRescueResult, *hcloud.Response, error) Get(context.Context, string) (*hcloud.Server, *hcloud.Response, error) GetByID(context.Context, int64) (*hcloud.Server, *hcloud.Response, error) GetByName(context.Context, string) (*hcloud.Server, *hcloud.Response, error) GetMetrics(context.Context, *hcloud.Server, hcloud.ServerGetMetricsOpts) (*hcloud.ServerMetrics, *hcloud.Response, error) List(context.Context, hcloud.ServerListOpts) ([]*hcloud.Server, *hcloud.Response, error) Poweroff(context.Context, *hcloud.Server) (*hcloud.Action, *hcloud.Response, error) Poweron(context.Context, *hcloud.Server) (*hcloud.Action, *hcloud.Response, error) Reboot(context.Context, *hcloud.Server) (*hcloud.Action, *hcloud.Response, error) Rebuild(context.Context, *hcloud.Server, hcloud.ServerRebuildOpts) (*hcloud.Action, *hcloud.Response, error) RebuildWithResult(context.Context, *hcloud.Server, hcloud.ServerRebuildOpts) (hcloud.ServerRebuildResult, *hcloud.Response, error) RemoveFromPlacementGroup(context.Context, *hcloud.Server) (*hcloud.Action, *hcloud.Response, error) RequestConsole(context.Context, *hcloud.Server) (hcloud.ServerRequestConsoleResult, *hcloud.Response, error) Reset(context.Context, *hcloud.Server) (*hcloud.Action, *hcloud.Response, error) ResetPassword(context.Context, *hcloud.Server) (hcloud.ServerResetPasswordResult, *hcloud.Response, error) Shutdown(context.Context, *hcloud.Server) (*hcloud.Action, *hcloud.Response, error) Update(context.Context, *hcloud.Server, hcloud.ServerUpdateOpts) (*hcloud.Server, *hcloud.Response, error) } cli-1.39.0/internal/hcapi2/zz_server_type_client_base.go000066400000000000000000000013741451614444200233200ustar00rootroot00000000000000// Code generated by interfacer; DO NOT EDIT package hcapi2 import ( "context" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) // ServerTypeClientBase is an interface generated for "github.com/hetznercloud/hcloud-go/v2/hcloud.ServerTypeClient". type ServerTypeClientBase interface { All(context.Context) ([]*hcloud.ServerType, error) AllWithOpts(context.Context, hcloud.ServerTypeListOpts) ([]*hcloud.ServerType, error) Get(context.Context, string) (*hcloud.ServerType, *hcloud.Response, error) GetByID(context.Context, int64) (*hcloud.ServerType, *hcloud.Response, error) GetByName(context.Context, string) (*hcloud.ServerType, *hcloud.Response, error) List(context.Context, hcloud.ServerTypeListOpts) ([]*hcloud.ServerType, *hcloud.Response, error) } cli-1.39.0/internal/hcapi2/zz_ssh_key_client_base.go000066400000000000000000000020601451614444200224070ustar00rootroot00000000000000// Code generated by interfacer; DO NOT EDIT package hcapi2 import ( "context" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) // SSHKeyClientBase is an interface generated for "github.com/hetznercloud/hcloud-go/v2/hcloud.SSHKeyClient". type SSHKeyClientBase interface { All(context.Context) ([]*hcloud.SSHKey, error) AllWithOpts(context.Context, hcloud.SSHKeyListOpts) ([]*hcloud.SSHKey, error) Create(context.Context, hcloud.SSHKeyCreateOpts) (*hcloud.SSHKey, *hcloud.Response, error) Delete(context.Context, *hcloud.SSHKey) (*hcloud.Response, error) Get(context.Context, string) (*hcloud.SSHKey, *hcloud.Response, error) GetByFingerprint(context.Context, string) (*hcloud.SSHKey, *hcloud.Response, error) GetByID(context.Context, int64) (*hcloud.SSHKey, *hcloud.Response, error) GetByName(context.Context, string) (*hcloud.SSHKey, *hcloud.Response, error) List(context.Context, hcloud.SSHKeyListOpts) ([]*hcloud.SSHKey, *hcloud.Response, error) Update(context.Context, *hcloud.SSHKey, hcloud.SSHKeyUpdateOpts) (*hcloud.SSHKey, *hcloud.Response, error) } cli-1.39.0/internal/hcapi2/zz_volume_client_base.go000066400000000000000000000027501451614444200222570ustar00rootroot00000000000000// Code generated by interfacer; DO NOT EDIT package hcapi2 import ( "context" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) // VolumeClientBase is an interface generated for "github.com/hetznercloud/hcloud-go/v2/hcloud.VolumeClient". type VolumeClientBase interface { All(context.Context) ([]*hcloud.Volume, error) AllWithOpts(context.Context, hcloud.VolumeListOpts) ([]*hcloud.Volume, error) Attach(context.Context, *hcloud.Volume, *hcloud.Server) (*hcloud.Action, *hcloud.Response, error) AttachWithOpts(context.Context, *hcloud.Volume, hcloud.VolumeAttachOpts) (*hcloud.Action, *hcloud.Response, error) ChangeProtection(context.Context, *hcloud.Volume, hcloud.VolumeChangeProtectionOpts) (*hcloud.Action, *hcloud.Response, error) Create(context.Context, hcloud.VolumeCreateOpts) (hcloud.VolumeCreateResult, *hcloud.Response, error) Delete(context.Context, *hcloud.Volume) (*hcloud.Response, error) Detach(context.Context, *hcloud.Volume) (*hcloud.Action, *hcloud.Response, error) Get(context.Context, string) (*hcloud.Volume, *hcloud.Response, error) GetByID(context.Context, int64) (*hcloud.Volume, *hcloud.Response, error) GetByName(context.Context, string) (*hcloud.Volume, *hcloud.Response, error) List(context.Context, hcloud.VolumeListOpts) ([]*hcloud.Volume, *hcloud.Response, error) Resize(context.Context, *hcloud.Volume, int) (*hcloud.Action, *hcloud.Response, error) Update(context.Context, *hcloud.Volume, hcloud.VolumeUpdateOpts) (*hcloud.Volume, *hcloud.Response, error) } cli-1.39.0/internal/state/000077500000000000000000000000001451614444200153145ustar00rootroot00000000000000cli-1.39.0/internal/state/command_helper_mocks.go000066400000000000000000000066171451614444200220260ustar00rootroot00000000000000// Code generated by MockGen. DO NOT EDIT. // Source: github.com/hetznercloud/cli/internal/state (interfaces: ActionWaiter,TokenEnsurer) // Package state is a generated GoMock package. package state import ( context "context" reflect "reflect" gomock "github.com/golang/mock/gomock" hcloud "github.com/hetznercloud/hcloud-go/v2/hcloud" cobra "github.com/spf13/cobra" ) // MockActionWaiter is a mock of ActionWaiter interface. type MockActionWaiter struct { ctrl *gomock.Controller recorder *MockActionWaiterMockRecorder } // MockActionWaiterMockRecorder is the mock recorder for MockActionWaiter. type MockActionWaiterMockRecorder struct { mock *MockActionWaiter } // NewMockActionWaiter creates a new mock instance. func NewMockActionWaiter(ctrl *gomock.Controller) *MockActionWaiter { mock := &MockActionWaiter{ctrl: ctrl} mock.recorder = &MockActionWaiterMockRecorder{mock} return mock } // EXPECT returns an object that allows the caller to indicate expected use. func (m *MockActionWaiter) EXPECT() *MockActionWaiterMockRecorder { return m.recorder } // ActionProgress mocks base method. func (m *MockActionWaiter) ActionProgress(arg0 context.Context, arg1 *hcloud.Action) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ActionProgress", arg0, arg1) ret0, _ := ret[0].(error) return ret0 } // ActionProgress indicates an expected call of ActionProgress. func (mr *MockActionWaiterMockRecorder) ActionProgress(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ActionProgress", reflect.TypeOf((*MockActionWaiter)(nil).ActionProgress), arg0, arg1) } // WaitForActions mocks base method. func (m *MockActionWaiter) WaitForActions(arg0 context.Context, arg1 []*hcloud.Action) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "WaitForActions", arg0, arg1) ret0, _ := ret[0].(error) return ret0 } // WaitForActions indicates an expected call of WaitForActions. func (mr *MockActionWaiterMockRecorder) WaitForActions(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WaitForActions", reflect.TypeOf((*MockActionWaiter)(nil).WaitForActions), arg0, arg1) } // MockTokenEnsurer is a mock of TokenEnsurer interface. type MockTokenEnsurer struct { ctrl *gomock.Controller recorder *MockTokenEnsurerMockRecorder } // MockTokenEnsurerMockRecorder is the mock recorder for MockTokenEnsurer. type MockTokenEnsurerMockRecorder struct { mock *MockTokenEnsurer } // NewMockTokenEnsurer creates a new mock instance. func NewMockTokenEnsurer(ctrl *gomock.Controller) *MockTokenEnsurer { mock := &MockTokenEnsurer{ctrl: ctrl} mock.recorder = &MockTokenEnsurerMockRecorder{mock} return mock } // EXPECT returns an object that allows the caller to indicate expected use. func (m *MockTokenEnsurer) EXPECT() *MockTokenEnsurerMockRecorder { return m.recorder } // EnsureToken mocks base method. func (m *MockTokenEnsurer) EnsureToken(arg0 *cobra.Command, arg1 []string) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "EnsureToken", arg0, arg1) ret0, _ := ret[0].(error) return ret0 } // EnsureToken indicates an expected call of EnsureToken. func (mr *MockTokenEnsurerMockRecorder) EnsureToken(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EnsureToken", reflect.TypeOf((*MockTokenEnsurer)(nil).EnsureToken), arg0, arg1) } cli-1.39.0/internal/state/command_helpers.go000066400000000000000000000012411451614444200210010ustar00rootroot00000000000000package state import ( "context" "github.com/spf13/cobra" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) //go:generate mockgen -package state -destination command_helper_mocks.go . ActionWaiter,TokenEnsurer type ActionWaiter interface { ActionProgress(context.Context, *hcloud.Action) error WaitForActions(context.Context, []*hcloud.Action) error } type TokenEnsurer interface { EnsureToken(cmd *cobra.Command, args []string) error } func WrapCtx( ctx context.Context, fn func(context.Context, *cobra.Command, []string) error, ) func(*cobra.Command, []string) error { return func(cmd *cobra.Command, args []string) error { return fn(ctx, cmd, args) } } cli-1.39.0/internal/state/config.go000066400000000000000000000040151451614444200171100ustar00rootroot00000000000000package state import ( "fmt" toml "github.com/pelletier/go-toml/v2" ) var DefaultConfigPath string type Config struct { Endpoint string ActiveContext *ConfigContext Contexts []*ConfigContext } type ConfigContext struct { Name string Token string } func (config *Config) ContextNames() []string { if len(config.Contexts) == 0 { return nil } names := make([]string, len(config.Contexts)) for i, ctx := range config.Contexts { names[i] = ctx.Name } return names } func (config *Config) ContextByName(name string) *ConfigContext { for _, c := range config.Contexts { if c.Name == name { return c } } return nil } func (config *Config) RemoveContext(context *ConfigContext) { for i, c := range config.Contexts { if c == context { config.Contexts = append(config.Contexts[:i], config.Contexts[i+1:]...) return } } } type RawConfig struct { ActiveContext string `toml:"active_context,omitempty"` Contexts []RawConfigContext `toml:"contexts"` } type RawConfigContext struct { Name string `toml:"name"` Token string `toml:"token"` } func MarshalConfig(c *Config) ([]byte, error) { if c == nil { return []byte{}, nil } var raw RawConfig if c.ActiveContext != nil { raw.ActiveContext = c.ActiveContext.Name } for _, context := range c.Contexts { raw.Contexts = append(raw.Contexts, RawConfigContext{ Name: context.Name, Token: context.Token, }) } return toml.Marshal(raw) } func UnmarshalConfig(config *Config, data []byte) error { var raw RawConfig if err := toml.Unmarshal(data, &raw); err != nil { return err } for _, rawContext := range raw.Contexts { config.Contexts = append(config.Contexts, &ConfigContext{ Name: rawContext.Name, Token: rawContext.Token, }) } if raw.ActiveContext != "" { for _, c := range config.Contexts { if c.Name == raw.ActiveContext { config.ActiveContext = c break } } if config.ActiveContext == nil { return fmt.Errorf("active context %s not found", raw.ActiveContext) } } return nil } cli-1.39.0/internal/state/config_unix.go000066400000000000000000000004251451614444200201540ustar00rootroot00000000000000//go:build !windows // +build !windows package state import ( "os/user" "path/filepath" ) func init() { usr, err := user.Current() if err != nil { return } if usr.HomeDir != "" { DefaultConfigPath = filepath.Join(usr.HomeDir, ".config", "hcloud", "cli.toml") } } cli-1.39.0/internal/state/config_windows.go000066400000000000000000000003271451614444200206640ustar00rootroot00000000000000//go:build windows // +build windows package state import ( "os" "path/filepath" ) func init() { dir := os.Getenv("APPDATA") if dir != "" { DefaultConfigPath = filepath.Join(dir, "hcloud", "cli.toml") } } cli-1.39.0/internal/state/helpers.go000066400000000000000000000076501451614444200173150ustar00rootroot00000000000000package state import ( "context" "errors" "fmt" "os" "time" "github.com/cheggaaa/pb/v3" "github.com/spf13/cobra" "golang.org/x/crypto/ssh/terminal" "github.com/hetznercloud/cli/internal/version" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) const ( progressCircleTpl = `{{ cycle . " . " " . " " ." " . " }}` progressBarTpl = `{{ etime . }} {{ bar . "" "=" }} {{ percent . }}` ) func (c *State) Wrap(f func(*State, *cobra.Command, []string) error) func(*cobra.Command, []string) error { return func(cmd *cobra.Command, args []string) error { return f(c, cmd, args) } } func (c *State) Client() *hcloud.Client { if c.client == nil { opts := []hcloud.ClientOption{ hcloud.WithToken(c.Token), hcloud.WithApplication("hcloud-cli", version.Version), } if c.Endpoint != "" { opts = append(opts, hcloud.WithEndpoint(c.Endpoint)) } if c.Debug { if c.DebugFilePath == "" { opts = append(opts, hcloud.WithDebugWriter(os.Stderr)) } else { writer, _ := os.Create(c.DebugFilePath) opts = append(opts, hcloud.WithDebugWriter(writer)) } } // TODO Somehow pass here // pollInterval, _ := c.RootCommand.PersistentFlags().GetDuration("poll-interval") pollInterval := 500 * time.Millisecond if pollInterval > 0 { opts = append(opts, hcloud.WithPollInterval(pollInterval)) } c.client = hcloud.NewClient(opts...) } return c.client } // StdoutIsTerminal returns whether the CLI is run in a terminal. func StdoutIsTerminal() bool { return terminal.IsTerminal(int(os.Stdout.Fd())) } func (c *State) ActionProgress(ctx context.Context, action *hcloud.Action) error { return c.ActionsProgresses(ctx, []*hcloud.Action{action}) } func (c *State) ActionsProgresses(ctx context.Context, actions []*hcloud.Action) error { progressCh, errCh := c.Client().Action.WatchOverallProgress(ctx, actions) if StdoutIsTerminal() { progress := pb.New(100) progress.SetMaxWidth(50) // width of progress bar is too large by default progress.SetTemplateString(progressBarTpl) progress.Start() defer progress.Finish() for { select { case err := <-errCh: if err == nil { progress.SetCurrent(100) } return err case p := <-progressCh: progress.SetCurrent(int64(p)) } } } else { return <-errCh } } func (c *State) EnsureToken(_ *cobra.Command, _ []string) error { if c.Token == "" { return errors.New("no active context or token (see `hcloud context --help`)") } return nil } func (c *State) WaitForActions(ctx context.Context, actions []*hcloud.Action) error { for _, action := range actions { resources := make(map[string]int64) for _, resource := range action.Resources { resources[string(resource.Type)] = resource.ID } var waitingFor string switch action.Command { default: waitingFor = fmt.Sprintf("Waiting for action %s to have finished", action.Command) case "start_server": waitingFor = fmt.Sprintf("Waiting for server %d to have started", resources["server"]) case "attach_volume": waitingFor = fmt.Sprintf("Waiting for volume %d to have been attached to server %d", resources["volume"], resources["server"]) } _, errCh := c.Client().Action.WatchProgress(ctx, action) err := DisplayProgressCircle(errCh, waitingFor) if err != nil { return err } } return nil } func DisplayProgressCircle(errCh <-chan error, waitingFor string) error { const ( done = "done" failed = "failed" ellipsis = " ... " ) if StdoutIsTerminal() { fmt.Println(waitingFor) progress := pb.New(1) // total progress of 1 will do since we use a circle here progress.SetTemplateString(progressCircleTpl) progress.Start() defer progress.Finish() if err := <-errCh; err != nil { progress.SetTemplateString(ellipsis + failed) return err } progress.SetTemplateString(ellipsis + done) } else { fmt.Print(waitingFor + ellipsis) if err := <-errCh; err != nil { fmt.Println(failed) return err } fmt.Println(done) } return nil } cli-1.39.0/internal/state/state.go000066400000000000000000000037461451614444200167750ustar00rootroot00000000000000package state import ( "context" "errors" "io/ioutil" "log" "os" "path/filepath" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) type State struct { Token string Endpoint string Context context.Context Config *Config ConfigPath string Debug bool DebugFilePath string client *hcloud.Client } func New() *State { s := &State{ Context: context.Background(), Config: &Config{}, ConfigPath: DefaultConfigPath, } if p := os.Getenv("HCLOUD_CONFIG"); p != "" { s.ConfigPath = p } return s } var ErrConfigPathUnknown = errors.New("config file path unknown") func (c *State) ReadEnv() { if s := os.Getenv("HCLOUD_TOKEN"); s != "" { c.Token = s } if s := os.Getenv("HCLOUD_ENDPOINT"); s != "" { c.Endpoint = s } if s := os.Getenv("HCLOUD_DEBUG"); s != "" { c.Debug = true } if s := os.Getenv("HCLOUD_DEBUG_FILE"); s != "" { c.DebugFilePath = s } if s := os.Getenv("HCLOUD_CONTEXT"); s != "" && c.Config != nil { if cfgCtx := c.Config.ContextByName(s); cfgCtx != nil { c.Config.ActiveContext = cfgCtx c.Token = cfgCtx.Token } else { log.Printf("warning: context %q specified in HCLOUD_CONTEXT does not exist\n", s) } } } func (c *State) ReadConfig() error { if c.ConfigPath == "" { return ErrConfigPathUnknown } data, err := ioutil.ReadFile(c.ConfigPath) if err != nil { return err } if err = UnmarshalConfig(c.Config, data); err != nil { return err } if c.Config.ActiveContext != nil { c.Token = c.Config.ActiveContext.Token } if c.Config.Endpoint != "" { c.Endpoint = c.Config.Endpoint } return nil } func (c *State) WriteConfig() error { if c.ConfigPath == "" { return ErrConfigPathUnknown } if c.Config == nil { return nil } data, err := MarshalConfig(c.Config) if err != nil { return err } if err := os.MkdirAll(filepath.Dir(c.ConfigPath), 0777); err != nil { return err } if err := ioutil.WriteFile(c.ConfigPath, data, 0600); err != nil { return err } return nil } cli-1.39.0/internal/testutil/000077500000000000000000000000001451614444200160515ustar00rootroot00000000000000cli-1.39.0/internal/testutil/fixture.go000066400000000000000000000025421451614444200200710ustar00rootroot00000000000000package testutil import ( "testing" "github.com/golang/mock/gomock" "github.com/spf13/cobra" hcapi2_mock "github.com/hetznercloud/cli/internal/hcapi2/mock" "github.com/hetznercloud/cli/internal/state" ) // Fixture provides affordances for testing CLI commands. type Fixture struct { MockController *gomock.Controller Client *hcapi2_mock.MockClient ActionWaiter *state.MockActionWaiter TokenEnsurer *state.MockTokenEnsurer } // NewFixture creates a new Fixture. func NewFixture(t *testing.T) *Fixture { ctrl := gomock.NewController(t) return &Fixture{ MockController: ctrl, Client: hcapi2_mock.NewMockClient(ctrl), ActionWaiter: state.NewMockActionWaiter(ctrl), TokenEnsurer: state.NewMockTokenEnsurer(ctrl), } } // ExpectEnsureToken makes the mock TokenEnsurer expect a EnsureToken call. func (f *Fixture) ExpectEnsureToken() { f.TokenEnsurer.EXPECT().EnsureToken(gomock.Any(), gomock.Any()).Return(nil) } // Run runs the given cobra command with the given arguments and returns stdout output and a // potential error. func (f *Fixture) Run(cmd *cobra.Command, args []string) (string, error) { cmd.SetArgs(args) return CaptureStdout(cmd.Execute) } // Finish must be called after the test is finished, preferably via `defer` directly after // creating the Fixture. func (f *Fixture) Finish() { f.MockController.Finish() } cli-1.39.0/internal/testutil/testing.go000066400000000000000000000016721451614444200200630ustar00rootroot00000000000000package testutil import ( "bytes" "fmt" "io" "os" ) // CaptureStdout redirects stdout while running fn and returns the output as a string. // If there's an error during capture, it returns the error, otherwise it returns the error // returned by fn. func CaptureStdout(fn func() error) (string, error) { r, w, err := os.Pipe() if err != nil { return "", fmt.Errorf("capture stdout: %v", err) } origOut := os.Stdout defer func() { os.Stdout = origOut }() buf := &bytes.Buffer{} os.Stdout = w copyDone := make(chan struct{}) var copyErr error go func() { defer close(copyDone) copied, err := io.Copy(buf, r) if err != nil { copyErr = fmt.Errorf("capture stdout: %v, copied: %d\n", err, copied) return } }() err = fn() if copyErr != nil { return "", copyErr } if err := w.Close(); err != nil { return "", fmt.Errorf("capture stdout close pipe reader: %v", err) } <-copyDone return buf.String(), err } cli-1.39.0/internal/version/000077500000000000000000000000001451614444200156615ustar00rootroot00000000000000cli-1.39.0/internal/version/version.go000066400000000000000000000001461451614444200176760ustar00rootroot00000000000000package version // Version is set via compiler flags (see goreleaser config) var Version = "unknown" cli-1.39.0/renovate.json000066400000000000000000000002051451614444200150730ustar00rootroot00000000000000{ "$schema": "https://docs.renovatebot.com/renovate-schema.json", "extends": ["github>hetznercloud/.github//renovate/default"] } cli-1.39.0/script/000077500000000000000000000000001451614444200136645ustar00rootroot00000000000000cli-1.39.0/script/decrypt_secrets.sh000077500000000000000000000015061451614444200174270ustar00rootroot00000000000000#!/bin/sh gpg --quiet --batch --yes --decrypt --passphrase="$SECRETS_PASSWORD" --output ./.github/secrets/hcloud_cli.p12 ./.github/secrets/hcloud_cli.p12.gpg security create-keychain -p "" build.keychain # Use long timeout for keychain to avoid issues where codesign fails because the keychain is locked # before it was used. Default timeout is 300s security set-keychain-settings -u -t 3600 ~/Library/Keychains/build.keychain security import ./.github/secrets/hcloud_cli.p12 -t agg -k ~/Library/Keychains/build.keychain -P "$CERT_PASSWORD" -A security list-keychains -s ~/Library/Keychains/build.keychain security default-keychain -s ~/Library/Keychains/build.keychain security unlock-keychain -p "" ~/Library/Keychains/build.keychain security set-key-partition-list -S apple-tool:,apple: -s -k "" ~/Library/Keychains/build.keychain cli-1.39.0/script/gon.sh000077500000000000000000000011141451614444200150030ustar00rootroot00000000000000#!/usr/bin/env bash set -eu -o posix # Only sign on releasing if [[ "${GITHUB_REF_TYPE:-}" != "tag" ]]; then exit 0 fi BINARY_PATH="$1" GON_CONFIG="gon_$RANDOM.json" cleanup() { rm -f "$GON_CONFIG" } trap cleanup EXIT printf '{ "source": ["%s"], "bundle_id": "cloud.hetzner.cli", "apple_id": { "username": "integrations@hetzner-cloud.de", "password": "@env:HC_APPLE_DEVELOPER_PASSWORD" }, "sign": { "application_identity": "Developer ID Application: Hetzner Cloud GmbH (4PM38G6W5R)" } }' "$BINARY_PATH" > "$GON_CONFIG" gon -log-level=debug "$GON_CONFIG" cli-1.39.0/script/install_tools.sh000077500000000000000000000003311451614444200171060ustar00rootroot00000000000000#!/usr/bin/env bash set -o errexit set -o pipefail set -o nounset go install github.com/boumenot/gocover-cobertura go install github.com/golang/mock/mockgen go install github.com/rjeczalik/interfaces/cmd/interfacer cli-1.39.0/tools.go000066400000000000000000000004521451614444200140500ustar00rootroot00000000000000//go:build tools // +build tools package tools // When updating this, think about also updating script/install_tools.sh import ( _ "github.com/boumenot/gocover-cobertura" _ "github.com/golang/mock/mockgen" _ "github.com/google/go-cmp/cmp" _ "github.com/rjeczalik/interfaces/cmd/interfacer" )