Skip to content
This repository has been archived by the owner on Jul 25, 2022. It is now read-only.

Commit

Permalink
history feature
Browse files Browse the repository at this point in the history
  • Loading branch information
tedteng committed Apr 28, 2021
1 parent 7b10ff9 commit 8b8ce9f
Show file tree
Hide file tree
Showing 107 changed files with 12,694 additions and 0 deletions.
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ require (
github.com/gardener/gardener v1.5.0
github.com/gardener/gardener-extension-provider-openstack v1.3.1-0.20200327120628-280d268ce96f
github.com/gardener/machine-controller-manager v0.27.0
github.com/goinggo/mapstructure v0.0.0-20140717182941-194205d9b4a9
github.com/golang/mock v1.4.3
github.com/jmoiron/jsonq v0.0.0-20150511023944-e874b168d07e
github.com/manifoldco/promptui v0.8.0
github.com/olekukonko/tablewriter v0.0.4
github.com/onsi/ginkgo v1.10.1
github.com/onsi/gomega v1.7.0
Expand Down
17 changes: 17 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,12 @@ github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnweb
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=
github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cloudflare/cloudflare-go v0.11.4/go.mod h1:ZB+hp7VycxPLpp0aiozQQezat46npDXhzHi1DVtRCn4=
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
Expand Down Expand Up @@ -255,6 +261,8 @@ github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d h1:3PaI8p3seN09Vjb
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/goinggo/mapstructure v0.0.0-20140717182941-194205d9b4a9 h1:wqckanyE9qc/XnvnybC6SHOb8Nyd62QXAZOzA8twFig=
github.com/goinggo/mapstructure v0.0.0-20140717182941-194205d9b4a9/go.mod h1:64ikIrMv84B+raz7akXOqbF7cK3/OQQ/6cClY10oy7A=
github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
Expand Down Expand Up @@ -365,6 +373,8 @@ github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGn
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a h1:FaWFmfWdAUKbSCtOU2QjDaorUexogfaMgbipgYATUMU=
github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a/go.mod h1:UJSiEoRfvx3hP73CvoARgeLjaIOjybY9vj8PUPPFGeU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4=
github.com/karrick/godirwalk v1.10.12/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA=
Expand All @@ -384,6 +394,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a h1:weJVJJRzAJBFRlAiJQROKQs8oC9vOxvm4rZmBBk0ONw=
github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
Expand All @@ -392,13 +404,17 @@ github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
github.com/manifoldco/promptui v0.8.0 h1:R95mMF+McvXZQ7j1g8ucVZE1gLP3Sv6j9vlF9kyRqQo=
github.com/manifoldco/promptui v0.8.0/go.mod h1:n4zTdgP0vr0S3w7/O/g98U+e0gwLScEXGwov2nIKuGQ=
github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE=
github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
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.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
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.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54=
Expand Down Expand Up @@ -694,6 +710,7 @@ golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/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-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
Expand Down
3 changes: 3 additions & 0 deletions pkg/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ func Execute() {
CreateDir(pathSessionID, 0751)
pathTarget = filepath.Join(pathSessionID, "target")
CreateFileIfNotExists(pathTarget, 0644)
pathHistory = filepath.Join(pathSessionID, "history")
CreateFileIfNotExists(pathHistory, 0644)
gardenConfig = os.Getenv("GARDENCONFIG")
if gardenConfig != "" {
if _, err := os.Stat(gardenConfig); err != nil {
Expand Down Expand Up @@ -159,6 +161,7 @@ func init() {
RootCmd.AddCommand(NewInfoCmd(targetReader, ioStreams))
RootCmd.AddCommand(NewVersionCmd(), NewUpdateCheckCmd())
RootCmd.AddCommand(NewDiagCmd(targetReader, ioStreams))
RootCmd.AddCommand(NewHistoryCmd())

RootCmd.SuggestionsMinimumDistance = suggestionsMinimumDistance
RootCmd.BashCompletionFunction = bashCompletionFunc
Expand Down
38 changes: 38 additions & 0 deletions pkg/cmd/target_history.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright (c) 2019 SAP SE or an SAP affiliate company. All rights reserved. This file is licensed under the Apache Software License, v. 2 except as noted otherwise in the LICENSE file
//
// 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 cmd

import (
"os"

history "github.com/gardener/gardenctl/pkg/internal/history"
"github.com/spf13/cobra"
)

//NewHistoryCmd use for list/search targting history
func NewHistoryCmd() *cobra.Command {
return &cobra.Command{
Use: "x",
Short: "List/Search targeting history, e.g. \"gardenctl x\"",
SilenceUsage: true,
Aliases: []string{"x"},
Long: `List Targeting Hisotry`,
Run: func(cmd *cobra.Command, args []string) {
h := history.Settings(pathHistory, os.Args[0])
list := h.List()
history.Execute(h.Binary, h.Run(list))
},
}
}
1 change: 1 addition & 0 deletions pkg/cmd/var.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ var (
// file pathes
pathGardenConfig string
pathTarget string
pathHistory string
pathDefault = filepath.Join(HomeDir(), ".garden")
pathDefaultSession = filepath.Join(HomeDir(), ".garden", "sessions")
)
249 changes: 249 additions & 0 deletions pkg/internal/history/history.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,249 @@
// Copyright (c) 2019 SAP SE or an SAP affiliate company. All rights reserved. This file is licensed under the Apache Software License, v. 2 except as noted otherwise in the LICENSE file
//
// 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 history

import (
"bufio"
"fmt"
"io"
"log"
"os"
"os/exec"
"reflect"
"strings"
"syscall"

"github.com/goinggo/mapstructure"
"github.com/manifoldco/promptui"
)

//History struct
type History struct {
ConfigPath string
Binary string
}

//Settings History
func Settings(path string, binary string) *History {
h := &History{
ConfigPath: path, //Config Path
Binary: binary, //executable Binary file
}
return h
}

//Write history record
func (h *History) Write(i interface{}) {
f, err := os.OpenFile(h.ConfigPath, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666)
if err != nil {
log.Fatalln("History file write error ", h.ConfigPath)
}
defer f.Close()
if _, err := f.WriteString(convert(i)); err != nil {
log.Fatalln("History file write error ", h.ConfigPath)
}
}

//Load History records order by descending
func (h *History) List() []string {
f, err := os.Open(h.ConfigPath)
if err != nil {
log.Fatalln("cannot open the file", err)
}
defer f.Close()
rd := bufio.NewReader(f)

var items []string

for {
line, _, err := rd.ReadLine()
if err == io.EOF {
break
} else if err != nil {
log.Fatalln("Load err:", err)
}
items = append(items, string(line))
}

//return last 1000 history records
items = reverse(items)
if len(items) > 1000 {
temp := make([]string, 1000)
copy(temp, items[:1000])
return temp
}

return items
}

//List all HIstory records and execute the select one
func (h *History) Run(str []string) string {
items := factoryMyBoxItem(str)
templates := &promptui.SelectTemplates{
Label: "{{ . }}?",
Active: "\U0001F4CC {{ .Cmd | cyan }} ",
Inactive: " {{ .Cmd | cyan }}",
Selected: "\U0001F4CC {{ .Cmd | red | cyan }} ",
Details: `
--------- Cluster Info ----------
{{ "Garden:" | faint }} {{ .Garden }}
{{ "Project:" | faint }} {{ .Project }}
{{ "Seed:" | faint }} {{ .Seed }}
{{ "Control Plane:" | faint }} {{ .ControlPlane }}
{{ "Shoot:" | faint }} {{ .Shoot }}`,
}
searcher := func(input string, index int) bool {
myboxitem := items[index]
name := strings.Replace(strings.ToLower(myboxitem.Cmd), " ", "", -1)
input = strings.Replace(strings.ToLower(input), " ", "", -1)
return strings.Contains(name, input)
}

prompt := promptui.Select{
Label: "Target hisotry",
Items: items,
Templates: templates,
Size: 10,
Searcher: searcher,
}

i, _, err := prompt.Run()

if err != nil {
log.Fatalln("Prompt failed: \n", err)
}

return str[i]
}

func factoryMyBoxItem(load []string) []MyBoxItem {
items := []MyBoxItem{}
box := Mybox{items}
for _, i := range load {
mapInstance := toMap(i)
var myBoxItem MyBoxItem
if err := mapstructure.Decode(mapInstance, &myBoxItem); err != nil {
fmt.Println(err)
}
box.addItem(myBoxItem)
}
return box.Items
}

//Execute binary eg gardenctl subcommand
func Execute(binary string, result string) {
binary, lookErr := exec.LookPath(binary)
if lookErr != nil {
panic(lookErr)
}

args := strings.Fields(result)
env := os.Environ()
execErr := syscall.Exec(binary, args, env)
if execErr != nil {
panic(execErr)
}
}

func convert(i interface{}) string {
var str string
switch x := i.(type) {
case []string:
str = strings.Join(x, " ")
case []byte:
str = string(x[:])
case string:
str = x
default:
log.Fatalln("convert type unknown")
}
return isLineBreak(str)
}

func isLineBreak(str string) string {
if strings.HasSuffix(str, "\n") {
return str
}
return str + "\n"
}

func reverse(s []string) []string {
n := reflect.ValueOf(s).Len()
swap := reflect.Swapper(s)
for i, j := 0, n-1; i < j; i, j = i+1, j-1 {
swap(i, j)
}
return s
}

func toMap(str string) map[string]string {
c := strings.Fields(str)
a := make(map[string]string)
a["Cmd"] = str
for i, k := range c {
k = format(k)
if i%2 == 0 {
a[k] = c[i+1]
}
}
return a
}

func format(str string) string {
for {
if strings.HasPrefix(str, "-") {
str = strings.TrimPrefix(str, "-")
} else {
break
}
}

switch strings.ToUpper(str) {

case "G", "GARDEN", "SERVER":
return "Garden"
case "S", "SEED":
return "Seed"
case "P", "Project":
return "Project"
case "t", "SHOOT":
return "Shoot"
case "n", "NAMESPACE":
return "ControlPlane"
default:
return str
}
}

//MyBoxItem struct
type MyBoxItem struct {
Cmd string
Seed string
Server string
Garden string
Project string
ControlPlane string
Shoot string
}

//Mybox struct
type Mybox struct {
Items []MyBoxItem
}

func (box *Mybox) addItem(item MyBoxItem) []MyBoxItem {
box.Items = append(box.Items, item)
return box.Items
}
1 change: 1 addition & 0 deletions vendor/github.com/chzyer/readline/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 8b8ce9f

Please sign in to comment.