Skip to content

Commit

Permalink
Completely revamped the litmusctl workflow (#16)
Browse files Browse the repository at this point in the history
* Refactored litmusctl

Signed-off-by: Raj Das <[email protected]>

* Refactored litmusctl

Signed-off-by: Raj Das <[email protected]>

* litmusctl refactor

Signed-off-by: Raj Das <[email protected]>

* litmusctl refactor

Signed-off-by: Raj Das <[email protected]>

* adding few commands

Signed-off-by: Raj Das <[email protected]>

* gofmt

Signed-off-by: Raj Das <[email protected]>

* adding config flag in litmusctl

Signed-off-by: Raj Das <[email protected]>

* goimport fix

Signed-off-by: Raj Das <[email protected]>

* add version cmd

Signed-off-by: Raj Das <[email protected]>

* add version cmd

Signed-off-by: Raj Das <[email protected]>

* removing old pkg and adding help doc

Signed-off-by: Raj Das <[email protected]>

* go mod tidy

Signed-off-by: Raj Das <[email protected]>

* Code changes

Signed-off-by: Raj Das <[email protected]>

* fixing bch

Signed-off-by: Raj Das <[email protected]>

* adding license, improving bch and gofmt

Signed-off-by: Raj Das <[email protected]>

* adding help doc

Signed-off-by: Raj Das <[email protected]>

* Adding auto project creation

Signed-off-by: Raj Das <[email protected]>

* fixing lint issues

Signed-off-by: Raj Das <[email protected]>

* fixing lint issues

Signed-off-by: Raj Das <[email protected]>

* lint fix

Signed-off-by: Raj Das <[email protected]>

* minor changes in help doc

Signed-off-by: Raj Das <[email protected]>

* fix minor issue in GetModeType()

Signed-off-by: Raj Das <[email protected]>

* fixing review dog

Signed-off-by: Raj Das <[email protected]>
  • Loading branch information
imrajdas authored Jul 8, 2021
1 parent 92c0419 commit 72546de
Show file tree
Hide file tree
Showing 53 changed files with 2,607 additions and 1,559 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
# Install golang
- uses: actions/setup-go@v2
with:
go-version: 1.14
go-version: 1.16

# Checkout to the latest commit
# On specific directory/path
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
# Install golang
- uses: actions/setup-go@v2
with:
go-version: 1.14
go-version: 1.16

# Checkout to the latest commit
# On specific directory/path
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ vendor/
platforms*

#IDE
.idea
.idea
1 change: 1 addition & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
Expand Down
9 changes: 6 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
module github.com/litmuschaos/litmusctl

go 1.14
go 1.16

require (
github.com/Azure/go-autorest/autorest v0.11.18 // indirect
github.com/argoproj/argo v2.5.2+incompatible
github.com/go-resty/resty/v2 v2.5.0
github.com/imdario/mergo v0.3.11 // indirect
github.com/mitchellh/go-homedir v1.1.0
github.com/spf13/cobra v1.1.3
github.com/spf13/viper v1.8.1
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 // indirect
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 // indirect
golang.org/x/text v0.3.6 // indirect
gopkg.in/yaml.v2 v2.4.0
k8s.io/api v0.20.4
k8s.io/apimachinery v0.20.4
Expand Down
411 changes: 229 additions & 182 deletions go.sum

Large diffs are not rendered by default.

15 changes: 3 additions & 12 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright © 2020 NAME HERE <EMAIL ADDRESS>
Copyright © 2021 The LitmusChaos Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand All @@ -16,18 +16,9 @@ limitations under the License.
package main

import (
"log"
"os"

cmd "github.com/litmuschaos/litmusctl/pkg/cmd/litmusctl"
"github.com/litmuschaos/litmusctl/pkg/cmd/root"
)

var CLIVersion string

func main() {
err := os.Setenv("CLIVersion", CLIVersion)
if err != nil {
log.Println("Failed to fetched CLIVersion")
}
cmd.Execute()
rootCmd.Execute()
}
212 changes: 212 additions & 0 deletions pkg/agent/ops.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
/*
Copyright © 2021 The LitmusChaos Authors
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.
*/
package agent

import (
"fmt"
"os"
"strings"

"github.com/litmuschaos/litmusctl/pkg/apis"
"github.com/litmuschaos/litmusctl/pkg/k8s"
"github.com/litmuschaos/litmusctl/pkg/types"
"github.com/litmuschaos/litmusctl/pkg/utils"
)

func PrintExistingAgents(agent apis.AgentData) {
fmt.Println("🚫 Agent with the given name already exists.")
// Print agent list if existing agent name is entered twice
fmt.Print("\n📘 Connected agents list -----------\n\n")

for i := range agent.Data.GetAgent {
fmt.Println("-", agent.Data.GetAgent[i].AgentName)
}

fmt.Println("\n-------------------------------------")

fmt.Println("❗ Please enter a different name.")
}

// GetProject display list of projects and returns the project id based on input
func GetProjectID(u apis.ProjectDetails) string {
var pid int
fmt.Println("\n✨ Projects List:")
for index := range u.Data.GetUser.Projects {
fmt.Printf("%d. %s\n", index+1, u.Data.GetUser.Projects[index].Name)
}

repeat:
fmt.Print("\n🔎 Select Project: ")
fmt.Scanln(&pid)

for pid < 1 || pid > len(u.Data.GetUser.Projects) {
fmt.Println("❗ Invalid Project. Please select a correct one.")
goto repeat
}

return u.Data.GetUser.Projects[pid-1].ID
}

// GetMode gets mode of agent installation as input
func GetModeType() string {
repeat:
var (
cluster_no = 1
namespace_no = 2
mode = cluster_no
)

fmt.Println("\n🔌 Installation Modes:\n1. Cluster\n2. Namespace")
fmt.Print("\n👉 Select Mode [", utils.DefaultMode, "]: ")
fmt.Scanln(&mode)

if mode == 1 {
return "cluster"
}

if mode == 2 {
return "namespace"
}

if (mode != cluster_no) || (mode != namespace_no) {
fmt.Println("🚫 Invalid mode. Please enter the correct mode")
goto repeat
}

return utils.DefaultMode
}

// GetAgentDetails take details of agent as input
func GetAgentDetails(mode string, pid string, c types.Credentials, kubeconfig *string) (types.Agent, error) {
var newAgent types.Agent
// Get agent name as input
fmt.Println("\n🔗 Enter the details of the agent ----")
// Label for goto statement in case of invalid agent name

AGENT_NAME:
fmt.Print("🤷 Agent Name: ")
newAgent.AgentName = utils.Scanner()
if newAgent.AgentName == "" {
fmt.Println("⛔ Agent name cannot be empty. Please enter a valid name.")
goto AGENT_NAME
}

// Check if agent with the given name already exists
agent, err := apis.GetAgentList(c, pid)
if err != nil {
return types.Agent{}, err
}

var isAgentExist = false
for i := range agent.Data.GetAgent {
if newAgent.AgentName == agent.Data.GetAgent[i].AgentName {
fmt.Println(agent.Data.GetAgent[i].AgentName)
isAgentExist = true
}
}

if isAgentExist {
PrintExistingAgents(agent)
goto AGENT_NAME
}

// Get agent description as input
fmt.Print("📘 Agent Description: ")
newAgent.Description = utils.Scanner()
// Get platform name as input
newAgent.PlatformName = GetPlatformName(kubeconfig)
// Set agent type
newAgent.ClusterType = utils.AgentType
// Set project id
newAgent.ProjectId = pid
// Get namespace
newAgent.Namespace, newAgent.NsExists = k8s.ValidNs(mode, utils.ChaosAgentLabel, kubeconfig)

return newAgent, nil
}

func ValidateSAPermissions(mode string, kubeconfig *string) {
var (
pems [2]bool
err error
resources [2]string
)

if mode == "cluster" {
resources = [2]string{"clusterrole", "clusterrolebinding"}
} else {
resources = [2]string{"role", "rolebinding"}
}

for i, resource := range resources {
pems[i], err = k8s.CheckSAPermissions(k8s.CheckSAPermissionsParams{Verb: "create", Resource: resource, Print: true}, kubeconfig)
if err != nil {
fmt.Println(err)
}
}

for _, pem := range pems {
if !pem {
fmt.Println("\n🚫 You don't have sufficient permissions.\n🙄 Please use a service account with sufficient permissions.")
os.Exit(1)
}
}

fmt.Println("\n🌟 Sufficient permissions. Connecting Agent")
}

// Summary display the agent details based on input
func Summary(agent types.Agent, kubeconfig *string) {
fmt.Printf("\n📌 Summary -------------------------- \nAgent Name: %s\nAgent Description: %s\nPlatform Name: %s\n", agent.AgentName, agent.Description, agent.PlatformName)
if ok, _ := k8s.NsExists(agent.Namespace, kubeconfig); ok {
fmt.Println("Namespace: ", agent.Namespace)
} else {
fmt.Println("Namespace: ", agent.Namespace, "(new)")
}

if k8s.SAExists(k8s.SAExistsParams{Namespace: agent.Namespace, Serviceaccount: agent.ServiceAccount}, kubeconfig) {
fmt.Println("Service Account: ", agent.ServiceAccount)
} else {
fmt.Println("Service Account: ", agent.ServiceAccount, "(new)")
}

fmt.Printf("\nInstallation Mode: %s\n-------------------------------------\n", agent.Mode)
}

func ConfirmInstallation() {
var descision string
fmt.Print("\n🤷 Do you want to continue with the above details? [Y/N]: ")
fmt.Scanln(&descision)

if strings.ToLower(descision) == "yes" || strings.ToLower(descision) == "y" {
fmt.Println("👍 Continuing agent connection!!")
} else {
fmt.Println("✋ Exiting agent connection!!")
os.Exit(1)
}
}

func CreateRandomProject(cred types.Credentials) string {
rand, err := utils.GenerateRandomString(10)
utils.PrintError(err)

projectName := cred.Username + "-" + rand

project, err := apis.CreateProjectRequest(projectName, cred)
utils.PrintError(err)

return project.Data.CreateProject.ID
}
56 changes: 49 additions & 7 deletions pkg/common/platform.go → pkg/agent/platform.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,56 @@
package common
/*
Copyright © 2021 The LitmusChaos Authors
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.
*/
package agent

import (
"context"
"fmt"
"strings"

"github.com/litmuschaos/litmusctl/pkg/common/k8s"
"github.com/litmuschaos/litmusctl/pkg/constants"
"github.com/litmuschaos/litmusctl/pkg/k8s"
"github.com/litmuschaos/litmusctl/pkg/utils"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// - Entering any character other than numbers returns 0. Input validation need to be done.
// - If input is given as "123abc", "abc" will be used for next user input. Buffer need to be read completely.
// - String literals like "AWS" are used at multiple places. Need to be changed to constants.
func GetPlatformName(kubeconfig *string) string {
var platform int
discoveredPlatform := DiscoverPlatform(kubeconfig)
fmt.Println("📦 Platform List")
fmt.Println(utils.PlatformList)
fmt.Print("🔎 Select Platform [", discoveredPlatform, "]: ")
fmt.Scanln(&platform)
switch platform {
case 0:
return discoveredPlatform
case 1:
return "AWS"
case 2:
return "GKE"
case 3:
return "Openshift"
case 4:
return "Rancher"
default:
return utils.DefaultPlatform
}
}

// discoverPlatform determines the host platform and returns it
func DiscoverPlatform(kubeconfig *string) string {
if ok, _ := IsAWSPlatform(kubeconfig); ok {
Expand All @@ -23,7 +65,7 @@ func DiscoverPlatform(kubeconfig *string) string {
if ok, _ := k8s.NsExists("cattle-system", kubeconfig); ok {
return "Rancher"
}
return constants.DefaultPlatform
return utils.DefaultPlatform
}

// IsAWSPlatform determines if the host platform is AWS
Expand All @@ -48,7 +90,7 @@ func IsAWSPlatform(kubeconfig *string) (bool, error) {
if err != nil {
return false, err
}
if strings.HasPrefix(nodeList.Items[0].Spec.ProviderID, constants.AWSIdentifier) {
if strings.HasPrefix(nodeList.Items[0].Spec.ProviderID, utils.AWSIdentifier) {
return true, nil
}
return false, nil
Expand Down Expand Up @@ -76,7 +118,7 @@ func IsGKEPlatform(kubeconfig *string) (bool, error) {
if err != nil {
return false, err
}
if strings.HasPrefix(nodeList.Items[0].Spec.ProviderID, constants.GKEIdentifier) {
if strings.HasPrefix(nodeList.Items[0].Spec.ProviderID, utils.GKEIdentifier) {
return true, nil
}
return false, nil
Expand All @@ -103,7 +145,7 @@ func IsOpenshiftPlatform(kubeconfig *string) (bool, error) {
return false, err
}
nodeList, err := clientset.CoreV1().Nodes().List(context.TODO(), v1.ListOptions{
LabelSelector: constants.OpenshiftIdentifier,
LabelSelector: utils.OpenshiftIdentifier,
})
if err != nil {
return false, err
Expand Down
Loading

0 comments on commit 72546de

Please sign in to comment.