File kubero-cli-2.4.7.obscpio of Package kubero-cli
07070100000000000041ED00000000000000000000000267BEEE0500000000000000000000000000000000000000000000001900000000kubero-cli-2.4.7/.github07070100000001000081A400000000000000000000000167BEEE05000001C9000000000000000000000000000000000000002800000000kubero-cli-2.4.7/.github/dependabot.yml# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
version: 2
updates:
- package-ecosystem: "gomod"
directory: "/"
schedule:
interval: "weekly"
07070100000002000041ED00000000000000000000000267BEEE0500000000000000000000000000000000000000000000002300000000kubero-cli-2.4.7/.github/workflows07070100000003000081A400000000000000000000000167BEEE0500000364000000000000000000000000000000000000002F00000000kubero-cli-2.4.7/.github/workflows/release.ymlname: goreleaser
on:
push:
#branches:
# - master
# Publish `v1.2.3` tags as releases.
tags:
- v*
workflow_dispatch:
jobs:
goreleaser:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
-
name: Set version
run: |
echo -n $(git describe --tags --abbrev=0) > cmd/kuberoCli/VERSION
-
name: Set up Go
uses: actions/setup-go@v3
with:
go-version: 1.21
-
name: Run GoReleaser
uses: goreleaser/goreleaser-action@v5
with:
distribution: goreleaser
version: latest
args: release --clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GORELEASER_GITHUB_TOKEN: ${{ secrets.GORELEASER_GITHUB_TOKEN }}07070100000004000081A400000000000000000000000167BEEE0500000180000000000000000000000000000000000000001C00000000kubero-cli-2.4.7/.gitignore# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, built with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Dependency directories (remove the comment below to include it)
# vendor/
/kubero
kubero.yaml
credentials.yaml
notes.txt
pipeline.yaml
app.*.yaml
kind.yaml
cmd/kuberoCli/VERSION
.kubero07070100000005000081A400000000000000000000000167BEEE05000003F6000000000000000000000000000000000000002200000000kubero-cli-2.4.7/.goreleaser.yaml# This is an example .goreleaser.yml file with some sensible defaults.
# Make sure to check the documentation at https://goreleaser.com
before:
hooks:
# You may remove this if you don't use go modules.
- go mod tidy
builds:
-
main: cmd/main.go
binary: kubero
env:
- CGO_ENABLED=0
goos:
- linux
- windows
- darwin
archives:
- name_template: "{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}"
format_overrides:
- goos: windows
format: zip
checksum:
name_template: 'checksums.txt'
snapshot:
name_template: "{{ incpatch .Version }}-next"
changelog:
sort: asc
filters:
exclude:
- '^docs:'
- '^test:'
- '^templates:'
- '^.github:'
brews:
-
repository:
owner: kubero-dev
name: homebrew-kubero
token: "{{ .Env.GORELEASER_GITHUB_TOKEN }}"
homepage: "https://www.kubero.dev"
description: "Manage your kubero applications with the CLI"
test: |
system "#{bin}/kubero", "--version"07070100000006000081A400000000000000000000000167BEEE0500002C5D000000000000000000000000000000000000001900000000kubero-cli-2.4.7/LICENSE Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
07070100000007000081A400000000000000000000000167BEEE050000192E000000000000000000000000000000000000001B00000000kubero-cli-2.4.7/README.md# kubero-cli



A powerful and user-friendly Command Line Interface (CLI) for [Kubero](https://github.com/kubero-dev/kubero), the simplest Platform as a Service (PaaS) for Kubernetes.
> **Note:** Please report any issues in the [main repository](https://github.com/kubero-dev/kubero).
---
## Table of Contents
- [Features](#features)
- [Installation](#installation)
- [Supported Platforms](#supported-platforms)
- [1. Shortcut Installation](#1-shortcut-installation)
- [2. Homebrew Installation](#2-homebrew-installation)
- [3. Build from Source](#3-build-from-source)
- [Supported Providers](#supported-providers)
- [Usage](#usage)
- [Command Overview](#command-overview)
- [Provider Credentials](#provider-credentials)
- [Scaleway](#scaleway)
- [Linode](#linode)
- [DigitalOcean](#digitalocean)
- [Google GKE](#google-gke)
- [Development Guide](#development-guide)
- [Contributing](#contributing)
- [License](#license)
- [Acknowledgments](#acknowledgments)
---
## Features
- **Easy Cluster Deployment:** Quickly create Kubernetes clusters on supported providers.
- **App Management:** Simplify application deployment and management.
- **Pipeline Integration:** Seamlessly integrate CI/CD pipelines.
- **User-Friendly Commands:** Intuitive CLI commands for efficient workflows.
- **Dashboard Access:** Easy access to the Kubero dashboard for monitoring.
---
## Installation
### Supported Platforms
- **macOS**
- **Linux**
### 1. Shortcut Installation
Install Kubero CLI with a single command:
```shell
curl -fsSL get.kubero.dev | bash
```
### 2. Homebrew Installation
If Homebrew is not installed, install it first:
```shell
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```
Install Kubero CLI via Homebrew:
```shell
brew tap kubero-dev/kubero
brew install kubero-cli
```
### 3. Build from Source
For advanced use cases, build and package the binary manually.
#### Requirements
- [Git](https://git-scm.com/downloads)
- [Go](https://go.dev/doc/install)
- [UPX](https://github.com/upx/upx/releases/)
#### Steps
1. **Clone the Repository:**
```shell
git clone https://github.com/kubero-dev/kubero-cli.git
```
2. **Navigate to the Project Directory:**
```shell
cd kubero-cli
```
3. **Create a Version Tag (Optional):**
```shell
git tag -a v1.0 -m "Version 1.0"
```
4. **Build and Package the Binary:**
```shell
cd cmd
go build -ldflags "-s -w -X main.version=$(git describe --tags --abbrev=0) -X main.commit=$(git rev-parse --short HEAD) -X main.date=$(date +%Y-%m-%d)" -trimpath -o kubero-cli
upx kubero-cli
mv kubero-cli ../kubero
cd ..
```
5. **Move the Binary to Your PATH:**
```shell
sudo mv kubero /usr/local/bin/
```
6. **Reload Shell Configuration:**
```shell
source "$HOME/.$(basename ${SHELL})rc"
```
7. **Verify Installation:**
```shell
kubero --version
```
---
## Supported Providers
Kubero CLI currently supports the following cloud providers:
- **Scaleway**
- **Linode**
- **DigitalOcean**
- **Google GKE**
- **Kind** (local clusters)
### Coming Soon
- **Vultr**
- **Oracle Cloud OCI/OKE**
- **Exoscale**
- **Swissflow**
---
## Usage
### Command Overview
```plaintext
kubero
├── install # Create a Kubernetes cluster and install Kubero with all required components
├── list # List all running clusters
├── login # Log in to Kubero and save credentials
├── logout # Log out from Kubero and remove saved credentials
├── create # Create new app and pipeline configurations
│ ├── app
│ └── pipeline
├── up # Deploy apps and pipelines
│ ├── app
│ └── pipeline
├── down # Remove apps and pipelines
│ ├── app
│ └── pipeline
├── fetch # Sync configurations to local files
│ ├── app
│ └── pipeline
├── dashboard # Open the Kubero dashboard
├── tunnel # Open a tunnel to a NAT-ed cluster
├── instance # Manage Kubero instances
│ ├── create # Create an instance configuration
│ ├── delete # Delete an instance configuration
│ └── select # Select an active instance
├── config # View available configurations
│ ├── addons # List addons
│ ├── buildpacks # List buildpacks
│ └── podsizes # List pod size configurations
└── help # Display help for commands
```
---
## Provider Credentials
Set the appropriate environment variables for your cloud provider before using Kubero CLI.
### Scaleway
```shell
export SCALEWAY_ACCESS_TOKEN=your_access_token
export SCALEWAY_PROJECT_ID=your_project_id
export SCALEWAY_ORGANIZATION_ID=your_organization_id
```
### Linode
```shell
export LINODE_ACCESS_TOKEN=your_access_token
```
### DigitalOcean
```shell
export DIGITALOCEAN_ACCESS_TOKEN=your_access_token
```
### Google GKE
```shell
export GOOGLE_API_KEY=your_api_key
```
---
## Development Guide
### Enable Development Mode
To enable development mode for testing and debugging, create a `VERSION` file:
```shell
echo "dev" > cmd/kuberoCli/VERSION
```
---
## Contributing
We welcome contributions from the community! Please check out our [Contributing Guidelines](https://github.com/kubero-dev/kubero/blob/main/CONTRIBUTING.md) for more information.
---
## License
This project is licensed under the [MIT License](LICENSE).
---
## Acknowledgments
- **[Kubero](https://github.com/kubero-dev/kubero):** The simplest PaaS for Kubernetes.
- **[Go](https://golang.org/):** The programming language used for development.
- **Community Contributors:** Thank you to all who have contributed to this project.
---
Thank you for using **kubero-cli**! If you have suggestions or encounter issues, please open an issue in the [main repository](https://github.com/kubero-dev/kubero).
---
07070100000008000081A400000000000000000000000167BEEE050000002C000000000000000000000000000000000000001A00000000kubero-cli-2.4.7/_headers/*
Content-Type: text/plain; charset=UTF-807070100000009000041ED00000000000000000000000267BEEE0500000000000000000000000000000000000000000000001500000000kubero-cli-2.4.7/cmd0707010000000A000041ED00000000000000000000000267BEEE0500000000000000000000000000000000000000000000001F00000000kubero-cli-2.4.7/cmd/kuberoCli0707010000000B000081A400000000000000000000000167BEEE0500000B68000000000000000000000000000000000000002600000000kubero-cli-2.4.7/cmd/kuberoCli/app.gopackage kuberoCli
import (
"encoding/json"
"kubero/pkg/kuberoApi"
"log"
"os"
"strings"
"github.com/i582/cfmt/cmd/cfmt"
"github.com/olekukonko/tablewriter"
"github.com/spf13/viper"
)
func appsList() {
pipelineResp, _ := api.GetPipelineApps(pipelineName)
var pl Pipeline
jsonUnmarshalErr := json.Unmarshal(pipelineResp.Body(), &pl)
if jsonUnmarshalErr != nil {
log.Fatal(jsonUnmarshalErr)
return
}
for _, phase := range pl.Phases {
if !phase.Enabled {
continue
}
_, _ = cfmt.Print("\n")
_, _ = cfmt.Println("{{ " + strings.ToUpper(phase.Name) + "}}::bold|white" + " (" + phase.Context + ")")
table := tablewriter.NewWriter(os.Stdout)
table.SetHeader([]string{
"Name",
"Phase",
"Pipeline",
"Repository",
"Domain",
})
table.SetBorder(false)
for _, app := range phase.Apps {
table.Append([]string{
app.Name,
app.Phase,
app.Pipeline,
app.Gitrepo.CloneURL + ":" +
app.Gitrepo.DefaultBranch,
app.Domain,
})
}
printCLI(table, pipelineResp)
}
}
func getAllRemoteApps() []string {
apps, _ := api.GetApps()
var appShortList []appShort
jsonUnmarshalErr := json.Unmarshal(apps.Body(), &appShortList)
if jsonUnmarshalErr != nil {
log.Fatal(jsonUnmarshalErr)
return nil
}
var appsList []string
for _, app := range appShortList {
if pipelineName != "" && app.Pipeline != pipelineName {
continue
}
if stageName != "" && app.Phase != stageName {
continue
}
if appName != "" && app.Name != appName {
continue
}
appsList = append(appsList, app.Name)
}
return appsList
}
func getAllLocalApps() []string {
baseDir := getIACBaseDir()
dir := baseDir + "/" + pipelineName + "/" + stageName
var appsList []string
appFiles, err := os.ReadDir(dir)
if err != nil {
log.Fatal(err)
}
for _, appFileName := range appFiles {
// remove the .yaml extension
appName := strings.TrimSuffix(appFileName.Name(), ".yaml")
a := loadLocalApp(pipelineName, stageName, appName)
if a.Kind == "KuberoApp" && a.Metadata.Name != "" {
appsList = append(appsList, a.Metadata.Name)
}
}
return appsList
}
func loadLocalApp(pipelineName string, stageName string, appName string) kuberoApi.AppCRD {
appConfig := loadAppConfig(pipelineName, stageName, appName)
var appCRD kuberoApi.AppCRD
appConfigUnmarshalErr := appConfig.Unmarshal(&appCRD)
if appConfigUnmarshalErr != nil {
log.Fatal(appConfigUnmarshalErr)
return kuberoApi.AppCRD{}
}
return appCRD
}
func loadAppConfig(pipelineName string, stageName string, appName string) *viper.Viper {
baseDir := getIACBaseDir()
dir := baseDir + "/" + pipelineName + "/" + stageName
appConfig := viper.New()
appConfig.SetConfigName(appName)
appConfig.SetConfigType("yaml")
appConfig.AddConfigPath(dir)
readInConfigErr := appConfig.ReadInConfig()
if readInConfigErr != nil {
log.Fatal(readInConfigErr)
return nil
}
return appConfig
}
0707010000000C000081A400000000000000000000000167BEEE0500000274000000000000000000000000000000000000002900000000kubero-cli-2.4.7/cmd/kuberoCli/config.gopackage kuberoCli
import (
"github.com/spf13/cobra"
)
// configCmd represents the config command
var configCmd = &cobra.Command{
Use: "config",
Short: "Show your configuration",
/*
Long: `A longer description that spans multiple lines and likely contains examples
and usage of using your command. For example:
Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.`,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("config called")
},
*/
}
func init() {
rootCmd.AddCommand(configCmd)
}
0707010000000D000081A400000000000000000000000167BEEE05000003E3000000000000000000000000000000000000002F00000000kubero-cli-2.4.7/cmd/kuberoCli/configAddons.gopackage kuberoCli
import (
"encoding/json"
"os"
"strconv"
"github.com/go-resty/resty/v2"
"github.com/olekukonko/tablewriter"
"github.com/spf13/cobra"
)
// addonsCmd represents the addons command
var addonsCmd = &cobra.Command{
Use: "addons",
Short: "A brief description of your command",
Run: func(cmd *cobra.Command, args []string) {
resp, _ := api.GetAddons()
//fmt.Println(resp)
printAddons(resp)
},
}
func init() {
configCmd.AddCommand(addonsCmd)
}
// print the response as a table
func printAddons(r *resty.Response) {
table := tablewriter.NewWriter(os.Stdout)
table.SetHeader([]string{"Name", "Description", "Version", "Beta", "Enabled"})
table.SetRowLine(true)
//table.SetBorder(false)
var addonsList []Addon
json.Unmarshal(r.Body(), &addonsList)
for _, addon := range addonsList {
table.Append([]string{addon.ID, addon.Description, addon.Version.Installed, strconv.FormatBool(addon.Beta), strconv.FormatBool(addon.Enabled)})
}
printCLI(table, r)
}
0707010000000E000081A400000000000000000000000167BEEE05000006A5000000000000000000000000000000000000003300000000kubero-cli-2.4.7/cmd/kuberoCli/configBuildpacks.gopackage kuberoCli
import (
"encoding/json"
"os"
"github.com/go-resty/resty/v2"
"github.com/olekukonko/tablewriter"
"github.com/spf13/cobra"
)
// buildpacksCmd represents the buildpacks command
var buildpacksCmd = &cobra.Command{
Use: "buildpacks",
Short: "List the available buildpacks",
Run: func(cmd *cobra.Command, args []string) {
resp, _ := api.GetBuildpacks()
printBuildpacks(resp)
},
}
func init() {
configCmd.AddCommand(buildpacksCmd)
}
var buildPacksSimpleList []string
func loadBuildpacks() {
b, _ := api.GetBuildpacks()
var buildPacks buildPacks
json.Unmarshal(b.Body(), &buildPacks)
for _, buildPack := range buildPacks {
buildPacksSimpleList = append(buildPacksSimpleList, buildPack.Name)
}
//buildPacks = []string{"java", "node", "python", "ruby", "php"}
}
// print the response as a table
func printBuildpacks(r *resty.Response) {
table := tablewriter.NewWriter(os.Stdout)
table.SetHeader([]string{"Name", "Language", "Phase", "Image", "Command"})
table.SetAutoMergeCells(true)
table.SetRowLine(true)
//table.SetBorder(false)
var buildPacksList buildPacks
json.Unmarshal(r.Body(), &buildPacksList)
for _, podsize := range buildPacksList {
table.Append([]string{
podsize.Name,
podsize.Language,
"Fetch",
podsize.Fetch.Repository + ":" + podsize.Fetch.Tag,
"git clone",
})
table.Append([]string{
podsize.Name,
podsize.Language,
"Build",
podsize.Build.Repository + ":" + podsize.Build.Tag,
podsize.Build.Command,
})
table.Append([]string{
podsize.Name,
podsize.Language,
"Run",
podsize.Run.Repository + ":" + podsize.Run.Tag + " (ro)",
podsize.Run.Command,
})
}
printCLI(table, r)
}
0707010000000F000081A400000000000000000000000167BEEE0500000378000000000000000000000000000000000000003100000000kubero-cli-2.4.7/cmd/kuberoCli/configPodsizes.gopackage kuberoCli
import (
"encoding/json"
"fmt"
"os"
"github.com/go-resty/resty/v2"
"github.com/olekukonko/tablewriter"
"github.com/spf13/cobra"
)
var podSizesCmd = &cobra.Command{
Use: "podsizes",
Short: "List the available pod sizes",
Run: func(cmd *cobra.Command, args []string) {
resp, _ := api.GetPodsize()
printPodSizes(resp)
},
}
func init() {
configCmd.AddCommand(podSizesCmd)
}
func printPodSizes(r *resty.Response) {
table := tablewriter.NewWriter(os.Stdout)
table.SetHeader([]string{"Name", "Description"})
//table.SetBorder(false)
var podsizeList []PodSize
unmarshalErr := json.Unmarshal(r.Body(), &podsizeList)
if unmarshalErr != nil {
fmt.Println("Failed to unmarshal the response body:", unmarshalErr)
return
}
for _, podsize := range podsizeList {
table.Append([]string{podsize.Name, podsize.Description})
}
printCLI(table, r)
}
07070100000010000081A400000000000000000000000167BEEE0500001ED9000000000000000000000000000000000000002900000000kubero-cli-2.4.7/cmd/kuberoCli/create.gopackage kuberoCli
/*
Copyright © 2023 NAME HERE <EMAIL ADDRESS>
*/
import (
"fmt"
"kubero/pkg/kuberoApi"
"os"
"strconv"
"github.com/AlecAivazis/survey/v2"
"github.com/i582/cfmt/cmd/cfmt"
"github.com/spf13/cobra"
"gopkg.in/yaml.v3"
)
// createCmd represents the create command
var createCmd = &cobra.Command{
Use: "create",
Aliases: []string{"cr", "add", "new"},
Short: "Create a new pipeline and/or app",
Long: `Initiate a new pipeline and app in your current repository.`,
Run: func(cmd *cobra.Command, args []string) {
createPipelineAndApp()
},
}
func init() {
rootCmd.AddCommand(createCmd)
createCmd.PersistentFlags().StringVarP(&pipelineName, "pipeline", "p", "", "name of the pipeline")
}
func createPipelineAndApp() {
createPipelineAndApp := promptLine("Create a new pipeline", "[y,n]", "y")
if createPipelineAndApp == "y" {
createPipeline()
}
pipelinesList := getAllLocalPipelines()
ensurePipelineIsSet(pipelinesList)
ensureStageNameIsSet()
ensureAppNameIsSet()
createApp()
}
func appForm() kuberoApi.AppCRD {
var appCRD kuberoApi.AppCRD
appconfig := loadAppConfig(pipelineName, stageName, appName)
pipelineConfig := loadPipelineConfig(pipelineName)
appCRD.APIVersion = "application.kubero.dev/v1alpha1"
appCRD.Kind = "KuberoApp"
appCRD.Spec.Name = appName
appCRD.Spec.Pipeline = pipelineName
appCRD.Spec.Phase = stageName
appCRD.Spec.Domain = promptLine("Domain", "", appconfig.GetString("spec.domain"))
unmarshalKeyErr := pipelineConfig.UnmarshalKey("spec.git.repository", &appCRD.Spec.Gitrepo)
if unmarshalKeyErr != nil {
fmt.Println(unmarshalKeyErr)
return kuberoApi.AppCRD{}
}
gitURL := pipelineConfig.GetString("spec.git.repository.sshurl")
appCRD.Spec.Branch = promptLine("Branch", gitURL+":", appconfig.GetString("spec.branch"))
appCRD.Spec.Buildpack = pipelineConfig.GetString("spec.buildpack.name")
autodeployDefault := "n"
if !appconfig.GetBool("spec.autodeploy") {
autodeployDefault = "y"
}
autodeploy := promptLine("Autodeploy", "[y,n]", autodeployDefault)
if autodeploy == "Y" {
appCRD.Spec.Autodeploy = true
} else {
appCRD.Spec.Autodeploy = false
}
envCount, _ := strconv.Atoi(promptLine("Number of Env Vars", "", "0"))
appCRD.Spec.EnvVars = []string{}
for i := 0; i < envCount; i++ {
appCRD.Spec.EnvVars = append(appCRD.Spec.EnvVars, promptLine("Env Var", "", ""))
}
appCRD.Spec.Image.ContainerPort, _ = strconv.Atoi(promptLine("Container Port", "8080", appconfig.GetString("spec.image.containerport")))
appCRD.Spec.Web = kuberoApi.Web{}
appCRD.Spec.Web.ReplicaCount, _ = strconv.Atoi(promptLine("Web Pods", "1", appconfig.GetString("spec.web.replicacount")))
appCRD.Spec.Worker = kuberoApi.Worker{}
appCRD.Spec.Worker.ReplicaCount, _ = strconv.Atoi(promptLine("Worker Pods", "0", appconfig.GetString("spec.worker.replicacount")))
return appCRD
}
func createApp() {
appCRD := appForm()
writeAppYaml(appCRD)
_, _ = cfmt.Println("\n\n{{Created appCRD.yaml}}::green")
}
func writeAppYaml(appCRD kuberoApi.AppCRD) {
// write pipeline.yaml
yamlData, err := yaml.Marshal(&appCRD)
if err != nil || appCRD.Spec.Name == "" {
panic("Unable to write data into the file")
}
fileName := ".kubero/" + appCRD.Spec.Pipeline + "/" + appCRD.Spec.Phase + "/" + appCRD.Spec.Name + ".yaml"
err = os.WriteFile(fileName, yamlData, 0644)
if err != nil {
panic("Unable to write data into the file")
}
}
func createPipeline() kuberoApi.PipelineCRD {
loadConfigs(pipelineName)
loadRepositories()
loadContexts()
loadBuildpacks()
pipelineCRD := pipelinesForm()
writePipelineYaml(pipelineCRD)
_, _ = cfmt.Println("\n\n{{Created pipeline.yaml}}::green")
_, _ = cfmt.Println(pipelineName)
return pipelineCRD
}
func writePipelineYaml(pipeline kuberoApi.PipelineCRD) {
basePath := "/.kubero/" //TODO Make it dynamic
gitdir := getGitdir()
dir := gitdir + basePath + pipelineName
err := os.MkdirAll(dir, 0755)
if err != nil {
fmt.Println(err)
panic("Unable to create directory")
}
yamlData, err := yaml.Marshal(&pipeline)
// iterate over phases to create the directory
for _, phase := range pipeline.Spec.Phases {
if phase.Enabled {
err := os.MkdirAll(dir+"/"+phase.Name, 0755)
if err != nil {
fmt.Println(err)
panic("Unable to create directory")
}
}
}
if err != nil {
fmt.Printf("Error while Marshaling. %v", err)
}
//fmt.Println(string(yamlData))
fileName := dir + "/pipeline.yaml"
err = os.WriteFile(fileName, yamlData, 0644)
if err != nil {
panic("Unable to write data into the file")
}
}
func pipelinesForm() kuberoApi.PipelineCRD {
var pipelineCRD kuberoApi.PipelineCRD
if pipelineName == "" {
pipelineName = promptLine("Define a PipelineName name", "", "")
}
pipelineCRD.Spec.Name = pipelineName
pipelineCRD.APIVersion = "application.kubero.dev/v1alpha1"
pipelineCRD.Kind = "KuberoPipeline"
fmt.Println("")
prompt := &survey.Select{
Message: "Select a buildpack",
Options: buildPacksSimpleList,
}
askOneErr := survey.AskOne(prompt, &pipelineCRD.Spec.Buildpack.Name)
if askOneErr != nil {
fmt.Println(askOneErr.Error())
return kuberoApi.PipelineCRD{}
}
domain := pipelineConfig.GetString("spec.domain")
pipelineCRD.Spec.Domain = promptLine("FQDN Domain ", "", domain)
// those fields are deprecated and may be removed in the future
pipelineCRD.Spec.DockerImage = ""
pipelineCRD.Spec.DeploymentStrategy = "git"
gitconnection := promptLine("Connect pipeline to a Git repository (GitOps)", "[y,n]", "n")
contextDefault := contextSimpleList[0]
if gitconnection == "y" {
gitProvider := pipelineConfig.GetString("spec.git.repository.provider")
pipelineCRD.Spec.Git.Repository.Provider = promptLine("Repository Provider", fmt.Sprint(repoSimpleList), gitProvider)
gitURL := pipelineConfig.GetString("spec.git.repository.sshurl")
pipelineCRD.Spec.Git.Repository.SshUrl = promptLine("Repository URL", "["+getGitRemote()+"]", gitURL)
phaseReview := promptLine("enable reviewapps", "[y,n]", "n")
if phaseReview == "y" {
pipelineCRD.Spec.ReviewApps = true
pipelineCRD.Spec.Phases = append(pipelineCRD.Spec.Phases, kuberoApi.Phase{
Name: "review",
Enabled: true,
Context: promptLine("Context for reviewapps", fmt.Sprint(contextSimpleList), contextDefault),
})
} else {
pipelineCRD.Spec.ReviewApps = false
pipelineCRD.Spec.Phases = append(pipelineCRD.Spec.Phases, kuberoApi.Phase{
Name: "review",
Enabled: false,
Context: "",
})
}
}
phaseTest := promptLine("enable test", "[y,n]", "n")
if phaseTest == "y" {
pipelineCRD.Spec.Phases = append(pipelineCRD.Spec.Phases, kuberoApi.Phase{
Name: "test",
Enabled: true,
Context: promptLine("Context for test", fmt.Sprint(contextSimpleList), contextDefault),
})
} else {
pipelineCRD.Spec.Phases = append(pipelineCRD.Spec.Phases, kuberoApi.Phase{
Name: "test",
Enabled: false,
Context: "",
})
}
phaseStage := promptLine("enable stage", "[y,n]", "n")
if phaseStage == "y" {
pipelineCRD.Spec.Phases = append(pipelineCRD.Spec.Phases, kuberoApi.Phase{
Name: "stage",
Enabled: true,
Context: promptLine("Context for stage", fmt.Sprint(contextSimpleList), contextDefault),
})
} else {
pipelineCRD.Spec.Phases = append(pipelineCRD.Spec.Phases, kuberoApi.Phase{
Name: "stage",
Enabled: false,
Context: "",
})
}
phaseProduction := promptLine("enable production", "[y,n]", "y")
if phaseProduction != "n" {
pipelineCRD.Spec.Phases = append(pipelineCRD.Spec.Phases, kuberoApi.Phase{
Name: "production",
Enabled: true,
Context: promptLine("Context for production ", fmt.Sprint(contextSimpleList), contextDefault),
})
} else {
pipelineCRD.Spec.Phases = append(pipelineCRD.Spec.Phases, kuberoApi.Phase{
Name: "production",
Enabled: false,
Context: "",
})
}
return pipelineCRD
}
07070100000011000081A400000000000000000000000167BEEE0500000328000000000000000000000000000000000000002C00000000kubero-cli-2.4.7/cmd/kuberoCli/createApp.gopackage kuberoCli
import (
"github.com/spf13/cobra"
)
// appCmd represents the app command
var createAppCmd = &cobra.Command{
Use: "app",
Short: "Create a new app in a Pipeline",
Long: `Create a new app in a Pipeline.
If called without arguments, it will ask for all the required information`,
Run: func(cmd *cobra.Command, args []string) {
pipelinesList := getAllLocalPipelines()
ensurePipelineIsSet(pipelinesList)
ensureStageNameIsSet()
ensureAppNameIsSet()
createApp()
},
}
func init() {
createCmd.AddCommand(createAppCmd)
createAppCmd.Flags().StringVarP(&pipelineName, "pipeline", "p", "", "Name of the pipeline")
createAppCmd.Flags().StringVarP(&stageName, "stage", "s", "", "Name of the stage")
createAppCmd.Flags().StringVarP(&appName, "app", "a", "", "Name of the app")
}
07070100000012000081A400000000000000000000000167BEEE0500000231000000000000000000000000000000000000003100000000kubero-cli-2.4.7/cmd/kuberoCli/createPipeline.gopackage kuberoCli
/*
Copyright © 2023 NAME HERE <EMAIL ADDRESS>
*/
import (
"fmt"
"github.com/spf13/cobra"
)
var pipelineName string
var stageName string
var appName string
// pipelineCmd represents the pipeline command
var createPipelineCmd = &cobra.Command{
Use: "pipeline",
Aliases: []string{"pl"},
Short: "Create a new pipeline",
Long: `Create a new Pipeline`,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("create a new pipeline")
_ = createPipeline()
},
}
func init() {
createCmd.AddCommand(createPipelineCmd)
}
07070100000013000081A400000000000000000000000167BEEE05000002B1000000000000000000000000000000000000002C00000000kubero-cli-2.4.7/cmd/kuberoCli/dashboard.gopackage kuberoCli
/*
Copyright © 2023 NAME HERE <EMAIL ADDRESS>
*/
import (
"github.com/pkg/browser"
"github.com/spf13/cobra"
"log"
)
// dashboardCmd represents the dashboard command
var dashboardCmd = &cobra.Command{
Use: "dashboard",
Aliases: []string{"db"},
Short: "Opens the Kubero dashboard in your browser",
Long: `Use the dashboard subcommand to open the Kubero dashboard in your browser.`,
Run: func(cmd *cobra.Command, args []string) {
url := currentInstance.ApiUrl
openURLErr := browser.OpenURL(url)
if openURLErr != nil {
log.Fatal("Failed to open the browser:", openURLErr)
return
}
},
}
func init() {
rootCmd.AddCommand(dashboardCmd)
}
07070100000014000081A400000000000000000000000167BEEE0500000CAC000000000000000000000000000000000000002800000000kubero-cli-2.4.7/cmd/kuberoCli/debug.gopackage kuberoCli
/*
Copyright © 2023 NAME HERE <EMAIL ADDRESS>
*/
import (
_ "embed"
"os"
"os/exec"
"runtime"
"github.com/i582/cfmt/cmd/cfmt"
"github.com/spf13/cobra"
)
// debugCmd represents the debug command
var debugCmd = &cobra.Command{
Use: "debug",
Aliases: []string{"dbg"},
Short: "Print debug informations",
Long: `This command will print debug informations like:
- Kubero CLI version
- OS/Arch
- Kubernetes version
- Kuberop operator version
- Kuberop operator namespace
- Kubernetes metrics server version
- Kubernetes cert-manager version`,
Run: func(cmd *cobra.Command, args []string) {
_, _ = cfmt.Println("{{Kubero CLI}}::bold")
printCLIVersion()
printOsArch()
_, _ = cfmt.Println("\n{{Kubernetes}}::bold")
printKubernetesVersion()
_, _ = cfmt.Println("{{Kubero Operator}}::bold")
checkKuberoOperator()
_, _ = cfmt.Println("{{\nKubero UI}}::bold")
checkKuberoUI()
_, _ = cfmt.Println("{{\nCert Manager}}::bold")
checkCertManager()
},
}
func init() {
rootCmd.AddCommand(debugCmd)
}
func printCLIVersion() {
_, _ = cfmt.Println("kuberoCLIVersion: ", kuberoCliVersion)
}
func printOsArch() {
_, _ = cfmt.Println("OS: ", runtime.GOOS)
_, _ = cfmt.Println("Arch: ", runtime.GOARCH)
_, _ = cfmt.Println("goVersion: ", runtime.Version())
}
func printKubernetesVersion() {
hasKubectl := checkBinary("kubectl")
if !hasKubectl {
promptWarning("kubectl is not installed. Installer won't be able to install kubero. Please install kubectl and try again.")
os.Exit(1)
}
version, _ := exec.Command("kubectl", "version", "-o", "yaml").Output()
_, _ = cfmt.Println(string(version))
}
func checkKuberoOperator() {
cmdOut, _ := exec.Command("kubectl", "get", "deployments.apps", "-n", "kubero-operator-system").Output()
_, _ = cfmt.Print(string(cmdOut))
_, _ = cfmt.Println("{{\nKubero Operator Image}}::bold")
cmdOut, _ = exec.Command("kubectl", "get", "deployment", "kubero-operator-controller-manager", "-o=jsonpath={$.spec.template.spec.containers[:1].image}", "-n", "kubero-operator-system").Output()
_, _ = cfmt.Print(string(cmdOut))
_, _ = cfmt.Println("")
}
func checkKuberoUI() {
cmdOut, _ := exec.Command("kubectl", "get", "deployments.apps", "-n", "kubero").Output()
_, _ = cfmt.Print(string(cmdOut))
_, _ = cfmt.Println("{{\nKubero UI Ingress}}::bold")
cmdOut, _ = exec.Command("kubectl", "get", "ingress", "-n", "kubero").Output()
_, _ = cfmt.Print(string(cmdOut))
_, _ = cfmt.Println("{{\nKubero UI Secrets}}::bold")
cmdOut, _ = exec.Command("kubectl", "get", "secrets", "-n", "kubero").Output()
_, _ = cfmt.Print(string(cmdOut))
_, _ = cfmt.Println("{{\nKubero UI Image}}::bold")
cmdOut, _ = exec.Command("kubectl", "get", "deployment", "kubero", "-o=jsonpath={$.spec.template.spec.containers[:1].image}", "-n", "kubero").Output()
_, _ = cfmt.Print(string(cmdOut))
_, _ = cfmt.Println("")
}
func checkCertManager() {
cmdOut, _ := exec.Command("kubectl", "get", "deployments.apps", "-n", "cert-manager").Output()
_, _ = cfmt.Print(string(cmdOut))
_, _ = cfmt.Println("{{\nCert Manager Cluster Issuers}}::bold")
cmdOut, _ = exec.Command("kubectl", "get", "clusterissuers.cert-manager.io").Output()
_, _ = cfmt.Print(string(cmdOut))
}
07070100000015000081A400000000000000000000000167BEEE05000007E5000000000000000000000000000000000000002700000000kubero-cli-2.4.7/cmd/kuberoCli/down.gopackage kuberoCli
import (
"github.com/spf13/cobra"
)
// downCmd represents the down command
var downCmd = &cobra.Command{
Use: "down",
Aliases: []string{"undeploy", "dn"},
Short: "Undeploy your pipelines and apps from the cluster",
Long: `Use the pipeline or app subcommand to undeploy your pipelines and apps from the cluster
Subcommands:
kubero down [pipeline|app]`,
Run: func(cmd *cobra.Command, args []string) {
if pipelineName != "" && appName == "" {
downPipeline()
} else if appName != "" {
downApp()
} else {
downAllPipelines()
}
},
}
func init() {
rootCmd.AddCommand(downCmd)
downCmd.Flags().StringVarP(&pipelineName, "pipeline", "p", "", "name of the pipeline")
downCmd.Flags().StringVarP(&stageName, "stage", "s", "", "Name of the stage [test|stage|production]")
downCmd.Flags().StringVarP(&appName, "app", "a", "", "name of the app")
downCmd.PersistentFlags().BoolVarP(&force, "force", "f", false, "Skip asking for confirmation")
}
func downPipeline() {
pipelinesList := getAllRemotePipelines()
ensurePipelineIsSet(pipelinesList)
downPipelineByName(pipelineName)
}
func downPipelineByName(pipelineName string) {
confirmationLine("Are you sure you want to undeploy the pipeline '"+pipelineName+"'?", "y")
_, err := api.UnDeployPipeline(pipelineName)
if err != nil {
panic("Unable to undeploy Pipeline")
}
}
func downApp() {
pipelinesList := getAllRemotePipelines()
ensurePipelineIsSet(pipelinesList)
ensureStageNameIsSet()
appsList := getAllRemoteApps()
ensureAppNameIsSelected(appsList)
confirmationLine("Are you sure you want to undeploy the app "+appName+" from "+stageName+" in "+pipelineName+"?", "y")
_, err := api.UnDeployApp(pipelineName, stageName, appName)
if err != nil {
panic("Unable to undeploy App")
}
}
func downAllPipelines() {
confirmationLine("Are you sure you want to undeploy all pipelines?", "y")
pipelinesList := getAllLocalPipelines()
for _, pipeline := range pipelinesList {
downPipelineByName(pipeline)
}
}
07070100000016000081A400000000000000000000000167BEEE05000002BB000000000000000000000000000000000000002A00000000kubero-cli-2.4.7/cmd/kuberoCli/downApp.gopackage kuberoCli
/*
Copyright © 2023 NAME HERE <EMAIL ADDRESS>
*/
import (
"github.com/spf13/cobra"
)
// appCmd represents the app command
var downAppCmd = &cobra.Command{
Use: "app",
Short: "Undeploy an apps from the cluster",
Long: `Use the app subcommand to undeploy your apps from the cluster`,
Run: func(cmd *cobra.Command, args []string) {
downApp()
},
}
func init() {
downCmd.AddCommand(downAppCmd)
downAppCmd.Flags().StringVarP(&pipelineName, "pipeline", "p", "", "name of the pipeline")
downAppCmd.Flags().StringVarP(&stageName, "stage", "s", "", "Name of the stage [test|stage|production]")
downAppCmd.Flags().StringVarP(&appName, "app", "a", "", "name of the app")
}
07070100000017000081A400000000000000000000000167BEEE050000024B000000000000000000000000000000000000002F00000000kubero-cli-2.4.7/cmd/kuberoCli/downPipeline.gopackage kuberoCli
/*
Copyright © 2023 NAME HERE <EMAIL ADDRESS>
*/
import (
"github.com/spf13/cobra"
)
// appCmd represents the app command
var downPipelineCmd = &cobra.Command{
Use: "pipeline",
Aliases: []string{"pl"},
Short: "Undeploy a pipeline from the cluster",
Long: `Use the pipeline subcommand to undeploy your pipelines from the cluster`,
Run: func(cmd *cobra.Command, args []string) {
downPipeline()
},
}
func init() {
downCmd.AddCommand(downPipelineCmd)
downPipelineCmd.Flags().StringVarP(&pipelineName, "pipeline", "p", "", "name of the pipeline")
}
07070100000018000081A400000000000000000000000167BEEE0500000D6F000000000000000000000000000000000000002800000000kubero-cli-2.4.7/cmd/kuberoCli/fetch.gopackage kuberoCli
import (
"encoding/json"
"fmt"
"kubero/pkg/kuberoApi"
"os"
"github.com/i582/cfmt/cmd/cfmt"
"github.com/spf13/cobra"
)
// fetchCmd represents the fetch command
var fetchCmd = &cobra.Command{
Use: "fetch",
Aliases: []string{"pull", "fe"},
Short: "Fetch your remote pipelines and apps to your local repository",
Long: `Use the pipeline or app subcommand to fetch your pipelines and apps to your local repository`,
Run: func(cmd *cobra.Command, args []string) {
if pipelineName != "" && appName == "" {
fetchPipeline(pipelineName)
} else if pipelineName != "" && appName != "" {
ensureStageNameIsSet()
fetchPipeline(pipelineName)
fetchApp(appName, stageName, pipelineName)
} else {
fetchAllPipelines()
}
},
}
func init() {
rootCmd.AddCommand(fetchCmd)
fetchCmd.Flags().StringVarP(&pipelineName, "pipeline", "p", "", "Name of the pipeline")
fetchCmd.Flags().StringVarP(&stageName, "stage", "s", "", "Name of the stage [test|stage|production]")
fetchCmd.Flags().StringVarP(&appName, "app", "a", "", "Name of the app")
}
func fetchPipeline(pipelineName string) {
confirmation := promptLine("Do you want to fetch the pipeline '"+pipelineName+"'?", "[y,n]", "y")
if confirmation == "y" {
_, _ = cfmt.Println("{{Fetching pipeline}}::yellow " + pipelineName)
var pipeline kuberoApi.PipelineCRD
pipeline.APIVersion = "application.kubero.dev/v1alpha1"
pipeline.Kind = "KuberoPipeline"
pipeline.Spec.Name = pipelineName
pipeline.Metadata.Name = appName
p, pipelineErr := api.GetPipeline(pipelineName)
if pipelineErr != nil {
if p == nil {
_, _ = cfmt.Println("{{ERROR:}}::red Pipeline '" + pipelineName + "' not found ")
os.Exit(1)
}
if p.StatusCode() == 404 {
_, _ = cfmt.Println("{{ERROR:}}::red Pipeline '" + pipelineName + "' not found ")
os.Exit(1)
}
fmt.Println(pipelineErr)
os.Exit(1)
}
jsonUnmarshalErr := json.Unmarshal(p.Body(), &pipeline.Spec)
if jsonUnmarshalErr != nil {
fmt.Println(jsonUnmarshalErr)
return
}
writePipelineYaml(pipeline)
} else {
return
}
}
func fetchApp(appName string, stageName string, pipelineName string) {
confirmation := promptLine("Do you want to fetch the app '"+appName+"' from '"+pipelineName+"'?", "[y,n]", "y")
if confirmation == "y" {
_, _ = cfmt.Println("{{Fetching app}}::yellow " + appName + "")
} else {
_, _ = cfmt.Println("{{Aborted}}::red")
return
}
var app kuberoApi.AppCRD
app.APIVersion = "application.kubero.dev/v1alpha1"
app.Kind = "KuberoApp"
app.Spec.Pipeline = pipelineName
app.Spec.Phase = stageName
app.Spec.Name = appName
app.Metadata.Name = appName
a, appErr := api.GetApp(pipelineName, stageName, appName)
if appErr != nil {
if a == nil {
_, _ = cfmt.Println("{{ERROR:}}::red App '" + appName + "' not found ")
os.Exit(1)
}
if a.StatusCode() == 404 {
_, _ = cfmt.Println("{{ERROR:}}::red App '" + appName + "' not found ")
os.Exit(1)
}
fmt.Println(appErr)
os.Exit(1)
}
jsonUnmarshalErr := json.Unmarshal(a.Body(), &app)
if jsonUnmarshalErr != nil {
fmt.Println(jsonUnmarshalErr)
return
}
writeAppYaml(app)
}
func fetchAllPipelines() {
confirmation := promptLine("Are you sure you want to fetch all pipelines?", "[y,n]", "n")
if confirmation == "y" {
_, _ = cfmt.Println("{{Fetching all pipelines}}::yellow")
} else {
_, _ = cfmt.Println("{{Aborted}}::red")
return
}
}
07070100000019000081A400000000000000000000000167BEEE05000004A3000000000000000000000000000000000000002B00000000kubero-cli-2.4.7/cmd/kuberoCli/fetchApp.gopackage kuberoCli
/*
Copyright © 2023 NAME HERE <EMAIL ADDRESS>
*/
import (
"os"
"github.com/i582/cfmt/cmd/cfmt"
"github.com/spf13/cobra"
)
// appCmd represents the app command
var fetchAppCmd = &cobra.Command{
Use: "app",
Short: "Fetch an app",
Long: `Fetch an app`,
Run: func(cmd *cobra.Command, args []string) {
pipelinesList := getAllRemotePipelines()
if len(pipelinesList) == 0 {
_, _ = cfmt.Println("\n{{ERROR:}}::red No pipelines found")
os.Exit(1)
}
ensurePipelineIsSet(pipelinesList)
ensureStageNameIsSet()
fetchPipeline(pipelineName)
appsList := getAllRemoteApps()
if len(appsList) == 0 {
_, _ = cfmt.Println("\n{{ERROR:}}::red No apps found in pipeline '" + pipelineName + "'")
os.Exit(1)
}
ensureAppNameIsSelected(appsList)
ensureAppNameIsSet()
fetchApp(appName, stageName, pipelineName)
},
}
func init() {
fetchCmd.AddCommand(fetchAppCmd)
fetchAppCmd.Flags().StringVarP(&pipelineName, "pipeline", "p", "", "Name of the pipeline")
fetchAppCmd.Flags().StringVarP(&stageName, "stage", "s", "", "Name of the stage [test|stage|production]")
fetchAppCmd.Flags().StringVarP(&appName, "app", "a", "", "Name of the app")
}
0707010000001A000081A400000000000000000000000167BEEE050000026B000000000000000000000000000000000000003000000000kubero-cli-2.4.7/cmd/kuberoCli/fetchPipeline.gopackage kuberoCli
/*
Copyright © 2023 NAME HERE <EMAIL ADDRESS>
*/
import (
"github.com/spf13/cobra"
)
// pipelineCmd represents the pipeline command
var fetchPipelineCmd = &cobra.Command{
Use: "pipeline",
Aliases: []string{"pl"},
Short: "Fetch a pipeline",
Long: `Fetch a pipeline`,
Run: func(cmd *cobra.Command, args []string) {
pipelinesList := getAllRemotePipelines()
ensurePipelineIsSet(pipelinesList)
fetchPipeline(pipelineName)
},
}
func init() {
fetchCmd.AddCommand(fetchPipelineCmd)
fetchPipelineCmd.Flags().StringVarP(&pipelineName, "pipeline", "p", "", "Name of the pipeline")
}
0707010000001B000081A400000000000000000000000167BEEE050000A10A000000000000000000000000000000000000002A00000000kubero-cli-2.4.7/cmd/kuberoCli/install.gopackage kuberoCli
import (
"bytes"
"encoding/base64"
"fmt"
"log"
"math/rand"
"os"
"os/exec"
"strings"
"time"
"encoding/json"
"github.com/go-resty/resty/v2"
"github.com/i582/cfmt/cmd/cfmt"
"github.com/leaanthony/spinner"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"golang.org/x/crypto/bcrypt"
"gopkg.in/yaml.v3"
"k8s.io/client-go/tools/clientcmd"
)
// installCmd represents the install command
var installCmd = &cobra.Command{
Use: "install",
Short: "Create a Kubernetes cluster and install all required components for kubero",
Long: `This command will create a kubernetes cluster and install all required components
for kubero on any kubernetes cluster.
required binaries:
- kubectl
- kind (optional)`,
Run: func(cmd *cobra.Command, args []string) {
rand.New(rand.NewSource(time.Now().UnixNano()))
checkAllBinaries()
switch argComponent {
case "metrics":
installMetrics()
return
case "certManager":
installCertManager()
return
case "olm":
installOLM()
return
case "kubero-operator":
installKuberoOperator()
return
case "kubero-ui":
installKuberoUi()
return
case "ingress":
installIngress()
return
case "monitoring":
installMonitoring()
return
case "kubernetes":
installKubernetes()
checkCluster()
return
case "":
printInstallSteps()
installKubernetes() // 1
checkCluster() //
installOLM() // 2
installKuberoOperator() // 3
installIngress() // 4
installMetrics() // 5
installCertManager() // 6
installMonitoring() // 7
installKuberoUi() // 8
writeCLIConfig() // 9
printDNSinfo()
finalMessage()
return
default:
return
}
},
}
var argAdminPassword string
var argAdminUser string
var argDomain string
var argApiToken string
var argPort string
var argPortSecure string
var clusterType string
var argComponent string
var installOlm bool
var monitoringInstalled bool
var ingressControllerVersion = "v1.10.0" // https://github.com/kubernetes/ingress-nginx/tags -> controller-v1.5.1
// var clusterTypeSelection = "[scaleway,linode,gke,digitalocean,kind]"
var clusterTypeList = []string{"kind", "linode", "scaleway", "gke", "digitalocean"}
func init() {
installCmd.Flags().StringVarP(&argComponent, "component", "c", "", "install component (kubernetes,olm,ingress,metrics,certManager,kubero-operator,monitoring,kubero-ui)")
installCmd.Flags().StringVarP(&argAdminUser, "user", "u", "", "Admin username for the kubero UI")
installCmd.Flags().StringVarP(&argAdminPassword, "user-password", "U", "", "Password for the admin user")
installCmd.Flags().StringVarP(&argApiToken, "apiToken", "a", "", "API token for the admin user")
installCmd.Flags().StringVarP(&argPort, "port", "p", "", "Kubero UI HTTP port")
installCmd.Flags().StringVarP(&argPortSecure, "securePort", "P", "", "Kubero UI HTTPS port")
installCmd.Flags().StringVarP(&argDomain, "domain", "d", "", "Domain name for the kubero UI")
rootCmd.AddCommand(installCmd)
installOlm = false
monitoringInstalled = false
}
func checkAllBinaries() {
_, _ = cfmt.Println("\n Check for required binaries")
if !checkBinary("kubectl") {
_, _ = cfmt.Println("{{✗ kubectl is not installed}}::red")
} else {
_, _ = cfmt.Println("{{✓ kubectl is installed}}::lightGreen")
}
if !checkBinary("kind") {
_, _ = cfmt.Println("{{⚠ kind is not installed}}::yellow (only required if you want to install a local kind cluster)")
} else {
_, _ = cfmt.Println("{{✓ kind is installed}}::lightGreen")
}
if !checkBinary("gcloud") {
_, _ = cfmt.Println("{{⚠ gcloud is not installed}}::yellow (only required if you want to install a GKE cluster)")
} else {
_, _ = cfmt.Println("{{✓ gcloud is installed}}::lightGreen")
}
}
func printInstallSteps() {
_, _ = cfmt.Print(`
Steps to install kubero:
1. Create a kubernetes cluster {{(optional)}}::gray
2. Install the OLM {{(optional)}}::gray
3. Install the kubero operator {{(required)}}::gray
4. Install the ingress controller {{(required)}}::gray
5. Install the metrics server {{(optional, but recommended)}}::gray
6. Install the cert-manager {{(optional)}}::gray
7. Install the monitoring stack {{(optional, but recommended)}}::gray
8. Install the kubero UI {{(optional, but highly recommended)}}::gray
9. Write the kubero CLI config
`)
}
func checkBinary(binary string) bool {
_, err := exec.LookPath(binary)
return err == nil
}
func installKubernetes() {
kubernetesInstall := promptLine("1) Create a kubernetes cluster", "[y,n]", "y")
if kubernetesInstall != "y" {
return
}
clusterType = selectFromList("Select a Kubernetes provider", clusterTypeList, "")
switch clusterType {
case "scaleway":
installScaleway()
case "linode":
installLinode()
case "gke":
installGKE()
case "digitalocean":
installDigitalOcean()
case "kind":
installKind()
default:
_, _ = cfmt.Println("{{✗ Unknown cluster type}}::red")
os.Exit(1)
}
}
func tellAChucknorrisJoke() {
jokesApi := resty.New().
SetHeader("Accept", "application/json").
SetHeader("Content-Type", "application/json").
SetHeader("User-Agent", "kubero-cli/"+kuberoCliVersion).
SetBaseURL("https://api.chucknorris.io/jokes/random")
joke, _ := jokesApi.R().Get("?category=dev")
var jokeResponse JokeResponse
_ = json.Unmarshal(joke.Body(), &jokeResponse)
_, _ = cfmt.Println("\r{{ " + jokeResponse.Value + " }}::gray")
}
func mergeKubeconfig(kubeconfig []byte) error {
newDefaultPathOptions := clientcmd.NewDefaultPathOptions()
config1, _ := newDefaultPathOptions.GetStartingConfig()
config2, err := clientcmd.Load(kubeconfig)
if err != nil {
return err
}
// append the second config to the first
for k, v := range config2.Clusters {
config1.Clusters[k] = v
}
for k, v := range config2.AuthInfos {
config1.AuthInfos[k] = v
}
for k, v := range config2.Contexts {
config1.Contexts[k] = v
}
config1.CurrentContext = config2.CurrentContext
_ = clientcmd.ModifyConfig(clientcmd.DefaultClientConfig.ConfigAccess(), *config1, true)
return nil
}
func checkCluster() {
var outb, errb bytes.Buffer
clusterInfo := exec.Command("kubectl", "cluster-info")
clusterInfo.Stdout = &outb
clusterInfo.Stderr = &errb
err := clusterInfo.Run()
if err != nil {
fmt.Println(errb.String())
fmt.Println(outb.String())
log.Fatal("command failed : kubectl cluster-info")
}
fmt.Println(outb.String())
out, _ := exec.Command("kubectl", "config", "get-contexts").Output()
fmt.Println(string(out))
clusterSelect := promptLine("Is the CURRENT cluster the one you wish to install Kubero?", "[y,n]", "y")
if clusterSelect == "n" {
os.Exit(0)
}
}
func installOLM() {
openshiftInstalled, _ := exec.Command("kubectl", "get", "deployment", "olm-operator", "-n", "openshift-operator-lifecycle-manager").Output()
if len(openshiftInstalled) > 0 {
_, _ = cfmt.Println("{{✓ OLM is already installed}}::lightGreen")
return
}
//namespace := promptLine("Install OLM in which namespace?", "[openshift-operator-lifecycle-manager,olm]", "olm")
namespace := "olm"
olmInstalled, _ := exec.Command("kubectl", "get", "deployment", "olm-operator", "-n", namespace).Output()
if len(olmInstalled) > 0 {
_, _ = cfmt.Println("{{✓ OLM is already installed}}::lightGreen")
return
}
olmInstall := promptLine("2) Install OLM", "[y,n]", "n")
if olmInstall != "y" {
installOlm = false
return
} else {
installOlm = true
}
olmVersionList := getGithubVersionList("operator-framework/operator-lifecycle-manager", 10)
olmRelease := selectFromList("Select OLM version", olmVersionList, "")
olmURL := "https://github.com/operator-framework/operator-lifecycle-manager/releases/download/" + olmRelease
olmSpinner := spinner.New("Install OLM")
olmCRDInstalled, _ := exec.Command("kubectl", "get", "crd", "subscriptions.operators.coreos.com").Output()
if len(olmCRDInstalled) > 0 {
_, _ = cfmt.Println("{{✓ OLM CRD's already installed}}::lightGreen")
} else {
_, _ = cfmt.Println(" run command : kubectl create -f " + olmURL + "/olm.yaml")
olmSpinner.Start("Installing OLM CRDs")
_, olmCRDErr := exec.Command("kubectl", "create", "-f", olmURL+"/crds.yaml").Output()
if olmCRDErr != nil {
fmt.Println("")
olmSpinner.Error("OLM CRD installation failed. Try running this command manually: kubectl create -f " + olmURL + "/crds.yaml")
log.Fatal(olmCRDErr)
} else {
olmSpinner.Success("OLM CRDs installed successfully")
}
}
_, _ = cfmt.Println(" run command : kubectl create -f " + olmURL + "/olm.yaml")
olmSpinner.Start("Install OLM")
_, olmOLMErr := exec.Command("kubectl", "create", "-f", olmURL+"/olm.yaml").Output()
if olmOLMErr != nil {
fmt.Println("")
olmSpinner.Error("Failed to run command. Try running this command manually: kubectl create -f " + olmURL + "/olm.yaml")
log.Fatal(olmOLMErr)
}
olmSpinner.Success("OLM installed successfully")
olmWaitSpinner := spinner.New("Wait for OLM to be ready")
_, _ = cfmt.Println(" run command : kubectl wait --for=condition=available deployment/olm-operator -n " + namespace + " --timeout=180s")
olmWaitSpinner.Start("Wait for OLM to be ready")
_, olmWaitErr := exec.Command("kubectl", "wait", "--for=condition=available", "deployment/olm-operator", "-n", namespace, "--timeout=180s").Output()
if olmWaitErr != nil {
olmWaitSpinner.Error("Failed to run command. Try running this command manually: kubectl wait --for=condition=available deployment/olm-operator -n " + namespace + " --timeout=180s")
log.Fatal(olmWaitErr)
}
olmWaitSpinner.Success("OLM is ready")
olmWaitCatalogSpinner := spinner.New("Wait for OLM Catalog to be ready")
_, _ = cfmt.Println(" run command : kubectl wait --for=condition=available deployment/catalog-operator -n " + namespace + " --timeout=180s")
olmWaitCatalogSpinner.Start("Wait for OLM Catalog to be ready")
_, olmWaitCatalogErr := exec.Command("kubectl", "wait", "--for=condition=available", "deployment/catalog-operator", "-n", namespace, "--timeout=180s").Output()
if olmWaitCatalogErr != nil {
olmWaitCatalogSpinner.Error("Failed to run command. Try running this command manually: kubectl wait --for=condition=available deployment/catalog-operator -n " + namespace + " --timeout=180s")
log.Fatal(olmWaitCatalogErr)
}
olmWaitCatalogSpinner.Success("OLM Catalog is ready")
}
func installMetrics() {
installed, _ := exec.Command("kubectl", "get", "deployments.apps", "metrics-server", "-n", "kube-system").Output()
if len(installed) > 0 {
_, _ = cfmt.Println("{{✓ Metrics is already enabled}}::lightGreen")
return
}
install := promptLine("5) Install Kubernetes internal metrics service (required for HPA, Horizontal Pod Autoscaling)", "[y,n]", "y")
if install != "y" {
return
}
//components := "https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml"
components := "https://raw.githubusercontent.com/kubero-dev/kubero-operator/main/deploy/metrics-server.yaml"
_, installErr := exec.Command("kubectl", "apply", "-f", components).Output()
if installErr != nil {
fmt.Println("failed to install metrics server")
log.Fatal(installErr)
}
_, _ = cfmt.Println("{{✓ Metrics server installed}}::lightGreen")
}
func installIngress() {
ingressInstalled, _ := exec.Command("kubectl", "get", "ns", "ingress-nginx").Output()
if len(ingressInstalled) > 0 {
_, _ = cfmt.Println("{{✓ Ingress is already installed}}::lightGreen")
return
}
ingressInstall := promptLine("4) Install Ingress", "[y,n]", "y")
if ingressInstall != "y" {
return
} else {
if clusterType == "" {
clusterType = selectFromList("Which cluster type have you installed?", clusterTypeList, "")
}
prefill := "baremetal"
switch clusterType {
case "kind":
prefill = "kind"
case "linode":
prefill = "cloud"
case "gke":
prefill = "cloud"
case "scaleway":
prefill = "scw"
case "digitalocean":
prefill = "do"
}
ingressProviderList := []string{"kind", "aws", "baremetal", "cloud", "do", "exoscale", "scw"}
ingressProvider := selectFromList("Provider [kind, aws, baremetal, cloud(Azure,Google,Oracle,Linode), do(digital ocean), exoscale, scw(scaleway)]", ingressProviderList, prefill)
// ingressController version can bot be loaded from GitHub api, since the return is alphabetic
ingressSpinner := spinner.New("Install Ingress")
URL := "https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-" + ingressControllerVersion + "/deploy/static/provider/" + ingressProvider + "/deploy.yaml"
_, _ = cfmt.Println(" run command : kubectl apply -f " + URL)
ingressSpinner.Start("Install Ingress")
_, ingressErr := exec.Command("kubectl", "apply", "-f", URL).Output()
if ingressErr != nil {
ingressSpinner.Error("Failed to run command. Try running this command manually: kubectl apply -f " + URL)
log.Fatal(ingressErr)
}
ingressSpinner.Success("Ingress installed successfully")
}
}
func installKuberoOperator() {
_, _ = cfmt.Println("\n {{3) Install Kubero Operator}}::bold")
kuberoInstalled, _ := exec.Command("kubectl", "get", "operator", "kubero-operator.operators").Output()
if len(kuberoInstalled) > 0 {
_, _ = cfmt.Println("{{✓ Kubero Operator is already installed}}::lightGreen")
return
}
if installOlm {
installKuberoOLMOperator()
} else {
installKuberoOperatorSlim()
}
}
func installKuberoOLMOperator() {
kuberoSpinner := spinner.New("Install Kubero Operator")
_, _ = cfmt.Println(" run command : kubectl apply -f https://operatorhub.io/install/kubero-operator.yaml")
kuberoSpinner.Start("Install Kubero Operator")
_, kuberoErr := exec.Command("kubectl", "apply", "-f", "https://operatorhub.io/install/kubero-operator.yaml").Output()
if kuberoErr != nil {
fmt.Println("")
kuberoSpinner.Error("Failed to run command to install the Operator. Try running this command manually: kubectl apply -f https://operatorhub.io/install/kubero-operator.yaml")
log.Fatal(kuberoErr)
}
kuberoSpinner.UpdateMessage("Wait for Kubero Operator to be ready")
var kuberoWait []byte
for len(kuberoWait) == 0 {
// kubectl api-resources --api-group=application.kubero.dev --no-headers=true
kuberoWait, _ = exec.Command("kubectl", "api-resources", "--api-group=application.kubero.dev", "--no-headers=true").Output()
time.Sleep(1 * time.Second)
}
kuberoSpinner.Success("Kubero Operator installed successfully")
}
func installKuberoOperatorSlim() {
kuberoSpinner := spinner.New("Install Kubero Operator")
_, _ = cfmt.Println(" run command : kubectl apply -f https://raw.githubusercontent.com/kubero-dev/kubero-operator/main/deploy/operator.yaml")
kuberoSpinner.Start("Install Kubero Operator")
_, kuberoErr := exec.Command("kubectl", "apply", "-f", "https://raw.githubusercontent.com/kubero-dev/kubero-operator/main/deploy/operator.yaml").Output()
if kuberoErr != nil {
fmt.Println("")
kuberoSpinner.Error("Failed to run command to install the Operator. Try running this command manually: kubectl apply -f https://raw.githubusercontent.com/kubero-dev/kubero-operator/main/deploy/operator.yaml")
log.Fatal(kuberoErr)
}
kuberoSpinner.UpdateMessage("Wait for Kubero Operator CRD's to be installed")
var kuberoWait []byte
for len(kuberoWait) == 0 {
// kubectl api-resources --api-group=application.kubero.dev --no-headers=true
kuberoWait, _ = exec.Command("kubectl", "api-resources", "--api-group=application.kubero.dev", "--no-headers=true").Output()
time.Sleep(1 * time.Second)
}
kuberoSpinner.UpdateMessage("Kubero Operator CRD's installed")
time.Sleep(5 * time.Second)
// kubectl wait --for=condition=available deployment/kubero -n kubero --timeout=180s
kuberoSpinner.UpdateMessage("Wait for Kubero Operator to be ready")
_, olmWaitErr := exec.Command("kubectl", "wait", "--for=condition=available", "deployment/kubero-operator-controller-manager", "-n", "kubero-operator-system", "--timeout=300s").Output()
if olmWaitErr != nil {
kuberoSpinner.Error("Failed to wait for Kubero UI to become ready")
log.Fatal(olmWaitErr)
}
kuberoSpinner.Success("Kubero Operator installed successfully")
}
func createNamespace(namespace string) {
kuberoNSInstalled, _ := exec.Command("kubectl", "get", "ns", namespace).Output()
if len(kuberoNSInstalled) > 0 {
_, _ = cfmt.Printf("{{✓ Namespace %s exists}}::lightGreen\n", namespace)
} else {
_, kuberoNSErr := exec.Command("kubectl", "create", "namespace", namespace).Output()
if kuberoNSErr != nil {
fmt.Println("Failed to run command to create the namespace. Try running this command manually: kubectl create namespace " + namespace)
log.Fatal(kuberoNSErr)
} else {
_, _ = cfmt.Printf("{{✓ Namespace %s created}}::lightGreen\n", namespace)
}
}
}
func installKuberoUi() {
ingressInstall := promptLine("9) Install Kubero UI", "[y,n]", "y")
if ingressInstall != "y" {
return
}
createNamespace("kubero")
kuberoSecretInstalled, _ := exec.Command("kubectl", "get", "secret", "kubero-secrets", "-n", "kubero").Output()
if len(kuberoSecretInstalled) > 0 {
_, _ = cfmt.Println("{{✓ Kubero Secret exists}}::lightGreen")
} else {
webhookSecret := promptLine("Random string for your webhook secret", "", generateRandomString(20, ""))
sessionKey := promptLine("Random string for your session key", "", generateRandomString(20, ""))
if argAdminUser == "" {
argAdminUser = promptLine("Admin User", "", "admin")
}
if argAdminPassword == "" {
argAdminPassword = promptLine("Admin Password", "", generateRandomString(12, ""))
}
if argApiToken == "" {
argApiToken = promptLine("Random string for admin API token", "", generateRandomString(20, ""))
}
var userDB []User
userDB = append(userDB, User{Username: argAdminUser, Password: argAdminPassword, Insecure: true, ApiToken: argApiToken})
userDBjson, _ := json.Marshal(userDB)
userDBencoded := base64.StdEncoding.EncodeToString(userDBjson)
createSecretCommand := exec.Command("kubectl", "create", "secret", "generic", "kubero-secrets",
"--from-literal=KUBERO_WEBHOOK_SECRET="+webhookSecret,
"--from-literal=KUBERO_SESSION_KEY="+sessionKey,
"--from-literal=KUBERO_USERS="+userDBencoded,
)
githubConfigure := promptLine("Configure Github", "[y,n]", "y")
githubPersonalAccessToken := ""
if githubConfigure == "y" {
githubPersonalAccessToken = promptLine("Github personal access token", "", "")
createSecretCommand.Args = append(createSecretCommand.Args, "--from-literal=GITHUB_PERSONAL_ACCESS_TOKEN="+githubPersonalAccessToken)
}
giteaConfigure := promptLine("Configure Gitea", "[y,n]", "n")
giteaPersonalAccessToken := ""
giteaBaseUrl := ""
if giteaConfigure == "y" {
giteaPersonalAccessToken = promptLine("Gitea personal access token", "", "")
giteaBaseUrl = promptLine("Gitea URL", "http://localhost:3000", "")
createSecretCommand.Args = append(createSecretCommand.Args, "--from-literal=GITEA_PERSONAL_ACCESS_TOKEN="+giteaPersonalAccessToken)
createSecretCommand.Args = append(createSecretCommand.Args, "--from-literal=GITEA_BASEURL="+giteaBaseUrl)
}
gogsConfigure := promptLine("Configure Gogs", "[y,n]", "n")
gogsPersonalAccessToken := ""
gogsBaseUrl := ""
if gogsConfigure == "y" {
gogsPersonalAccessToken = promptLine("Gogs personal access token", "", "")
gogsBaseUrl = promptLine("Gogs URL", "http://localhost:3000", "")
createSecretCommand.Args = append(createSecretCommand.Args, "--from-literal=GOGS_PERSONAL_ACCESS_TOKEN="+gogsPersonalAccessToken)
createSecretCommand.Args = append(createSecretCommand.Args, "--from-literal=GOGS_BASEURL="+gogsBaseUrl)
}
gitlabConfigure := promptLine("Configure Gitlab", "[y,n]", "n")
gitlabPersonalAccessToken := ""
gitlabBaseUrl := ""
if gitlabConfigure == "y" {
gitlabPersonalAccessToken = promptLine("Gitlab personal access token", "", "")
gitlabBaseUrl = promptLine("Gitlab URL", "http://localhost:3080", "")
createSecretCommand.Args = append(createSecretCommand.Args, "--from-literal=GITLAB_PERSONAL_ACCESS_TOKEN="+gitlabPersonalAccessToken)
createSecretCommand.Args = append(createSecretCommand.Args, "--from-literal=GITLAB_BASEURL="+gitlabBaseUrl)
}
bitbucketConfigure := promptLine("Configure Bitbucket", "[y,n]", "n")
bitbucketUsername := ""
bitbucketAppPassword := ""
if bitbucketConfigure == "y" {
bitbucketUsername = promptLine("Bitbucket Username", "", "")
bitbucketAppPassword = promptLine("Bitbucket App Password", "", "")
createSecretCommand.Args = append(createSecretCommand.Args, "--from-literal=BITBUCKET_USERNAME="+bitbucketUsername)
createSecretCommand.Args = append(createSecretCommand.Args, "--from-literal=BITBUCKET_APP_PASSWORD="+bitbucketAppPassword)
}
createSecretCommand.Args = append(createSecretCommand.Args, "-n", "kubero")
_, kuberoErr := createSecretCommand.Output()
if kuberoErr != nil {
_, _ = cfmt.Println("{{✗ Failed to run command to create the secrets.}}::red")
log.Fatal(kuberoErr)
} else {
_, _ = cfmt.Println("{{✓ Kubero Secret created}}::lightGreen")
}
}
kuberoUIInstalled, _ := exec.Command("kubectl", "get", "kuberoes.application.kubero.dev", "-n", "kubero").Output()
if len(kuberoUIInstalled) > 0 {
_, _ = cfmt.Println("{{✓ Kubero UI already installed}}::lightGreen")
} else {
installer := resty.New()
installer.SetBaseURL("https://raw.githubusercontent.com")
kf, _ := installer.R().Get("kubero-dev/kubero-operator/main/config/samples/application_v1alpha1_kubero.yaml")
var kuberoUIConfig KuberoUIConfig
_ = yaml.Unmarshal(kf.Body(), &kuberoUIConfig)
if argDomain == "" {
argDomain = promptLine("Kubero UI Domain", "", "kubero.localhost")
}
kuberoUIConfig.Spec.Ingress.Hosts[0].Host = argDomain
// Warn if domain contains kubero.net
webhookDomain := argDomain
if strings.Contains(argDomain, "kubero.localhost") {
_, _ = cfmt.Println("{{⚠ kubero.localhost might not be reachable won't get any Webhooks. GitHub will fail to connect your pipeline. }}::yellow")
webhookDomain = "webhook.local.kubero.net"
}
webhookURL := promptLine("URL to which the webhooks should be sent (localhost fails with GitHub)", "", "https://"+webhookDomain+"/api/repo/webhooks")
kuberoUIConfig.Spec.Kubero.WebhookURL = webhookURL
kuberoUISsl := promptLine("Enable SSL for the Kubero UI", "[y/n]", "y")
if kuberoUISsl == "y" {
clusterIssuer := promptLine("Kubero UI ClusterIssuer", "", "letsencrypt-prod")
kuberoUIConfig.Spec.Ingress.Annotations.KubernetesIoIngressClass = clusterIssuer
kuberoUIConfig.Spec.Ingress.Annotations.KubernetesIoTlsAcme = "true"
kuberoUIConfig.Spec.Ingress.TLS = []KuberoUITls{
{
Hosts: []string{argDomain},
SecretName: "kubero-tls",
},
}
}
kuberoUIRegistry := promptLine("Enable BuildPipeline for Kubero (BETA)", "[y/n]", "n")
if kuberoUIRegistry == "y" {
kuberoUIConfig.Spec.Registry.Enabled = true
kuberoUICreateRegistry := promptLine("Create a local Registry for Kubero", "[y/n]", "n")
if kuberoUICreateRegistry == "y" {
kuberoUIConfig.Spec.Registry.Create = true
kuberoUIRegistryStorage := promptLine("Registry storage size", "", "10Gi")
kuberoUIConfig.Spec.Registry.Storage = kuberoUIRegistryStorage
storageClassList := getAvailableStorageClasses()
kuberoUIRegistryStorageClassName := selectFromList("Registry storage class", storageClassList, "")
kuberoUIConfig.Spec.Registry.StorageClassName = kuberoUIRegistryStorageClassName
}
kuberoUIRegistryHost := promptLine("Registry", "[registry.kubero.mydomain.com]", "")
kuberoUIConfig.Spec.Registry.Host = kuberoUIRegistryHost
kuberoUIRegistrySubPath := promptLine("SubPath (optional) ", "[example/foo/bar]", "")
kuberoUIConfig.Spec.Registry.SubPath = kuberoUIRegistrySubPath
kuberoUIConfig.Spec.Registry.Port = 443
kuberoUIRegistryUsername := promptLine("Registry username", "", "admin")
kuberoUIConfig.Spec.Registry.Account.Username = kuberoUIRegistryUsername
kuberoUIRegistryPassword := promptLine("Registry password", "", generateRandomString(12, ""))
kuberoUIConfig.Spec.Registry.Account.Password = kuberoUIRegistryPassword
kuberoUIRegistryPasswordBytes, _ := bcrypt.GenerateFromPassword([]byte(kuberoUIRegistryPassword), 14)
kuberoUIConfig.Spec.Registry.Account.Hash = string(kuberoUIRegistryPasswordBytes)
}
kuberoUIAudit := promptLine("Enable Audit Logging", "[y/n]", "n")
if kuberoUIAudit == "y" {
kuberoUIConfig.Spec.Kubero.AuditLogs.Enabled = true
storageClassList := getAvailableStorageClasses()
kuberoUIRegistryStorageClassName := selectFromList("AuditLogs storage class", storageClassList, "")
kuberoUIConfig.Spec.Kubero.AuditLogs.StorageClassName = kuberoUIRegistryStorageClassName
}
if monitoringInstalled {
kuberoUIConfig.Spec.Prometheus.Enabled = true
kuberoUIConfig.Spec.Prometheus.Endpoint = promptLine("Prometheus URL", "", "http://kubero-prometheus-server")
} else {
kuberoUIConfig.Spec.Prometheus.Enabled = false
}
kuberoUIConsole := promptLine("Enable Console Access to running containers", "[y/n]", "y")
if kuberoUIConsole == "y" {
kuberoUIConfig.Spec.Kubero.Config.Kubero.Console.Enabled = true
}
//kuberoUIConfig.Spec.Image.Tag = "v2.0.0-rc.8"
if clusterType == "" {
clusterType = selectFromList("Which cluster type have you installed?", clusterTypeList, "")
}
if clusterType == "linode" ||
clusterType == "digitalocean" ||
clusterType == "scaleway" ||
clusterType == "gke" {
kuberoUIConfig.Spec.Ingress.ClassName = "nginx"
}
kuberoUIYaml, _ := yaml.Marshal(kuberoUIConfig)
kuberoUIErr := os.WriteFile("kuberoUI.yaml", kuberoUIYaml, 0644)
if kuberoUIErr != nil {
fmt.Println(kuberoUIErr)
return
}
_, olmInstallErr := exec.Command("kubectl", "apply", "-f", "kuberoUI.yaml", "-n", "kubero").Output()
if olmInstallErr != nil {
_, _ = cfmt.Println("{{✗ Failed to run command to install Kubero UI. Try running this command manually: kubectl apply -f kuberoUI.yaml -n kubero}}::red")
return
} else {
e := os.Remove("kuberoUI.yaml")
if e != nil {
log.Fatal(e)
}
_, _ = cfmt.Println("{{✓ Kubero UI installed}}::lightGreen")
}
kuberoUISpinner := spinner.New("Wait for Kubero UI to be created")
kuberoUISpinner.Start("Wait for Kubero UI to be created")
var kuberoWait []byte
for len(kuberoWait) == 0 {
// kubectl get --ignore-not-found deployment kubero
kuberoWait, _ = exec.Command("kubectl", "get", "--ignore-not-found", "deployment", "kubero", "-n", "kubero").Output()
kuberoUISpinner.UpdateMessage("Waiting for Kubero UI to be created")
time.Sleep(1 * time.Second)
}
kuberoUISpinner.UpdateMessage("Waiting for Kubero UI to be ready")
time.Sleep(5 * time.Second)
// kubectl wait --for=condition=available deployment/kubero -n kubero --timeout=180s
_, olmWaitErr := exec.Command("kubectl", "wait", "--for=condition=available", "deployment/kubero", "-n", "kubero", "--timeout=300s").Output()
if olmWaitErr != nil {
kuberoUISpinner.Error("Failed to wait for Kubero UI to become ready")
log.Fatal(olmWaitErr)
}
kuberoUISpinner.Success("Kubero UI is ready")
}
}
func installMonitoring() {
if promptLine("7) Enable long-term metrics", "[y/n]", "y") == "y" {
monitoringInstalled = true
} else {
monitoringInstalled = false
return
}
createNamespace("kubero")
spinnerObj := spinner.New("enable metrics")
if promptLine("7.1) Create local Prometheus instance", "[y/n]", "y") == "y" {
URL := "https://raw.githubusercontent.com/kubero-dev/kubero-operator/main/config/samples/application_v1alpha1_kuberoprometheus.yaml"
_, _ = cfmt.Println(" run command : kubectl apply -n kubero -f " + URL)
spinnerObj.Start("Installing Prometheus")
_, ingressErr := exec.Command("kubectl", "apply", "-n", "kubero", "-f", URL).Output()
if ingressErr != nil {
spinnerObj.Error("Failed to run command. Try running this command manually: kubectl apply -f " + URL)
log.Fatal(ingressErr)
}
/*
spinner.UpdateMessage("Waiting for Prometheus to be ready")
time.Sleep(5 * time.Second)
// kubectl wait --for=condition=available deployment/kubero -n kubero --timeout=180s
_, olmWaitErr := exec.Command("kubectl", "wait", "--for=condition=available", "deployment/kubero-prometheus-server", "-n", "kubero", "--timeout=300s").Output()
if olmWaitErr != nil {
spinner.Error("Failed to wait for Prometheus to become ready")
log.Fatal(olmWaitErr)
}
*/
spinnerObj.Success("Prometheus installed successfully")
}
if promptLine("7.2) Enable KubeMetrics", "[y/n]", "y") == "y" {
_, _ = cfmt.Println(" run command : kubectl patch kuberoes kubero -n kubero --type=merge")
spinnerObj.Start("Enabling Metrics")
patch := `{
"spec": {
"prometheus": {
"kube-state-metrics": {
"enabled": true
}
}
}
}`
_, patchResult := exec.Command("kubectl", "patch", "kuberoprometheuses", "kubero-prometheus", "-n", "kubero", "--type=merge", "-p", patch).Output()
if patchResult != nil {
spinnerObj.Error("Failed to patch the kubero prometheus CRD to enable kube metrics", patchResult.Error(), patch)
}
spinnerObj.Success("Metrics enabled successfully")
}
patch := `{
"spec": {
"template": {
"metadata": {
"annotations": {
"prometheus.io/port": "10254",
"prometheus.io/scrape": "true"
}
},
"spec": {
"containers": [
{
"name": "controller",
"ports": [
{
"containerPort": 10254,
"name": "prometheus",
"protocol": "TCP"
}
],
"args": [
"/nginx-ingress-controller",
"--election-id=ingress-nginx-leader",
"--controller-class=k8s.io/ingress-nginx",
"--ingress-class=nginx",
"--configmap=$(POD_NAMESPACE)/ingress-nginx-controller",
"--validating-webhook=:8443",
"--validating-webhook-certificate=/usr/local/certificates/cert",
"--validating-webhook-key=/usr/local/certificates/key",
"--watch-ingress-without-class=true",
"--enable-metrics=true",
"--publish-status-address=localhost"
]
}
]
}
}
}
}`
_, ingressPatch := exec.Command("kubectl", "patch", "deployments.apps", "ingress-nginx-controller", "-n", "ingress-nginx", "-p", patch).Output()
if ingressPatch != nil {
_, _ = cfmt.Println("{{✗ Failed to patch the ingress controller. }}::red\nHere is a detailed information how to do it manually: https://github.com/kubernetes/ingress-nginx/blob/main/docs/user-guide/monitoring.md")
//log.Fatal(ingressPatch)
}
patch = `{
"spec": {
"ports": [
{
"name": "prometheus",
"nodePort": 31280,
"port": 10254,
"protocol": "TCP",
"targetPort": "prometheus"
}
]
}
}`
_, ingressPatch = exec.Command("kubectl", "patch", "svc", "ingress-nginx-controller", "-n", "ingress-nginx", "-p", patch).Output()
if ingressPatch != nil {
_, _ = cfmt.Println("{{✗ Failed to patch the ingress controller service. }}::red\nHere is a detailed information how to do it manually: https://github.com/kubernetes/ingress-nginx/blob/main/docs/user-guide/monitoring.md")
//log.Fatal(ingressPatch)
}
}
func installCertManager() {
install := promptLine("6) Install SSL CertManager", "[y,n]", "y")
if install != "y" {
return
}
if installOlm {
installOLMCertManager()
} else {
installCertManagerSlim()
}
}
func installCertManagerSlim() {
kuberoUIInstalled, _ := exec.Command("kubectl", "get", "crd", "certificates.cert-manager.io").Output()
if len(kuberoUIInstalled) > 0 {
_, _ = cfmt.Println("{{✓ CertManager already installed}}::lightGreen")
return
}
certManagerSpinner := spinner.New("Install Cert Manager")
//certManagerUrl := "https://github.com/cert-manager/cert-manager/releases/download/v1.11.0/cert-manager.yaml"
certManagerUrl := "https://github.com/cert-manager/cert-manager/releases/latest/download/cert-manager.yaml"
_, _ = cfmt.Println(" run command : kubectl create -f " + certManagerUrl)
certManagerSpinner.Start("Installing Cert Manager")
_, certManagerErr := exec.Command("kubectl", "create", "-f", certManagerUrl).Output()
if certManagerErr != nil {
certManagerSpinner.Error("Failed to run command. Try running this command manually: kubectl create -f " + certManagerUrl)
log.Fatal(certManagerErr)
}
certManagerSpinner.UpdateMessage("Waiting for Cert Manager to be ready")
time.Sleep(10 * time.Second)
_, certManagerWaitErr := exec.Command("kubectl", "wait", "--for=condition=available", "deployment/cert-manager-webhook", "-n", "cert-manager", "--timeout=180s", "-n", "cert-manager").Output()
if certManagerWaitErr != nil {
certManagerSpinner.Error("Failed to run command. Try running it manually: kubectl wait --for=condition=available deployment/cert-manager-webhook -n cert-manager --timeout=180s -n cert-manager")
log.Fatal(certManagerWaitErr)
}
certManagerSpinner.Success("Cert Manager installed")
installCertManagerClusterIssuer("cert-manager")
}
func installCertManagerClusterIssuer(namespace string) {
installer := resty.New()
installer.SetBaseURL("https://raw.githubusercontent.com")
kf, _ := installer.R().Get("kubero-dev/kubero-cli/main/templates/certManagerClusterIssuer.prod.yaml")
var certManagerClusterIssuer CertManagerClusterIssuer
_ = yaml.Unmarshal(kf.Body(), &certManagerClusterIssuer)
argCertManagerContact := promptLine("6.1) Letsencrypt ACME contact email", "", "noreply@yourdomain.com")
certManagerClusterIssuer.Spec.Acme.Email = argCertManagerContact
clusterIssuer := promptLine("6.2) ClusterIssuer Name", "", "letsencrypt-prod")
certManagerClusterIssuer.Metadata.Name = clusterIssuer
certManagerClusterIssuerYaml, _ := yaml.Marshal(certManagerClusterIssuer)
certManagerClusterIssuerYamlErr := os.WriteFile("kuberoCertManagerClusterIssuer.yaml", certManagerClusterIssuerYaml, 0644)
if certManagerClusterIssuerYamlErr != nil {
fmt.Println(certManagerClusterIssuerYamlErr)
return
}
_, certManagerClusterIssuerErr := exec.Command("kubectl", "apply", "-f", "kuberoCertManagerClusterIssuer.yaml", "-n", namespace).Output()
if certManagerClusterIssuerErr != nil {
_, _ = cfmt.Println("{{✗ Failed to create CertManager ClusterIssuer. Try running this command manually: kubectl apply -f kuberoCertManagerClusterIssuer.yaml -n cert-manager}}::red")
return
} else {
e := os.Remove("kuberoCertManagerClusterIssuer.yaml")
if e != nil {
log.Fatal(e)
}
_, _ = cfmt.Println("{{✓ Cert Manager Cluster Issuer created}}::lightGreen")
}
}
func installOLMCertManager() {
certManagerInstalled, _ := exec.Command("kubectl", "get", "deployment", "cert-manager-webhook", "-n", "operators").Output()
if len(certManagerInstalled) > 0 {
_, _ = cfmt.Println("{{✓ Cert Manager already installed}}::lightGreen")
return
}
certManagerSpinner := spinner.New("Install Cert Manager")
_, _ = cfmt.Println(" run command : kubectl create -f https://operatorhub.io/install/cert-manager.yaml")
certManagerSpinner.Start("Installing Cert Manager")
_, certManagerErr := exec.Command("kubectl", "create", "-f", "https://operatorhub.io/install/cert-manager.yaml").Output()
if certManagerErr != nil {
certManagerSpinner.Error("Failed to run command. Try running this command manually: kubectl create -f https://operatorhub.io/install/cert-manager.yaml")
log.Fatal(certManagerErr)
}
certManagerSpinner.Success("Cert Manager installed")
certManagerSpinner = spinner.New("Wait for Cert Manager to be ready")
certManagerSpinner.Start("installing Cert Manager")
_, _ = cfmt.Println("\r run command : kubectl wait --for=condition=available deployment/cert-manager-webhook -n cert-manager --timeout=180s -n operators")
_, _ = cfmt.Println("\r This might take a while. Time enough for a joke:")
for i := 0; i < 4; i++ {
tellAChucknorrisJoke()
time.Sleep(15 * time.Second)
}
_, certManagerWaitErr := exec.Command("kubectl", "wait", "--for=condition=available", "deployment/cert-manager-webhook", "-n", "cert-manager", "--timeout=180s", "-n", "operators").Output()
if certManagerWaitErr != nil {
certManagerSpinner.Error("Failed to run command. Try running it manually: kubectl wait --for=condition=available deployment/cert-manager-webhook -n cert-manager --timeout=180s -n operators")
log.Fatal(certManagerWaitErr)
}
certManagerSpinner.Success("Cert Manager is ready")
installCertManagerClusterIssuer("default")
}
func writeCLIConfig() {
ingressInstall := promptLine("10) Write the Kubero CLI config", "[y,n]", "n")
if ingressInstall != "y" {
return
}
//TODO consider using SSL here.
url := promptLine("Kubero Host address", "", "http://"+argDomain+":"+argPort)
viper.Set("api.url", url)
token := promptLine("Kubero Token", "", argApiToken)
viper.Set("api.token", token)
var config Config
if err := viper.Unmarshal(&config); err != nil {
fmt.Println(err)
return
}
fmt.Printf("%+v\n", config)
_ = viper.WriteConfig()
}
func printDNSinfo() {
ingressInstalled, err := exec.Command("kubectl", "get", "ingress", "-n", "kubero", "-o", "json").Output()
if err != nil {
_, _ = cfmt.Println("{{✗ Failed to fetch DNS information}}::red")
return
}
var kuberoIngress KuberoIngress
_ = json.Unmarshal(ingressInstalled, &kuberoIngress)
_, _ = cfmt.Println("{{⚠ make sure your DNS is pointing to your Kubernetes cluster}}::yellow")
//TODO this should be replaces by the default review app domain
if len(kuberoIngress.Items) > 0 &&
len(kuberoIngress.Items[0].Spec.Rules[0].Host) > 0 &&
len(kuberoIngress.Items[0].Status.LoadBalancer.Ingress) > 0 &&
len(kuberoIngress.Items[0].Status.LoadBalancer.Ingress[0].IP) > 0 {
_, _ = cfmt.Printf("{{ %s. IN A %s}}::lightBlue\n", kuberoIngress.Items[0].Spec.Rules[0].Host, kuberoIngress.Items[0].Status.LoadBalancer.Ingress[0].IP)
_, _ = cfmt.Printf("{{ *.review.example.com. IN A %s}}::lightBlue", kuberoIngress.Items[0].Status.LoadBalancer.Ingress[0].IP)
}
}
func finalMessage() {
_, _ = cfmt.Println(`
,--. ,--. ,--.
| .' /,--.,--.| |-. ,---. ,--.--. ,---.
| . ' | || || .-. '| .-. :| .--'| .-. |
| |\ \' '' '| '-' |\ --.| | ' '-' '
'--' '--' '----' '---' '----''--' '---'
Documentation:
https://docs.kubero.dev
`)
protocol := "https"
if argPort == "80" {
protocol = "http"
}
_, _ = cfmt.Println(`
Your Kubero UI :{{
URL : ` + protocol + "://" + argDomain + ":" + argPort + `
User: ` + argAdminUser + `
Pass: ` + argAdminPassword + `}}::lightBlue
`)
_, _ = cfmt.Println("\n\n {{Done - you can now login to your Kubero UI}}::lightGreen\n\n ")
}
func generateRandomString(length int, chars string) string {
if chars == "" {
chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!+?._-%"
}
var letterRunes = []rune(chars)
b := make([]rune, length)
rand.New(rand.NewSource(time.Now().UnixNano()))
for i := range b {
b[i] = letterRunes[rand.Intn(len(letterRunes))]
}
return string(b)
}
func getAvailableStorageClasses() []string {
var storageClasses []string
storageClassesRaw, _ := exec.Command("kubectl", "get", "storageClasses", "-o", "json").Output()
var storageClassesList StorageClassesList
_ = json.Unmarshal(storageClassesRaw, &storageClassesList)
for _, storageClass := range storageClassesList.Items {
storageClasses = append(storageClasses, storageClass.Metadata.Name)
}
return storageClasses
}
func getGithubVersionList(repository string, limit int) []string {
githubapi := resty.New().
SetHeader("Accept", "application/json").
SetHeader("Content-Type", "application/json").
SetHeader("User-Agent", "kubero-cli/"+kuberoCliVersion).
SetBaseURL("https://api.github.com/repos/")
tags, _ := githubapi.R().Get(repository + "/tags")
var versions []GithubVersion
_ = json.Unmarshal(tags.Body(), &versions)
var versionList []string
versionList = make([]string, 0)
for _, version := range versions {
if limit == 0 || len(versionList) < limit {
versionList = append(versionList, version.Name)
}
}
return versionList
}
type StorageClassesList struct {
APIVersion string `json:"apiVersion"`
Items []struct {
APIVersion string `json:"apiVersion"`
Kind string `json:"kind"`
Metadata struct {
Annotations struct {
KubectlKubernetesIoLastAppliedConfiguration string `json:"kubectl.kubernetes.io/last-applied-configuration"`
StorageClassKubernetesIoIsDefaultClass string `json:"storageClass.kubernetes.io/is-default-class"`
} `json:"annotations"`
CreationTimestamp time.Time `json:"creationTimestamp"`
Name string `json:"name"`
ResourceVersion string `json:"resourceVersion"`
UID string `json:"uid"`
} `json:"metadata"`
Provisioner string `json:"provisioner"`
ReclaimPolicy string `json:"reclaimPolicy"`
VolumeBindingMode string `json:"volumeBindingMode"`
} `json:"items"`
Kind string `json:"kind"`
Metadata struct {
ResourceVersion string `json:"resourceVersion"`
SelfLink string `json:"selfLink"`
} `json:"metadata"`
}
0707010000001C000081A400000000000000000000000167BEEE0500006222000000000000000000000000000000000000003000000000kubero-cli-2.4.7/cmd/kuberoCli/install.types.gopackage kuberoCli
import (
"time"
"gorm.io/gorm"
)
type DigitalOceanKubernetesConfig struct {
Name string `json:"name" gorm:"column:name"`
Region string `json:"region" gorm:"column:region"`
Version string `json:"version" gorm:"column:version"`
NodePools []struct {
Size string `json:"size" gorm:"column:size"`
Count int `json:"count" gorm:"column:count"`
Name string `json:"name" gorm:"column:name"`
} `json:"node_pools" gorm:"embedded"`
}
type DigitalOcean struct {
KubernetesCluster struct {
ID string `json:"id" gorm:"column:id"`
Name string `json:"name" gorm:"column:name"`
Region string `json:"region" gorm:"column:region"`
Version string `json:"version" gorm:"column:version"`
ClusterSubnet string `json:"cluster_subnet" gorm:"column:cluster_subnet"`
ServiceSubnet string `json:"service_subnet" gorm:"column:service_subnet"`
VpcUUID string `json:"vpc_uuid" gorm:"column:vpc_uuid"`
Ipv4 string `json:"ipv4" gorm:"column:ipv4"`
Endpoint string `json:"endpoint" gorm:"column:endpoint"`
Tags []string `json:"tags" gorm:"column:tags"`
NodePools []struct {
ID string `json:"id" gorm:"column:id"`
Name string `json:"name" gorm:"column:name"`
Size string `json:"size" gorm:"column:size"`
Count int `json:"count" gorm:"column:count"`
Tags []string `json:"tags" gorm:"column:tags"`
Labels interface{} `json:"labels" gorm:"column:labels"`
Taints []interface{} `json:"taints" gorm:"column:taints"`
AutoScale bool `json:"auto_scale" gorm:"column:auto_scale"`
MinNodes int `json:"min_nodes" gorm:"column:min_nodes"`
MaxNodes int `json:"max_nodes" gorm:"column:max_nodes"`
Nodes []struct {
ID string `json:"id" gorm:"column:id"`
Name string `json:"name" gorm:"column:name"`
Status struct {
State string `json:"state" gorm:"column:state"`
} `json:"status" gorm:"embedded"`
DropletID string `json:"droplet_id" gorm:"column:droplet_id"`
CreatedAt time.Time `json:"created_at" gorm:"column:created_at"`
UpdatedAt time.Time `json:"updated_at" gorm:"column:updated_at"`
} `json:"nodes" gorm:"embedded"`
} `json:"node_pools" gorm:"embedded"`
MaintenancePolicy struct {
StartTime string `json:"start_time" gorm:"column:start_time"`
Duration string `json:"duration" gorm:"column:duration"`
Day string `json:"day" gorm:"column:day"`
} `json:"maintenance_policy" gorm:"embedded"`
AutoUpgrade bool `json:"auto_upgrade" gorm:"column:auto_upgrade"`
Status struct {
State string `json:"state" gorm:"column:state"`
Message string `json:"message" gorm:"column:message"`
} `json:"status" gorm:"embedded"`
CreatedAt time.Time `json:"created_at" gorm:"column:created_at"`
UpdatedAt time.Time `json:"updated_at" gorm:"column:updated_at"`
SurgeUpgrade bool `json:"surge_upgrade" gorm:"column:surge_upgrade"`
RegistryEnabled bool `json:"registry_enabled" gorm:"column:registry_enabled"`
Ha bool `json:"ha" gorm:"column:ha"`
SupportedFeatures []string `json:"supported_features" gorm:"column:supported_features"`
} `json:"kubernetes_cluster" gorm:"embedded"`
}
type DigitaloceanOptions struct {
Options struct {
Regions []struct {
Name string `json:"name" gorm:"column:name"`
Slug string `json:"slug" gorm:"column:slug"`
} `json:"regions" gorm:"embedded"`
Versions []struct {
Slug string `json:"slug" gorm:"column:slug"`
KubernetesVersion string `json:"kubernetes_version" gorm:"column:kubernetes_version"`
SupportedFeatures []string `json:"supported_features" gorm:"column:supported_features"`
} `json:"versions" gorm:"embedded"`
Sizes []struct {
Name string `json:"name" gorm:"column:name"`
Slug string `json:"slug" gorm:"column:slug"`
} `json:"sizes" gorm:"embedded"`
} `json:"options" gorm:"embedded"`
}
type User struct {
gorm.Model
Method string `json:"method" gorm:"column:method"`
Username string `json:"username" gorm:"column:username"`
Password string `json:"password" gorm:"column:password"`
Insecure bool `json:"insecure" gorm:"column:insecure"`
ApiToken string `json:"apiToken,omitempty" gorm:"column:apiToken"`
}
type KindConfig struct {
Kind string `yaml:"kind" gorm:"column:kind"`
APIVersion string `yaml:"apiVersion" gorm:"column:apiVersion"`
Name string `yaml:"name" gorm:"column:name"`
Networking struct {
IPFamily string `yaml:"ipFamily" gorm:"column:ipFamily"`
APIServerAddress string `yaml:"apiServerAddress" gorm:"column:apiServerAddress"`
} `yaml:"networking" gorm:"embedded"`
Nodes []struct {
Role string `yaml:"role" gorm:"column:role"`
Image string `yaml:"image,omitempty" gorm:"column:image"`
KubeadmConfigPatches []string `yaml:"kubeadmConfigPatches" gorm:"column:kubeadmConfigPatches"`
ExtraPortMappings []struct {
ContainerPort int `yaml:"containerPort" gorm:"column:containerPort"`
HostPort int `yaml:"hostPort" gorm:"column:hostPort"`
Protocol string `yaml:"protocol" gorm:"column:protocol"`
} `yaml:"extraPortMappings" gorm:"embedded"`
} `yaml:"nodes" gorm:"embedded"`
ContainerdConfigPatches []string `yaml:"containerdConfigPatches" gorm:"column:containerdConfigPatches"`
}
type KuberoUIConfig struct {
APIVersion string `yaml:"apiVersion" gorm:"column:apiVersion"`
Kind string `yaml:"kind" gorm:"column:kind"`
Metadata struct {
Name string `yaml:"name" gorm:"column:name"`
} `yaml:"metadata" gorm:"embedded"`
Spec struct {
FullnameOverride string `yaml:"fullnameOverride" gorm:"column:fullnameOverride"`
Image struct {
PullPolicy string `yaml:"pullPolicy" gorm:"column:pullPolicy"`
Repository string `yaml:"repository" gorm:"column:repository"`
Tag string `yaml:"tag" gorm:"column:tag"`
} `yaml:"image" gorm:"embedded"`
ImagePullSecrets []interface{} `yaml:"imagePullSecrets" gorm:"-"`
Ingress struct {
Annotations struct {
KubernetesIoIngressClass string `yaml:"cert-manager.io/cluster-issuer,omitempty" gorm:"column:cert_manager_io_cluster_issuer"`
KubernetesIoTlsAcme string `yaml:"kubernetes.io/tls-acme,omitempty" gorm:"column:kubernetes_io_tls_acme"`
} `yaml:"annotations" gorm:"embedded"`
ClassName string `yaml:"className" gorm:"column:className"`
Enabled bool `yaml:"enabled" gorm:"column:enabled"`
Hosts []struct {
Host string `yaml:"host" gorm:"column:host"`
Paths []struct {
Path string `yaml:"path" gorm:"column:path"`
PathType string `yaml:"pathType" gorm:"column:pathType"`
} `yaml:"paths" gorm:"embedded"`
} `yaml:"hosts" gorm:"embedded"`
TLS []KuberoUITls `yaml:"tls" gorm:"-"`
} `yaml:"ingress" gorm:"embedded"`
NameOverride string `yaml:"nameOverride" gorm:"column:nameOverride"`
NodeSelector struct {
} `yaml:"nodeSelector" gorm:"-"`
PodAnnotations struct {
} `yaml:"podAnnotations" gorm:"-"`
PodSecurityContext struct {
} `yaml:"podSecurityContext" gorm:"-"`
Prometheus struct {
Enabled bool `yaml:"enabled" gorm:"column:enabled"`
Endpoint string `yaml:"endpoint" gorm:"column:endpoint"`
} `yaml:"prometheus,omitempty" gorm:"embedded"`
Registry struct {
Enabled bool `yaml:"enabled" gorm:"column:enabled"`
Create bool `yaml:"create" gorm:"column:create"`
Host string `yaml:"host" gorm:"column:host"`
SubPath string `yaml:"subPath" gorm:"column:subPath"`
Account struct {
Username string `yaml:"username" gorm:"column:username"`
Password string `yaml:"password" gorm:"column:password"`
Hash string `yaml:"hash" gorm:"column:hash"`
} `yaml:"account" gorm:"embedded"`
Port int `yaml:"port" gorm:"column:port"`
Storage string `yaml:"storage" gorm:"column:storage"`
StorageClassName interface{} `yaml:"storageClassName" gorm:"column:storageClassName"`
} `yaml:"registry" gorm:"embedded"`
ReplicaCount int `yaml:"replicaCount" gorm:"column:replicaCount"`
Resources struct {
} `yaml:"resources" gorm:"-"`
SecurityContext struct {
} `yaml:"securityContext" gorm:"-"`
Service struct {
Port int `yaml:"port" gorm:"column:port"`
Type string `yaml:"type" gorm:"column:type"`
} `yaml:"service" gorm:"embedded"`
ServiceAccount struct {
Annotations struct {
} `yaml:"annotations" gorm:"-"`
Create bool `yaml:"create" gorm:"column:create"`
Name string `yaml:"name" gorm:"column:name"`
} `yaml:"serviceAccount" gorm:"embedded"`
Tolerations []interface{} `yaml:"tolerations" gorm:"-"`
Kubero struct {
Debug string `yaml:"debug" gorm:"column:debug"`
Namespace string `yaml:"namespace" gorm:"column:namespace"`
Context string `yaml:"context" gorm:"column:context"`
WebhookURL string `yaml:"webhook_url" gorm:"column:webhook_url"`
SessionKey string `yaml:"sessionKey" gorm:"column:sessionKey"`
Auth struct {
Github struct {
Enabled bool `yaml:"enabled" gorm:"column:enabled"`
ID string `yaml:"id,omitempty" gorm:"column:id"`
Secret string `yaml:"secret,omitempty" gorm:"column:secret"`
CallbackURL string `yaml:"callbackUrl,omitempty" gorm:"column:callbackUrl"`
Org string `yaml:"org,omitempty" gorm:"column:org"`
} `yaml:"github" gorm:"embedded"`
Oauth2 struct {
Enabled bool `yaml:"enabled" gorm:"column:enabled"`
Name string `yaml:"name,omitempty" gorm:"column:name"`
ID string `yaml:"id,omitempty" gorm:"column:id"`
AuthURL string `yaml:"authUrl,omitempty" gorm:"column:authUrl"`
TokenURL string `yaml:"tokenUrl,omitempty" gorm:"column:tokenUrl"`
Secret string `yaml:"secret,omitempty" gorm:"column:secret"`
CallbackURL string `yaml:"callbackUrl,omitempty" gorm:"column:callbackUrl"`
} `yaml:"oauth2" gorm:"embedded"`
} `yaml:"auth" gorm:"embedded"`
AuditLogs struct {
Enabled bool `yaml:"enabled" gorm:"column:enabled"`
StorageClassName string `yaml:"storageClassName" gorm:"column:storageClassName"`
Size string `yaml:"size" gorm:"column:size"`
AccessModes []string `yaml:"accessModes" gorm:"column:accessModes"`
Limit string `yaml:"limit" gorm:"column:limit"`
} `yaml:"auditLogs" gorm:"embedded"`
Config KuberoConfigfile `yaml:"config,omitempty" gorm:"embedded"`
} `yaml:"kubero" gorm:"embedded"`
} `yaml:"spec" gorm:"embedded"`
}
type NotificationsConfig struct {
Enabled bool `yaml:"enabled" gorm:"column:enabled"`
Name string `yaml:"name" gorm:"column:name"`
Type string `yaml:"type" gorm:"column:type"`
Pipelines []string `yaml:"pipelines" gorm:"column:pipelines"`
Events []string `yaml:"events" gorm:"column:events"`
Config struct {
Url string `yaml:"url" gorm:"column:url"`
Channel string `yaml:"channel,omitempty" gorm:"column:channel"`
Secret string `yaml:"secret,omitempty" gorm:"column:secret"`
} `yaml:"config" gorm:"embedded"`
}
type KuberoConfigfile struct {
Kubero struct {
Readonly bool `yaml:"readonly" gorm:"column:readonly"`
Admin struct {
Disabled bool `yaml:"disabled" gorm:"column:enabled"`
} `yaml:"admin" gorm:"embedded"`
Console struct {
Enabled bool `yaml:"enabled" gorm:"column:enabled"`
} `yaml:"console" gorm:"embedded"`
Banner struct {
Show bool `yaml:"show" gorm:"column:show"`
Message string `yaml:"message" gorm:"column:message"`
BgColor string `yaml:"bgColor" gorm:"column:bgColor"`
Fontcolor string `yaml:"fontcolor" gorm:"column:fontcolor"`
} `yaml:"banner" gorm:"embedded"`
} `yaml:"kubero" gorm:"embedded"`
Notifications []NotificationsConfig `yaml:"notifications" gorm:"embedded"`
ClusterIssuer string `yaml:"clusterIssuer" gorm:"column:clusterIssuer"`
Templates struct {
Enabled bool `yaml:"enabled" gorm:"column:enabled"`
Catalogs []struct {
Name string `yaml:"name" gorm:"column:name"`
Description string `yaml:"description" gorm:"column:description"`
TemplateBasePath string `yaml:"templateBasePath" gorm:"column:templateBasePath"`
Index struct {
URL string `yaml:"url" gorm:"column:url"`
Format string `yaml:"format" gorm:"column:format"`
} `yaml:"index" gorm:"embedded"`
} `yaml:"catalogs" gorm:"embedded"`
} `yaml:"templates" gorm:"embedded"`
BuildPacks []struct {
Name string `yaml:"name" gorm:"column:name"`
Language string `yaml:"language" gorm:"column:language"`
Fetch struct {
Repository string `yaml:"repository" gorm:"column:repository"`
Tag string `yaml:"tag" gorm:"column:tag"`
SecurityContext struct {
RunAsUser int `yaml:"runAsUser" gorm:"column:runAsUser"`
} `yaml:"securityContext" gorm:"embedded"`
} `yaml:"fetch" gorm:"embedded"`
Build struct {
Repository string `yaml:"repository" gorm:"column:repository"`
Tag string `yaml:"tag" gorm:"column:tag"`
Command string `yaml:"command" gorm:"column:command"`
SecurityContext struct {
RunAsUser int `yaml:"runAsUser" gorm:"column:runAsUser"`
} `yaml:"securityContext" gorm:"embedded"`
} `yaml:"build,omitempty" gorm:"embedded"`
Run struct {
Repository string `yaml:"repository" gorm:"column:repository"`
Tag string `yaml:"tag" gorm:"column:tag"`
ReadOnlyAppStorage bool `yaml:"readOnlyAppStorage" gorm:"column:readOnlyAppStorage"`
SecurityContext struct {
AllowPrivilegeEscalation bool `yaml:"allowPrivilegeEscalation" gorm:"column:allowPrivilegeEscalation"`
ReadOnlyRootFilesystem bool `yaml:"readOnlyRootFilesystem" gorm:"column:readOnlyRootFilesystem"`
} `yaml:"securityContext" gorm:"embedded"`
Command string `yaml:"command" gorm:"column:command"`
} `yaml:"run,omitempty" gorm:"embedded"`
} `yaml:"buildPacks" gorm:"embedded"`
PodSizeList []struct {
Active bool `yaml:"active,omitempty" gorm:"column:active"`
Name string `yaml:"name" gorm:"column:name"`
Description string `yaml:"description" gorm:"column:description"`
Default bool `yaml:"default,omitempty" gorm:"column:default"`
Resources struct {
Requests struct {
Memory string `yaml:"memory" gorm:"column:memory"`
CPU string `yaml:"cpu" gorm:"column:cpu"`
} `yaml:"requests" gorm:"embedded"`
Limits struct {
Memory string `yaml:"memory" gorm:"column:memory"`
CPU string `yaml:"cpu" gorm:"column:cpu"`
} `yaml:"limits" gorm:"embedded"`
} `yaml:"resources,omitempty" gorm:"embedded"`
} `yaml:"podSizeList" gorm:"embedded"`
}
type KuberoUITls struct {
SecretName string `yaml:"secretName" gorm:"column:secretName"`
Hosts []string `yaml:"hosts" gorm:"column:hosts"`
}
// ScalewayCreate https://developers.scaleway.com/en/products/k8s/api/#post-612200
type ScalewayCreate struct {
OrganizationID string `json:"organization_id,omitempty" gorm:"column:organization_id"`
ProjectID string `json:"project_id,omitempty" gorm:"column:project_id"`
Type string `json:"type" gorm:"column:type"`
Name string `json:"name" gorm:"column:name"`
Description string `json:"description" gorm:"column:description"`
Tags []string `json:"tags" gorm:"column:tags"`
Version string `json:"version" gorm:"column:version"`
Cni string `json:"cni" gorm:"column:cni"`
Pools []ScalewayNodePool `json:"pools" gorm:"embedded"`
AutoUpgrade struct {
Enable bool `json:"enable" gorm:"column:enable"`
MaintenanceWindow struct {
StartHour int `json:"start_hour" gorm:"column:start_hour"`
Day string `json:"day" gorm:"column:day"`
} `json:"maintenance_window" gorm:"embedded"`
} `json:"auto_upgrade" gorm:"embedded"`
FeatureGates []string `json:"feature_gates" gorm:"column:feature_gates"`
AdmissionPlugins []string `json:"admission_plugins" gorm:"column:admission_plugins"`
ApiServerCertSans []string `json:"apiServer_cert_sans" gorm:"column:apiServer_cert_sans"`
Ingress string `json:"ingress" gorm:"column:ingress"`
}
type ScalewayNodePool struct {
Name string `json:"name" gorm:"column:name"`
NodeType string `json:"node_type" gorm:"column:node_type"`
PlacementGroupID string `json:"placement_group_id,omitempty" gorm:"column:placement_group_id"`
Autoscaling bool `json:"autoscaling" gorm:"column:autoscaling"`
Size int `json:"size" gorm:"column:size"`
MinSize int `json:"min_size" gorm:"column:min_size"`
MaxSize int `json:"max_size" gorm:"column:max_size"`
ContainerRuntime string `json:"container_runtime" gorm:"column:container_runtime"`
AutoHealing bool `json:"autoHealing" gorm:"column:autoHealing"`
Tags []string `json:"tags" gorm:"column:tags"`
Zone string `json:"zone" gorm:"column:zone"`
RootVolumeType string `json:"root_volume_type" gorm:"column:root_volume_type"`
RootVolumeSize int `json:"root_volume_size" gorm:"column:root_volume_size"`
}
type ScalewayVersionsResponse struct {
Versions []struct {
Name string `json:"name" gorm:"column:name"`
Label string `json:"label" gorm:"column:label"`
Region string `json:"region" gorm:"column:region"`
AvailableCnis []string `json:"available_cnis" gorm:"column:available_cnis"`
AvailableIngresses []string `json:"available_ingresses" gorm:"column:available_ingresses"`
AvailableContainerRuntimes []string `json:"available_container_runtimes" gorm:"column:available_container_runtimes"`
AvailableFeatureGates []string `json:"available_feature_gates" gorm:"column:available_feature_gates"`
AvailableAdmissionPlugins []string `json:"available_admission_plugins" gorm:"column:available_admission_plugins"`
AvailableKubeletArgs struct {
AvailableKubeletArgKey string `json:"<available_kubelet_argKey>" gorm:"column:available_kubelet_arg_key"`
} `json:"available_kubelet_args" gorm:"embedded"`
} `json:"versions" gorm:"embedded"`
}
type ScalewayCreateResponse struct {
ID string `json:"id" gorm:"column:id"`
Type string `json:"type" gorm:"column:type"`
Name string `json:"name" gorm:"column:name"`
Status string `json:"status" gorm:"column:status"`
Version string `json:"version" gorm:"column:version"`
Region string `json:"region" gorm:"column:region"`
OrganizationID string `json:"organization_id" gorm:"column:organization_id"`
ProjectID string `json:"project_id" gorm:"column:project_id"`
Tags []string `json:"tags" gorm:"column:tags"`
Cni string `json:"cni" gorm:"column:cni"`
Description string `json:"description" gorm:"column:description"`
ClusterURL string `json:"cluster_url" gorm:"column:cluster_url"`
DNSWildcard string `json:"dns_wildcard" gorm:"column:dns_wildcard"`
CreatedAt time.Time `json:"created_at" gorm:"column:created_at"`
UpdatedAt time.Time `json:"updated_at" gorm:"column:updated_at"`
AutoscalerConfig struct {
ScaleDownDisabled bool `json:"scale_down_disabled" gorm:"column:scale_down_disabled"`
ScaleDownDelayAfterAdd string `json:"scale_down_delay_after_add" gorm:"column:scale_down_delay_after_add"`
Estimator string `json:"estimator" gorm:"column:estimator"`
Expander string `json:"expander" gorm:"column:expander"`
IgnoreDaemonSetsUtilization bool `json:"ignore_daemonSets_utilization" gorm:"column:ignore_daemonSets_utilization"`
BalanceSimilarNodeGroups bool `json:"balance_similar_node_groups" gorm:"column:balance_similar_node_groups"`
ExpendablePodsPriorityCutoff int `json:"expendable_pods_priority_cutoff" gorm:"column:expendable_pods_priority_cutoff"`
ScaleDownUnneededTime int `json:"scale_down_unneeded_time" gorm:"column:scale_down_unneeded_time"`
ScaleDownUtilizationThreshold float32 `json:"scale_down_utilization_threshold" gorm:"column:scale_down_utilization_threshold"`
MaxGracefulTerminationSec int `json:"max_graceful_termination_sec" gorm:"column:max_graceful_termination_sec"`
} `json:"autoscaler_config" gorm:"embedded"`
DashboardEnabled bool `json:"dashboard_enabled" gorm:"column:dashboard_enabled"`
Ingress string `json:"ingress" gorm:"column:ingress"`
AutoUpgrade struct {
Enabled bool `json:"enabled" gorm:"column:enabled"`
MaintenanceWindow struct {
StartHour int `json:"start_hour" gorm:"column:start_hour"`
Day string `json:"day" gorm:"column:day"`
} `json:"maintenance_window" gorm:"embedded"`
} `json:"auto_upgrade" gorm:"embedded"`
UpgradeAvailable string `json:"upgrade_available" gorm:"column:upgrade_available"`
FeatureGates []string `json:"feature_gates" gorm:"column:feature_gates"`
AdmissionPlugins []string `json:"admission_plugins" gorm:"column:admission_plugins"`
OpenIDConnectConfig struct {
IssuerURL string `json:"issuer_url" gorm:"column:issuer_url"`
ClientID string `json:"client_id" gorm:"column:client_id"`
UsernameClaim string `json:"username_claim" gorm:"column:username_claim"`
UsernamePrefix string `json:"username_prefix" gorm:"column:username_prefix"`
GroupsClaim []string `json:"groups_claim" gorm:"column:groups_claim"`
GroupsPrefix string `json:"groups_prefix" gorm:"column:groups_prefix"`
RequiredClaim []string `json:"required_claim" gorm:"column:required_claim"`
} `json:"open_id_connect_config" gorm:"embedded"`
ApiServerCertSans []string `json:"apiServer_cert_sans" gorm:"column:apiServer_cert_sans"`
}
type ScalewayKubeconfigResponse struct {
Name string `json:"name" gorm:"column:name"`
ContentType string `json:"content_type" gorm:"column:content_type"`
Content string `json:"content" gorm:"column:content"`
}
type JokeResponse struct {
Categories []string `json:"categories"`
CreatedAt string `json:"created_at"`
IconURL string `json:"icon_url"`
ID string `json:"id"`
UpdatedAt string `json:"updated_at"`
URL string `json:"url"`
Value string `json:"value"`
}
type KuberoIngress struct {
Items []struct {
Kind string `json:"kind"`
Spec struct {
IngressClassName string `json:"ingressClassName"`
Rules []struct {
Host string `json:"host"`
HTTP struct {
Paths []struct {
Backend struct {
Service struct {
Name string `json:"name"`
Port struct {
Number int `json:"number"`
} `json:"port"`
} `json:"service"`
} `json:"backend"`
Path string `json:"path"`
} `json:"paths"`
} `json:"http"`
} `json:"rules"`
} `json:"spec"`
Status struct {
LoadBalancer struct {
Ingress []struct {
Hostname string `json:"hostname"`
IP string `json:"ip"`
} `json:"ingress"`
} `json:"loadBalancer"`
} `json:"status"`
} `json:"items"`
}
type LinodeCreateClusterRequest struct {
Label string `json:"label"`
Region string `json:"region"`
K8SVersion string `json:"k8s_version"`
Tags []string `json:"tags"`
ControlPlane struct {
HighAvailability bool `json:"high_availability"`
} `json:"control_plane"`
NodePools []LinodeNodepool `json:"node_pools"`
}
type LinodeCreateClusterResponse struct {
ControlPlane struct {
HighAvailability bool `json:"high_availability"`
} `json:"control_plane"`
Created time.Time `json:"created"`
ID int `json:"id"`
K8SVersion string `json:"k8s_version"`
Label string `json:"label"`
Region string `json:"region"`
Tags []string `json:"tags"`
Updated time.Time `json:"updated"`
}
type LinodeNodepool struct {
Type string `json:"type"`
Count int `json:"count"`
Autoscaler struct {
Enabled bool `json:"enabled"`
Max int `json:"max,omitempty"`
Min int `json:"min,omitempty"`
} `json:"autoscaler,omitempty"`
}
type CertManagerClusterIssuer struct {
APIVersion string `yaml:"apiVersion"`
Kind string `yaml:"kind"`
Metadata struct {
Name string `yaml:"name"`
} `yaml:"metadata"`
Spec struct {
Acme struct {
Server string `yaml:"server"`
Email string `yaml:"email"`
PrivateKeySecretRef struct {
Name string `yaml:"name"`
} `yaml:"privateKeySecretRef"`
Solvers []struct {
HTTP01 struct {
Ingress struct {
Class string `yaml:"class"`
} `yaml:"ingress"`
} `yaml:"http01"`
} `yaml:"solvers"`
} `yaml:"acme"`
} `yaml:"spec"`
}
0707010000001D000081A400000000000000000000000167BEEE0500001156000000000000000000000000000000000000003700000000kubero-cli-2.4.7/cmd/kuberoCli/install_digitalocean.gopackage kuberoCli
import (
"encoding/json"
"fmt"
"log"
"math/rand"
"os"
"strconv"
"time"
"github.com/go-resty/resty/v2"
"github.com/i582/cfmt/cmd/cfmt"
"github.com/leaanthony/spinner"
)
func installDigitalOcean() {
// https://docs.digitalocean.com/reference/api/api-reference/#operation/kubernetes_create_cluster
_, _ = cfmt.Println("{{⚠ Installing Kubernetes on Digital Ocean is currently beta state in kubero-cli}}::yellow")
_, _ = cfmt.Println("{{ Please report if you run into errors}}::yellow")
token := os.Getenv("DIGITALOCEAN_ACCESS_TOKEN")
if token == "" {
_, _ = cfmt.Println("{{✗ DIGITALOCEAN_ACCESS_TOKEN is not set}}::red")
log.Fatal("missing DIGITALOCEAN_ACCESS_TOKEN")
}
doApi := resty.New().
SetAuthScheme("Bearer").
SetAuthToken(token).
SetHeader("Accept", "application/json").
SetHeader("Content-Type", "application/json").
SetHeader("User-Agent", "kubero-cli/"+kuberoCliVersion).
SetBaseURL("https://api.digitalocean.com")
var doConfig DigitalOceanKubernetesConfig
doConfig.NodePools = []struct {
Size string `json:"size" gorm:"column:size"`
Count int `json:"count" gorm:"column:count"`
Name string `json:"name" gorm:"column:name"`
}([]struct {
Size string `json:"size"`
Count int `json:"count"`
Name string `json:"name"`
}{
{
Size: "s-1vcpu-2gb",
Count: 1,
Name: "worker-pool",
},
})
kubernetesVersions, regions, sizes := getDigitaloceanOptions(doApi)
doConfig.Name = promptLine("Kubernetes Cluster Name", "", "kubero-"+strconv.Itoa(rand.Intn(1000)))
doConfig.Region = selectFromList("Cluster Region", regions, "")
doConfig.Version = selectFromList("Cluster Version", kubernetesVersions, "")
doConfig.NodePools[0].Size = selectFromList("Cluster Node Size", sizes, "")
doConfig.NodePools[0].Count, _ = strconv.Atoi(promptLine("Cluster Node Count", "", "3"))
kf, _ := doApi.R().
SetBody(doConfig).
Post("/v2/kubernetes/clusters")
if kf.StatusCode() > 299 {
fmt.Println(kf.String())
_, _ = cfmt.Println("{{✗ failed to create digital ocean cluster}}::red")
os.Exit(1)
} else {
_, _ = cfmt.Println("{{✓ digital ocean cluster created}}::lightGreen")
}
var doCluster DigitalOcean
jsonUnmarshalErr := json.Unmarshal(kf.Body(), &doCluster)
if jsonUnmarshalErr != nil {
fmt.Println(jsonUnmarshalErr)
return
}
doSpinner := spinner.New("Starting a kubernetes cluster on digital ocean")
doSpinner.Start("Waiting for digital ocean cluster to be ready. This may take a few minutes. Time enough to get a coffee ☕")
clusterID := doCluster.KubernetesCluster.ID
for {
time.Sleep(2 * time.Second)
doWait, _ := doApi.R().
Get("/v2/kubernetes/clusters/" + clusterID)
if doWait.StatusCode() > 299 {
fmt.Println(doWait.String())
doSpinner.Error("Failed to create digital ocean cluster")
continue
} else {
var doCluster DigitalOcean
jsonUnmarshalBErr := json.Unmarshal(doWait.Body(), &doCluster)
if jsonUnmarshalBErr != nil {
fmt.Println(jsonUnmarshalBErr)
return
}
if doCluster.KubernetesCluster.Status.State == "running" {
doSpinner.Success("digital ocean cluster created")
break
}
}
}
kubectl, _ := doApi.R().
Get("v2/kubernetes/clusters/" + clusterID + "/kubeconfig")
mergeKubeconfigErr := mergeKubeconfig(kubectl.Body())
if mergeKubeconfigErr != nil {
fmt.Println(mergeKubeconfigErr)
return
}
}
func getDigitaloceanOptions(api *resty.Client) ([]string, []string, []string) {
token := os.Getenv("DIGITALOCEAN_ACCESS_TOKEN")
if token == "" {
_, _ = cfmt.Println("{{✗ DIGITALOCEAN_ACCESS_TOKEN is not set}}::red")
log.Fatal("missing DIGITALOCEAN_ACCESS_TOKEN")
}
optionsResponse, err := api.R().Get("/v2/kubernetes/options")
if err != nil {
_, _ = cfmt.Println("{{✗ failed to get digitalocean options}}::red")
log.Fatal(err)
}
var versionsResponse DigitaloceanOptions
jsonUnmarshalErr := json.Unmarshal(optionsResponse.Body(), &versionsResponse)
if jsonUnmarshalErr != nil {
fmt.Println(jsonUnmarshalErr)
return nil, nil, nil
}
var versions []string
for _, v := range versionsResponse.Options.Versions {
versions = append(versions, v.Slug)
}
var regions []string
for _, v := range versionsResponse.Options.Regions {
regions = append(regions, v.Slug)
}
var sizes []string
for _, v := range versionsResponse.Options.Sizes {
sizes = append(sizes, v.Slug)
}
return versions, regions, sizes
}
0707010000001E000081A400000000000000000000000167BEEE0500000858000000000000000000000000000000000000002E00000000kubero-cli-2.4.7/cmd/kuberoCli/install_gke.gopackage kuberoCli
import (
"fmt"
"log"
"math/rand"
"os/exec"
"strconv"
"github.com/leaanthony/spinner"
)
func installGKE() {
// implememted with gcloud, since it is required for the download of the kubeconfig anyway
// gcloud config list
// gcloud config get project
// gcloud container clusters create kubero-cluster-4 --region=us-central1-c
// gcloud container clusters get-credentials kubero-cluster-4 --region=us-central1-c
// https://cloud.google.com/kubernetes-engine/docs/reference/libraries#client-libraries-install-go
// https://github.com/googleapis/google-cloud-go
gcloudName := promptLine("Kubernetes Cluster Name", "", "kubero-"+strconv.Itoa(rand.Intn(1000)))
gcloudRegion := promptLine("Region", "[https://cloud.google.com/compute/docs/regions-zones]", "us-central1-c")
gcloudClusterVersion := promptLine("Cluster Version", "[https://cloud.google.com/kubernetes-engine/docs/release-notes-regular]", "1.23.8-gke.1900")
spinner := spinner.New("Spin up a GKE cluster")
spinner.Start("run command : gcloud container clusters create " + gcloudName + " --region=" + gcloudRegion + " --cluster-version=" + gcloudClusterVersion)
_, err := exec.Command("gcloud", "container", "clusters", "create", gcloudName,
"--region="+gcloudRegion,
"--cluster-version="+gcloudClusterVersion).Output()
if err != nil {
fmt.Println()
spinner.Error("Failed to run command. Try runnig this command manually and skip this step: 'gcloud container clusters create " + gcloudName + " --region=" + gcloudRegion + " --cluster-version=" + gcloudClusterVersion + "'")
log.Fatal(err)
}
spinner.Success("GKE cluster started sucessfully")
spinner.Start("Get credentials for the GKE cluster")
_, err = exec.Command("gcloud", "container", "clusters", "get-credentials", gcloudName, "--region="+gcloudRegion).Output()
if err != nil {
fmt.Println()
spinner.Error("Failed to run command. Try runnig this command manually and skip this step: 'gcloud container clusters get-credentials " + gcloudName + " --region=" + gcloudRegion + "'")
log.Fatal(err)
} else {
spinner.Success("GKE cluster credentials set")
}
}
0707010000001F000081A400000000000000000000000167BEEE05000009A6000000000000000000000000000000000000002F00000000kubero-cli-2.4.7/cmd/kuberoCli/install_kind.gopackage kuberoCli
import (
"fmt"
"log"
"math/rand"
"os"
"os/exec"
"strconv"
"github.com/go-resty/resty/v2"
"github.com/i582/cfmt/cmd/cfmt"
"github.com/leaanthony/spinner"
"gopkg.in/yaml.v3"
)
func installKind() {
if !checkBinary("kind") {
log.Fatal("kind binary is not installed")
}
installer := resty.New()
// get kind.yaml
installer.SetBaseURL("https://raw.githubusercontent.com")
kf, _ := installer.R().Get("/kubero-dev/kubero/main/kind.yaml")
var kindConfig KindConfig
yamlUnmarshalErr := yaml.Unmarshal(kf.Body(), &kindConfig)
if yamlUnmarshalErr != nil {
fmt.Println(yamlUnmarshalErr)
return
}
// set cluster name
kindConfig.Name = promptLine("Kind Cluster Name", "", "kubero-"+strconv.Itoa(rand.Intn(1000)))
// select Kubernetes version
kv, _ := installer.R().Get("/kubero-dev/kubero-cli/main/templates/kindVersions.yaml")
var kindDefaults struct {
AvailableKubernetesVersions []string `yaml:"availableKubernetesVersions"`
}
yamlUnmarshalBErr := yaml.Unmarshal(kv.Body(), &kindDefaults)
if yamlUnmarshalBErr != nil {
fmt.Println(yamlUnmarshalBErr)
return
}
version := selectFromList("Kubernetes Version", kindDefaults.AvailableKubernetesVersions, "")
kindConfig.Nodes[0].Image = "kindest/node:" + version
if argPort == "" {
argPort = promptLine("Local HTTP Port", "", "80")
}
kindConfig.Nodes[0].ExtraPortMappings[0].HostPort, _ = strconv.Atoi(argPort)
if argPortSecure == "" {
argPortSecure = promptLine("Local HTTPS Port", "", "443")
}
kindConfig.Nodes[0].ExtraPortMappings[1].HostPort, _ = strconv.Atoi(argPortSecure)
kindConfigYaml, _ := yaml.Marshal(kindConfig)
//fmt.Println("-------------- kind.yaml ---------------")
//fmt.Println(string(kindConfigYaml))
//fmt.Println("----------------------------------------")
kindConfigErr := os.WriteFile("kind.yaml", kindConfigYaml, 0644)
if kindConfigErr != nil {
fmt.Println(kindConfigErr)
return
}
kindSpinner := spinner.New("Spin up a local Kind cluster")
_, _ = cfmt.Println("run command : kind create cluster --config kind.yaml")
kindSpinner.Start("Creating Kind cluster")
out, err := exec.Command("kind", "create", "cluster", "--config", "kind.yaml").Output()
if err != nil {
kindSpinner.Error("Failed to run command. Try running this command manually and skip this step : 'kind create cluster --config kind.yaml'")
log.Fatal(err)
}
kindSpinner.Success("Kind cluster started successfully")
fmt.Println(string(out))
}
07070100000020000081A400000000000000000000000167BEEE0500000E9C000000000000000000000000000000000000003100000000kubero-cli-2.4.7/cmd/kuberoCli/install_linode.gopackage kuberoCli
import (
"encoding/base64"
"encoding/json"
"fmt"
"log"
"math/rand"
"os"
"strconv"
"time"
"github.com/go-resty/resty/v2"
"github.com/i582/cfmt/cmd/cfmt"
"github.com/leaanthony/spinner"
)
func installLinode() {
// https://www.linode.com/docs/api/linode-kubernetes-engine-lke/#kubernetes-cluster-create
// https://www.linode.com/docs/api/linode-kubernetes-engine-lke/#kubernetes-cluster-view
// https://www.linode.com/docs/api/linode-kubernetes-engine-lke/#kubeconfig-view
_, _ = cfmt.Println("{{⚠ Installing Kubernetes on Linode is currently beta state in kubero-cli}}::yellow")
_, _ = cfmt.Println("{{ Please report if you run into errors}}::yellow")
token := os.Getenv("LINODE_ACCESS_TOKEN")
if token == "" {
_, _ = cfmt.Println("{{✗ LINODE_ACCESS_TOKEN is not set}}::red")
log.Fatal("missing LINODE_ACCESS_TOKEN")
}
api := resty.New().
SetAuthScheme("Bearer").
SetAuthToken(token).
SetHeader("Accept", "application/json").
SetHeader("Content-Type", "application/json").
SetHeader("User-Agent", "kubero-cli/"+kuberoCliVersion).
SetBaseURL("https://api.linode.com/v4/lke/clusters")
var clusterConfig LinodeCreateClusterRequest
clusterConfig.Label = promptLine("Cluster Name", "", "kubero-"+strconv.Itoa(rand.Intn(1000)))
clusterConfig.Region = promptLine("Region", "[https://www.linode.com/global-infrastructure/]", "us-central") // TODO load the list of regions or point to e better document
workerNodesCount, _ := strconv.Atoi(promptLine("Worker Nodes Count", "", "3"))
workerNodesType := promptLine("Worker Nodes Type", "[https://www.linode.com/pricing/]", "g6-standard-2") // TODO load the list of types or point to e better document
clusterConfig.K8SVersion = promptLine("Kubernetes Version", "[1.25]", "1.25")
clusterConfig.Tags = []string{"kubero"}
clusterConfig.NodePools = []LinodeNodepool{
{
Type: workerNodesType,
Count: workerNodesCount,
},
}
spinnerObj := spinner.New("Spin up a Linode Kubernetes Cluster")
spinnerObj.Start("Create Linode Kubernetes Cluster")
clusterResponse, _ := api.R().SetBody(clusterConfig).Post("")
if clusterResponse.StatusCode() > 299 {
fmt.Println()
spinnerObj.Error("Failed to create Linode Kubernetes Cluster")
log.Fatal(clusterResponse.String())
}
spinnerObj.Success("Linode Kubernetes Cluster created")
var cluster LinodeCreateClusterResponse
jsonUnmarshalErr := json.Unmarshal(clusterResponse.Body(), &cluster)
if jsonUnmarshalErr != nil {
log.Fatal(jsonUnmarshalErr)
return
}
// According to the docs, the cluster is ready after 2-5 minutes.
_, _ = cfmt.Println("{{ Wait for Linode Kubernetes Cluster to be ready}}::lightBlue")
_, _ = cfmt.Println("{{ According to the docs this may take up to 7 minutes}}::lightBlue")
_, _ = cfmt.Println("{{ Time for a coffee break and some Chuck Norris jokes.}}::lightBlue")
spinnerObj.Start("Wait for Linode Kubernetes Cluster to be ready")
var LinodeKubeconfig struct {
Kubeconfig string `json:"kubeconfig"`
}
for i := 0; true; i++ {
time.Sleep(15 * time.Second)
r, _ := api.R().SetResult(&LinodeKubeconfig).Get("/" + strconv.Itoa(cluster.ID) + "/kubeconfig")
if r.StatusCode() > 299 {
tellAChucknorrisJoke()
}
if LinodeKubeconfig.Kubeconfig != "" {
spinnerObj.Success("Linode Kubernetes Cluster is ready")
break
}
}
kubeconfig, err := base64.StdEncoding.DecodeString(LinodeKubeconfig.Kubeconfig)
if err != nil {
fmt.Println()
spinnerObj.Error("Failed to decode kubeconfig")
log.Fatal(err)
}
err = mergeKubeconfig(kubeconfig)
if err != nil {
fmt.Println()
spinnerObj.Error("Failed to merge kubeconfig")
log.Fatal(err)
}
spinnerObj.Success("Linode Kubernetes Cluster credentials set")
}
07070100000021000081A400000000000000000000000167BEEE0500001557000000000000000000000000000000000000003300000000kubero-cli-2.4.7/cmd/kuberoCli/install_scaleway.gopackage kuberoCli
import (
"encoding/base64"
"encoding/json"
"log"
"math/rand"
"os"
"strconv"
"time"
"github.com/go-resty/resty/v2"
"github.com/i582/cfmt/cmd/cfmt"
"github.com/leaanthony/spinner"
)
func installScaleway() {
// create the cluster
// https://api.scaleway.com/k8s/v1/regions/{region}/clusters/{cluster_id}/available-versions
// check state of cluster
// https://api.scaleway.com/k8s/v1/regions/{region}/clusters
// get the kubeconfig
// https://api.scaleway.com/k8s/v1/regions/{region}/clusters/{cluster_id}/kubeconfig
// _, _ = cfmt.Println("{{⚠ Installing Kubernetes on Scaleway is currently beta state in kubero-cli}}::yellow")
// _, _ = cfmt.Println("{{ Please report if you run into errors}}::yellow")
var cluster ScalewayCreate
/*
cluster.ProjectID = os.Getenv("SCALEWAY_PROJECTID")
if cluster.ProjectID == "" {
_, _ = cfmt.Println("{{✗ SCALEWAY_PROJECTID is not set}}::red")
log.Fatal("missing SCALEWAY_PROJECTID")
}
*/
cluster.OrganizationID = os.Getenv("SCALEWAY_PROJECTID")
token := os.Getenv("SCALEWAY_ACCESS_TOKEN")
if token == "" {
_, _ = cfmt.Println("{{✗ SCALEWAY_ACCESS_TOKEN is not set}}::red")
log.Fatal("missing SCALEWAY_ACCESS_TOKEN")
}
api := resty.New().
SetHeader("X-Auth-Token", token).
SetHeader("Accept", "application/json").
SetHeader("Content-Type", "application/json").
SetHeader("User-Agent", "kubero-cli/"+kuberoCliVersion).
SetBaseURL("https://api.scaleway.com/k8s/v1/regions")
cluster.Name = promptLine("Kubernetes Cluster Name", "", "kubero-"+strconv.Itoa(rand.Intn(1000)))
regionsList := []string{"fr-par", "nl-ams", "pl-waw"}
region := selectFromList("Cluster Region", regionsList, "")
versions := getScalewayVersions(api, region)
cluster.Version = selectFromList("Kubernetes Version", versions, "")
// TODO lets make this configurable if needed in the future
cluster.Cni = "unknown_cni"
cluster.Ingress = "unknown_ingress" // is marked as deprecated in the api but required for now
/*
TODO : not implemented yet, but prepare for it in the future
cluster.AutoscalerConfig.Estimator = "unknown_estimator"
cluster.AutoscalerConfig.Expander = "unknown_expander"
cluster.AutoscalerConfig.ScaleDownUtilizationThreshold = 0.5
cluster.AutoscalerConfig.MaxGracefulTerminationSec = 60
*/
cluster.AutoUpgrade.Enable = false
cluster.AutoUpgrade.MaintenanceWindow.StartHour = 3
cluster.AutoUpgrade.MaintenanceWindow.Day = "any"
// TODO load the options from the api
nodeType := promptLine("Node Types", "[DEV1-M,DEV1-XL,START1-M]", "DEV1-M")
clusterSize, _ := strconv.Atoi(promptLine("Cluster Size", "[at least 3]", "3"))
cluster.Pools = append(cluster.Pools, ScalewayNodePool{
Name: "default",
NodeType: nodeType,
Autoscaling: false,
Size: clusterSize,
ContainerRuntime: "unknown_runtime",
RootVolumeType: "default_volume_type",
//RootVolumeSize: 50,
})
//fmt.Printf("%+v\n", cluster)
newCluster, _ := api.R().SetBody(cluster).Post(region + "/clusters")
var clusterResponse ScalewayCreateResponse
if newCluster.StatusCode() < 299 {
jsonUnmarshalErr := json.Unmarshal(newCluster.Body(), &clusterResponse)
if jsonUnmarshalErr != nil {
_, _ = cfmt.Println("{{✗ Failed to create Scaleway Kubernetes cluster}}::red")
return
}
_, _ = cfmt.Println("{{✓ Scaleway Kubernetes cluster created}}::lightGreen")
} else {
_, _ = cfmt.Println("{{✗ Scaleway Kubernetes Cluster creation failed}}::red")
log.Fatal(string(newCluster.Body()))
}
spinnerObj := spinner.New()
spinnerObj.Start("Waiting for cluster to be ready")
for {
clusterStatus, _ := api.R().Get(region + "/clusters/" + clusterResponse.ID)
var clusterStatusResponse ScalewayCreateResponse
jsonUnmarshalErr := json.Unmarshal(clusterStatus.Body(), &clusterStatusResponse)
if jsonUnmarshalErr != nil {
_, _ = cfmt.Println("{{✗ Failed to get Scaleway Kubernetes cluster status}}::red")
return
}
if clusterStatusResponse.Status == "ready" {
spinnerObj.Success("Scaleway Kubernetes Cluster is ready")
break
}
time.Sleep(2 * time.Second)
}
k, _ := api.R().Get(region + "/clusters/" + clusterResponse.ID + "/kubeconfig")
var scalewayKubeconfigResponse ScalewayKubeconfigResponse
jsonUnmarshalErr := json.Unmarshal(k.Body(), &scalewayKubeconfigResponse)
if jsonUnmarshalErr != nil {
_, _ = cfmt.Println("{{✗ Failed to download kubeconfig}}::red")
return
}
kubeconfig, _ := base64.StdEncoding.DecodeString(scalewayKubeconfigResponse.Content)
err := mergeKubeconfig(kubeconfig)
if err != nil {
_, _ = cfmt.Println("{{✗ Failed to download kubeconfig}}::red")
log.Fatal(err)
} else {
_, _ = cfmt.Println("{{✓ Kubeconfig downloaded}}::lightGreen")
}
}
func getScalewayVersions(api *resty.Client, region string) []string {
token := os.Getenv("SCALEWAY_ACCESS_TOKEN")
if token == "" {
_, _ = cfmt.Println("{{✗ SCALEWAY_ACCESS_TOKEN is not set}}::red")
log.Fatal("missing SCALEWAY_ACCESS_TOKEN")
}
versionsR, _ := api.R().Get(region + "/versions")
var versionsResponse ScalewayVersionsResponse
jsonUnmarshalErr := json.Unmarshal(versionsR.Body(), &versionsResponse)
if jsonUnmarshalErr != nil {
_, _ = cfmt.Println("{{✗ Failed to get Scaleway Kubernetes versions}}::red")
return nil
}
var versions []string
for _, v := range versionsResponse.Versions {
versions = append(versions, v.Name)
}
return versions
}
07070100000022000081A400000000000000000000000167BEEE0500000C53000000000000000000000000000000000000002B00000000kubero-cli-2.4.7/cmd/kuberoCli/instance.gopackage kuberoCli
/*
Copyright © 2023 NAME HERE <EMAIL ADDRESS>
*/
import (
"fmt"
"os"
"github.com/i582/cfmt/cmd/cfmt"
"github.com/olekukonko/tablewriter"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
// instanceCmd represents the instance command
var instanceCmd = &cobra.Command{
Use: "instance",
Aliases: []string{"i"},
Short: "List available instances",
Long: `Print a list of available instances.`,
Run: func(cmd *cobra.Command, args []string) {
/*
fmt.Println("current instance : " + currentInstanceName)
fmt.Println(instanceList)
if currentInstance.ApiUrl == "" {
fmt.Println("No current instance api URL")
} else {
fmt.Println("Current instance api URL : " + currentInstance.ApiUrl)
}
*/
printInstanceList()
},
}
func init() {
rootCmd.AddCommand(instanceCmd)
}
func printInstanceList() {
table := tablewriter.NewWriter(os.Stdout)
table.SetHeader([]string{"Active", "Token", "Name", "API URL", "Path", "IAC Base Dir"})
table.SetAutoWrapText(false)
table.SetAutoFormatHeaders(true)
//table.SetHeaderAlignment(tablewriter.ALIGN_LEFT)
//table.SetAlignment(tablewriter.ALIGN_LEFT)
table.SetRowLine(true)
table.SetCenterSeparator("")
//table.SetColumnSeparator("")
table.SetRowSeparator("")
table.SetBorder(false)
table.SetTablePadding("\t")
table.SetNoWhiteSpace(true)
for _, instanceName := range instanceNameList {
active := ""
if instanceName == currentInstanceName {
active = cfmt.Sprintf(" {{✔}}::green")
}
token := ""
// check if instanceName is in credentialsConfig
if credentialsConfig.GetString(instanceName) != "" {
token = cfmt.Sprintf(" {{✔}}::green")
}
table.Append([]string{
active,
token,
instanceName,
instanceList[instanceName].ApiUrl,
instanceList[instanceName].ConfigPath,
instanceList[instanceName].IacBaseDir,
})
}
table.Render()
}
func createInstanceForm() {
fmt.Println("Create a new instance")
instanceName := promptLine("Enter the name of the instance", "", "")
instanceApiurl := promptLine("Enter the API URL of the instance", "", "http://localhost:80")
instancePath := viper.ConfigFileUsed()
personalInstanceList := viper.GetStringMap("instances")
personalInstanceList[instanceName] = Instance{
Name: instanceName,
ApiUrl: instanceApiurl,
ConfigPath: instancePath,
}
viper.Set("instances", personalInstanceList)
instanceNameList = append(instanceNameList, instanceName)
setCurrentInstance(instanceName)
}
func setCurrentInstance(instanceName string) {
currentInstanceName = instanceName
currentInstance = instanceList[instanceName]
viper.Set("currentInstance", instanceName)
writeConfigErr := viper.WriteConfig()
if writeConfigErr != nil {
fmt.Println("Failed to save configuration:", writeConfigErr)
return
}
}
func deleteInstanceForm() {
instanceName := selectFromList("Select an instance to delete", instanceNameList, "")
delete(instanceList, instanceName)
viper.Set("instances", instanceList)
writeConfigErr := viper.WriteConfig()
if writeConfigErr != nil {
fmt.Println("Failed to save configuration:", writeConfigErr)
return
}
}
07070100000023000081A400000000000000000000000167BEEE0500000205000000000000000000000000000000000000003100000000kubero-cli-2.4.7/cmd/kuberoCli/instanceCreate.gopackage kuberoCli
/*
Copyright © 2023 NAME HERE <EMAIL ADDRESS>
*/
import (
"fmt"
"github.com/spf13/cobra"
)
// instanceCreateCmd represents the instanceCreate command
var instanceCreateCmd = &cobra.Command{
Use: "create",
Aliases: []string{"new", "cr"},
Short: "Create an new instance",
Long: `Create an new instance.`,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("instanceCreate called")
createInstanceForm()
},
}
func init() {
instanceCmd.AddCommand(instanceCreateCmd)
}
07070100000024000081A400000000000000000000000167BEEE05000001FD000000000000000000000000000000000000003100000000kubero-cli-2.4.7/cmd/kuberoCli/instanceDelete.gopackage kuberoCli
/*
Copyright © 2023 NAME HERE <EMAIL ADDRESS>
*/
import (
"fmt"
"github.com/spf13/cobra"
)
// instanceDeleteCmd represents the instanceDelete command
var instanceDeleteCmd = &cobra.Command{
Use: "delete",
Aliases: []string{"del", "rm"},
Short: "Delete an instance",
Long: `Delete an instance.`,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("instanceDelete called")
deleteInstanceForm()
},
}
func init() {
instanceCmd.AddCommand(instanceDeleteCmd)
}
07070100000025000081A400000000000000000000000167BEEE050000022E000000000000000000000000000000000000003100000000kubero-cli-2.4.7/cmd/kuberoCli/instanceSelect.gopackage kuberoCli
/*
Copyright © 2023 NAME HERE <EMAIL ADDRESS>
*/
import (
"github.com/spf13/cobra"
)
// instanceSelectCmd represents the instanceSelect command
var instanceSelectCmd = &cobra.Command{
Use: "select",
Aliases: []string{"use"},
Short: "Select an instance",
Long: `Select an instance to use.`,
Run: func(cmd *cobra.Command, args []string) {
newInstanceName := selectFromList("Select an instance", instanceNameList, "")
setCurrentInstance(newInstanceName)
},
}
func init() {
instanceCmd.AddCommand(instanceSelectCmd)
}
07070100000026000081A400000000000000000000000167BEEE05000004A8000000000000000000000000000000000000002700000000kubero-cli-2.4.7/cmd/kuberoCli/list.gopackage kuberoCli
/*
Copyright © 2023 NAME HERE <EMAIL ADDRESS>
*/
import (
"fmt"
"os"
"github.com/i582/cfmt/cmd/cfmt"
"github.com/spf13/cobra"
)
// listCmd represents the list command
var listCmd = &cobra.Command{
Use: "list",
Aliases: []string{"ls"},
Short: "List pipelines and apps",
Long: `List pipelines and apps`,
Run: func(cmd *cobra.Command, args []string) {
if pipelineName != "" {
// get a single pipeline
pipelineResp, err := client.Get("/api/cli/pipelines/" + pipelineName)
if pipelineResp.StatusCode() == 404 {
_, _ = cfmt.Println("{{ Pipeline not found}}::red")
os.Exit(1)
}
if err != nil {
fmt.Println(err)
os.Exit(1)
}
printPipeline(pipelineResp)
appsList()
} else {
// get the pipelines
pipelineListResp, err := client.Get("/api/cli/pipelines")
if err != nil {
fmt.Println(err)
os.Exit(1)
}
printPipelinesList(pipelineListResp)
}
},
}
func init() {
rootCmd.AddCommand(listCmd)
listCmd.Flags().StringVarP(&pipelineName, "pipeline", "p", "", "name of the pipeline")
listCmd.PersistentFlags().StringVarP(&outputFormat, "output", "o", "table", "output format [table, json]")
}
07070100000027000081A400000000000000000000000167BEEE0500000409000000000000000000000000000000000000002800000000kubero-cli-2.4.7/cmd/kuberoCli/login.gopackage kuberoCli
import (
"fmt"
"github.com/spf13/cobra"
)
// loginCmd represents the login command
var loginCmd = &cobra.Command{
Use: "login",
Short: "Login to your Kubero instance",
Long: `Use the login subcommand to login to your Kubero instance.`,
Run: func(cmd *cobra.Command, args []string) {
ensureIntanceOrCreate()
setKuberoCredentials("")
},
}
func init() {
rootCmd.AddCommand(loginCmd)
}
func ensureIntanceOrCreate() {
instanceNameList = append(instanceNameList, "<create new>")
instanceName := selectFromList("Select an instance", instanceNameList, currentInstanceName)
if instanceName == "<create new>" {
createInstanceForm()
} else {
setCurrentInstance(instanceName)
}
}
func setKuberoCredentials(token string) {
if token == "" {
token = promptLine("Kubero Token", "", "")
}
credentialsConfig.Set(currentInstanceName, token)
writeConfigErr := credentialsConfig.WriteConfig()
if writeConfigErr != nil {
fmt.Println("Error writing config file: ", writeConfigErr)
return
}
}
07070100000028000081A400000000000000000000000167BEEE0500001344000000000000000000000000000000000000002B00000000kubero-cli-2.4.7/cmd/kuberoCli/pipeline.gopackage kuberoCli
import (
"encoding/json"
"fmt"
"kubero/pkg/kuberoApi"
"log"
"os"
"strconv"
"github.com/go-resty/resty/v2"
"github.com/i582/cfmt/cmd/cfmt"
"github.com/olekukonko/tablewriter"
"github.com/spf13/viper"
)
func loadAllLocalPipelines() pipelinesConfigsList {
pipelines := getAllLocalPipelines()
//var pipelinesConfigsList pipelinesConfigsList
pipelinesConfigsList := make(pipelinesConfigsList)
for _, pipeline := range pipelines {
pipelinesConfigsList[pipeline] = loadLocalPipeline(pipeline)
}
return pipelinesConfigsList
}
func printPipeline(r *resty.Response) {
//fmt.Println(r)
var pipeline Pipeline
unmarshalErr := json.Unmarshal(r.Body(), &pipeline)
if unmarshalErr != nil {
fmt.Println("Error: ", "Unable to decode response")
return
}
_, _ = cfmt.Printf("{{Name:}}::lightWhite %v \n", pipeline.Name)
_, _ = cfmt.Printf("{{BuildPack:}}::lightWhite %v\n", pipeline.BuildPack.Name)
_, _ = cfmt.Printf("{{Language:}}::lightWhite %v\n", pipeline.BuildPack.Language)
if pipeline.DockerImage != "" {
fmt.Printf("{{Docker Image:}}::lightWhite %v \n", pipeline.DockerImage)
}
_, _ = cfmt.Printf("{{Deployment Strategy:}}::lightWhite %v \n", pipeline.DeploymentStrategy)
_, _ = cfmt.Printf("{{Git:}}::lightWhite %v:%v \n", pipeline.Git.Repository.SshUrl, pipeline.Git.Repository.DefaultBranch)
}
// print the response as a table
func printPipelinesList(r *resty.Response) {
table := tablewriter.NewWriter(os.Stdout)
//table.SetAutoFormatHeaders(true)
//table.SetBorder(false)
//table.SetAlignment(tablewriter.ALIGN_CENTER)
table.SetHeader([]string{
"Name",
"Repository",
//"Branch",
"BuildPack",
"reviewapps",
"test",
"staging",
"production",
//"Docker Image",
//"Deployment Strategy",
//"Review Apps"
})
var pipelinesList PipelinesList
unmarshalErr := json.Unmarshal(r.Body(), &pipelinesList)
if unmarshalErr != nil {
fmt.Println("Error: ", "Unable to decode response")
return
}
for _, pipeline := range pipelinesList.Items {
table.Append([]string{
pipeline.Name,
pipeline.Git.Repository.SshUrl,
//pipeline.Git.Repository.DefaultBranch,
pipeline.BuildPack.Name,
//pipeline.DockerImage,
//pipeline.DeploymentStrategy,
//fmt.Sprintf("%t", pipeline.ReviewApps)
boolToEmoji(pipeline.Phases[0].Enabled),
boolToEmoji(pipeline.Phases[1].Enabled),
boolToEmoji(pipeline.Phases[2].Enabled),
boolToEmoji(pipeline.Phases[3].Enabled),
})
}
printCLI(table, r)
}
func getAllRemotePipelines() []string {
var pipelinesList PipelinesList
res, err := api.GetPipelines()
if err != nil {
fmt.Println("Error: ", "Unable to load pipelines")
fmt.Println(err)
os.Exit(1)
}
unmarshalErr := json.Unmarshal(res.Body(), &pipelinesList)
if unmarshalErr != nil {
fmt.Println("Error: ", "Unable to decode response")
return nil
}
var pipelines []string
pipelines = make([]string, 0)
for _, pipeline := range pipelinesList.Items {
pipelines = append(pipelines, pipeline.Name)
}
return pipelines
}
func getAllLocalPipelines() []string {
baseDir := getIACBaseDir()
dir := baseDir + "/" + pipelineName
var pipelineNames []string
pipelineNames = make([]string, 0)
files, err := os.ReadDir(dir)
if err != nil {
log.Fatal(err)
}
for _, f := range files {
if f.IsDir() {
if _, err := os.Stat(dir + "/" + f.Name() + "/pipeline.yaml"); err == nil {
pipelineNames = append(pipelineNames, f.Name())
}
}
}
return pipelineNames
}
func getPipelinePhases(pipelineConfig *viper.Viper) []string {
var phases []string
//pipelineConfig := getPipelineConfig(pipelineName)
phasesList := pipelineConfig.GetStringSlice("spec.phases")
for p := range phasesList {
enabled := pipelineConfig.GetBool("spec.phases." + strconv.Itoa(p) + ".enabled")
if enabled {
phases = append(phases, pipelineConfig.GetString("spec.phases."+strconv.Itoa(p)+".name"))
}
}
return phases
}
func loadPipelineConfig(pipelineName string) *viper.Viper {
baseDir := getIACBaseDir()
dir := baseDir + "/" + pipelineName
pipelineConfig := viper.New()
pipelineConfig.SetConfigName("pipeline") // name of config file (without extension)
pipelineConfig.SetConfigType("yaml") // REQUIRED if the config file does not have the extension in the name
pipelineConfig.AddConfigPath(dir) // path to look for the config file in
readInConfigErr := pipelineConfig.ReadInConfig()
if readInConfigErr != nil {
fmt.Println("Error: ", "Unable to read config file")
return nil
}
return pipelineConfig
}
func loadLocalPipeline(pipelineName string) kuberoApi.PipelineCRD {
pipelineConfig := loadPipelineConfig(pipelineName)
var pipelineCRD kuberoApi.PipelineCRD
pipelineConfigUnmarshalErr := pipelineConfig.Unmarshal(&pipelineCRD)
if pipelineConfigUnmarshalErr != nil {
fmt.Println("Error: ", "Unable to unmarshal config file")
return kuberoApi.PipelineCRD{}
}
return pipelineCRD
}
07070100000029000081A400000000000000000000000167BEEE050000292B000000000000000000000000000000000000002700000000kubero-cli-2.4.7/cmd/kuberoCli/root.gopackage kuberoCli
import (
"bufio"
_ "embed"
"encoding/json"
"errors"
"fmt"
"log"
"os"
"reflect"
"strings"
"kubero/pkg/kuberoApi"
"github.com/AlecAivazis/survey/v2"
"github.com/go-git/go-billy/v5/osfs"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing/cache"
"github.com/go-git/go-git/v5/storage/filesystem"
"github.com/go-resty/resty/v2"
"github.com/i582/cfmt/cmd/cfmt"
"github.com/olekukonko/tablewriter"
"github.com/spf13/cobra"
_ "github.com/spf13/pflag"
"github.com/spf13/viper"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
var (
outputFormat string
force bool
repoSimpleList []string
client *resty.Request
api *kuberoApi.KuberoClient
contextSimpleList []string
currentInstanceName string
instanceList map[string]Instance
instanceNameList []string
currentInstance Instance
kuberoCliVersion string
pipelineConfig *viper.Viper
credentialsConfig *viper.Viper
db *gorm.DB
)
var rootCmd = &cobra.Command{
Use: "kubero",
Short: "Kubero is a platform as a service (PaaS) that enables developers to build, run, and operate applications on Kubernetes.",
Long: `
,--. ,--. ,--.
| .' /,--.,--.| |-. ,---. ,--.--. ,---.
| . ' | || || .-. '| .-. :| .--'| .-. |
| |\ \' '' '| '-' |\ --.| | ' '-' '
'--' '--' '----' '---' '----''--' '---'
Documentation:
https://docs.kubero.dev
`,
Example: `kubero install`,
Aliases: []string{"kbr"},
}
func Execute() {
rootCmd.CompletionOptions.HiddenDefaultCmd = false
SetUsageDefinition(rootCmd)
loadCLIConfig()
loadCredentials()
api = new(kuberoApi.KuberoClient)
client = api.Init(currentInstance.ApiUrl, credentialsConfig.GetString(currentInstanceName))
err := rootCmd.Execute()
if err != nil {
os.Exit(1)
}
}
func init() {
rootCmd.CompletionOptions.HiddenDefaultCmd = true
initDB()
}
func initDB() {
var err error
db, err = gorm.Open(sqlite.Open("kubero.db"), &gorm.Config{})
if err != nil {
log.Fatal("Failed to connect to database:", err)
}
autoMigrateErr := db.AutoMigrate(&Instance{})
if autoMigrateErr != nil {
log.Fatal("Failed to migrate database:", autoMigrateErr)
return
}
}
func printCLI(table *tablewriter.Table, r *resty.Response) {
if outputFormat == "json" {
fmt.Println(r)
} else {
table.Render()
}
}
func promptWarning(msg string) {
_, _ = cfmt.Println("{{\n⚠️ " + msg + ".\n}}::yellow")
}
//func promptBanner(msg string) {
// _, _ = cfmt.Printf(`
// {{ }}::bgRed
// {{ %-72s }}::bgRed|#ffffff
// {{ }}::bgRed
// `, msg)
//}
func promptLine(question, options, def string) string {
if def != "" && force {
_, _ = cfmt.Printf("\n{{?}}::green %s %s : {{%s}}::cyan\n", question, options, def)
return def
}
reader := bufio.NewReader(os.Stdin)
_, _ = cfmt.Printf("\n{{?}}::green|bold {{%s %s}}::bold {{%s}}::cyan : ", question, options, def)
text, _ := reader.ReadString('\n')
text = strings.TrimSpace(text)
if text == "" {
text = def
}
return text
}
func selectFromList(question string, options []string, def string) string {
_, _ = cfmt.Println("")
if def != "" && force {
_, _ = cfmt.Printf("\n{{?}}::green %s : {{%s}}::cyan\n", question, def)
return def
}
prompt := &survey.Select{
Message: question,
Options: options,
}
askOneErr := survey.AskOne(prompt, &def)
if askOneErr != nil {
fmt.Println("Error while selecting:", askOneErr)
return ""
}
return def
}
func confirmationLine(question, def string) bool {
confirmation := promptLine(question, "[y,n]", def)
if confirmation != "y" {
_, _ = cfmt.Println("{{\n✗ Aborted\n}}::red")
os.Exit(0)
return false
}
return true
}
func loadRepositories() {
res, err := api.GetRepositories()
if res == nil {
fmt.Println("Error: Can't reach Kubero API. Make sure, you are logged in.")
os.Exit(1)
}
if res.StatusCode() != 200 {
fmt.Println("Error:", res.StatusCode(), "Can't reach Kubero API. Make sure, you are logged in.")
os.Exit(1)
}
if err != nil {
fmt.Println("Error: Unable to load repositories")
fmt.Println(err)
os.Exit(1)
}
var availRep Repositories
jsonUnmarshalErr := json.Unmarshal(res.Body(), &availRep)
if jsonUnmarshalErr != nil {
fmt.Println("Error: Unable to load repositories")
return
}
t := reflect.TypeOf(availRep)
repoSimpleList = make([]string, t.NumField())
for i := range repoSimpleList {
if reflect.ValueOf(availRep).Field(i).Bool() {
repoSimpleList[i] = t.Field(i).Name
}
}
}
func loadContexts() {
cont, _ := api.GetContexts()
var contexts Contexts
jsonUnmarshalErr := json.Unmarshal(cont.Body(), &contexts)
if jsonUnmarshalErr != nil {
fmt.Println("Error: Unable to load contexts")
return
}
for _, context := range contexts {
contextSimpleList = append(contextSimpleList, context.Name)
}
}
func getGitRemote() string {
gitdir := getGitdir() + "/.git"
fs := osfs.New(gitdir)
s := filesystem.NewStorageWithOptions(fs, cache.NewObjectLRUDefault(), filesystem.Options{KeepDescriptors: true})
r, err := git.Open(s, fs)
if err == nil {
remotes, _ := r.Remotes()
return remotes[0].Config().URLs[0]
}
return ""
}
func getGitdir() string {
wd, _ := os.Getwd()
path := strings.Split(wd, "/")
for i := len(path); i >= 0; i-- {
subPath := strings.Join(path[:i], "/")
fileInfo, err := os.Stat(subPath + "/.git")
if err == nil && fileInfo.IsDir() {
return subPath
}
}
return ""
}
func getIACBaseDir() string {
basePath := "."
if currentInstance.IacBaseDir == "" {
currentInstance.IacBaseDir = ".kubero"
basePath += "/" + currentInstance.IacBaseDir
}
gitdir := getGitdir()
if gitdir != "" {
basePath = gitdir + "/" + currentInstance.IacBaseDir
}
if _, err := os.Stat(basePath); os.IsNotExist(err) {
_, _ = cfmt.Println("{{Creating directory}}::yellow " + basePath)
mkDirAllErr := os.MkdirAll(basePath, 0755)
if mkDirAllErr != nil {
fmt.Println("Error while creating directory:", mkDirAllErr)
return ""
}
}
return basePath
}
//func loadConfigs(basePath, pipelineName string) {
// baseDir := getIACBaseDir()
// dir := baseDir + "/" + pipelineName
// pipelineConfig = viper.New()
// pipelineConfig.SetConfigName("pipeline")
// pipelineConfig.SetConfigType("yaml")
// pipelineConfig.AddConfigPath(dir)
// readInConfigErr := pipelineConfig.ReadInConfig()
// if readInConfigErr != nil {
// fmt.Println("Error while loading pipeline config file:", readInConfigErr)
// return
// }
//}
func loadConfigs(pipelineName string) {
baseDir := getIACBaseDir()
dir := baseDir + "/" + pipelineName
pipelineConfig = viper.New()
pipelineConfig.SetConfigName("pipeline")
pipelineConfig.SetConfigType("yaml")
pipelineConfig.AddConfigPath(dir)
readInConfigErr := pipelineConfig.ReadInConfig()
if readInConfigErr != nil {
fmt.Println("Error while loading pipeline config file:", readInConfigErr)
return
}
}
func loadCLIConfig() {
dir := getGitdir()
repoConfig := viper.New()
repoConfig.SetConfigName("kubero")
repoConfig.SetConfigType("yaml")
repoConfig.AddConfigPath(dir)
repoConfig.ConfigFileUsed()
errCred := repoConfig.ReadInConfig()
viper.SetDefault("api.url", "http://default:2000")
viper.SetConfigName("kubero")
viper.SetConfigType("yaml")
viper.AddConfigPath("/etc/kubero/")
viper.AddConfigPath("$HOME/.kubero/")
err := viper.ReadInConfig()
if err != nil && errCred != nil {
var configFileNotFoundError viper.ConfigFileNotFoundError
if errors.As(err, &configFileNotFoundError) {
fmt.Println("No config file found; using defaults")
} else {
fmt.Println("Error while loading config file:", err)
return
}
}
viperUnmarshalErr := viper.UnmarshalKey("instances", &instanceList)
if viperUnmarshalErr != nil {
fmt.Println("Error while unmarshalling instances:", viperUnmarshalErr)
return
}
for instanceName, instance := range instanceList {
instance.Name = instanceName
instance.ConfigPath = viper.ConfigFileUsed()
instanceList[instanceName] = instance
}
var repoInstancesList map[string]Instance
unmarshalKeyErr := repoConfig.UnmarshalKey("instances", &repoInstancesList)
if unmarshalKeyErr != nil {
fmt.Println("Error while unmarshalling instances:", unmarshalKeyErr)
return
}
for instanceName, repoInstance := range repoInstancesList {
repoInstance.Name = instanceName
repoInstance.ConfigPath = repoConfig.ConfigFileUsed()
instanceList[instanceName] = repoInstance
}
currentInstanceName = viper.GetString("currentInstance")
for instanceName, instance := range instanceList {
instance.Name = instanceName
instanceNameList = append(instanceNameList, instanceName)
if instanceName == currentInstanceName {
currentInstance = instance
}
}
}
func loadCredentials() {
credentialsConfig = viper.New()
credentialsConfig.SetConfigName("credentials")
credentialsConfig.SetConfigType("yaml")
credentialsConfig.AddConfigPath("/etc/kubero/")
credentialsConfig.AddConfigPath("$HOME/.kubero/")
err := credentialsConfig.ReadInConfig()
if err != nil {
fmt.Println("Error while loading credentialsConfig file:", err)
}
}
func boolToEmoji(b bool) string {
if b {
return "✅"
}
return "❌"
}
func ensurePipelineIsSet(pipelinesList []string) {
if pipelineName == "" {
fmt.Println("")
prompt := &survey.Select{
Message: "Select a pipeline",
Options: pipelinesList,
}
askOneErr := survey.AskOne(prompt, &pipelineName)
if askOneErr != nil {
fmt.Println("Error while selecting pipeline:", askOneErr)
return
}
}
}
func ensureAppNameIsSet() {
if appName == "" {
appName = promptLine("Define a app name", "", appName)
}
}
func ensureStageNameIsSet() {
if stageName == "" {
fmt.Println("")
pipelineConfig := loadPipelineConfig(pipelineName)
availablePhases := getPipelinePhases(pipelineConfig)
prompt := &survey.Select{
Message: "Select a stage",
Options: availablePhases,
}
askOneErr := survey.AskOne(prompt, &stageName)
if askOneErr != nil {
fmt.Println("Error while selecting stage:", askOneErr)
return
}
}
}
func ensureAppNameIsSelected(availableApps []string) {
if appName == "" {
fmt.Println("")
prompt := &survey.Select{
Message: "Select an app",
Options: availableApps,
}
askOneErr := survey.AskOne(prompt, &appName)
if askOneErr != nil {
fmt.Println("Error while selecting app:", askOneErr)
return
}
}
}
0707010000002A000081A400000000000000000000000167BEEE0500000E8A000000000000000000000000000000000000002900000000kubero-cli-2.4.7/cmd/kuberoCli/tunnel.gopackage kuberoCli
/*
Copyright © 2023 NAME HERE <EMAIL ADDRESS>
*/
import (
"fmt"
"os"
"regexp"
"strconv"
"time"
"github.com/go-resty/resty/v2"
"github.com/i582/cfmt/cmd/cfmt"
"github.com/jonasfj/go-localtunnel"
"github.com/leaanthony/spinner"
"github.com/spf13/cobra"
)
var tunnelHost string
var tunnelPort int
var tunnelSubdomain string
var tunnelDuration string
// tunnelCmd represents the tunnel command
var tunnelCmd = &cobra.Command{
Use: "tunnel",
Short: cfmt.Sprint("Create a tunnel to the cluster in NATed infrastructures {{[BETA]}}::cyan "),
Long: `Use the tunnel subcommand to create a tunnel to the cluster in NATed infrastructures.`,
Run: func(cmd *cobra.Command, args []string) {
startTunnel()
},
}
func init() {
rootCmd.AddCommand(tunnelCmd)
tunnelCmd.Flags().StringVarP(&tunnelHost, "host", "H", "localhost", "Hostname")
tunnelCmd.Flags().IntVarP(&tunnelPort, "port", "p", 80, "Port to use")
tunnelCmd.Flags().StringVarP(&tunnelDuration, "timeout", "t", "1h", "Timeout for the tunnel")
tunnelCmd.Flags().StringVarP(&tunnelSubdomain, "subdomain", "s", "", "Subdomain to use ('-' to generate a random one)")
}
func startTunnel() {
promptWarning("WARNING: your traffic will routed thru localtunnel.me")
if tunnelSubdomain == "" {
tunnelSubdomainSugestion := "kubero-" + generateRandomString(10, "abcdefghijklmnopqrstuvwxyz0123456789")
if currentInstance.Tunnel.Subdomain != "" {
tunnelSubdomainSugestion = currentInstance.Tunnel.Subdomain
} else if currentInstance.Name != "" {
tunnelSubdomainSugestion = "kubero-" + currentInstance.Name
}
tunnelSubdomain = promptLine("Subdomain", "", tunnelSubdomainSugestion)
}
// Check if subdomain is valid
// localtunnel.me allows only lowercasae letters, numbers and dashes
if !regexp.MustCompile(`^[a-z0-9-]+$`).MatchString(tunnelSubdomain) {
_, _ = cfmt.Println("{{✖}}::red Subdomain {{" + tunnelSubdomain + "}}::yellow can only contain lowercase letters, numbers and dashes")
os.Exit(1)
}
// genereate a subdomain if the user entered "-"
if tunnelSubdomain == "-" {
tunnelSubdomain = ""
}
ipclient := resty.New().R()
ipres, err := ipclient.Get("https://api.ipify.org")
if err != nil {
_, _ = cfmt.Println("{{✖}}::red Error getting your IP")
os.Exit(1)
}
_, _ = cfmt.Println()
_, _ = cfmt.Println(" Endpoint IP (Tunnel Password) : {{" + ipres.String() + "}}::cyan")
_, _ = cfmt.Println(" Destination Host : {{" + tunnelHost + "}}::cyan")
_, _ = cfmt.Println(" Destination Port : {{" + strconv.Itoa(tunnelPort) + "}}::cyan\n\n")
spinnerObj := spinner.New()
spinnerObj.Start("Waiting for tunnel to be ready")
tunnel, err := localtunnel.New(
tunnelPort,
tunnelHost,
localtunnel.Options{
Subdomain: tunnelSubdomain,
//BaseURL: "https://localtunnel.me",
MaxConnections: 5,
},
)
if err != nil {
spinnerObj.Error("Error creating tunnel : " + err.Error())
//cfmt.Println("{{✖}}::red Error creating tunnel : " + err.Error() + "")
os.Exit(1)
}
defer func(tunnel *localtunnel.LocalTunnel) {
localTunnelErr := tunnel.Close()
if localTunnelErr != nil {
fmt.Println("Error closing tunnel : " + localTunnelErr.Error())
}
}(tunnel)
spinnerObj.UpdateMessage(cfmt.Sprint("Tunnel active at {{" + tunnel.URL() + "}}::cyan with an expiration of {{" + tunnelDuration + "}}::cyan"))
//cfmt.Println("{{✔}}::green Tunnel created at {{" + tunnel.URL() + "}}::cyan with an expiration of {{" + tunnelDuration + "}}::cyan")
tunnelTimeout, err := time.ParseDuration(tunnelDuration)
if err != nil {
_, _ = cfmt.Println("{{✗}}::red Error parsing timeout")
os.Exit(1)
}
time.Sleep(tunnelTimeout * time.Second)
}
0707010000002B000081A400000000000000000000000167BEEE0500003385000000000000000000000000000000000000002800000000kubero-cli-2.4.7/cmd/kuberoCli/types.gopackage kuberoCli
import (
"gorm.io/gorm"
"kubero/pkg/kuberoApi"
"time"
)
type Pipeline struct {
gorm.Model
BuildPack struct {
Build struct {
Command string `json:"command" gorm:"column:command"`
Repository string `json:"repository" gorm:"column:repository"`
Tag string `json:"tag" gorm:"column:tag"`
} `json:"build" gorm:"embedded"`
Fetch struct {
Repository string `json:"repository" gorm:"column:repository"`
Tag string `json:"tag" gorm:"column:tag"`
} `json:"fetch" gorm:"embedded"`
Language string `json:"language" gorm:"column:language"`
Name string `json:"name" gorm:"column:name"`
Run struct {
Command string `json:"command" gorm:"column:command"`
Repository string `json:"repository" gorm:"column:repository"`
Tag string `json:"tag" gorm:"column:tag"`
} `json:"run" gorm:"embedded"`
} `json:"buildpack" gorm:"embedded"`
DeploymentStrategy string `json:"deploymentstrategy" gorm:"column:deploymentstrategy"`
DockerImage string `json:"dockerimage" gorm:"column:dockerimage"`
Git struct {
Keys struct {
ReadOnly bool `json:"read_only" gorm:"column:read_only"`
Title string `json:"title" gorm:"column:title"`
URL string `json:"url" gorm:"column:url"`
Verified bool `json:"verified" gorm:"column:verified"`
} `json:"keys" gorm:"embedded"`
Repository struct {
Admin bool `json:"admin" gorm:"column:admin"`
CloneURL string `json:"clone_url" gorm:"column:clone_url"`
DefaultBranch string `json:"default_branch" gorm:"column:default_branch"`
Description string `json:"description" gorm:"column:description"`
Homepage string `json:"homepage" gorm:"column:homepage"`
ID int `json:"id" gorm:"column:id"`
Language string `json:"language" gorm:"column:language"`
Name string `json:"name" gorm:"column:name"`
NodeID string `json:"node_id" gorm:"column:node_id"`
Owner string `json:"owner" gorm:"column:owner"`
Private bool `json:"private" gorm:"column:private"`
Push bool `json:"push" gorm:"column:push"`
SshUrl string `json:"ssh_url" gorm:"column:ssh_url"`
Visibility string `json:"visibility" gorm:"column:visibility"`
} `json:"repository" gorm:"embedded"`
Webhook struct {
Active bool `json:"active" gorm:"column:active"`
CreatedAt time.Time `json:"created_at" gorm:"column:created_at"`
Events []string `json:"events" gorm:"column:events"`
Insecure string `json:"insecure" gorm:"column:insecure"`
URL string `json:"url" gorm:"column:url"`
} `json:"webhook" gorm:"embedded"`
} `json:"git" gorm:"embedded"`
Name string `json:"name" gorm:"column:name"`
Phases []Phase `json:"phases" gorm:"foreignKey:PipelineID"`
ReviewApps bool `json:"reviewapps" gorm:"column:reviewapps"`
}
type Phase struct {
gorm.Model
PipelineID uint `gorm:"column:pipeline_id"`
Context string `json:"context" gorm:"column:context"`
Enabled bool `json:"enabled" gorm:"column:enabled"`
Name string `json:"name" gorm:"column:name"`
Apps []App `json:"apps" gorm:"foreignKey:PhaseID"`
}
type PipelinesList struct {
Items []Pipeline `json:"items"`
}
type Contexts []struct {
Cluster string `json:"cluster"`
Name string `json:"name"`
User string `json:"user"`
}
type Repositories struct {
Github bool `json:"github"`
Gitea bool `json:"gitea"`
Gitlab bool `json:"gitlab"`
Bitbucket bool `json:"bitbucket"`
Docker bool `json:"docker"`
}
type App struct {
gorm.Model
PhaseID uint `gorm:"column:phase_id"`
Addons []interface{} `json:"addons" gorm:"-"`
Autodeploy bool `json:"autodeploy" gorm:"column:autodeploy"`
Autoscale bool `json:"autoscale" gorm:"column:autoscale"`
Autoscaling struct {
Enabled bool `json:"enabled" gorm:"column:enabled"`
} `json:"autoscaling" gorm:"embedded"`
Branch string `json:"branch" gorm:"column:branch"`
CronJobs []interface{} `json:"cronjobs" gorm:"-"`
DeploymentStrategy string `json:"deploymentstrategy" gorm:"column:deploymentstrategy"`
Domain string `json:"domain" gorm:"column:domain"`
EnvVars []interface{} `json:"envVars" gorm:"-"`
FullnameOverride string `json:"fullnameOverride" gorm:"column:fullnameOverride"`
Gitrepo struct {
Admin bool `json:"admin" gorm:"column:admin"`
CloneURL string `json:"clone_url" gorm:"column:clone_url"`
DefaultBranch string `json:"default_branch" gorm:"column:default_branch"`
Description string `json:"description" gorm:"column:description"`
Homepage string `json:"homepage" gorm:"column:homepage"`
ID int `json:"id" gorm:"column:id"`
Language string `json:"language" gorm:"column:language"`
Name string `json:"name" gorm:"column:name"`
NodeID string `json:"node_id" gorm:"column:node_id"`
Owner string `json:"owner" gorm:"column:owner"`
Private bool `json:"private" gorm:"column:private"`
Push bool `json:"push" gorm:"column:push"`
SshUrl string `json:"ssh_url" gorm:"column:ssh_url"`
Visibility string `json:"visibility" gorm:"column:visibility"`
} `json:"gitrepo" gorm:"embedded"`
Image struct {
Build struct {
Command string `json:"command" gorm:"column:command"`
Repository string `json:"repository" gorm:"column:repository"`
Tag string `json:"tag" gorm:"column:tag"`
} `json:"build" gorm:"embedded"`
ContainerPort int `json:"containerPort" gorm:"column:containerPort"`
Fetch struct {
Repository string `json:"repository" gorm:"column:repository"`
Tag string `json:"tag" gorm:"column:tag"`
} `json:"fetch" gorm:"embedded"`
PullPolicy string `json:"pullPolicy" gorm:"column:pullPolicy"`
Repository string `json:"repository" gorm:"column:repository"`
Run struct {
Command string `json:"command" gorm:"column:command"`
Repository string `json:"repository" gorm:"column:repository"`
Tag string `json:"tag" gorm:"column:tag"`
} `json:"run" gorm:"embedded"`
Tag string `json:"tag" gorm:"column:tag"`
} `json:"image" gorm:"embedded"`
ImagePullSecrets []interface{} `json:"imagePullSecrets" gorm:"-"`
Ingress struct {
Annotations struct {
} `json:"annotations" gorm:"-"`
ClassName string `json:"className" gorm:"column:className"`
Enabled bool `json:"enabled" gorm:"column:enabled"`
Hosts []struct {
Host string `json:"host" gorm:"column:host"`
Paths []struct {
Path string `json:"path" gorm:"column:path"`
PathType string `json:"pathType" gorm:"column:pathType"`
} `json:"paths" gorm:"-"`
} `json:"hosts" gorm:"-"`
TLS []interface{} `json:"tls" gorm:"-"`
} `json:"ingress" gorm:"embedded"`
Name string `json:"name" gorm:"column:name"`
NameOverride string `json:"nameOverride" gorm:"column:nameOverride"`
NodeSelector struct {
} `json:"nodeSelector" gorm:"-"`
Phase string `json:"phase" gorm:"column:phase"`
Pipeline string `json:"pipeline" gorm:"column:pipeline"`
PodAnnotations struct {
} `json:"podAnnotations" gorm:"-"`
PodSecurityContext struct {
} `json:"podSecurityContext" gorm:"-"`
PodSize string `json:"podsize" gorm:"column:podsize"`
ReplicaCount int `json:"replicaCount" gorm:"column:replicaCount"`
Service struct {
Port int `json:"port" gorm:"column:port"`
Type string `json:"type" gorm:"column:type"`
} `json:"service" gorm:"embedded"`
ServiceAccount struct {
Annotations struct {
} `json:"annotations" gorm:"-"`
Create bool `json:"create" gorm:"column:create"`
Name string `json:"name" gorm:"column:name"`
} `json:"serviceAccount" gorm:"embedded"`
Tolerations []interface{} `json:"tolerations" gorm:"-"`
Web Web `json:"web" gorm:"embedded"`
Worker Worker `json:"worker" gorm:"embedded"`
}
type Web struct {
Autoscaling struct {
MaxReplicas int `json:"maxReplicas" gorm:"column:maxReplicas"`
MinReplicas int `json:"minReplicas" gorm:"column:minReplicas"`
TargetCPUUtilizationPercentage int `json:"targetCPUUtilizationPercentage" gorm:"column:targetCPUUtilizationPercentage"`
TargetMemoryUtilizationPercentage int `json:"targetMemoryUtilizationPercentage" gorm:"column:targetMemoryUtilizationPercentage"`
} `json:"autoscaling" gorm:"embedded"`
ReplicaCount int `json:"replicaCount" gorm:"column:replicaCount"`
}
type Worker struct {
Autoscaling struct {
MaxReplicas int `json:"maxReplicas" gorm:"column:maxReplicas"`
MinReplicas int `json:"minReplicas" gorm:"column:minReplicas"`
TargetCPUUtilizationPercentage int `json:"targetCPUUtilizationPercentage" gorm:"column:targetCPUUtilizationPercentage"`
TargetMemoryUtilizationPercentage int `json:"targetMemoryUtilizationPercentage" gorm:"column:targetMemoryUtilizationPercentage"`
} `json:"autoscaling" gorm:"embedded"`
ReplicaCount int `json:"replicaCount" gorm:"column:replicaCount"`
}
type Addon struct {
gorm.Model
ID string `json:"id" gorm:"column:id"`
Enabled bool `json:"enabled" gorm:"column:enabled"`
Version struct {
Latest string `json:"latest" gorm:"column:latest"`
Installed string `json:"installed" gorm:"column:installed"`
} `json:"version,omitempty" gorm:"embedded"`
Description string `json:"description,omitempty" gorm:"column:description"`
Readme string `json:"readme,omitempty" gorm:"column:readme"`
ArtifactURL string `json:"artifact_url" gorm:"column:artifact_url"`
Kind string `json:"kind" gorm:"column:kind"`
Install string `json:"install" gorm:"column:install"`
Beta bool `json:"beta" gorm:"column:beta"`
}
type buildPacks []struct {
Name string `json:"name" gorm:"column:name"`
Language string `json:"language" gorm:"column:language"`
Fetch struct {
Repository string `json:"repository" gorm:"column:repository"`
Tag string `json:"tag" gorm:"column:tag"`
} `json:"fetch" gorm:"embedded"`
Build struct {
Repository string `json:"repository" gorm:"column:repository"`
Tag string `json:"tag" gorm:"column:tag"`
Command string `json:"command" gorm:"column:command"`
} `json:"build" gorm:"embedded"`
Run struct {
Repository string `json:"repository" gorm:"column:repository"`
Tag string `json:"tag" gorm:"column:tag"`
ReadOnlyAppStorage bool `json:"readOnlyAppStorage" gorm:"column:readOnlyAppStorage"`
SecurityContext *struct {
AllowPrivilegeEscalation *bool `json:"allowPrivilegeEscalation" gorm:"column:allowPrivilegeEscalation"`
ReadOnlyRootFilesystem *bool `json:"readOnlyRootFilesystem" gorm:"column:readOnlyRootFilesystem"`
} `json:"securityContext" gorm:"embedded"`
Command string `json:"command" gorm:"column:command"`
} `json:"run,omitempty" gorm:"embedded"`
}
type PodSize struct {
Name string `json:"name" gorm:"column:name"`
Description string `json:"description" gorm:"column:description"`
Default bool `json:"default,omitempty" gorm:"column:default"`
Resources struct {
Requests struct {
Memory string `json:"memory" gorm:"column:memory"`
CPU string `json:"cpu" gorm:"column:cpu"`
} `json:"requests" gorm:"embedded"`
Limits struct {
Memory string `json:"memory" gorm:"column:memory"`
CPU string `json:"cpu" gorm:"column:cpu"`
} `json:"limits,omitempty" gorm:"embedded"`
} `json:"resources,omitempty" gorm:"embedded"`
Active bool `json:"active,omitempty" gorm:"column:active"`
}
type pipelinesConfigsList map[string]kuberoApi.PipelineCRD
type appShort struct {
Name string `json:"name" gorm:"column:name"`
Phase string `json:"phase" gorm:"column:phase"`
Pipeline string `json:"pipeline" gorm:"column:pipeline"`
}
type Instance struct {
gorm.Model
Name string `json:"-" yaml:"-"`
ApiUrl string `json:"apiurl" yaml:"apiurl" gorm:"column:apiurl"`
IacBaseDir string `json:"iacBaseDir,omitempty" yaml:"iacBaseDir,omitempty" gorm:"column:iacBaseDir"`
ConfigPath string `json:"-" yaml:"-"`
Tunnel struct {
Subdomain string `json:"subdomain" yaml:"subdomain" gorm:"column:subdomain"`
Port int `json:"port" yaml:"port" gorm:"column:port"`
Host string `json:"host" yaml:"host" gorm:"column:host"`
} `json:"tunnel,omitempty" yaml:"tunnel,omitempty" gorm:"embedded"`
}
type Config struct {
gorm.Model
Api struct {
Url string `json:"url" yaml:"url" gorm:"column:url"`
Token string `json:"token" yaml:"token" gorm:"column:token"`
} `json:"api" yaml:"api" gorm:"embedded"`
}
type GithubVersion struct {
gorm.Model
Name string `json:"name" gorm:"column:name"`
ZipballUrl string `json:"zipball_url" gorm:"column:zipball_url"`
TarballURL string `json:"tarball_url" gorm:"column:tarball_url"`
Commit struct {
Sha string `json:"sha" gorm:"column:sha"`
URL string `json:"url" gorm:"column:url"`
} `json:"commit" gorm:"embedded"`
NodeID string `json:"node_id" gorm:"column:node_id"`
}
0707010000002C000081A400000000000000000000000167BEEE050000096F000000000000000000000000000000000000002500000000kubero-cli-2.4.7/cmd/kuberoCli/up.gopackage kuberoCli
import (
"github.com/i582/cfmt/cmd/cfmt"
"github.com/spf13/cobra"
)
// upCmd represents the up command
var upCmd = &cobra.Command{
Use: "up",
Aliases: []string{"deploy", "dp"},
Short: "Deploy your pipelines and apps to the cluster",
Long: ``,
Run: func(cmd *cobra.Command, args []string) {
if pipelineName != "" && appName == "" {
pipelinesList := getAllLocalPipelines()
ensurePipelineIsSet(pipelinesList)
upPipeline()
} else if appName != "" {
pipelinesList := getAllLocalPipelines()
ensurePipelineIsSet(pipelinesList)
upApp()
} else {
upAllPipelines()
}
},
}
func init() {
rootCmd.AddCommand(upCmd)
upCmd.Flags().StringVarP(&pipelineName, "pipeline", "p", "", "name of the pipeline")
upCmd.Flags().StringVarP(&stageName, "stage", "s", "", "Name of the stage [test|stage|production]")
upCmd.Flags().StringVarP(&appName, "app", "a", "", "name of the app")
upCmd.PersistentFlags().BoolVarP(&force, "force", "f", false, "Skip asking for confirmation")
}
func upPipeline() {
confirmationLine("Are you sure you want to deploy the pipeline '"+pipelineName+"'?", "y")
pipeline := loadLocalPipeline(pipelineName)
_, deployPipelineErr := api.DeployPipeline(pipeline)
if deployPipelineErr != nil {
_, _ = cfmt.Println("{{Error deploying pipeline}}::red", deployPipelineErr)
return
}
}
func upApp() {
confirmationLine("Are you sure you want to deploy the app "+appName+" to "+pipelineName+"?", "y")
app := loadLocalApp(pipelineName, stageName, appName)
app.Spec.Pipeline = pipelineName // ensure pipeline is set
app.Spec.Phase = stageName // ensure stage is set
app.Spec.Security.VulnerabilityScans = false // TODO: ask for this
_, DeployAppErr := api.DeployApp(app)
if DeployAppErr != nil {
_, _ = cfmt.Println("{{Error deploying app}}::red", DeployAppErr)
return
}
}
func upAllPipelines() {
confirmationLine("Are you sure you want to deploy all pipelines?", "y")
pipelinesConfigs := loadAllLocalPipelines()
_, _ = cfmt.Println("{{Deploying all pipelines}}::yellow")
for _, pipelineCRD := range pipelinesConfigs {
_, _ = cfmt.Println("{{Deploying pipeline}}::yellow " + pipelineCRD.Spec.Name + "")
_, deployPipelineErr := api.DeployPipeline(pipelineCRD)
if deployPipelineErr != nil {
_, _ = cfmt.Println("{{Error deploying pipeline}}::red", deployPipelineErr)
return
}
}
}
0707010000002D000081A400000000000000000000000167BEEE0500000405000000000000000000000000000000000000002800000000kubero-cli-2.4.7/cmd/kuberoCli/upApp.gopackage kuberoCli
/*
Copyright © 2023 NAME HERE <EMAIL ADDRESS>
*/
import (
"os"
"github.com/i582/cfmt/cmd/cfmt"
"github.com/spf13/cobra"
)
// appCmd represents the app command
var upAppCmd = &cobra.Command{
Use: "app",
Short: "Deploy an apps to the cluster",
Long: `Use the app subcommand to deploy your apps to the cluster`,
Run: func(cmd *cobra.Command, args []string) {
pipelinesList := getAllLocalPipelines()
ensurePipelineIsSet(pipelinesList)
ensureStageNameIsSet()
appsList := getAllLocalApps()
if len(appsList) == 0 {
_, _ = cfmt.Println("\n{{ERROR:}}::red No apps found in pipeline '" + pipelineName + "'")
os.Exit(1)
}
ensureAppNameIsSelected(appsList)
upApp()
},
}
func init() {
upCmd.AddCommand(upAppCmd)
upAppCmd.Flags().StringVarP(&pipelineName, "pipeline", "p", "", "name of the pipeline")
upAppCmd.Flags().StringVarP(&stageName, "stage", "s", "", "Name of the stage [test|stage|production]")
upAppCmd.Flags().StringVarP(&appName, "app", "a", "", "name of the app")
}
0707010000002E000081A400000000000000000000000167BEEE0500000293000000000000000000000000000000000000002D00000000kubero-cli-2.4.7/cmd/kuberoCli/upPipeline.gopackage kuberoCli
/*
Copyright © 2023 NAME HERE <EMAIL ADDRESS>
*/
import (
"github.com/spf13/cobra"
)
// pipelineCmd represents the pipeline command
var upPipelineCmd = &cobra.Command{
Use: "pipeline",
Aliases: []string{"pl"},
Short: "Deploy a pipeline to the cluster",
Long: `Use the pipeline subcommand to deploy your pipelines to the cluster`,
Run: func(cmd *cobra.Command, args []string) {
pipelinesList := getAllLocalPipelines()
ensurePipelineIsSet(pipelinesList)
upPipeline()
},
}
func init() {
upCmd.AddCommand(upPipelineCmd)
upPipelineCmd.Flags().StringVarP(&pipelineName, "pipeline", "p", "", "name of the pipeline")
}
0707010000002F000081A400000000000000000000000167BEEE05000009AC000000000000000000000000000000000000002800000000kubero-cli-2.4.7/cmd/kuberoCli/usage.gopackage kuberoCli
import (
"github.com/fatih/color"
"github.com/spf13/cobra"
)
func colorYellow(s string) string {
return color.New(color.FgYellow).SprintFunc()(s)
}
func colorGreen(s string) string {
return color.New(color.FgGreen).SprintFunc()(s)
}
func colorBlue(s string) string {
return color.New(color.FgBlue).SprintFunc()(s)
}
func colorRed(s string) string {
return color.New(color.FgRed).SprintFunc()(s)
}
func colorHelp(s string) string {
return color.New(color.FgCyan).SprintFunc()(s)
}
func hasServiceCommands(cmds []*cobra.Command) bool {
for _, cmd := range cmds {
if cmd.Annotations["service"] == "true" {
return true
}
}
return false
}
func hasModuleCommands(cmds []*cobra.Command) bool {
for _, cmd := range cmds {
if cmd.Annotations["service"] != "true" {
return true
}
}
return false
}
var cliUsageTemplate = `{{colorYellow "Usage:"}}{{if .Runnable}}
{{.UseLine}}{{end}}{{if .HasAvailableSubCommands}}
{{.CommandPath}} [command] [args]{{end}}{{if gt (len .Aliases) 0}}
{{colorYellow "Aliases:"}}
{{.NameAndAliases}}{{end}}{{if .HasExample}}
{{colorYellow "Example:"}}
{{.Example}}{{end}}{{if .HasAvailableSubCommands}}
{{colorYellow "Available Commands:"}}
{{range .Commands}}{{if (or .IsAvailableCommand (eq .Name "help"))}}
{{colorGreen (rpad .Name .NamePadding) }} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableLocalFlags}}
{{colorYellow "Flags:"}}
{{.LocalFlags.FlagUsages | trimTrailingWhitespaces | colorHelp}}{{end}}{{if .HasAvailableInheritedFlags}}
{{colorYellow "Global Options:"}}
{{.InheritedFlags.FlagUsages | trimTrailingWhitespaces | colorHelp}}{{end}}{{if .HasHelpSubCommands}}
{{colorYellow "Additional help topics:"}}
{{range .Commands}}{{if .IsHelpCommand}}
{{colorGreen (rpad .CommandPath .CommandPathPadding) }} {{.Short}}{{end}}{{end}}{{end}}{{if .HasSubCommands}}
{{colorYellow (printf "Use \"%s [command] --help\" for more information about a command." .CommandPath)}}{{end}}
`
func SetUsageDefinition(cmd *cobra.Command) {
cobra.AddTemplateFunc("colorYellow", colorYellow)
cobra.AddTemplateFunc("colorGreen", colorGreen)
cobra.AddTemplateFunc("colorRed", colorRed)
cobra.AddTemplateFunc("colorBlue", colorBlue)
cobra.AddTemplateFunc("colorHelp", colorHelp)
cobra.AddTemplateFunc("hasServiceCommands", hasServiceCommands)
cobra.AddTemplateFunc("hasModuleCommands", hasModuleCommands)
// Altera o template de uso do cobra
cmd.SetUsageTemplate(cliUsageTemplate)
}
07070100000030000081A400000000000000000000000167BEEE05000000C4000000000000000000000000000000000000001D00000000kubero-cli-2.4.7/cmd/main.go/*
Copyright © 2022 NAME HERE <EMAIL ADDRESS>
*/
package main
import "kubero/cmd/kuberoCli"
func main() {
kuberoCli.Execute()
}
// var configPath = os.Getenv("HOME") + "/.config/kubero-cli"
07070100000031000081A400000000000000000000000167BEEE0500001050000000000000000000000000000000000000001800000000kubero-cli-2.4.7/go.modmodule kubero
go 1.23.0
toolchain go1.23.5
require (
github.com/go-git/go-billy/v5 v5.6.2
github.com/go-git/go-git/v5 v5.13.2
github.com/go-resty/resty/v2 v2.16.5
github.com/i582/cfmt v1.4.0
github.com/jonasfj/go-localtunnel v0.0.0-20170326223115-8a804488f275
github.com/leaanthony/spinner v0.5.4
github.com/olekukonko/tablewriter v0.0.5
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c
github.com/spf13/cobra v1.8.1
github.com/spf13/viper v1.19.0
gopkg.in/yaml.v3 v3.0.1
gorm.io/driver/sqlite v1.5.7
gorm.io/gorm v1.25.12
)
require google.golang.org/protobuf v1.36.4 // indirect
require (
dario.cat/mergo v1.0.1 // indirect
github.com/AlecAivazis/survey/v2 v2.3.7
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/ProtonMail/go-crypto v1.1.5 // indirect
github.com/cloudflare/circl v1.5.0 // indirect
github.com/cyphar/filepath-securejoin v0.4.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/emirpasic/gods v1.18.1 // indirect
github.com/fatih/color v1.18.0
github.com/fsnotify/fsnotify v1.8.0 // indirect
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/gookit/color v1.5.4 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
github.com/kevinburke/ssh_config v1.2.0 // indirect
github.com/leaanthony/synx v0.1.0 // indirect
github.com/leaanthony/wincursor v0.1.0 // indirect
github.com/magiconair/properties v1.8.9 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.16 // indirect
github.com/mattn/go-sqlite3 v1.14.24 // indirect
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
github.com/pjbgf/sha1cd v0.3.2 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/sagikazarmark/locafero v0.7.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
github.com/skeema/knownhosts v1.3.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/afero v1.12.0 // indirect
github.com/spf13/cast v1.7.1 // indirect
github.com/spf13/pflag v1.0.6
github.com/subosito/gotenv v1.6.0 // indirect
github.com/x448/float16 v0.8.4 // indirect
github.com/xanzy/ssh-agent v0.3.3 // indirect
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/crypto v0.34.0
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 // indirect
golang.org/x/net v0.34.0 // indirect
golang.org/x/oauth2 v0.25.0 // indirect
golang.org/x/sys v0.30.0 // indirect
golang.org/x/term v0.29.0 // indirect
golang.org/x/text v0.22.0 // indirect
golang.org/x/time v0.9.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
k8s.io/apimachinery v0.32.2 // indirect
k8s.io/client-go v0.32.2
k8s.io/klog/v2 v2.130.1 // indirect
k8s.io/utils v0.0.0-20241210054802-24370beab758 // indirect
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.5.0 // indirect
sigs.k8s.io/yaml v1.4.0 // indirect
)
07070100000032000081A400000000000000000000000167BEEE05000072A3000000000000000000000000000000000000001800000000kubero-cli-2.4.7/go.sumdario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
github.com/AlecAivazis/survey/v2 v2.3.7 h1:6I/u8FvytdGsgonrYsVn2t8t4QiRnh6QSTqkkhIiSjQ=
github.com/AlecAivazis/survey/v2 v2.3.7/go.mod h1:xUTIdE4KCOIjsBAE1JYsUPoCqYdZ1reCfTwbto0Fduo=
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 h1:+vx7roKuyA63nhn5WAunQHLTznkw5W8b1Xc0dNjp83s=
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w=
github.com/ProtonMail/go-crypto v1.1.5 h1:eoAQfK2dwL+tFSFpr7TbOaPNUbPiJj4fLYwwGE1FQO4=
github.com/ProtonMail/go-crypto v1.1.5/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE=
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/cloudflare/circl v1.5.0 h1:hxIWksrX6XN5a1L2TI/h53AGPhNHoUBo+TD1ms9+pys=
github.com/cloudflare/circl v1.5.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.17 h1:QeVUsEDNrLBW4tMgZHvxy18sKtr6VI492kBhUfhDJNI=
github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
github.com/cyphar/filepath-securejoin v0.4.0 h1:PioTG9TBRSApBpYGnDU8HC+miIsX8vitBH9LGNNMoLQ=
github.com/cyphar/filepath-securejoin v0.4.0/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/elazarl/goproxy v1.4.0 h1:4GyuSbFa+s26+3rmYNSuUVsx+HgPrV1bk1jXI0l9wjM=
github.com/elazarl/goproxy v1.4.0/go.mod h1:X/5W/t+gzDyLfHW4DrMdpjqYjpXsURlBt9lpBDxZZZQ=
github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=
github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c=
github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU=
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UNbRM=
github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU=
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
github.com/go-git/go-git/v5 v5.13.2 h1:7O7xvsK7K+rZPKW6AQR1YyNhfywkv7B8/FsP3ki6Zv0=
github.com/go-git/go-git/v5 v5.13.2/go.mod h1:hWdW5P4YZRjmpGHwRH2v3zkWcNl6HeXaXQEMGb3NJ9A=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=
github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
github.com/go-resty/resty/v2 v2.16.5 h1:hBKqmWrr7uRc3euHVqmh1HTHcKn99Smr7o5spptdhTM=
github.com/go-resty/resty/v2 v2.16.5/go.mod h1:hkJtXbA2iKHzJheXYvQ8snQES5ZLGKMwQ07xAwp/fiA=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ=
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
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/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gookit/color v1.3.2/go.mod h1:R3ogXq2B9rTbXoSHJ1HyUVAZ3poOJHpd9nQmyGZsfvQ=
github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0=
github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec h1:qv2VnGeEQHchGaZ/u7lxST/RaJw+cv273q79D81Xbog=
github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec/go.mod h1:Q48J4R4DvxnHolD5P8pOtXigYlRuPLGl6moFx3ulM68=
github.com/i582/cfmt v1.4.0 h1:DNugs+dvy3xjJSUk9Oita0udy1YVQh2vDP6cWYhDCIQ=
github.com/i582/cfmt v1.4.0/go.mod h1:tpHWAxhE4Y7yy7sliaNe0pnnEs1SZe67KLljyOlEYI8=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/jonasfj/go-localtunnel v0.0.0-20170326223115-8a804488f275 h1:CHhhnqQGmniRCgMx34aIcqasiKme7gsscUYO/2rMFnk=
github.com/jonasfj/go-localtunnel v0.0.0-20170326223115-8a804488f275/go.mod h1:2jVFHClLG6ANLzONRisiL5vkbUOd82KNdQhdW4vykgY=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leaanthony/spinner v0.5.4 h1:XA2ElQgqwCg3gkTR6bJD+amKZ/VU0Ou94Vhv3W+GQug=
github.com/leaanthony/spinner v0.5.4/go.mod h1:oHlrvWicr++CVV7ALWYi+qHk/XNA91D9IJ48IqmpVUo=
github.com/leaanthony/synx v0.1.0 h1:R0lmg2w6VMb8XcotOwAe5DLyzwjLrskNkwU7LLWsyL8=
github.com/leaanthony/synx v0.1.0/go.mod h1:Iz7eybeeG8bdq640iR+CwYb8p+9EOsgMWghkSRyZcqs=
github.com/leaanthony/wincursor v0.1.0 h1:Dsyp68QcF5cCs65AMBmxoYNEm0n8K7mMchG6a8fYxf8=
github.com/leaanthony/wincursor v0.1.0/go.mod h1:7TVwwrzSH/2Y9gLOGH+VhA+bZhoWXBRgbGNTMk+yimE=
github.com/magiconair/properties v1.8.9 h1:nWcCbLq1N2v/cpNsy5WvQ37Fb+YElfq20WJ/a8RkpQM=
github.com/magiconair/properties v1.8.9/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBWDRM=
github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI=
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4=
github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
github.com/pjbgf/sha1cd v0.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4=
github.com/pjbgf/sha1cd v0.3.2/go.mod h1:zQWigSxVmsHEZow5qaLtPYxpcKMMQpa09ixqBxuCS6A=
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo=
github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k=
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/skeema/knownhosts v1.3.0 h1:AM+y0rI04VksttfwjkSTNQorvGqmwATnvnAHpSgc0LY=
github.com/skeema/knownhosts v1.3.0/go.mod h1:sPINvnADmT/qYH1kfv+ePMmOBTH6Tbl7b5LvTDjFK7M=
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs=
github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4=
github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI=
github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
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.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.34.0 h1:+/C6tk6rf/+t5DhUketUbD1aNGqiSX3j15Z6xuIDlBA=
golang.org/x/crypto v0.34.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 h1:yqrTHse8TCMW1M1ZCP+VAR/l0kKxwaAIqN/il7x4voA=
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8/go.mod h1:tujkw807nyEEAamNbDrEGzRav+ilXA7PCRAd6xsmwiU=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
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-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
golang.org/x/oauth2 v0.25.0 h1:CY4y7XT9v0cRI9oupztF8AgiIu99L/ksR/Xp/6jrZ70=
golang.org/x/oauth2 v0.25.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
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-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20181228144115-9a3f9b0469bb/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/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-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU=
golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s=
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.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
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-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
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.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM=
google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/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/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=
gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
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=
gorm.io/driver/sqlite v1.5.7 h1:8NvsrhP0ifM7LX9G4zPB97NwovUakUxc+2V2uuf3Z1I=
gorm.io/driver/sqlite v1.5.7/go.mod h1:U+J8craQU6Fzkcvu8oLeAQmi50TkwPEhHDEjQZXDah4=
gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8=
gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
k8s.io/api v0.32.2 h1:bZrMLEkgizC24G9eViHGOPbW+aRo9duEISRIJKfdJuw=
k8s.io/api v0.32.2/go.mod h1:hKlhk4x1sJyYnHENsrdCWw31FEmCijNGPJO5WzHiJ6Y=
k8s.io/apimachinery v0.32.2 h1:yoQBR9ZGkA6Rgmhbp/yuT9/g+4lxtsGYwW6dR6BDPLQ=
k8s.io/apimachinery v0.32.2/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
k8s.io/client-go v0.32.2 h1:4dYCD4Nz+9RApM2b/3BtVvBHw54QjMFUl1OLcJG5yOA=
k8s.io/client-go v0.32.2/go.mod h1:fpZ4oJXclZ3r2nDOv+Ux3XcJutfrwjKTCHz2H3sww94=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y=
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4=
k8s.io/utils v0.0.0-20241210054802-24370beab758 h1:sdbE21q2nlQtFh65saZY+rRM6x6aJJI8IUa1AmH/qa0=
k8s.io/utils v0.0.0-20241210054802-24370beab758/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE=
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
sigs.k8s.io/structured-merge-diff/v4 v4.5.0 h1:nbCitCK2hfnhyiKo6uf2HxUPTCodY6Qaf85SbDIaMBk=
sigs.k8s.io/structured-merge-diff/v4 v4.5.0/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4=
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
07070100000033000081ED00000000000000000000000167BEEE0500000A7A000000000000000000000000000000000000001C00000000kubero-cli-2.4.7/install.sh#!/usr/bin/env bash
################################################################################
# This Script is used to install kubero-cli binaries. #
# #
# Supported OS: Linux, macOS ---> Windows(not supported) #
# Supported Architecture: amd64, arm64 #
# Source: https://github.com/kubero-dev/kubero-cli #
# Binary Release: https://github.com/kubero-dev/kubero-cli/releases/latest #
# License: Apache License 2.0 #
# Usage: #
# curl -fsSL get.kubero.dev | bash #
# curl -fsSL get.kubero.dev | bash -s -- v1.10.0 #
# bash <(curl -fsSL get.kubero.dev) v1.9.2 #
################################################################################
set -eo pipefail
[[ $TRACE ]] && set -x
get_os() {
case "$(uname -s)" in
Linux*) echo "linux" ;;
Darwin*) echo "darwin" ;;
*) echo "unsupported" ;;
esac
}
get_arch() {
case "$(uname -m)" in
x86_64) echo "amd64" ;;
arm*|aarch64) echo "arm64" ;;
*) echo "unsupported" ;;
esac
}
os=$(get_os)
arch=$(get_arch)
version=${1:-latest}
if [[ "$os" == "unsupported" || "$arch" == "unsupported" ]]; then
echo "Unsupported OS or architecture."
exit 1
fi
if [[ -f "/usr/local/bin/kubero" ]]; then
read -r -p "Do you want to replace it? [y/n] " replaceBinary
[[ "$replaceBinary" != "y" && "$replaceBinary" != "" ]] && echo "Aborting installation." && exit 1
fi
release_url="https://github.com/kubero-dev/kubero-cli/releases/${version}/download/kubero-cli_${os}_${arch}.tar.gz"
temp_dir=$(mktemp -d)
echo "Downloading ${release_url} ..."
curl -L -s -o "${temp_dir}/kubero-cli.tar.gz" "$release_url" || { echo "Failed to download the binary."; rm -rf "$temp_dir"; exit 1; }
echo "Unpacking the binary..."
tar -xzvf "${temp_dir}/kubero-cli.tar.gz" -C "$temp_dir" || { echo "Failed to unpack the binary."; rm -rf "$temp_dir"; exit 1; }
[[ ! -f "${temp_dir}/kubero" ]] && { echo "Failed to unpack the binary."; rm -rf "$temp_dir"; exit 1; }
echo "Installing kubero in /usr/local/bin ..."
sudo mv "${temp_dir}/kubero" "/usr/local/bin/kubero" || { echo "Failed to install kubero."; rm -rf "$temp_dir"; exit 1; }
rm -rf "$temp_dir"
echo "Kubero has been successfully installed."
echo "Run 'kubero install' to create a kubernetes cluster."07070100000034000081A400000000000000000000000167BEEE05000000C0000000000000000000000000000000000000002500000000kubero-cli-2.4.7/kubero.yaml.exampleinstances:
kubero-examlpe:
iacBaseDir: .kubero/
apiurl: http://localhost:80
tunnel:
subdomain: kubero-local-dev-example
port: 80
host: localhost
07070100000035000041ED00000000000000000000000267BEEE0500000000000000000000000000000000000000000000001500000000kubero-cli-2.4.7/pkg07070100000036000041ED00000000000000000000000267BEEE0500000000000000000000000000000000000000000000001F00000000kubero-cli-2.4.7/pkg/kuberoApi07070100000037000081A400000000000000000000000167BEEE0500000003000000000000000000000000000000000000002700000000kubero-cli-2.4.7/pkg/kuberoApi/VERSIONdev07070100000038000081A400000000000000000000000167BEEE0500000B87000000000000000000000000000000000000002700000000kubero-cli-2.4.7/pkg/kuberoApi/main.gopackage kuberoApi
import (
_ "embed"
"github.com/go-resty/resty/v2"
)
type KuberoClient struct {
baseURL string
bearerToken string
client *resty.Request
}
//go:embed VERSION
var version string
func (k *KuberoClient) Init(baseURL string, bearerToken string) *resty.Request {
client := resty.New().SetBaseURL(baseURL).R().
EnableTrace().
SetAuthScheme("Bearer").
SetAuthToken(bearerToken).
SetHeader("Accept", "application/json").
SetHeader("Content-Type", "application/json").
SetHeader("User-Agent", "kubero-cli/"+version)
k.baseURL = baseURL
k.bearerToken = bearerToken
k.client = client
return client
}
func (k *KuberoClient) DeployPipeline(pipeline PipelineCRD) (*resty.Response, error) {
k.client.SetBody(pipeline.Spec)
res, err := k.client.Post("/api/cli/pipelines/")
return res, err
}
func (k *KuberoClient) UnDeployPipeline(pipelineName string) (*resty.Response, error) {
res, err := k.client.Delete("/api/cli/pipelines/" + pipelineName)
return res, err
}
func (k *KuberoClient) GetPipeline(pipelineName string) (*resty.Response, error) {
res, err := k.client.Get("/api/cli/pipelines/" + pipelineName)
return res, err
}
func (k *KuberoClient) UnDeployApp(pipelineName string, stageName string, appName string) (*resty.Response, error) {
res, err := k.client.Delete("/api/cli/pipelines/" + pipelineName + "/" + stageName + "/" + appName)
return res, err
}
func (k *KuberoClient) GetApp(pipelineName string, stageName string, appName string) (*resty.Response, error) {
res, err := k.client.Get("/api/cli/pipelines/" + pipelineName + "/" + stageName + "/" + appName)
return res, err
}
func (k *KuberoClient) GetApps() (*resty.Response, error) {
res, err := k.client.Get("/api/cli/apps")
return res, err
}
func (k *KuberoClient) GetPipelines() (*resty.Response, error) {
res, err := k.client.Get("/api/cli/pipelines")
return res, err
}
func (k *KuberoClient) DeployApp(app AppCRD) (*resty.Response, error) {
k.client.SetBody(app.Spec)
res, err := k.client.Post("/api/cli/apps")
return res, err
}
func (k *KuberoClient) GetPipelineApps(pipelineName string) (*resty.Response, error) {
res, err := k.client.Get("/api/cli/pipelines/" + pipelineName + "/apps")
return res, err
}
func (k *KuberoClient) GetAddons() (*resty.Response, error) {
res, err := k.client.Get("/api/cli/addons")
return res, err
}
func (k *KuberoClient) GetBuildpacks() (*resty.Response, error) {
res, err := k.client.Get("/api/cli/config/buildpacks")
return res, err
}
func (k *KuberoClient) GetPodsize() (*resty.Response, error) {
res, err := k.client.Get("/api/cli/config/podsize")
return res, err
}
func (k *KuberoClient) GetRepositories() (*resty.Response, error) {
res, err := k.client.Get("/api/cli/config/repositories")
return res, err
}
func (k *KuberoClient) GetContexts() (*resty.Response, error) {
res, err := k.client.Get("/api/cli/config/k8s/context")
return res, err
}
07070100000039000081A400000000000000000000000167BEEE0500001A32000000000000000000000000000000000000002800000000kubero-cli-2.4.7/pkg/kuberoApi/types.gopackage kuberoApi
import (
"gorm.io/gorm"
"time"
)
type Metadata struct {
gorm.Model
Name string `json:"name,omitempty" yaml:"name,omitempty"`
Labels interface{} `json:"labels,omitempty" yaml:"labels,omitempty"`
}
type GitKeys struct {
gorm.Model
ReadOnly bool `json:"read_only"`
Title string `json:"title"`
URL string `json:"url"`
Verified bool `json:"verified"`
}
type GitRepository struct {
gorm.Model
Provider string `json:"provider"`
Admin bool `json:"admin"`
CloneURL string `json:"clone_url"`
DefaultBranch string `json:"default_branch"`
Description string `json:"description"`
Homepage string `json:"homepage"`
Language string `json:"language"`
Name string `json:"name"`
NodeID string `json:"node_id" yaml:"node_id"`
Owner string `json:"owner"`
Private bool `json:"private"`
Push bool `json:"push"`
SshUrl string `json:"ssh_url"`
Visibility string `json:"visibility"`
}
type GitWebhook struct {
gorm.Model
Active bool `json:"active"`
CreatedAt time.Time `json:"created_at"`
Events []string `json:"events"`
Insecure string `json:"insecure"`
URL string `json:"url"`
}
type Git struct {
gorm.Model
Keys GitKeys `json:"keys" gorm:"embedded"`
Repository GitRepository `json:"repository" gorm:"embedded"`
Webhook GitWebhook `json:"webhook" gorm:"embedded"`
}
type Build struct {
gorm.Model
Command string `json:"command"`
Repository string `json:"repository"`
Tag string `json:"tag"`
}
type Fetch struct {
gorm.Model
Repository string `json:"repository"`
Tag string `json:"tag"`
}
type Run struct {
gorm.Model
Command string `json:"command"`
Repository string `json:"repository"`
Tag string `json:"tag"`
}
type Buildpack struct {
gorm.Model
Build Build `json:"build" gorm:"embedded"`
Fetch Fetch `json:"fetch" gorm:"embedded"`
Language string `json:"language"`
Name string `json:"name"`
Run Run `json:"run" gorm:"embedded"`
}
type Phase struct {
gorm.Model
Name string `json:"name"`
Enabled bool `json:"enabled"`
Context string `json:"context"`
}
type PipelineSpec struct {
gorm.Model
Buildpack Buildpack `json:"buildpack" gorm:"embedded"`
DeploymentStrategy string `json:"deploymentstrategy"`
Domain string `json:"domain"`
DockerImage string `json:"dockerimage,omitempty" yaml:"dockerimage,omitempty"`
Git Git `json:"git,omitempty" yaml:"git,omitempty" gorm:"embedded"`
Name string `json:"pipelineName" yaml:"pipelineName"`
Phases []Phase `json:"phases" gorm:"foreignKey:PipelineID"`
ReviewApps bool `json:"reviewapps"`
}
type PipelineCRD struct {
gorm.Model
APIVersion string `json:"apiVersion" yaml:"apiVersion"`
Kind string `json:"kind"`
Metadata Metadata `json:"metadata,omitempty" yaml:"metadata,omitempty"`
Spec PipelineSpec `json:"spec" gorm:"embedded"`
}
type AppSpec struct {
gorm.Model
Autodeploy bool `json:"autodeploy"`
Autoscale bool `json:"autoscale"`
Autoscaling struct {
Enabled bool `json:"enabled"`
} `json:"autoscaling" gorm:"embedded"`
Branch string `json:"branch"`
Buildpack string `json:"buildpack"`
Domain string `json:"domain"`
FullnameOverride string `json:"fullnameOverride" yaml:"fullnameOverride"`
Gitrepo GitRepository `json:"gitrepo" gorm:"embedded"`
Image struct {
Fetch struct {
Repository string `json:"repository"`
Tag string `json:"tag"`
} `json:"fetch" gorm:"embedded"`
Build struct {
Command string `json:"command"`
Repository string `json:"repository"`
Tag string `json:"tag"`
} `json:"build" gorm:"embedded"`
Run struct {
Command string `json:"command"`
Repository string `json:"repository"`
Tag string `json:"tag"`
} `json:"run" gorm:"embedded"`
ContainerPort int `json:"containerPort"`
PullPolicy string `json:"pullPolicy" yaml:"pullPolicy"`
Repository string `json:"repository"`
Tag string `json:"tag"`
} `json:"image" gorm:"embedded"`
Ingress struct {
ClassName string `json:"className"`
Enabled bool `json:"enabled"`
} `json:"ingress" gorm:"embedded"`
Name string `json:"appname" yaml:"appname"`
NameOverride string `json:"nameOverride" yaml:"nameOverride"`
Phase string `json:"phase"`
Pipeline string `json:"pipeline"`
PodSize string `json:"podsize"`
ReplicaCount int `json:"replicaCount" yaml:"replicaCount"`
Service struct {
Port int `json:"port"`
Type string `json:"type"`
} `json:"service" gorm:"embedded"`
ServiceAccount struct {
Create bool `json:"create"`
Name string `json:"name"`
} `json:"serviceAccount" yaml:"serviceAccount" gorm:"embedded"`
EnvVars []string `json:"envVars" gorm:"-"`
Web Web `json:"web" gorm:"embedded"`
Worker Worker `json:"worker" gorm:"embedded"`
Security struct {
VulnerabilityScans bool `json:"vulnerabilityScans,omitempty" yaml:"vulnerabilityScans,omitempty"`
} `json:"security,omitempty" yaml:"security,omitempty"`
}
type Web struct {
Autoscaling struct {
MaxReplicas int `json:"maxReplicas" gorm:"column:maxReplicas"`
MinReplicas int `json:"minReplicas" gorm:"column:minReplicas"`
TargetCPUUtilizationPercentage int `json:"targetCPUUtilizationPercentage" gorm:"column:targetCPUUtilizationPercentage"`
TargetMemoryUtilizationPercentage int `json:"targetMemoryUtilizationPercentage" gorm:"column:targetMemoryUtilizationPercentage"`
} `json:"autoscaling" gorm:"embedded"`
ReplicaCount int `json:"replicaCount" gorm:"column:replicaCount"`
}
type Worker struct {
Autoscaling struct {
MaxReplicas int `json:"maxReplicas" gorm:"column:maxReplicas"`
MinReplicas int `json:"minReplicas" gorm:"column:minReplicas"`
TargetCPUUtilizationPercentage int `json:"targetCPUUtilizationPercentage" gorm:"column:targetCPUUtilizationPercentage"`
TargetMemoryUtilizationPercentage int `json:"targetMemoryUtilizationPercentage" gorm:"column:targetMemoryUtilizationPercentage"`
} `json:"autoscaling" gorm:"embedded"`
ReplicaCount int `json:"replicaCount" gorm:"column:replicaCount"`
}
type AppCRD struct {
gorm.Model
APIVersion string `json:"apiVersion" yaml:"apiVersion"`
Kind string `json:"kind"`
Metadata Metadata `json:"metadata,omitempty" yaml:"metadata,omitempty"`
Spec AppSpec `json:"spec" gorm:"embedded"`
}
0707010000003A000041ED00000000000000000000000267BEEE0500000000000000000000000000000000000000000000001B00000000kubero-cli-2.4.7/templates0707010000003B000081A400000000000000000000000167BEEE0500000137000000000000000000000000000000000000003E00000000kubero-cli-2.4.7/templates/certmanagerClusterIssuer.prod.yamlapiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: noreply@kubero.dev
privateKeySecretRef:
name: letsencrypt
solvers:
- http01:
ingress:
class: nginx
0707010000003C000081A400000000000000000000000167BEEE050000014A000000000000000000000000000000000000003F00000000kubero-cli-2.4.7/templates/certmanagerClusterIssuer.stage.yamlapiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-staging
spec:
acme:
server: https://acme-staging-v02.api.letsencrypt.org/directory
email: noreply@kubero.dev
privateKeySecretRef:
name: letsencrypt-staging
solvers:
- http01:
ingress:
class: nginx
0707010000003D000081A400000000000000000000000167BEEE050000005D000000000000000000000000000000000000002D00000000kubero-cli-2.4.7/templates/kindVersions.yamlavailableKubernetesVersions:
- v1.31.4
- v1.30.8
- v1.29.12
- v1.28.15
- v1.27.16
- v1.26.15
07070100000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000B00000000TRAILER!!!463 blocks