Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
da85262f
Commit
da85262f
authored
May 05, 2017
by
Fabiano Franz
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Adds support to a tree hierarchy of kubectl plugins
parent
8594af76
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
126 additions
and
14 deletions
+126
-14
test-cmd-util.sh
hack/make-rules/test-cmd-util.sh
+15
-0
loader.go
pkg/kubectl/plugins/loader.go
+9
-2
loader_test.go
pkg/kubectl/plugins/loader_test.go
+66
-4
plugins.go
pkg/kubectl/plugins/plugins.go
+23
-8
plugin.yaml
test/fixtures/pkg/kubectl/plugins/tree/plugin.yaml
+13
-0
No files found.
hack/make-rules/test-cmd-util.sh
View file @
da85262f
...
...
@@ -3769,6 +3769,21 @@ __EOF__
output_message
=
$(
!
KUBECTL_PLUGINS_PATH
=
test
/fixtures/pkg/kubectl/plugins/ kubectl plugin error 2>&1
)
kube::test::if_has_string
"
${
output_message
}
"
'error: exit status 1'
# plugin tree
output_message
=
$(
KUBECTL_PLUGINS_PATH
=
test
/fixtures/pkg/kubectl/plugins kubectl plugin tree 2>&1
)
kube::test::if_has_string
"
${
output_message
}
"
'Plugin with a tree of commands'
kube::test::if_has_string
"
${
output_message
}
"
'child1\s\+The first child of a tree'
kube::test::if_has_string
"
${
output_message
}
"
'child2\s\+The second child of a tree'
kube::test::if_has_string
"
${
output_message
}
"
'child3\s\+The third child of a tree'
output_message
=
$(
KUBECTL_PLUGINS_PATH
=
test
/fixtures/pkg/kubectl/plugins kubectl plugin tree child1
--help
2>&1
)
kube::test::if_has_string
"
${
output_message
}
"
'The first child of a tree'
kube::test::if_has_not_string
"
${
output_message
}
"
'The second child'
kube::test::if_has_not_string
"
${
output_message
}
"
'child2'
output_message
=
$(
KUBECTL_PLUGINS_PATH
=
test
/fixtures/pkg/kubectl/plugins kubectl plugin tree child1 2>&1
)
kube::test::if_has_string
"
${
output_message
}
"
'child one'
kube::test::if_has_not_string
"
${
output_message
}
"
'child1'
kube::test::if_has_not_string
"
${
output_message
}
"
'The first child'
#################
# Impersonation #
#################
...
...
pkg/kubectl/plugins/loader.go
View file @
da85262f
...
...
@@ -88,8 +88,15 @@ func (l *DirectoryPluginLoader) Load() (Plugins, error) {
return
nil
}
plugin
.
Dir
=
filepath
.
Dir
(
path
)
plugin
.
DescriptorName
=
fileInfo
.
Name
()
var
setSource
func
(
path
string
,
fileInfo
os
.
FileInfo
,
p
*
Plugin
)
setSource
=
func
(
path
string
,
fileInfo
os
.
FileInfo
,
p
*
Plugin
)
{
p
.
Dir
=
filepath
.
Dir
(
path
)
p
.
DescriptorName
=
fileInfo
.
Name
()
for
_
,
child
:=
range
p
.
Tree
{
setSource
(
path
,
fileInfo
,
child
)
}
}
setSource
(
path
,
fileInfo
,
plugin
)
glog
.
V
(
6
)
.
Infof
(
"Plugin loaded: %s"
,
plugin
.
Name
)
list
=
append
(
list
,
plugin
)
...
...
pkg/kubectl/plugins/loader_test.go
View file @
da85262f
...
...
@@ -27,7 +27,7 @@ import (
)
func
TestSuccessfulDirectoryPluginLoader
(
t
*
testing
.
T
)
{
tmp
,
err
:=
setupValidPlugins
(
3
)
tmp
,
err
:=
setupValidPlugins
(
3
,
0
)
if
err
!=
nil
{
t
.
Fatalf
(
"unexpected error: %v"
,
err
)
}
...
...
@@ -55,6 +55,9 @@ func TestSuccessfulDirectoryPluginLoader(t *testing.T) {
if
m
,
_
:=
regexp
.
MatchString
(
"^echo plugin[123]$"
,
plugin
.
Command
);
!
m
{
t
.
Errorf
(
"Unexpected plugin command %s"
,
plugin
.
Command
)
}
if
count
:=
len
(
plugin
.
Tree
);
count
!=
0
{
t
.
Errorf
(
"Unexpected number of loaded child plugins, wanted 0, got %d"
,
count
)
}
}
}
...
...
@@ -107,7 +110,7 @@ func TestUnexistentDirectoryPluginLoader(t *testing.T) {
}
func
TestPluginsEnvVarPluginLoader
(
t
*
testing
.
T
)
{
tmp
,
err
:=
setupValidPlugins
(
1
)
tmp
,
err
:=
setupValidPlugins
(
1
,
0
)
if
err
!=
nil
{
t
.
Fatalf
(
"unexpected error: %v"
,
err
)
}
...
...
@@ -172,19 +175,78 @@ shortDesc: The incomplete test plugin`
}
}
func
setupValidPlugins
(
count
int
)
(
string
,
error
)
{
func
TestDirectoryTreePluginLoader
(
t
*
testing
.
T
)
{
tmp
,
err
:=
setupValidPlugins
(
1
,
2
)
if
err
!=
nil
{
t
.
Fatalf
(
"unexpected error: %v"
,
err
)
}
defer
os
.
RemoveAll
(
tmp
)
loader
:=
&
DirectoryPluginLoader
{
Directory
:
tmp
,
}
plugins
,
err
:=
loader
.
Load
()
if
err
!=
nil
{
t
.
Errorf
(
"Unexpected error loading plugins: %v"
,
err
)
}
if
count
:=
len
(
plugins
);
count
!=
1
{
t
.
Errorf
(
"Unexpected number of loaded plugins, wanted 1, got %d"
,
count
)
}
for
_
,
plugin
:=
range
plugins
{
if
m
,
_
:=
regexp
.
MatchString
(
"^plugin1$"
,
plugin
.
Name
);
!
m
{
t
.
Errorf
(
"Unexpected plugin name %s"
,
plugin
.
Name
)
}
if
m
,
_
:=
regexp
.
MatchString
(
"^The plugin1 test plugin$"
,
plugin
.
ShortDesc
);
!
m
{
t
.
Errorf
(
"Unexpected plugin short desc %s"
,
plugin
.
ShortDesc
)
}
if
m
,
_
:=
regexp
.
MatchString
(
"^echo plugin1$"
,
plugin
.
Command
);
!
m
{
t
.
Errorf
(
"Unexpected plugin command %s"
,
plugin
.
Command
)
}
if
count
:=
len
(
plugin
.
Tree
);
count
!=
2
{
t
.
Errorf
(
"Unexpected number of loaded child plugins, wanted 2, got %d"
,
count
)
}
for
_
,
child
:=
range
plugin
.
Tree
{
if
m
,
_
:=
regexp
.
MatchString
(
"^child[12]$"
,
child
.
Name
);
!
m
{
t
.
Errorf
(
"Unexpected plugin child name %s"
,
child
.
Name
)
}
if
m
,
_
:=
regexp
.
MatchString
(
"^The child[12] test plugin child of plugin1 of House Targaryen$"
,
child
.
ShortDesc
);
!
m
{
t
.
Errorf
(
"Unexpected plugin child short desc %s"
,
child
.
ShortDesc
)
}
if
m
,
_
:=
regexp
.
MatchString
(
"^echo child[12]$"
,
child
.
Command
);
!
m
{
t
.
Errorf
(
"Unexpected plugin child command %s"
,
child
.
Command
)
}
}
}
}
func
setupValidPlugins
(
nPlugins
,
nChildren
int
)
(
string
,
error
)
{
tmp
,
err
:=
ioutil
.
TempDir
(
""
,
""
)
if
err
!=
nil
{
return
""
,
fmt
.
Errorf
(
"unexpected ioutil.TempDir error: %v"
,
err
)
}
for
i
:=
1
;
i
<=
count
;
i
++
{
for
i
:=
1
;
i
<=
nPlugins
;
i
++
{
name
:=
fmt
.
Sprintf
(
"plugin%d"
,
i
)
descriptor
:=
fmt
.
Sprintf
(
`
name: %[1]s
shortDesc: The %[1]s test plugin
command: echo %[1]s`
,
name
)
if
nChildren
>
0
{
descriptor
+=
`
tree:`
}
for
j
:=
1
;
j
<=
nChildren
;
j
++
{
child
:=
fmt
.
Sprintf
(
"child%d"
,
i
)
descriptor
+=
fmt
.
Sprintf
(
`
- name: %[1]s
shortDesc: The %[1]s test plugin child of %[2]s of House Targaryen
command: echo %[1]s`
,
child
,
name
)
}
if
err
:=
os
.
Mkdir
(
filepath
.
Join
(
tmp
,
name
),
0755
);
err
!=
nil
{
return
""
,
fmt
.
Errorf
(
"unexpected os.Mkdir error: %v"
,
err
)
}
...
...
pkg/kubectl/plugins/plugins.go
View file @
da85262f
...
...
@@ -16,7 +16,10 @@ limitations under the License.
package
plugins
import
"fmt"
import
(
"fmt"
"strings"
)
// Plugin is the representation of a CLI extension (plugin).
type
Plugin
struct
{
...
...
@@ -28,11 +31,12 @@ type Plugin struct {
// PluginDescription holds everything needed to register a
// plugin as a command. Usually comes from a descriptor file.
type
Description
struct
{
Name
string
`json:"name"`
ShortDesc
string
`json:"shortDesc"`
LongDesc
string
`json:"longDesc,omitempty"`
Example
string
`json:"example,omitempty"`
Command
string
`json:"command"`
Name
string
`json:"name"`
ShortDesc
string
`json:"shortDesc"`
LongDesc
string
`json:"longDesc,omitempty"`
Example
string
`json:"example,omitempty"`
Command
string
`json:"command"`
Tree
[]
*
Plugin
`json:"tree,omitempty"`
}
// PluginSource holds the location of a given plugin in the filesystem.
...
...
@@ -41,12 +45,23 @@ type Source struct {
DescriptorName
string
`json:"-"`
}
var
IncompleteError
=
fmt
.
Errorf
(
"incomplete plugin descriptor: name, shortDesc and command fields are required"
)
var
(
IncompleteError
=
fmt
.
Errorf
(
"incomplete plugin descriptor: name, shortDesc and command fields are required"
)
InvalidNameError
=
fmt
.
Errorf
(
"plugin name can't contain spaces"
)
)
func
(
p
Plugin
)
Validate
()
error
{
if
len
(
p
.
Name
)
==
0
||
len
(
p
.
ShortDesc
)
==
0
||
len
(
p
.
Command
)
==
0
{
if
len
(
p
.
Name
)
==
0
||
len
(
p
.
ShortDesc
)
==
0
||
(
len
(
p
.
Command
)
==
0
&&
len
(
p
.
Tree
)
==
0
)
{
return
IncompleteError
}
if
strings
.
Index
(
p
.
Name
,
" "
)
>
-
1
{
return
InvalidNameError
}
for
_
,
child
:=
range
p
.
Tree
{
if
err
:=
child
.
Validate
();
err
!=
nil
{
return
err
}
}
return
nil
}
...
...
test/fixtures/pkg/kubectl/plugins/tree/plugin.yaml
0 → 100644
View file @
da85262f
name
:
"
tree"
shortDesc
:
"
Plugin
with
a
tree
of
commands"
tree
:
-
name
:
"
child1"
shortDesc
:
"
The
first
child
of
a
tree"
command
:
echo child1
-
name
:
"
child2"
shortDesc
:
"
The
second
child
of
a
tree"
command
:
echo child2
-
name
:
"
child3"
shortDesc
:
"
The
third
child
of
a
tree"
command
:
echo child3
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment