added subcommands
parent
5baa447e46
commit
92a5d2a636
7
go.mod
7
go.mod
|
|
@ -27,10 +27,8 @@ replace (
|
|||
)
|
||||
|
||||
require (
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect
|
||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4 // indirect
|
||||
github.com/atotto/clipboard v0.1.2
|
||||
github.com/derailed/tview v0.2.1
|
||||
github.com/derailed/tview v0.2.4
|
||||
github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c // indirect
|
||||
github.com/elazarl/goproxy v0.0.0-20190421051319-9d40249d3c2f // indirect
|
||||
github.com/elazarl/goproxy/ext v0.0.0-20190421051319-9d40249d3c2f // indirect
|
||||
|
|
@ -44,7 +42,7 @@ require (
|
|||
github.com/imdario/mergo v0.3.7 // indirect
|
||||
github.com/kylelemons/godebug v1.1.0 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.4
|
||||
github.com/petergtz/pegomock v2.5.0+incompatible
|
||||
github.com/petergtz/pegomock v2.6.0+incompatible
|
||||
github.com/rakyll/hey v0.1.2
|
||||
github.com/rs/zerolog v1.14.3
|
||||
github.com/sahilm/fuzzy v0.1.0
|
||||
|
|
@ -52,7 +50,6 @@ require (
|
|||
github.com/stretchr/testify v1.3.0
|
||||
golang.org/x/text v0.3.2
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 // indirect
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/yaml.v2 v2.2.2
|
||||
gotest.tools v2.2.0+incompatible
|
||||
|
|
|
|||
27
go.sum
27
go.sum
|
|
@ -39,8 +39,6 @@ github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdko
|
|||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/Rican7/retry v0.1.0/go.mod h1:FgOROf8P5bebcC1DS0PdOQiqGUridaZvikzUmkFW6gg=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
|
||||
|
|
@ -89,8 +87,12 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
|
|||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd/go.mod h1:dv4zxwHi5C/8AeI+4gX4dCWOIvNi7I6JCSX0HvlKPgE=
|
||||
github.com/derailed/tview v0.2.1 h1:3UjeNni+Q94WmmVnc8tLSTZab5NuRVrwolghCiXCtSs=
|
||||
github.com/derailed/tview v0.2.1/go.mod h1:aDhJBLLf7pXbkaNmVroSvsjiP8ry6sfBVWNHTz6klZw=
|
||||
github.com/derailed/tview v0.2.2 h1:APBixkqfHz3fL+XJ/bjxZivvd8HUtrXVcTUb/qu6wR0=
|
||||
github.com/derailed/tview v0.2.2/go.mod h1:rFq1AIpLyyo8ilN1vG//2YnXmHg6szt4zIdg1ftJx9E=
|
||||
github.com/derailed/tview v0.2.3 h1:bvoF230amMmzrwDYTHnToSLjemeCp6shmBJ+lnJRiAA=
|
||||
github.com/derailed/tview v0.2.3/go.mod h1:rFq1AIpLyyo8ilN1vG//2YnXmHg6szt4zIdg1ftJx9E=
|
||||
github.com/derailed/tview v0.2.4 h1:txiIdBLeSH1JV+9uP7hfuZAQBt1qJ+iDasmDCtVsvk0=
|
||||
github.com/derailed/tview v0.2.4/go.mod h1:rFq1AIpLyyo8ilN1vG//2YnXmHg6szt4zIdg1ftJx9E=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
|
||||
|
|
@ -112,7 +114,6 @@ github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb
|
|||
github.com/emicklei/go-restful v2.9.5+incompatible h1:spTtZBk5DYEvbxMVutUuTyh1Ao2r4iyvLdACqsl/Ljk=
|
||||
github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
||||
github.com/euank/go-kmsg-parser v2.0.0+incompatible/go.mod h1:MhmAMZ8V4CYH4ybgdRwPr2TU5ThnS43puaKEMpja1uw=
|
||||
github.com/evanphx/json-patch v4.1.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||
github.com/evanphx/json-patch v4.2.0+incompatible h1:fUDGZCv/7iAN7u0puUVhvKCcsR6vRfwrJatElLBEf0I=
|
||||
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4=
|
||||
|
|
@ -124,6 +125,7 @@ github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV
|
|||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko=
|
||||
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
|
||||
github.com/gdamore/tcell v1.1.1/go.mod h1:K1udHkiR3cOtlpKG5tZPD5XxrF7v2y7lDq7Whcj+xkQ=
|
||||
github.com/gdamore/tcell v1.1.2 h1:Afe8cU6SECC06UmvaJ55Jr3Eh0tz/ywLjqWYqjGZp3s=
|
||||
github.com/gdamore/tcell v1.1.2/go.mod h1:h3kq4HO9l2On+V9ed8w8ewqQEmGCSSHOgQ+2h8uzurE=
|
||||
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
|
|
@ -175,7 +177,6 @@ github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+
|
|||
github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA=
|
||||
github.com/go-ozzo/ozzo-validation v3.5.0+incompatible/go.mod h1:gsEKFIVnabGBt6mXmxK0MoFy+cZoTJY6mu5Ll3LVLBU=
|
||||
github.com/godbus/dbus v4.1.0+incompatible/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d h1:3PaI8p3seN09VjbTYC/QWlUZdZ1qS1zGjy7LH2Wt07I=
|
||||
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
|
|
@ -211,7 +212,6 @@ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+
|
|||
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
|
||||
github.com/googleapis/gnostic v0.2.0 h1:l6N3VoaVzTncYYW+9yOz2LJJammFZGBO13sqgEhpy9g=
|
||||
github.com/googleapis/gnostic v0.2.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
|
||||
github.com/gophercloud/gophercloud v0.0.0-20190427020117-60507118a582/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
|
||||
github.com/gophercloud/gophercloud v0.1.0 h1:P/nh25+rzXouhytV2pUHBb65fnds26Ghl8/391+sT5o=
|
||||
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
|
|
@ -251,7 +251,6 @@ github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/u
|
|||
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/karrick/godirwalk v1.7.5/go.mod h1:2c9FRhkDxdIbgkOnCEvnSWs71Bhugbl46shStcFDJ34=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
|
|
@ -273,6 +272,7 @@ github.com/lucas-clemente/aes12 v0.0.0-20171027163421-cd47fb39b79f/go.mod h1:JpH
|
|||
github.com/lucas-clemente/quic-clients v0.1.0/go.mod h1:y5xVIEoObKqULIKivu+gD/LU90pL73bTdtQjPBvtCBk=
|
||||
github.com/lucas-clemente/quic-go v0.10.2/go.mod h1:hvaRS9IHjFLMq76puFJeWNfmn+H70QZ/CXoxqw9bzao=
|
||||
github.com/lucas-clemente/quic-go-certificates v0.0.0-20160823095156-d2f86524cced/go.mod h1:NCcRLrOTZbzhZvixZLlERbJtDtYsmMw8Jc4vS8Z0g58=
|
||||
github.com/lucasb-eyer/go-colorful v0.0.0-20181028223441-12d3b2882a08/go.mod h1:NXg0ArsFk0Y01623LgUqoqcouGDB+PwCCQlrwrG6xJ4=
|
||||
github.com/lucasb-eyer/go-colorful v1.0.2 h1:mCMFu6PgSozg9tDNMMK3g18oJBX7oYGrC09mS6CXfO4=
|
||||
github.com/lucasb-eyer/go-colorful v1.0.2/go.mod h1:0MS4r+7BZKSJ5mw4/S5MPN+qHFF1fYclkSPilDOKW0s=
|
||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
|
|
@ -331,8 +331,8 @@ github.com/pelletier/go-toml v1.0.1/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/9
|
|||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
||||
github.com/petergtz/pegomock v2.5.0+incompatible h1:NgwX1/qc+tsl7I45OkDxYZ1mIonYWbOESnpZcd20sR0=
|
||||
github.com/petergtz/pegomock v2.5.0+incompatible/go.mod h1:nuBLWZpVyv/fLo56qTwt/AUau7jgouO1h7bEvZCq82o=
|
||||
github.com/petergtz/pegomock v2.6.0+incompatible h1:gD9YvI42LylIA/il2Cy8lMfg+CncNFMqexYepyEWGaQ=
|
||||
github.com/petergtz/pegomock v2.6.0+incompatible/go.mod h1:nuBLWZpVyv/fLo56qTwt/AUau7jgouO1h7bEvZCq82o=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
|
|
@ -373,7 +373,6 @@ github.com/soheilhy/cmux v0.1.3/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4k
|
|||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
|
||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s=
|
||||
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
|
||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
|
|
@ -416,7 +415,6 @@ golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnf
|
|||
golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8 h1:1wopBVtVdWnn03fZelqdXTqk7U7zPQCb+T4rbU9ZEoU=
|
||||
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
|
|
@ -446,7 +444,6 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn
|
|||
golang.org/x/net v0.0.0-20190320064053-1272bf9dcd53/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190328230028-74de082e2cca/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190424112056-4829fb13d2c6/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190812203447-cdfb69ac37fc h1:gkKoSkUmnU6bpS/VhkuO27bzQeSA51uaEfbOW5dNb68=
|
||||
|
|
@ -485,7 +482,6 @@ golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxb
|
|||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20170824195420-5d2fd3ccab98/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
|
|
@ -517,8 +513,8 @@ google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRn
|
|||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
gopkg.in/DATA-DOG/go-sqlmock.v1 v1.3.0/go.mod h1:OdE7CF6DbADk7lN8LIKRzRJTTZXIjtWgA5THM5lhBAw=
|
||||
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
|
@ -569,7 +565,6 @@ k8s.io/gengo v0.0.0-20190822140433-26a664648505/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8
|
|||
k8s.io/heapster v1.2.0-beta.1/go.mod h1:h1uhptVXMwC8xtZBYsPXKVi8fpdlYkTs6k949KozGrM=
|
||||
k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
|
||||
k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
|
||||
k8s.io/klog v0.3.1/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
|
||||
k8s.io/klog v0.4.0 h1:lCJCxf/LIowc2IGS9TPjWDyXY4nOmdGdfcwwDQCOURQ=
|
||||
k8s.io/klog v0.4.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
|
||||
k8s.io/kube-aggregator v0.0.0-20190918161219-8c8f079fddc3/go.mod h1:NJisPUqwlg1A99RhO1BTnNtwC4pKUyXJ2f3Xc4PxKQg=
|
||||
|
|
|
|||
|
|
@ -26,20 +26,6 @@ const NA = "n/a"
|
|||
var supportedMetricsAPIVersions = []string{"v1beta1"}
|
||||
|
||||
type (
|
||||
// GKV tracks api resource version info.
|
||||
GKV struct {
|
||||
Group, Kind, Version string
|
||||
}
|
||||
|
||||
// APIGroup represents a K8s resource descriptor.
|
||||
APIGroup struct {
|
||||
GKV
|
||||
|
||||
Resource string
|
||||
Plural, Singular string
|
||||
Aliases []string
|
||||
}
|
||||
|
||||
// Collection of empty interfaces.
|
||||
Collection []interface{}
|
||||
|
||||
|
|
@ -72,7 +58,7 @@ type (
|
|||
CurrentNamespaceName() (string, error)
|
||||
CheckNSAccess(ns string) error
|
||||
CheckListNSAccess() error
|
||||
CanIAccess(ns, resURL string, verbs []string) (bool, error)
|
||||
CanIAccess(ns, rvg string, verbs []string) (bool, error)
|
||||
}
|
||||
|
||||
k8sClient struct {
|
||||
|
|
@ -121,12 +107,12 @@ func (a *APIClient) CheckNSAccess(n string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
func makeSAR(ns, resURL string) *authorizationv1.SelfSubjectAccessReview {
|
||||
gvr, _ := schema.ParseResourceArg(strings.ToLower(resURL))
|
||||
func makeSAR(ns, rvg string) *authorizationv1.SelfSubjectAccessReview {
|
||||
gvr, _ := schema.ParseResourceArg(strings.ToLower(rvg))
|
||||
if gvr == nil {
|
||||
panic(fmt.Errorf("Unable to get GVR from url %s", resURL))
|
||||
panic(fmt.Errorf("Unable to get GVR from url %s", rvg))
|
||||
}
|
||||
log.Debug().Msgf("GVR for %s -- %#v", resURL, *gvr)
|
||||
log.Debug().Msgf("GVR for %s -- %#v", rvg, *gvr)
|
||||
return &authorizationv1.SelfSubjectAccessReview{
|
||||
Spec: authorizationv1.SelfSubjectAccessReviewSpec{
|
||||
ResourceAttributes: &authorizationv1.ResourceAttributes{
|
||||
|
|
@ -139,8 +125,8 @@ func makeSAR(ns, resURL string) *authorizationv1.SelfSubjectAccessReview {
|
|||
}
|
||||
|
||||
// CanIAccess checks if user has access to a certain resource.
|
||||
func (a *APIClient) CanIAccess(ns, resURL string, verbs []string) (bool, error) {
|
||||
sar := makeSAR(ns, resURL)
|
||||
func (a *APIClient) CanIAccess(ns, rvg string, verbs []string) (bool, error) {
|
||||
sar := makeSAR(ns, rvg)
|
||||
dial := a.DialOrDie().AuthorizationV1().SelfSubjectAccessReviews()
|
||||
for _, v := range verbs {
|
||||
sar.Spec.ResourceAttributes.Verb = v
|
||||
|
|
@ -210,7 +196,7 @@ func (a *APIClient) IsNamespaced(res string) bool {
|
|||
func (a *APIClient) SupportsResource(group string) bool {
|
||||
list, err := a.DialOrDie().Discovery().ServerPreferredResources()
|
||||
if err != nil {
|
||||
log.Debug().Err(err).Msg("Unable to dial api server")
|
||||
log.Error().Err(err).Msg("Unable to dial api server")
|
||||
return false
|
||||
}
|
||||
for _, l := range list {
|
||||
|
|
@ -294,7 +280,7 @@ func (a *APIClient) MXDial() (*versioned.Clientset, error) {
|
|||
}
|
||||
var err error
|
||||
if a.mxsClient, err = versioned.NewForConfig(a.RestConfigOrDie()); err != nil {
|
||||
a.log.Debug().Err(err)
|
||||
a.log.Error().Err(err)
|
||||
}
|
||||
|
||||
return a.mxsClient, err
|
||||
|
|
|
|||
|
|
@ -33,6 +33,15 @@ func (g GVR) AsGR() schema.GroupVersion {
|
|||
}
|
||||
}
|
||||
|
||||
// AsGVR returns a schema gvr instance.
|
||||
func (g GVR) AsGVR() schema.GroupVersionResource {
|
||||
return schema.GroupVersionResource{
|
||||
Group: g.ToG(),
|
||||
Version: g.ToV(),
|
||||
Resource: g.ToR(),
|
||||
}
|
||||
}
|
||||
|
||||
// String returns a GVR as a string.
|
||||
func (g GVR) String() string {
|
||||
return string(g)
|
||||
|
|
@ -41,6 +50,9 @@ func (g GVR) String() string {
|
|||
// ToV returns the resource version.
|
||||
func (g GVR) ToV() string {
|
||||
tokens := strings.Split(string(g), "/")
|
||||
if len(tokens) < 2 {
|
||||
return ""
|
||||
}
|
||||
return tokens[len(tokens)-2]
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,146 @@
|
|||
package k8s_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/derailed/k9s/internal/k8s"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
func TestAsGR(t *testing.T) {
|
||||
uu := map[string]struct {
|
||||
gvr string
|
||||
e schema.GroupVersion
|
||||
}{
|
||||
"full": {"apps/v1/deployments", schema.GroupVersion{"apps", "v1"}},
|
||||
"core": {"v1/pods", schema.GroupVersion{"", "v1"}},
|
||||
"bork": {"users", schema.GroupVersion{"", ""}},
|
||||
}
|
||||
|
||||
for k, u := range uu {
|
||||
t.Run(k, func(t *testing.T) {
|
||||
assert.Equal(t, u.e, k8s.GVR(u.gvr).AsGR())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewGVR(t *testing.T) {
|
||||
uu := map[string]struct {
|
||||
g, v, r string
|
||||
e string
|
||||
}{
|
||||
"full": {"apps", "v1", "deployments", "apps/v1/deployments"},
|
||||
"core": {"", "v1", "pods", "v1/pods"},
|
||||
}
|
||||
|
||||
for k, u := range uu {
|
||||
t.Run(k, func(t *testing.T) {
|
||||
assert.Equal(t, u.e, k8s.NewGVR(u.g, u.v, u.r).String())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestToGVR(t *testing.T) {
|
||||
uu := map[string]struct {
|
||||
gv, r, e string
|
||||
}{
|
||||
"full": {"apps/v1", "deployments", "apps/v1/deployments"},
|
||||
"core": {"v1", "pods", "v1/pods"},
|
||||
}
|
||||
|
||||
for k, u := range uu {
|
||||
t.Run(k, func(t *testing.T) {
|
||||
assert.Equal(t, u.e, k8s.ToGVR(u.gv, u.r).String())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestResName(t *testing.T) {
|
||||
uu := map[string]struct {
|
||||
gvr string
|
||||
e string
|
||||
}{
|
||||
"full": {"apps/v1/deployments", "deployments.v1.apps"},
|
||||
"core": {"v1/pods", "pods.v1."},
|
||||
"k9s": {"users", "users.."},
|
||||
"empty": {"", ".."},
|
||||
}
|
||||
|
||||
for k, u := range uu {
|
||||
t.Run(k, func(t *testing.T) {
|
||||
assert.Equal(t, u.e, k8s.GVR(u.gvr).ResName())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestToR(t *testing.T) {
|
||||
uu := map[string]struct {
|
||||
gvr string
|
||||
e string
|
||||
}{
|
||||
"full": {"apps/v1/deployments", "deployments"},
|
||||
"core": {"v1/pods", "pods"},
|
||||
"k9s": {"users", "users"},
|
||||
"empty": {"", ""},
|
||||
}
|
||||
|
||||
for k, u := range uu {
|
||||
t.Run(k, func(t *testing.T) {
|
||||
assert.Equal(t, u.e, k8s.GVR(u.gvr).ToR())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestToG(t *testing.T) {
|
||||
uu := map[string]struct {
|
||||
gvr string
|
||||
e string
|
||||
}{
|
||||
"full": {"apps/v1/deployments", "apps"},
|
||||
"core": {"v1/pods", ""},
|
||||
"k9s": {"users", ""},
|
||||
"empty": {"", ""},
|
||||
}
|
||||
|
||||
for k, u := range uu {
|
||||
t.Run(k, func(t *testing.T) {
|
||||
assert.Equal(t, u.e, k8s.GVR(u.gvr).ToG())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestToV(t *testing.T) {
|
||||
uu := map[string]struct {
|
||||
gvr string
|
||||
e string
|
||||
}{
|
||||
"full": {"apps/v1/deployments", "v1"},
|
||||
"core": {"v1beta1/pods", "v1beta1"},
|
||||
"k9s": {"users", ""},
|
||||
"empty": {"", ""},
|
||||
}
|
||||
|
||||
for k, u := range uu {
|
||||
t.Run(k, func(t *testing.T) {
|
||||
assert.Equal(t, u.e, k8s.GVR(u.gvr).ToV())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestToStringer(t *testing.T) {
|
||||
uu := map[string]struct {
|
||||
gvr string
|
||||
}{
|
||||
"full": {"apps/v1/deployments"},
|
||||
"core": {"v1beta1/pods"},
|
||||
"k9s": {"users"},
|
||||
"empty": {""},
|
||||
}
|
||||
|
||||
for k, u := range uu {
|
||||
t.Run(k, func(t *testing.T) {
|
||||
assert.Equal(t, u.gvr, k8s.GVR(u.gvr).String())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -20,7 +20,7 @@ func (i *Ingress) Get(ns, n string) (interface{}, error) {
|
|||
return i.DialOrDie().ExtensionsV1beta1().Ingresses(ns).Get(n, metav1.GetOptions{})
|
||||
}
|
||||
|
||||
// List all Ingresss in a given namespace.
|
||||
// List all Ingresses in a given namespace.
|
||||
func (i *Ingress) List(ns string) (Collection, error) {
|
||||
opts := metav1.ListOptions{
|
||||
LabelSelector: i.labelSelector,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import (
|
|||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
"k8s.io/client-go/dynamic"
|
||||
"k8s.io/client-go/rest"
|
||||
|
|
@ -31,12 +30,7 @@ func (r *Resource) GetInfo() GVR {
|
|||
}
|
||||
|
||||
func (r *Resource) nsRes() dynamic.NamespaceableResourceInterface {
|
||||
g := schema.GroupVersionResource{
|
||||
Group: r.gvr.ToG(),
|
||||
Version: r.gvr.ToV(),
|
||||
Resource: r.gvr.ToR(),
|
||||
}
|
||||
return r.DynDialOrDie().Resource(g)
|
||||
return r.DynDialOrDie().Resource(r.gvr.AsGVR())
|
||||
}
|
||||
|
||||
// Get a Resource.
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ func (b *Base) Describe(gvr, pa string) (string, error) {
|
|||
mapper := k8s.RestMapper{Connection: b.Connection}
|
||||
mapping, err := mapper.ResourceFor(k8s.GVR(gvr).ResName())
|
||||
if err != nil {
|
||||
log.Debug().Err(err).Msgf("Unable to find mapper for %s %s", gvr, pa)
|
||||
log.Error().Err(err).Msgf("Unable to find mapper for %s %s", gvr, pa)
|
||||
return "", err
|
||||
}
|
||||
ns, n := Namespaced(pa)
|
||||
|
|
|
|||
|
|
@ -203,22 +203,58 @@ func (a *appView) refreshIndicator() {
|
|||
a.indicator().SetPermanent(info)
|
||||
}
|
||||
|
||||
func (a *appView) startInformer(ns string) {
|
||||
func (a *appView) switchNS(ns string) bool {
|
||||
if ns == a.Config.ActiveNamespace() {
|
||||
log.Debug().Msgf("Namespace did not change %s", ns)
|
||||
return true
|
||||
}
|
||||
a.Config.SetActiveNamespace(ns)
|
||||
|
||||
return a.startInformer(ns)
|
||||
}
|
||||
|
||||
func (a *appView) switchCtx(ctx string, load bool) error {
|
||||
l := resource.NewContext(a.Conn())
|
||||
if err := l.Switch(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
a.stopForwarders()
|
||||
ns, err := a.Conn().Config().CurrentNamespaceName()
|
||||
if err != nil {
|
||||
log.Info().Err(err).Msg("No namespace specified using all namespaces")
|
||||
}
|
||||
a.startInformer(ns)
|
||||
a.Config.Reset()
|
||||
a.Config.Save()
|
||||
a.Flash().Infof("Switching context to %s", ctx)
|
||||
if load {
|
||||
a.gotoResource("po", true)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *appView) startInformer(ns string) bool {
|
||||
if a.stopCh != nil {
|
||||
close(a.stopCh)
|
||||
a.stopCh = nil
|
||||
}
|
||||
|
||||
var err error
|
||||
a.stopCh = make(chan struct{})
|
||||
a.informer, err = watch.NewInformer(a.Conn(), ns)
|
||||
if err != nil {
|
||||
log.Panic().Err(err).Msgf("%v", err)
|
||||
log.Error().Err(err).Msgf("%v", err)
|
||||
a.Flash().Err(err)
|
||||
return false
|
||||
}
|
||||
a.stopCh = make(chan struct{})
|
||||
a.informer.Run(a.stopCh)
|
||||
|
||||
if a.Config.K9s.GetHeadless() {
|
||||
a.refreshIndicator()
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// BailOut exists the application.
|
||||
|
|
@ -340,9 +376,9 @@ func (a *appView) helpCmd(evt *tcell.EventKey) *tcell.EventKey {
|
|||
if _, ok := a.Frame().GetPrimitive("main").(*helpView); ok {
|
||||
return evt
|
||||
}
|
||||
|
||||
h := newHelpView(a, a.ActiveView(), a.GetHints())
|
||||
a.inject(h)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -350,7 +386,6 @@ func (a *appView) aliasCmd(evt *tcell.EventKey) *tcell.EventKey {
|
|||
if _, ok := a.Frame().GetPrimitive("main").(*aliasView); ok {
|
||||
return evt
|
||||
}
|
||||
|
||||
a.inject(newAliasView(a, a.ActiveView()))
|
||||
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package views
|
|||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/derailed/k9s/internal/k8s"
|
||||
|
|
@ -55,18 +56,22 @@ func (c *command) defaultCmd() {
|
|||
|
||||
var policyMatcher = regexp.MustCompile(`\Apol\s([u|g|s]):([\w-:]+)\b`)
|
||||
|
||||
func (c *command) isCustCmd(cmd string) bool {
|
||||
switch {
|
||||
case cmd == "q", cmd == "quit":
|
||||
func (c *command) isK9sCmd(cmd string) bool {
|
||||
cmds := strings.Split(cmd, " ")
|
||||
switch cmds[0] {
|
||||
case "q", "quit":
|
||||
c.app.BailOut()
|
||||
return true
|
||||
case cmd == "?", cmd == "help":
|
||||
case "?", "help":
|
||||
c.app.helpCmd(nil)
|
||||
return true
|
||||
case cmd == "alias":
|
||||
case "alias":
|
||||
c.app.aliasCmd(nil)
|
||||
return true
|
||||
case policyMatcher.MatchString(cmd):
|
||||
default:
|
||||
if !policyMatcher.MatchString(cmd) {
|
||||
return false
|
||||
}
|
||||
tokens := policyMatcher.FindAllStringSubmatch(cmd, -1)
|
||||
if len(tokens) == 1 && len(tokens[0]) == 3 {
|
||||
c.app.inject(newPolicyView(c.app, tokens[0][1], tokens[0][2]))
|
||||
|
|
@ -76,36 +81,72 @@ func (c *command) isCustCmd(cmd string) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// Exec the command by showing associated display.
|
||||
func (c *command) run(cmd string) bool {
|
||||
defer func(t time.Time) {
|
||||
log.Debug().Msgf("RUN CMD Elapsed %v", time.Since(t))
|
||||
}(time.Now())
|
||||
|
||||
if c.isCustCmd(cmd) {
|
||||
return true
|
||||
}
|
||||
|
||||
vv := make(viewers, 200)
|
||||
// load scrape api for resources and populate aliases.
|
||||
func (c *command) load() viewers {
|
||||
vv := make(viewers, 100)
|
||||
resourceViews(c.app.Conn(), vv)
|
||||
allCRDs(c.app.Conn(), vv)
|
||||
|
||||
return vv
|
||||
}
|
||||
|
||||
func (c *command) viewMetaFor(cmd string) (string, *viewer) {
|
||||
vv := c.load()
|
||||
gvr, ok := aliases.Get(cmd)
|
||||
if !ok {
|
||||
log.Error().Err(fmt.Errorf("Huh? `%s` command not found", cmd)).Msg("Command Failed")
|
||||
c.app.Flash().Warnf("Huh? `%s` command not found", cmd)
|
||||
return false
|
||||
return "", nil
|
||||
}
|
||||
v, ok := vv[gvr]
|
||||
if !ok {
|
||||
log.Error().Err(fmt.Errorf("Huh? `%s` viewer not found", cmd)).Msg("Viewer Failed")
|
||||
c.app.Flash().Warnf("Huh? `%s` viewer not found", gvr)
|
||||
return false
|
||||
}
|
||||
return c.execCmd(gvr, v)
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (c *command) execCmd(gvr string, v viewer) bool {
|
||||
log.Debug().Msgf("ExecCmd gvr %s", gvr)
|
||||
return gvr, &v
|
||||
}
|
||||
|
||||
// Exec the command by showing associated display.
|
||||
func (c *command) run(cmd string) bool {
|
||||
log.Debug().Msgf("Running command %v", cmd)
|
||||
defer func(t time.Time) {
|
||||
log.Debug().Msgf("RUN CMD Elapsed %v", time.Since(t))
|
||||
}(time.Now())
|
||||
|
||||
if c.isK9sCmd(cmd) {
|
||||
return true
|
||||
}
|
||||
|
||||
cmds := strings.Split(cmd, " ")
|
||||
gvr, v := c.viewMetaFor(cmds[0])
|
||||
if v == nil {
|
||||
return false
|
||||
}
|
||||
switch cmds[0] {
|
||||
case "ctx", "context", "contexts":
|
||||
if len(cmds) == 2 {
|
||||
c.app.switchCtx(cmds[1], true)
|
||||
return true
|
||||
}
|
||||
view := c.viewerFor(gvr, v)
|
||||
return c.exec(gvr, "", view)
|
||||
default:
|
||||
ns := c.app.Config.ActiveNamespace()
|
||||
if len(cmds) == 2 {
|
||||
ns = cmds[1]
|
||||
}
|
||||
if !c.app.switchNS(ns) {
|
||||
return false
|
||||
}
|
||||
return c.exec(gvr, ns, c.viewerFor(gvr, v))
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *command) viewerFor(gvr string, v *viewer) resourceViewer {
|
||||
var r resource.List
|
||||
if v.listFn != nil {
|
||||
r = v.listFn(c.app.Conn(), resource.DefaultNamespace)
|
||||
|
|
@ -127,10 +168,10 @@ func (c *command) execCmd(gvr string, v viewer) bool {
|
|||
view.setDecorateFn(v.decorateFn)
|
||||
}
|
||||
|
||||
return c.exec(gvr, view)
|
||||
return view
|
||||
}
|
||||
|
||||
func (c *command) exec(gvr string, v ui.Igniter) bool {
|
||||
func (c *command) exec(gvr string, ns string, v ui.Igniter) bool {
|
||||
if v == nil {
|
||||
log.Error().Err(fmt.Errorf("No igniter given for %s", gvr))
|
||||
return false
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import (
|
|||
|
||||
"github.com/derailed/k9s/internal/resource"
|
||||
"github.com/derailed/k9s/internal/ui"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
type contextView struct {
|
||||
|
|
@ -50,18 +49,19 @@ func (v *contextView) useContext(name string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
v.app.stopForwarders()
|
||||
ns, err := v.app.Conn().Config().CurrentNamespaceName()
|
||||
if err != nil {
|
||||
log.Info().Err(err).Msg("No namespace specified using all namespaces")
|
||||
}
|
||||
v.app.startInformer(ns)
|
||||
v.app.Config.Reset()
|
||||
v.app.Config.Save()
|
||||
v.app.Flash().Infof("Switching context to %s", ctx)
|
||||
v.app.switchCtx(name, false)
|
||||
// v.app.stopForwarders()
|
||||
// ns, err := v.app.Conn().Config().CurrentNamespaceName()
|
||||
// if err != nil {
|
||||
// log.Info().Err(err).Msg("No namespace specified using all namespaces")
|
||||
// }
|
||||
// v.app.startInformer(ns)
|
||||
// v.app.Config.Reset()
|
||||
// v.app.Config.Save()
|
||||
// v.app.Flash().Infof("Switching context to %s", ctx)
|
||||
v.refresh()
|
||||
if tv, ok := v.GetPrimitive("ctx").(*tableView); ok {
|
||||
tv.Select(0, 0)
|
||||
tv.Select(1, 0)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import (
|
|||
|
||||
func TestContextView(t *testing.T) {
|
||||
l := resource.NewContextList(nil, "fred")
|
||||
v := newContextView("blee", NewApp(config.NewConfig(ks{})), l).(*contextView)
|
||||
v := newContextView("blee", "", NewApp(config.NewConfig(ks{})), l).(*contextView)
|
||||
|
||||
assert.Equal(t, 10, len(v.hints()))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import (
|
|||
|
||||
func TestDeployView(t *testing.T) {
|
||||
l := resource.NewDeploymentList(nil, "fred")
|
||||
v := newDeployView("blee", NewApp(config.NewConfig(ks{})), l).(*deployView)
|
||||
v := newDeployView("blee", "", NewApp(config.NewConfig(ks{})), l).(*deployView)
|
||||
|
||||
assert.Equal(t, 10, len(v.hints()))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import (
|
|||
|
||||
func TestDaemonSetView(t *testing.T) {
|
||||
l := resource.NewDaemonSetList(nil, "fred")
|
||||
v := newDaemonSetView("blee", NewApp(config.NewConfig(ks{})), l).(*daemonSetView)
|
||||
v := newDaemonSetView("blee", "", NewApp(config.NewConfig(ks{})), l).(*daemonSetView)
|
||||
|
||||
assert.Equal(t, 10, len(v.hints()))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,13 +50,13 @@ func showPods(app *appView, ns, labelSel, fieldSel string, a ui.ActionHandler) {
|
|||
list.SetLabelSelector(labelSel)
|
||||
list.SetFieldSelector(fieldSel)
|
||||
|
||||
pv := newPodView("Pods", "v1/pods", app, list)
|
||||
pv := newPodView("Pod", "v1/pods", app, list)
|
||||
pv.setColorerFn(podColorer)
|
||||
// pv.setExtraActionsFn(func(aa ui.KeyActions) {
|
||||
pv.masterPage().SetActions(ui.KeyActions{
|
||||
tcell.KeyEsc: ui.NewKeyAction("Back", a, true),
|
||||
})
|
||||
// Reset active namespace to all.
|
||||
// Reset active namespace to ns.
|
||||
app.Config.SetActiveNamespace(ns)
|
||||
app.inject(pv)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ func (v *namespaceView) useNamespace(ns string) {
|
|||
v.app.Flash().Infof("Namespace %s is now active!", ns)
|
||||
}
|
||||
v.app.Config.Save()
|
||||
v.app.startInformer(ns)
|
||||
}
|
||||
|
||||
func (*namespaceView) cleanser(s string) string {
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ func (v *podView) listContainers(app *appView, _, res, sel string) {
|
|||
|
||||
pod := po.(*v1.Pod)
|
||||
list := resource.NewContainerList(app.Conn(), pod)
|
||||
title := skinTitle(fmt.Sprintf(containerFmt, "Containers", sel), app.Styles.Frame())
|
||||
title := skinTitle(fmt.Sprintf(containerFmt, "Container", sel), app.Styles.Frame())
|
||||
|
||||
// Stop my updater
|
||||
if v.cancelFn != nil {
|
||||
|
|
|
|||
|
|
@ -90,7 +90,8 @@ func (v *policyView) getTitle() string {
|
|||
func (v *policyView) refresh() {
|
||||
data, err := v.reconcile()
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msgf("Unable to reconcile for %s:%s", v.subjectKind, v.subjectName)
|
||||
log.Error().Err(err).Msgf("Refresh for %s:%s", v.subjectKind, v.subjectName)
|
||||
v.app.Flash().Err(err)
|
||||
}
|
||||
v.Update(data)
|
||||
}
|
||||
|
|
@ -129,7 +130,7 @@ func (v *policyView) reconcile() (resource.TableData, error) {
|
|||
evts, errs := v.clusterPolicies()
|
||||
if len(errs) > 0 {
|
||||
for _, err := range errs {
|
||||
log.Debug().Err(err).Msg("Unable to find cluster policies")
|
||||
log.Error().Err(err).Msg("Unable to find cluster policies")
|
||||
}
|
||||
return table, errs[0]
|
||||
}
|
||||
|
|
@ -137,7 +138,7 @@ func (v *policyView) reconcile() (resource.TableData, error) {
|
|||
nevts, errs := v.namespacedPolicies()
|
||||
if len(errs) > 0 {
|
||||
for _, err := range errs {
|
||||
log.Debug().Err(err).Msg("Unable to find cluster policies")
|
||||
log.Error().Err(err).Msg("Unable to find cluster policies")
|
||||
}
|
||||
return table, errs[0]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -136,7 +136,8 @@ func (v *rbacView) getTitle() string {
|
|||
func (v *rbacView) refresh() {
|
||||
data, err := v.reconcile(v.ActiveNS(), v.roleName, v.roleType)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msgf("Unable to reconcile for %s:%d", v.roleName, v.roleType)
|
||||
log.Error().Err(err).Msgf("Refresh for %s:%d", v.roleName, v.roleType)
|
||||
v.app.Flash().Err(err)
|
||||
}
|
||||
v.Update(data)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -334,8 +334,9 @@ func (v *resourceView) refresh() {
|
|||
if v.list.Namespaced() {
|
||||
v.list.SetNamespace(v.currentNS)
|
||||
}
|
||||
log.Debug().Msgf("Reconcile with NS %q", v.currentNS)
|
||||
if err := v.list.Reconcile(v.app.informer, v.path); err != nil {
|
||||
v.app.Flash().Errf("Reconciliation for %s failed - %s", v.list.GetName(), err)
|
||||
v.app.Flash().Err(err)
|
||||
}
|
||||
data := v.list.Data()
|
||||
if v.decorateFn != nil {
|
||||
|
|
@ -345,6 +346,11 @@ func (v *resourceView) refresh() {
|
|||
}
|
||||
|
||||
func (v *resourceView) namespaceActions(aa ui.KeyActions) {
|
||||
ns, err := v.app.Conn().Config().CurrentNamespaceName()
|
||||
log.Debug().Msgf("NAMESPACE %q -- %v", ns, err)
|
||||
if err == nil && ns != resource.AllNamespace {
|
||||
return
|
||||
}
|
||||
if !v.list.Access(resource.NamespaceAccess) {
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -115,7 +115,8 @@ func (v *subjectView) SetSubject(s string) {
|
|||
func (v *subjectView) refresh() {
|
||||
data, err := v.reconcile()
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msgf("Unable to reconcile for %s", v.subjectKind)
|
||||
log.Error().Err(err).Msgf("Refresh for %s", v.subjectKind)
|
||||
v.app.Flash().Err(err)
|
||||
}
|
||||
v.Update(data)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -209,20 +209,10 @@ func benchTimedOut(app *appView) {
|
|||
})
|
||||
}
|
||||
|
||||
func (v *svcView) showSvcPods(ns string, sel map[string]string, b ui.ActionHandler) {
|
||||
func (v *svcView) showSvcPods(ns string, sel map[string]string, a ui.ActionHandler) {
|
||||
var s []string
|
||||
for k, v := range sel {
|
||||
s = append(s, fmt.Sprintf("%s=%s", k, v))
|
||||
}
|
||||
list := resource.NewPodList(v.app.Conn(), ns)
|
||||
list.SetLabelSelector(strings.Join(s, ","))
|
||||
|
||||
pv := newPodView("Pods", "v1/pods", v.app, list)
|
||||
pv.setColorerFn(podColorer)
|
||||
pv.setExtraActionsFn(func(aa ui.KeyActions) {
|
||||
aa[tcell.KeyEsc] = ui.NewKeyAction("Back", b, true)
|
||||
})
|
||||
// set active namespace to service ns.
|
||||
v.app.Config.SetActiveNamespace(ns)
|
||||
v.app.inject(pv)
|
||||
showPods(v.app, ns, strings.Join(s, ","), "", a)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,17 +64,12 @@ type Informer struct {
|
|||
// NewInformer creates a new cluster resource informer
|
||||
func NewInformer(client k8s.Connection, ns string) (*Informer, error) {
|
||||
i := Informer{client: client, informers: map[string]StoreInformer{}}
|
||||
if client.CheckListNSAccess() == nil {
|
||||
i.init(allNamespaces)
|
||||
return &i, nil
|
||||
}
|
||||
|
||||
if err := client.CheckNSAccess(ns); err != nil {
|
||||
log.Error().Err(err).Msg("Checking NS Access")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
i.init(ns)
|
||||
|
||||
return &i, nil
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue