diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 000000000..80ececf97 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,27 @@ +name: CI + +on: + push: + pull_request: + +jobs: + + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: '1.22' + cache: false + + - name: Lint + uses: golangci/golangci-lint-action@v4 + + - name: Test + run: go test -v ./... + + - name: Build + run: make build diff --git a/.golangci.json b/.golangci.json index 9dc0a5cc2..507068a48 100644 --- a/.golangci.json +++ b/.golangci.json @@ -1,12 +1,4 @@ { - "linters": { - "disable-all": true, - "enable": [ - "govet", - "golint", - "goimports" - ] - }, "run": { "timeout": "10m" } diff --git a/cmd/app.go b/cmd/app.go index cb26d9bc5..c060a52e1 100644 --- a/cmd/app.go +++ b/cmd/app.go @@ -5,7 +5,6 @@ import ( "encoding/base64" "encoding/json" "fmt" - "io/ioutil" "net/http" "net/url" "os" @@ -799,7 +798,7 @@ func walkTemplateDirectory(templatePath string) (string, map[string]string, erro return nil } version := &chartVersion{} - content, err := ioutil.ReadFile(path) + content, err := os.ReadFile(path) if err != nil { return err } @@ -816,7 +815,7 @@ func walkTemplateDirectory(templatePath string) (string, map[string]string, erro if info.IsDir() { return nil } - content, err := ioutil.ReadFile(path) + content, err := os.ReadFile(path) if err != nil { return err } @@ -1254,7 +1253,7 @@ func parseAnswersFile(location string, answers map[string]string) error { } func parseFile(location string) (map[string]interface{}, error) { - bytes, err := ioutil.ReadFile(location) + bytes, err := os.ReadFile(location) if err != nil { return nil, err } diff --git a/cmd/cluster.go b/cmd/cluster.go index 2e8576de1..8d19c566e 100644 --- a/cmd/cluster.go +++ b/cmd/cluster.go @@ -4,6 +4,7 @@ import ( "encoding/json" "errors" "fmt" + "slices" "strconv" "strings" @@ -255,9 +256,14 @@ func clusterCreate(ctx *cli.Context) error { return err } - if ctx.String("k8s-version") != "" { - k8sVersions := getClusterK8sOptions(c) - if ok := findStringInArray(ctx.String("k8s-version"), k8sVersions); !ok { + k8sVersion := ctx.String("k8s-version") + if k8sVersion != "" { + k8sVersions, err := getClusterK8sOptions(c) + if err != nil { + return err + } + + if slices.Contains(k8sVersions, k8sVersion) { fmt.Println("Available Kubernetes versions:") for _, val := range k8sVersions { fmt.Println(val) @@ -742,16 +748,24 @@ func getClusterPods(cluster managementClient.Cluster) string { return cluster.Requested["pods"] + "/" + cluster.Allocatable["pods"] } -func getClusterK8sOptions(c *cliclient.MasterClient) []string { +func getClusterK8sOptions(c *cliclient.MasterClient) ([]string, error) { var options []string - setting, _ := c.ManagementClient.Setting.ByID("k8s-version-to-images") + + setting, err := c.ManagementClient.Setting.ByID("k8s-version-to-images") + if err != nil { + return nil, err + } + var objmap map[string]*json.RawMessage + err = json.Unmarshal([]byte(setting.Value), &objmap) + if err != nil { + return nil, err + } - json.Unmarshal([]byte(setting.Value), &objmap) for key := range objmap { options = append(options, key) } - return options + return options, nil } func getClusterConfig(ctx *cli.Context) (*managementClient.Cluster, error) { diff --git a/cmd/common.go b/cmd/common.go index 8931b90ec..db3856e1e 100644 --- a/cmd/common.go +++ b/cmd/common.go @@ -3,12 +3,10 @@ package cmd import ( "bufio" "bytes" - "context" "crypto/x509" "encoding/pem" "fmt" "io" - "io/ioutil" "math/rand" "net/url" "os" @@ -22,7 +20,6 @@ import ( "time" "unicode" - "github.com/docker/docker/pkg/namesgenerator" "github.com/ghodss/yaml" "github.com/pkg/errors" "github.com/rancher/cli/cliclient" @@ -33,6 +30,8 @@ import ( managementClient "github.com/rancher/rancher/pkg/client/generated/management/v3" "github.com/sirupsen/logrus" "github.com/urfave/cli" + "golang.org/x/text/cases" + "golang.org/x/text/language" "k8s.io/client-go/tools/clientcmd/api" ) @@ -43,7 +42,6 @@ const ( ) var ( - errNoURL = errors.New("RANCHER_URL environment or --Url is not set, run `login`") // ManagementResourceTypes lists the types we use the management client for ManagementResourceTypes = []string{"cluster", "node", "project"} // ProjectResourceTypes lists the types we use the cluster client for @@ -151,7 +149,7 @@ func getKubeConfigForUser(ctx *cli.Context, user string) (*api.Config, error) { } focusedServer := cf.FocusedServer() - kubeConfig, _ := focusedServer.KubeConfigs[fmt.Sprintf(kubeConfigKeyFormat, user, focusedServer.FocusedCluster())] + kubeConfig := focusedServer.KubeConfigs[fmt.Sprintf(kubeConfigKeyFormat, user, focusedServer.FocusedCluster())] return kubeConfig, nil } @@ -230,7 +228,7 @@ func getRancherServerVersion(c *cliclient.MasterClient) (string, error) { } func loadAndVerifyCert(path string) (string, error) { - caCert, err := ioutil.ReadFile(path) + caCert, err := os.ReadFile(path) if err != nil { return "", err } @@ -301,21 +299,21 @@ func GetClient(ctx *cli.Context) (*cliclient.MasterClient, error) { func GetResourceType(c *cliclient.MasterClient, resource string) (string, error) { if c.ManagementClient != nil { for key := range c.ManagementClient.APIBaseClient.Types { - if strings.ToLower(key) == strings.ToLower(resource) { + if strings.EqualFold(key, resource) { return key, nil } } } if c.ProjectClient != nil { for key := range c.ProjectClient.APIBaseClient.Types { - if strings.ToLower(key) == strings.ToLower(resource) { + if strings.EqualFold(key, resource) { return key, nil } } } if c.ClusterClient != nil { for key := range c.ClusterClient.APIBaseClient.Types { - if strings.ToLower(key) == strings.ToLower(resource) { + if strings.EqualFold(key, resource) { return key, nil } } @@ -417,13 +415,8 @@ func Lookup(c *cliclient.MasterClient, name string, types ...string) (*ntypes.Re return byName, nil } -func RandomName() string { - return strings.Replace(namesgenerator.GetRandomName(0), "_", "-", -1) -} - // RandomLetters returns a string with random letters of length n func RandomLetters(n int) string { - rand.Seed(time.Now().UnixNano()) b := make([]byte, n) for i := range b { b[i] = letters[rand.Intn(len(letters))] @@ -461,8 +454,7 @@ func SimpleFormat(values [][]string) (string, string) { func defaultAction(fn func(ctx *cli.Context) error) func(ctx *cli.Context) error { return func(ctx *cli.Context) error { if ctx.Bool("help") { - cli.ShowAppHelp(ctx) - return nil + return cli.ShowAppHelp(ctx) } return fn(ctx) } @@ -519,14 +511,6 @@ func SplitOnColon(s string) []string { return strings.Split(s, ":") } -func parseClusterAndProjectName(name string) (string, string, error) { - parts := strings.SplitN(name, "/", 2) - if len(parts) == 2 { - return parts[0], parts[1], nil - } - return "", "", fmt.Errorf("Unable to extract clustername and projectname from [%s]", name) -} - func parseClusterAndProjectID(id string) (string, string, error) { // Validate id // Examples: @@ -543,7 +527,7 @@ func parseClusterAndProjectID(id string) (string, string, error) { // Return a JSON blob of the file at path func readFileReturnJSON(path string) ([]byte, error) { - file, err := ioutil.ReadFile(path) + file, err := os.ReadFile(path) if err != nil { return []byte{}, err } @@ -577,21 +561,6 @@ func hasPrefix(buf []byte, prefix []byte) bool { return bytes.HasPrefix(trim, prefix) } -func settingsToMap(client *cliclient.MasterClient) (map[string]string, error) { - configMap := make(map[string]string) - - settings, err := client.ManagementClient.Setting.List(baseListOpts()) - if err != nil { - return nil, err - } - - for _, setting := range settings.Data { - configMap[setting.Name] = setting.Value - } - - return configMap, nil -} - // getClusterNames maps cluster ID to name and defaults to ID if name is blank func getClusterNames(ctx *cli.Context, c *cliclient.MasterClient) (map[string]string, error) { clusterNames := make(map[string]string) @@ -617,15 +586,6 @@ func getClusterName(cluster *managementClient.Cluster) string { return cluster.ID } -func findStringInArray(s string, a []string) bool { - for _, val := range a { - if s == val { - return true - } - } - return false -} - func createdTimetoHuman(t string) (string, error) { parsedTime, err := time.Parse(time.RFC3339, t) if err != nil { @@ -652,9 +612,11 @@ func outputMembers(ctx *cli.Context, c *cliclient.MasterClient, members []manage if err != nil { return err } + + memberType := fmt.Sprintf("%s %s", principal.Provider, principal.PrincipalType) writer.Write(&MemberData{ Name: principal.Name, - MemberType: strings.Title(fmt.Sprintf("%s %s", principal.Provider, principal.PrincipalType)), + MemberType: cases.Title(language.Und).String(memberType), AccessType: m.AccessType, }) } @@ -699,15 +661,6 @@ func deleteMembersByNames(ctx *cli.Context, c *cliclient.MasterClient, members [ return members, nil } -func tickerContext(ctx context.Context, duration time.Duration) <-chan time.Time { - ticker := time.NewTicker(duration) - go func() { - <-ctx.Done() - ticker.Stop() - }() - return ticker.C -} - func ConfigDir() (string, error) { homeDir, err := os.UserHomeDir() if err != nil { diff --git a/cmd/delete.go b/cmd/delete.go deleted file mode 100644 index f7b062bc4..000000000 --- a/cmd/delete.go +++ /dev/null @@ -1,36 +0,0 @@ -package cmd - -import ( - "fmt" - - "github.com/pkg/errors" - "github.com/urfave/cli" -) - -func DeleteCommand() cli.Command { - return cli.Command{ - Name: "delete", - Aliases: []string{"rm"}, - Usage: "Delete resources by ID", - Action: deleteResource, - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "type", - Usage: "type of resource to delete", - }, - }, - } -} - -func deleteResource(ctx *cli.Context) error { - if ctx.String("type") == "" { - return errors.New("type is required for deletes") - } - //c, err := GetClient(ctx) - //if err != nil { - // return err - //} - fmt.Println("This isn't implemented yet") - - return nil -} diff --git a/cmd/kubectl.go b/cmd/kubectl.go index 4f5f60a89..8cf27577d 100644 --- a/cmd/kubectl.go +++ b/cmd/kubectl.go @@ -2,7 +2,6 @@ package cmd import ( "fmt" - "io/ioutil" "os" "os/exec" "strings" @@ -98,7 +97,7 @@ func runKubectl(ctx *cli.Context) error { } } - tmpfile, err := ioutil.TempFile("", "rancher-") + tmpfile, err := os.CreateTemp("", "rancher-") if err != nil { return err } diff --git a/cmd/kubectl_token.go b/cmd/kubectl_token.go index cda71f2f5..7433808b1 100644 --- a/cmd/kubectl_token.go +++ b/cmd/kubectl_token.go @@ -485,6 +485,8 @@ func samlAuth(input *LoginInput, tlsConfig *tls.Config) (managementClient.Token, // log error and use the token if login succeeds customPrint(fmt.Errorf("DeleteToken: %v", err)) } + defer res.Body.Close() + return token, nil case <-timeout.C: @@ -502,12 +504,18 @@ func samlAuth(input *LoginInput, tlsConfig *tls.Config) (managementClient.Token, func getAuthProviders(server string) (map[string]string, error) { authProviders := fmt.Sprintf(authProviderURL, server) customPrint(authProviders) + response, err := request(http.MethodGet, authProviders, nil) + if err != nil { + return nil, err + } + data := map[string]interface{}{} err = json.Unmarshal(response, &data) if err != nil { return nil, err } + providers := map[string]string{} i := 0 for _, value := range convert.ToMapSlice(data["data"]) { diff --git a/cmd/login.go b/cmd/login.go index b0d669972..d7af6ff6b 100644 --- a/cmd/login.go +++ b/cmd/login.go @@ -6,7 +6,7 @@ import ( "encoding/json" "errors" "fmt" - "io/ioutil" + "io" "net/http" "net/url" "os" @@ -272,7 +272,7 @@ func getCertFromServer(ctx *cli.Context, cf *config.ServerConfig) (*cliclient.Ma defer res.Body.Close() - content, err := ioutil.ReadAll(res.Body) + content, err := io.ReadAll(res.Body) if err != nil { return nil, err } diff --git a/cmd/machine.go b/cmd/machine.go index 71994d2d3..87086529d 100644 --- a/cmd/machine.go +++ b/cmd/machine.go @@ -97,26 +97,6 @@ func getMachineByNodeName( "`rancher machines` to see available nodes", nodeName) } -func getMachineByID( - ctx *cli.Context, - c *cliclient.MasterClient, - machineID string, -) (capiClient.Machine, error) { - machineCollection, err := getMachinesList(ctx, c) - if err != nil { - return capiClient.Machine{}, err - } - - for _, machine := range machineCollection.Data { - if machine.ID == machineID { - return machine, nil - } - } - - return capiClient.Machine{}, fmt.Errorf("no machine found with the ID [%s], run "+ - "`rancher machines` to see available nodes", machineID) -} - func getMachineName(machine capiClient.Machine) string { if machine.Name != "" { return machine.Name diff --git a/cmd/multiclusterapp.go b/cmd/multiclusterapp.go index ce621dd9a..5ef82c5c2 100644 --- a/cmd/multiclusterapp.go +++ b/cmd/multiclusterapp.go @@ -345,6 +345,10 @@ func multiClusterAppLs(ctx *cli.Context) error { } collection, err := c.ManagementClient.MultiClusterApp.List(defaultListOpts(ctx)) + if err != nil { + return err + } + writer := NewTableWriter([][]string{ {"ID", "ID"}, {"NAME", "App.Name"}, diff --git a/cmd/prompt.go b/cmd/prompt.go deleted file mode 100644 index dc727c66e..000000000 --- a/cmd/prompt.go +++ /dev/null @@ -1,35 +0,0 @@ -package cmd - -import ( - "fmt" - - rancherprompt "github.com/rancher/cli/rancher_prompt" - - "github.com/c-bata/go-prompt" - "github.com/urfave/cli" -) - -func PromptCommand() cli.Command { - return cli.Command{ - Name: "prompt", - Usage: "Enter rancher cli auto-prompt mode", - ArgsUsage: "None", - Action: promptAction, - Flags: []cli.Flag{}, - } -} - -func promptAction(ctx *cli.Context) error { - fmt.Print("rancher cli auto-completion mode") - defer fmt.Println("Goodbye!") - p := prompt.New( - rancherprompt.Executor, - rancherprompt.Completer, - prompt.OptionTitle("rancher-prompt: interactive rancher client"), - prompt.OptionPrefix("rancher$ "), - prompt.OptionInputTextColor(prompt.Yellow), - prompt.OptionMaxSuggestion(20), - ) - p.Run() - return nil -} diff --git a/cmd/ps.go b/cmd/ps.go index 6b0c8923e..2797bef0a 100644 --- a/cmd/ps.go +++ b/cmd/ps.go @@ -2,10 +2,11 @@ package cmd import ( "strconv" - "strings" "github.com/rancher/cli/cliclient" "github.com/urfave/cli" + "golang.org/x/text/cases" + "golang.org/x/text/language" ) type PSHolder struct { @@ -85,6 +86,8 @@ func psLs(ctx *cli.Context) error { defer wlWriter.Close() + titleCaser := cases.Title(language.Und) + for _, item := range workLoads.Data { var scale string @@ -94,7 +97,7 @@ func psLs(ctx *cli.Context) error { scale = strconv.Itoa(int(*item.Scale)) } - item.Type = strings.Title(item.Type) + item.Type = titleCaser.String(item.Type) wlWriter.Write(&PSHolder{ NameSpace: item.NamespaceId, @@ -116,7 +119,7 @@ func psLs(ctx *cli.Context) error { if len(orphanPods.Data) > 0 { for _, item := range orphanPods.Data { - item.Type = strings.Title(item.Type) + item.Type = titleCaser.String(item.Type) wlWriter.Write(&PSHolder{ NameSpace: item.NamespaceId, Name: item.Name, diff --git a/cmd/run.go b/cmd/run.go deleted file mode 100644 index c31130223..000000000 --- a/cmd/run.go +++ /dev/null @@ -1,269 +0,0 @@ -package cmd - -import ( - "github.com/urfave/cli" -) - -/* - -a, --attach=[] Attach to STDIN, STDOUT or STDERR - --add-host=[] Add a custom host-to-IP mapping (host:ip) - --blkio-weight Block IO (relative weight), between 10 and 1000 - --blkio-weight-device=[] Block IO weight (relative device weight) - --cgroup-parent Optional parent cgroup for the container - --cidfile Write the container ID to the file - --cpu-period Limit CPU CFS (Completely Fair Scheduler) period - --cpu-quota Limit CPU CFS (Completely Fair Scheduler) quota - --cpuset-cpus CPUs in which to allow execution (0-3, 0,1) - --cpuset-mems MEMs in which to allow execution (0-3, 0,1) - -d, --detach Run container in background and print container ID - --detach-keys Override the key sequence for detaching a container - --device-read-bps=[] Limit read rate (bytes per second) from a device - --device-read-iops=[] Limit read rate (IO per second) from a device - --device-write-bps=[] Limit write rate (bytes per second) to a device - --device-write-iops=[] Limit write rate (IO per second) to a device - --disable-content-trust=true Skip Image verification - --dns-opt=[] Set DNS options - -e, --env=[] Set environment variables - --env-file=[] Read in a file of environment variables - --group-add=[] Add additional groups to join - --help Print usage - --ip Container IPv4 address (e.g. 172.30.100.104) - --ip6 Container IPv6 address (e.g. 2001:db8::33) - --ipc IPC namespace to use - --isolation Container isolation level - --kernel-memory Kernel memory limit - -l, --label=[] Set meta data on a container - --label-file=[] Read in a line delimited file of labels - --link=[] Add link to another container - --log-driver Logging driver for container - --log-opt=[] Log driver options - --mac-address Container MAC address (e.g. 92:d0:c6:0a:29:33) - --memory-reservation Memory soft limit - --memory-swappiness=-1 Tune container memory swappiness (0 to 100) - --net=default Connect a container to a network - --net-alias=[] Add network-scoped alias for the container - --oom-kill-disable Disable OOM Killer - --oom-score-adj Tune host's OOM preferences (-1000 to 1000) - --restart=no Restart policy to apply when a container exits - --rm Automatically remove the container when it exits - --shm-size Size of /dev/shm, default value is 64MB - --sig-proxy=true Proxy received signals to the process - --stop-signal=SIGTERM Signal to stop a container, SIGTERM by default - --tmpfs=[] Mount a tmpfs directory - --ulimit=[] Ulimit options - --uts UTS namespace to use - -v, --volume=[] Bind mount a volume - --volumes-from=[] Mount volumes from the specified container(s) -*/ - -func RunCommand() cli.Command { - return cli.Command{ - Name: "run", - Usage: "Run services", - Action: serviceRun, - Flags: []cli.Flag{ - cli.Int64Flag{ - Name: "blkio-weight", - Usage: "Block IO (relative weight), between 10 and 1000, or 0 to disable (default 0)", - }, - cli.Int64Flag{ - Name: "cpu-quota", - Usage: "Limit CPU CFS (Completely Fair Scheduler) quota", - }, - cli.Int64Flag{ - Name: "cpu-shares", - Usage: "CPU shares (relative weight)", - }, - cli.StringSliceFlag{ - Name: "cap-add", - Usage: "Add Linux capabilities", - }, - cli.StringSliceFlag{ - Name: "cap-drop", - Usage: "Drop Linux capabilities", - }, - cli.StringFlag{ - Name: "cgroup-parent", - Usage: "Optional parent cgroup for the container", - }, - cli.Int64Flag{ - Name: "cpu-period", - Usage: "Limit CPU CFS (Completely Fair Scheduler) period", - }, - cli.StringFlag{ - Name: "cpuset-mems", - Usage: "MEMs in which to allow execution (0-3, 0,1)", - }, - cli.StringSliceFlag{ - Name: "device", - Usage: "Add a host device to the container", - }, - cli.StringSliceFlag{ - Name: "dns", - Usage: "Set custom DNS servers", - }, - cli.StringSliceFlag{ - Name: "dns-opt, dns-option", - Usage: "Set DNS options", - }, - cli.StringSliceFlag{ - Name: "dns-search", - Usage: "Set custom DNS search domains", - }, - cli.StringSliceFlag{ - Name: "entrypoint", - Usage: "Overwrite the default ENTRYPOINT of the Image", - }, - cli.StringSliceFlag{ - Name: "expose", - Usage: "Expose a port or a range of ports", - }, - cli.StringSliceFlag{ - Name: "group-add", - Usage: "Add additional groups to join", - }, - cli.StringFlag{ - Name: "hostname", - Usage: "Container host name", - }, - cli.BoolFlag{ - Name: "init", - Usage: "Run an init inside the container that forwards signals and reaps processes", - }, - cli.BoolFlag{ - Name: "interactive, i", - Usage: "Keep STDIN open even if not attached", - }, - cli.Int64Flag{ - Name: "kernel-memory", - Usage: "Kernel memory limit", - }, - cli.Int64Flag{ - Name: "memory, m", - Usage: "Memory limit", - }, - cli.Int64Flag{ - Name: "memory-reservation", - Usage: "Memory soft limit", - }, - cli.Int64Flag{ - Name: "memory-swap", - Usage: "Swap limit equal to memory plus swap: '-1' to enable unlimited swap", - }, - cli.Int64Flag{ - Name: "memory-swappiness", - Usage: "Tune container memory swappiness (0 to 100)", - }, - cli.StringFlag{ - Name: "name", - Usage: "Assign a name to the container", - }, - cli.BoolFlag{ - Name: "oom-kill-disable", - Usage: "Disable OOM Killer", - }, - cli.Int64Flag{ - Name: "oom-score-adj", - Usage: "Tune host’s OOM preferences (-1000 to 1000)", - }, - cli.BoolFlag{ - Name: "publish-all, P", - Usage: "Publish all exposed ports to random ports", - }, - cli.StringSliceFlag{ - Name: "publish, p", - Usage: "Publish a container's `port`(s) to the host", - }, - cli.StringFlag{ - Name: "pid", - Usage: "PID namespace to use", - }, - cli.Int64Flag{ - Name: "pids-limit", - Usage: "Tune container pids limit (set -1 for unlimited)", - }, - cli.BoolFlag{ - Name: "privileged", - Usage: "Give extended privileges to this container", - }, - cli.BoolFlag{ - Name: "read-only", - Usage: "Mount the container's root filesystem as read only", - }, - cli.StringSliceFlag{ - Name: "security-opt", - Usage: "Security Options", - }, - cli.Int64Flag{ - Name: "shm-size", - Usage: "Size of /dev/shm", - }, - cli.BoolFlag{ - Name: "tty, t", - Usage: "Allocate a pseudo-TTY", - }, - cli.StringFlag{ - Name: "user, u", - Usage: "Username or UID (format: [:])", - }, - cli.StringFlag{ - Name: "volume-driver", - Usage: "Optional volume driver for the container", - }, - cli.StringFlag{ - Name: "workdir, w", - Usage: "Working directory inside the container", - }, - cli.StringFlag{ - Name: "log-driver", - Usage: "Logging driver for container", - }, - cli.StringSliceFlag{ - Name: "log-opt", - Usage: "Log driver options", - }, - cli.StringFlag{ - Name: "uts", - Usage: "UTS namespace to use", - }, - cli.StringSliceFlag{ - Name: "volume, v", - Usage: "Bind mount a volume", - }, - cli.StringFlag{ - Name: "net", - Usage: "Connect a container to a network: host, none, bridge, managed", - Value: "managed", - }, - cli.IntFlag{ - Name: "scale", - Usage: "Number of containers to run", - Value: 1, - }, - cli.BoolFlag{ - Name: "schedule-global", - Usage: "Run 1 container per host", - }, - cli.StringFlag{ - Name: "stop-signal", - Usage: "Signal to stop a container", - }, - cli.StringSliceFlag{ - Name: "label,l", - Usage: "Add label in the form of key=value", - }, - cli.StringSliceFlag{ - Name: "env,e", - Usage: "Set one or more environment variable in the form of key=value, key=, and key", - }, - cli.BoolFlag{ - Name: "pull", - Usage: "Always pull Image on container start", - }, - }, - } -} - -func serviceRun(ctx *cli.Context) error { - return nil -} diff --git a/cmd/server.go b/cmd/server.go index e523233e1..d60f37d3f 100644 --- a/cmd/server.go +++ b/cmd/server.go @@ -175,7 +175,10 @@ func getSelectedServer(ctx *cli.Context, cfg *config.Config) (string, error) { // prompt the user to select one. func serverFromInput(ctx *cli.Context, cf *config.Config) (string, error) { servers := getServers(cf) - displayListServers(ctx, servers) + + if err := displayListServers(ctx, servers); err != nil { + return "", err + } fmt.Print("Select a Server:") reader := bufio.NewReader(os.Stdin) diff --git a/cmd/ssh.go b/cmd/ssh.go index be1e8cbb9..53a0d8590 100644 --- a/cmd/ssh.go +++ b/cmd/ssh.go @@ -7,7 +7,7 @@ import ( "crypto/x509" "encoding/json" "fmt" - "io/ioutil" + "io" "net/http" "os" "os/exec" @@ -132,7 +132,7 @@ func getNodeAndKey(ctx *cli.Context, c *cliclient.MasterClient, nodeName string) func callSSH(content []byte, ip string, user string, args []string) error { dest := fmt.Sprintf("%s@%s", user, ip) - tmpfile, err := ioutil.TempFile("", "ssh") + tmpfile, err := os.CreateTemp("", "ssh") if err != nil { return err } @@ -192,7 +192,7 @@ func getSSHKey(c *cliclient.MasterClient, link, nodeName string) ([]byte, string } defer resp.Body.Close() - zipFiles, err := ioutil.ReadAll(resp.Body) + zipFiles, err := io.ReadAll(resp.Body) if err != nil { return nil, "", err } @@ -240,5 +240,5 @@ func readFile(file *zip.File) ([]byte, error) { return nil, err } defer r.Close() - return ioutil.ReadAll(r) + return io.ReadAll(r) } diff --git a/cmd/up.go b/cmd/up.go index 4253d4c71..9d7fde8ad 100644 --- a/cmd/up.go +++ b/cmd/up.go @@ -1,7 +1,7 @@ package cmd import ( - "io/ioutil" + "os" "github.com/rancher/cli/cliclient" client "github.com/rancher/rancher/pkg/client/generated/management/v3" @@ -33,7 +33,7 @@ func apply(ctx *cli.Context) error { } filePath := ctx.String("file") - compose, err := ioutil.ReadFile(filePath) + compose, err := os.ReadFile(filePath) if err != nil { return err } diff --git a/cmd/util_ls.go b/cmd/util_ls.go index 065aa4d68..21b040b90 100644 --- a/cmd/util_ls.go +++ b/cmd/util_ls.go @@ -5,20 +5,6 @@ import ( "github.com/urfave/cli" ) -func listAllFlag() cli.BoolFlag { - return cli.BoolFlag{ - Name: "all,a", - Usage: "Show stop/inactive and recently removed resources", - } -} - -func listSystemFlag() cli.BoolFlag { - return cli.BoolFlag{ - Name: "system,s", - Usage: "Show system resources", - } -} - func baseListOpts() *types.ListOpts { return &types.ListOpts{ Filters: map[string]interface{}{ diff --git a/cmd/wait.go b/cmd/wait.go index 90cd5abac..abd98b5df 100644 --- a/cmd/wait.go +++ b/cmd/wait.go @@ -62,13 +62,13 @@ func wait(ctx *cli.Context) error { } timeout := time.After(time.Duration(ctx.Int("timeout")) * time.Second) - every := time.Tick(1 * time.Second) + ticker := time.NewTicker(time.Second) for { select { case <-timeout: return fmt.Errorf("Timeout reached %v:%v transitioningMessage: %v", resource.Type, resource.ID, mapResource["transitioningMessage"]) - case <-every: + case <-ticker.C: err = c.ByID(resource, &mapResource) if err != nil { return err diff --git a/cmd/writer.go b/cmd/writer.go index 811828ce8..9a5dc75ea 100644 --- a/cmd/writer.go +++ b/cmd/writer.go @@ -11,7 +11,6 @@ import ( ) type TableWriter struct { - quite bool HeaderFormat string ValueFormat string err error diff --git a/go.mod b/go.mod index a7f588762..77710bc31 100644 --- a/go.mod +++ b/go.mod @@ -5,13 +5,9 @@ go 1.22 replace k8s.io/client-go => k8s.io/client-go v0.20.1 require ( - github.com/c-bata/go-prompt v0.2.6 - github.com/docker/docker v1.6.1 github.com/ghodss/yaml v1.0.0 - github.com/gorilla/websocket v1.4.2 github.com/grantae/certinfo v0.0.0-20170412194111-59d56a35515b github.com/hashicorp/go-version v1.2.1 - github.com/patrickmn/go-cache v2.1.0+incompatible github.com/pkg/errors v0.9.1 github.com/rancher/norman v0.0.0-20200820172041-261460ee9088 github.com/rancher/rancher/pkg/client v0.0.0-20211110212758-cc2b8beb1473 @@ -21,6 +17,7 @@ require ( golang.org/x/exp v0.0.0-20240205201215-2c58cdc269a3 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c golang.org/x/term v0.10.0 + golang.org/x/text v0.11.0 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c gopkg.in/yaml.v2 v2.4.0 k8s.io/client-go v12.0.0+incompatible @@ -34,17 +31,13 @@ require ( github.com/golang/protobuf v1.4.3 // indirect github.com/google/go-cmp v0.5.8 // indirect github.com/google/gofuzz v1.1.0 // indirect + github.com/gorilla/websocket v1.4.2 // indirect github.com/imdario/mergo v0.3.7 // indirect github.com/json-iterator/go v1.1.10 // indirect github.com/kr/pretty v0.2.1 // indirect github.com/kr/text v0.2.0 // indirect - github.com/mattn/go-colorable v0.1.7 // indirect - github.com/mattn/go-isatty v0.0.12 // indirect - github.com/mattn/go-runewidth v0.0.9 // indirect - github.com/mattn/go-tty v0.0.3 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.1 // indirect - github.com/pkg/term v1.2.0-beta.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rancher/wrangler v0.7.4-security1 // indirect github.com/russross/blackfriday/v2 v2.0.1 // indirect @@ -54,7 +47,6 @@ require ( golang.org/x/net v0.12.0 // indirect golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d // indirect golang.org/x/sys v0.10.0 // indirect - golang.org/x/text v0.11.0 // indirect golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e // indirect google.golang.org/appengine v1.6.5 // indirect google.golang.org/protobuf v1.25.0 // indirect diff --git a/go.sum b/go.sum index d739865ef..ef52d5b7b 100644 --- a/go.sum +++ b/go.sum @@ -58,8 +58,6 @@ github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+Ce github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= -github.com/c-bata/go-prompt v0.2.6 h1:POP+nrHE+DfLYx370bedwNhsqmpCUynWPxuHi0C5vZI= -github.com/c-bata/go-prompt v0.2.6/go.mod h1:/LMAke8wD2FsNu9EXNdHxNLbd9MedkPnCdfpU9wwHfY= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -97,8 +95,6 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker v1.6.1 h1:4xYASHy5cScPkLD7PO0uTmnVc860m9NarPN1X8zeMe8= -github.com/docker/docker v1.6.1/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= @@ -320,20 +316,8 @@ github.com/maruel/panicparse v0.0.0-20171209025017-c0182c169410/go.mod h1:nty42Y github.com/maruel/ut v1.0.0/go.mod h1:I68ffiAt5qre9obEVTy7S2/fj2dJku2NYLvzPuY0gqE= github.com/matryer/moq v0.0.0-20200607124540-4638a53893e6/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.7 h1:bQGKb3vps/j0E9GfJQ03JyhRuxsvdAanXlT9BTw3mdw= -github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= 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.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= -github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-tty v0.0.3 h1:5OfyWorkyO7xP52Mq7tB36ajHDG5OHrmBGIS/DtakQI= -github.com/mattn/go-tty v0.0.3/go.mod h1:ihxohKRERHTVzN+aSVRwACLCeqIoZAWpoICkkvrWyR0= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= @@ -366,8 +350,6 @@ github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= -github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= -github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= github.com/paulmach/orb v0.1.3/go.mod h1:VFlX/8C+IQ1p6FTRRKzKoOPJnvEtA5G0Veuqwbu//Vk= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= @@ -376,8 +358,6 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/term v1.2.0-beta.2 h1:L3y/h2jkuBVFdWiJvNfYfKmzcCnILw7mJWm2JQuMppw= -github.com/pkg/term v1.2.0-beta.2/go.mod h1:E25nymQcrSllhX42Ok8MRm1+hyBdHY0dCeiKZ9jpNGw= github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -605,7 +585,6 @@ golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/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-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190321052220-f7bb7a8bee54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -620,22 +599,17 @@ golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200918174421-af09f7315aff/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/main.go b/main.go index de121ec3e..9e6564bfb 100644 --- a/main.go +++ b/main.go @@ -8,7 +8,6 @@ import ( "github.com/pkg/errors" "github.com/rancher/cli/cmd" "github.com/rancher/cli/config" - rancherprompt "github.com/rancher/cli/rancher_prompt" "github.com/sirupsen/logrus" "github.com/urfave/cli" ) @@ -128,11 +127,6 @@ func mainErr() error { cmd.CredentialCommand(), } - for _, com := range app.Commands { - rancherprompt.Commands[com.Name] = com - rancherprompt.Commands[com.ShortName] = com - } - rancherprompt.Flags = app.Flags parsed, err := parseArgs(os.Args) if err != nil { logrus.Error(err) diff --git a/monitor/monitor.go b/monitor/monitor.go deleted file mode 100644 index f647db91a..000000000 --- a/monitor/monitor.go +++ /dev/null @@ -1,156 +0,0 @@ -package monitor - -import ( - "encoding/json" - "fmt" - "sync" - "time" - - "github.com/gorilla/websocket" - "github.com/patrickmn/go-cache" - "github.com/rancher/cli/cliclient" - "github.com/sirupsen/logrus" -) - -type Event struct { - Name string `json:"name"` - ResourceType string `json:"resourceType"` - ResourceID string `json:"resourceId"` - Data map[string]interface{} `json:"data"` -} - -type Monitor struct { - sync.Mutex - c *cliclient.MasterClient - cache *cache.Cache - subCounter int - subscriptions map[int]*Subscription -} - -func (m *Monitor) Subscribe() *Subscription { - m.Lock() - defer m.Unlock() - - m.subCounter++ - sub := &Subscription{ - id: m.subCounter, - C: make(chan *Event, 1024), - } - m.subscriptions[sub.id] = sub - - return sub -} - -func (m *Monitor) Unsubscribe(sub *Subscription) { - m.Lock() - defer m.Unlock() - - close(sub.C) - delete(m.subscriptions, sub.id) -} - -type Subscription struct { - id int - C chan *Event -} - -func New(c *cliclient.MasterClient) *Monitor { - return &Monitor{ - c: c, - cache: cache.New(5*time.Minute, 30*time.Second), - subscriptions: map[int]*Subscription{}, - } -} - -//func (m *Monitor) Start() error { -// schema, err := m.c.ManagementClient.DynamicSchema.ByID("subscribe") -// if nil != err { -// return fmt.Errorf("not authorized to subscribe") -// } -// -// urlString := schema.Links["collection"] -// u, err := url.Parse(urlString) -// if err != nil { -// return err -// } -// -// switch u.Scheme { -// case "http": -// u.Scheme = "ws" -// case "https": -// u.Scheme = "wss" -// } -// -// q := u.Query() -// q.Add("eventNames", "resource.change") -// q.Add("eventNames", "service.kubernetes.change") -// -// u.RawQuery = q.Encode() -// -// conn, resp, err := m.c.Websocket(u.String(), nil) -// if err != nil { -// return err -// } -// -// if resp.StatusCode != 101 { -// return fmt.Errorf("Bad status code: %d %s", resp.StatusCode, resp.Status) -// } -// -// logrus.Debugf("Connected to: %s", u.String()) -// -// return m.watch(conn) -//} - -func (m *Monitor) Get(resourceType, resourceID string, obj interface{}) (bool, error) { - val, ok := m.cache.Get(key(resourceType, resourceID)) - if !ok { - return ok, nil - } - - if val == nil { - return true, nil - } - - content, err := json.Marshal(val) - if err != nil { - return ok, err - } - - return true, json.Unmarshal(content, obj) -} - -func key(a, b string) string { - return fmt.Sprintf("%s:%s", a, b) -} - -func (m *Monitor) put(resourceType, resourceID string, event *Event) { - if resourceType == "" && resourceID == "" { - return - } - - m.cache.Replace(key(resourceType, resourceID), event.Data["resource"], cache.DefaultExpiration) - - m.Lock() - defer m.Unlock() - - for _, sub := range m.subscriptions { - sub.C <- event - } -} - -func (m *Monitor) watch(conn *websocket.Conn) error { - for { - v := Event{} - _, r, err := conn.NextReader() - if err != nil { - return err - } - if err := json.NewDecoder(r).Decode(&v); err != nil { - logrus.Errorf("Failed to parse json in message") - continue - } - - logrus.Debugf("Event: %s %s %s %v", v.Name, v.ResourceType, v.ResourceID, v.Data) - m.put(v.ResourceType, v.ResourceID, &v) - } -} diff --git a/rancher_prompt/client.go b/rancher_prompt/client.go deleted file mode 100644 index 3bc29ea49..000000000 --- a/rancher_prompt/client.go +++ /dev/null @@ -1 +0,0 @@ -package rancherprompt diff --git a/rancher_prompt/completer.go b/rancher_prompt/completer.go deleted file mode 100644 index addeecdf1..000000000 --- a/rancher_prompt/completer.go +++ /dev/null @@ -1,120 +0,0 @@ -package rancherprompt - -import ( - "strings" - - "github.com/c-bata/go-prompt" - "github.com/urfave/cli" -) - -// thanks for the idea from github.com/c-bata/kube-prompt - -var ( - Commands = map[string]cli.Command{} - Flags = []cli.Flag{} -) - -func Completer(d prompt.Document) []prompt.Suggest { - if d.TextBeforeCursor() == "" { - return []prompt.Suggest{} - } - - args := strings.Split(d.TextBeforeCursor(), " ") - w := d.GetWordBeforeCursor() - - // If PIPE is in text before the cursor, returns empty suggestions. - for i := range args { - if args[i] == "|" { - return []prompt.Suggest{} - } - } - - // If word before the cursor starts with "-", returns CLI flag options. - if strings.HasPrefix(w, "-") { - return optionCompleter(args, strings.HasPrefix(w, "--")) - } - - return argumentsCompleter(excludeOptions(args)) -} - -func argumentsCompleter(args []string) []prompt.Suggest { - suggests := []prompt.Suggest{} - for name, command := range Commands { - if command.Name != "prompt" { - suggests = append(suggests, prompt.Suggest{ - Text: name, - Description: command.Usage, - }) - } - } - if len(args) <= 1 { - return prompt.FilterHasPrefix(suggests, args[0], true) - } - - switch args[0] { - case "docker": - if len(args) == 3 { - subcommands := []prompt.Suggest{ - {Text: "attach", Description: "Attach local standard input, output, and error streams to a running container"}, - {Text: "build", Description: "Build an image from a Dockerfile"}, - {Text: "commit", Description: "Create a new image from a container’s changes"}, - {Text: "cp", Description: "Copy files/folders between a container and the local filesystem"}, - {Text: "create", Description: "Create a new container"}, - {Text: "events", Description: "Get real time events from the server"}, - {Text: "exec", Description: "Run a command in a running container"}, - {Text: "export", Description: "Export a container’s filesystem as a tar archive"}, - {Text: "image", Description: "Manage images"}, - {Text: "images", Description: "List images"}, - {Text: "import", Description: "Import the contents from a tarball to create a filesystem image"}, - {Text: "info", Description: "Display system-wide information"}, - {Text: "inspect", Description: "Return low-level information on Docker objects"}, - {Text: "kill", Description: "Kill one or more running containers"}, - {Text: "load", Description: "Load an image from a tar archive or STDIN"}, - {Text: "login", Description: "Log in to a Docker registry"}, - {Text: "logout", Description: "Log out from a Docker registry"}, - {Text: "logs", Description: "Fetch the logs of a container"}, - {Text: "network", Description: "Manage networks"}, - {Text: "pause", Description: "Pause all processes within one or more containers"}, - {Text: "plugin", Description: "Manage plugins"}, - {Text: "port", Description: "List port mappings or a specific mapping for the container"}, - {Text: "ps", Description: "List containers"}, - {Text: "pull", Description: "Pull an image or a repository from a registry"}, - {Text: "push", Description: "Push an image or a repository to a registry"}, - {Text: "rename", Description: "Rename a container"}, - {Text: "restart", Description: "Restart one or more containers"}, - {Text: "rm", Description: "Remove one or more containers"}, - {Text: "rmi", Description: "Remove one or more images"}, - {Text: "run", Description: "Run a command in a new container"}, - {Text: "save", Description: "Save one or more images to a tar archive (streamed to STDOUT by default)"}, - {Text: "search", Description: "Search the Docker Hub for images"}, - {Text: "start", Description: "Start one or more stopped containers"}, - {Text: "stats", Description: "Display a live stream of container(s) resource usage statistics"}, - {Text: "stop", Description: "Stop one or more running containers"}, - {Text: "tag", Description: "Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE"}, - {Text: "top", Description: "Display the running processes of a container"}, - {Text: "unpause", Description: "Unpause all processes within one or more containers"}, - {Text: "update", Description: "Update configuration of one or more containers"}, - {Text: "version", Description: "Show the Docker version information"}, - {Text: "volume", Description: "Manage volumes"}, - {Text: "wait", Description: "Block until one or more containers stop, then print their exit codes"}, - } - return prompt.FilterHasPrefix(subcommands, args[2], true) - } - default: - if len(args) == 2 { - return prompt.FilterHasPrefix(getSubcommandSuggest(args[0]), args[1], true) - } - } - return []prompt.Suggest{} -} - -func getSubcommandSuggest(name string) []prompt.Suggest { - subcommands := []prompt.Suggest{} - for _, com := range Commands[name].Subcommands { - subcommands = append(subcommands, prompt.Suggest{ - Text: com.Name, - Description: com.Usage, - }) - } - return subcommands -} diff --git a/rancher_prompt/executor.go b/rancher_prompt/executor.go deleted file mode 100644 index f53275adb..000000000 --- a/rancher_prompt/executor.go +++ /dev/null @@ -1,40 +0,0 @@ -package rancherprompt - -import ( - "fmt" - "os" - "os/exec" - "strings" -) - -func Executor(s string) { - s = strings.TrimSpace(s) - if s == "" { - return - } - if s == "exit" { - os.Exit(0) - return - } - //hack for rancher docker - // docker --host 1h1 ps -> --host 1h1 docker ps - if strings.HasPrefix(s, "docker ") { - parts := strings.Split(s, " ") - if len(parts) > 2 && (parts[1] == "--host" || parts[1] == "-host") { - t := parts[0] - parts[0] = parts[1] - parts[1] = parts[2] - parts[2] = t - s = strings.Join(parts, " ") - } - } - - cmd := exec.Command("/bin/sh", "-c", "rancher "+s) - cmd.Stdin = os.Stdin - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - if err := cmd.Run(); err != nil { - fmt.Printf("Got error: %s\n", err.Error()) - } - return -} diff --git a/rancher_prompt/options.go b/rancher_prompt/options.go deleted file mode 100644 index 1156b7222..000000000 --- a/rancher_prompt/options.go +++ /dev/null @@ -1,117 +0,0 @@ -package rancherprompt - -import ( - "strings" - - "github.com/c-bata/go-prompt" - "github.com/urfave/cli" -) - -func optionCompleter(args []string, long bool) []prompt.Suggest { - l := len(args) - if l <= 1 { - if long { - return prompt.FilterHasPrefix(optionHelp, "--", false) - } - return optionHelp - } - flagGlobal := getGlobalFlag() - - var suggests []prompt.Suggest - commandArgs := excludeOptions(args) - - if command, ok := Commands[commandArgs[0]]; ok { - if len(commandArgs) > 1 && len(command.Subcommands) > 0 { - for _, sub := range command.Subcommands { - if sub.Name == commandArgs[1] { - suggests = append(getFlagsSuggests(sub), flagGlobal...) - break - } - } - } else { - suggests = append(getFlagsSuggests(command), flagGlobal...) - } - } - - if long { - return prompt.FilterContains( - prompt.FilterHasPrefix(suggests, "--", false), - strings.TrimLeft(args[l-1], "--"), - true, - ) - } - return prompt.FilterHasPrefix(suggests, strings.TrimLeft(args[l-1], "-"), true) -} - -var optionHelp = []prompt.Suggest{ - {Text: "-h", Description: "Help Command"}, - {Text: "--help", Description: "Help Command"}, -} - -func excludeOptions(args []string) []string { - ret := make([]string, 0, len(args)) - for i := range args { - if !strings.HasPrefix(args[i], "-") { - ret = append(ret, args[i]) - } - } - return ret -} - -func getGlobalFlag() []prompt.Suggest { - suggests := []prompt.Suggest{} - for _, flag := range Flags { - name := flag.GetName() - parts := strings.Split(name, ",") - for _, part := range parts { - prefix := "--" - if len(parts) == 1 { - prefix = "-" - } - suggests = append(suggests, prompt.Suggest{ - Text: prefix + strings.TrimSpace(part), - Description: getUsageForFlag(flag), - }) - } - } - suggests = append(suggests, optionHelp...) - return suggests -} - -func getFlagsSuggests(command cli.Command) []prompt.Suggest { - suggests := []prompt.Suggest{} - for _, f := range command.Flags { - name := f.GetName() - parts := strings.Split(name, ",") - for _, part := range parts { - prefix := "--" - if len(parts) == 1 { - prefix = "-" - } - suggests = append(suggests, prompt.Suggest{ - Text: prefix + strings.TrimSpace(part), - Description: getUsageForFlag(f), - }) - } - } - return suggests -} - -func getUsageForFlag(flag cli.Flag) string { - if v, ok := flag.(cli.StringFlag); ok { - return v.Usage - } - if v, ok := flag.(cli.StringSliceFlag); ok { - return v.Usage - } - if v, ok := flag.(cli.IntFlag); ok { - return v.Usage - } - if v, ok := flag.(cli.IntSliceFlag); ok { - return v.Usage - } - if v, ok := flag.(cli.BoolFlag); ok { - return v.Usage - } - return "" -}