Skip to content
This repository was archived by the owner on Jan 21, 2020. It is now read-only.

Commit cb420e3

Browse files
author
David Chung
authored
API Change - Instance plugin to optionally output instance details (#464)
Signed-off-by: David Chung <[email protected]>
1 parent 2153cbb commit cb420e3

File tree

27 files changed

+184
-88
lines changed

27 files changed

+184
-88
lines changed

cmd/cli/base/output.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package base
2+
3+
import (
4+
"fmt"
5+
"io"
6+
7+
"github.com/docker/infrakit/pkg/types"
8+
"github.com/ghodss/yaml"
9+
"github.com/spf13/pflag"
10+
)
11+
12+
// RawOutputFunc is a function that writes some data to the output writer
13+
type RawOutputFunc func(w io.Writer, v interface{}) (rendered bool, err error)
14+
15+
// RawOutput returns the flagset and the func for printing output
16+
func RawOutput() (*pflag.FlagSet, RawOutputFunc) {
17+
18+
fs := pflag.NewFlagSet("output", pflag.ExitOnError)
19+
20+
raw := fs.BoolP("raw", "r", false, "True to dump to output instead of executing")
21+
yamlDoc := fs.BoolP("yaml", "y", false, "True if input is in yaml format; json is the default")
22+
23+
return fs, func(w io.Writer, v interface{}) (rendered bool, err error) {
24+
if !*raw {
25+
return false, nil
26+
}
27+
28+
any, err := types.AnyValue(v)
29+
if err != nil {
30+
return false, err
31+
}
32+
33+
buff := any.Bytes()
34+
if *yamlDoc {
35+
buff, err = yaml.JSONToYAML(buff)
36+
}
37+
38+
fmt.Fprintln(w, string(buff))
39+
return true, nil
40+
}
41+
}

cmd/cli/base/template.go

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -159,21 +159,6 @@ func TemplateProcessor(plugins func() discovery.Plugins) (*pflag.FlagSet, ToJSON
159159
return
160160
}
161161

162-
// if *yamlDoc {
163-
164-
// // Convert this to json if it's not in JSON -- the default is for the template to be in YAML
165-
// converted, e := yaml.YAMLToJSON([]byte(view))
166-
// log.Debug("converting yaml to json", "before", view, "after", string(converted))
167-
168-
// if e != nil {
169-
// err = e
170-
// return
171-
// }
172-
173-
// view = string(converted)
174-
// log.Debug("view", "rendered", view)
175-
// }
176-
177162
log.Debug("rendered", "view", view)
178163
if *dump {
179164
fmt.Println("Final:")

cmd/cli/instance/instance.go

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
package instance
22

33
import (
4+
"bytes"
45
"fmt"
56
"os"
67
"sort"
78
"strings"
9+
"text/template"
810

911
"github.com/docker/infrakit/cmd/cli/base"
1012
"github.com/docker/infrakit/pkg/cli"
@@ -150,8 +152,19 @@ func Command(plugins func() discovery.Plugins) *cobra.Command {
150152
Short: "Describe all managed instances across all groups, subject to filter",
151153
}
152154
tags := describe.Flags().StringSlice("tags", []string{}, "Tags to filter")
155+
properties := describe.Flags().BoolP("properties", "p", false, "Also returns current status/ properties")
156+
propertiesTemplate := describe.Flags().StringP("view", "v", "{{.}}", "Template to render properties")
157+
158+
rawOutputFlags, rawOutput := base.RawOutput()
159+
describe.Flags().AddFlagSet(rawOutputFlags)
160+
153161
describe.RunE = func(cmd *cobra.Command, args []string) error {
154162

163+
view, err := template.New("describe-instances").Parse(*propertiesTemplate)
164+
if err != nil {
165+
return err
166+
}
167+
155168
filter := map[string]string{}
156169
for _, t := range *tags {
157170
p := strings.Split(t, "=")
@@ -162,13 +175,28 @@ func Command(plugins func() discovery.Plugins) *cobra.Command {
162175
}
163176
}
164177

165-
desc, err := instancePlugin.DescribeInstances(filter)
178+
desc, err := instancePlugin.DescribeInstances(filter, *properties)
166179
if err == nil {
167180

181+
rendered, err := rawOutput(os.Stdout, desc)
182+
if err != nil {
183+
return err
184+
}
185+
186+
if rendered {
187+
return nil
188+
}
189+
168190
if !*quiet {
169-
fmt.Printf("%-30s\t%-30s\t%-s\n", "ID", "LOGICAL", "TAGS")
191+
if *properties {
192+
fmt.Printf("%-30s\t%-30s\t%-30s\t%-s\n", "ID", "LOGICAL", "TAGS", "PROPERTIES")
193+
194+
} else {
195+
fmt.Printf("%-30s\t%-30s\t%-s\n", "ID", "LOGICAL", "TAGS")
196+
}
170197
}
171198
for _, d := range desc {
199+
172200
logical := " - "
173201
if d.LogicalID != nil {
174202
logical = string(*d.LogicalID)
@@ -180,7 +208,12 @@ func Command(plugins func() discovery.Plugins) *cobra.Command {
180208
}
181209
sort.Strings(printTags)
182210

183-
fmt.Printf("%-30s\t%-30s\t%-s\n", d.ID, logical, strings.Join(printTags, ","))
211+
if *properties {
212+
fmt.Printf("%-30s\t%-30s\t%-30s\t%-s\n", d.ID, logical, strings.Join(printTags, ","),
213+
renderProperties(d.Properties, view))
214+
} else {
215+
fmt.Printf("%-30s\t%-30s\t%-s\n", d.ID, logical, strings.Join(printTags, ","))
216+
}
184217
}
185218
}
186219

@@ -196,3 +229,18 @@ func Command(plugins func() discovery.Plugins) *cobra.Command {
196229

197230
return cmd
198231
}
232+
233+
func renderProperties(properties *types.Any, view *template.Template) string {
234+
var v interface{}
235+
err := properties.Decode(&v)
236+
if err != nil {
237+
return err.Error()
238+
}
239+
240+
buff := new(bytes.Buffer)
241+
err = view.Execute(buff, v)
242+
if err != nil {
243+
return err.Error()
244+
}
245+
return buff.String()
246+
}

cmd/cli/manager/manager.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ func Command(plugins func() discovery.Plugins) *cobra.Command {
7676
return nil
7777
},
7878
}
79-
pretend := cmd.PersistentFlags().Bool("pretend", true, "Don't actually make changes; explain where appropriate")
79+
pretend := cmd.PersistentFlags().Bool("pretend", false, "Don't actually make changes; explain where appropriate")
8080

8181
///////////////////////////////////////////////////////////////////////////////////
8282
// commit

docs/plugins/instance.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Instance plugin API
22

3-
<!-- SOURCE-CHECKSUM pkg/spi/instance/* befb47292c2f062637d65e9777d88c322856baf650feb6b527cd3a4242f86d3482b656246051d2ca -->
3+
<!-- SOURCE-CHECKSUM pkg/spi/instance/* af33b7b157a24a90e4ecef4b99c997a4039edf7832ae259bfe527c06caec5455f3c083481586eda2 -->
44

55
## API
66

@@ -115,21 +115,23 @@ Fetches details about Instances.
115115
#### Request
116116
```json
117117
{
118-
"Tags": {"tag_key": "tag_value"}
118+
"Tags": {"tag_key": "tag_value"},
119+
"Properties" : true
119120
}
120121
```
121122

122123
Parameters:
123124
- `Tags`: Instance tags to match. If multiple tags are specified, only Instances matching all tags are returned.
124-
125+
- `Properties`: Boolean to indicate whether the client requests additional details via the `Description.Properties` field.
125126
#### Response
126127
```json
127128
{
128129
"Descriptions": [
129130
{
130131
"ID": "instance_id",
131132
"LogicalID": "logical_id",
132-
"Tags": {"tag_key": "tag_value"}
133+
"Tags": {"tag_key": "tag_value"},
134+
"Properties" : { "some_status" : "ok", "some_state" : 10 }
133135
}
134136
]
135137
}

examples/instance/file/plugin.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ func (p *plugin) Destroy(instance instance.ID) error {
142142

143143
// DescribeInstances returns descriptions of all instances matching all of the provided tags.
144144
// TODO - need to define the fitlering of tags => AND or OR of matches?
145-
func (p *plugin) DescribeInstances(tags map[string]string) ([]instance.Description, error) {
145+
func (p *plugin) DescribeInstances(tags map[string]string, properties bool) ([]instance.Description, error) {
146146
log.Debugln("describe-instances", tags)
147147
entries, err := afero.ReadDir(p.fs, p.Dir)
148148
if err != nil {
@@ -166,6 +166,11 @@ scan:
166166
continue scan
167167
}
168168

169+
if properties {
170+
if blob, err := types.AnyValue(inst.Spec); err == nil {
171+
inst.Properties = blob
172+
}
173+
}
169174
if len(tags) == 0 {
170175
result = append(result, inst.Description)
171176
} else {

examples/instance/file/plugin_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ func run(t *testing.T, properties string) {
8787
"label3": "value3",
8888
}, parsed.Description.Tags)
8989

90-
list, err := fileinst.DescribeInstances(map[string]string{"label1": "changed1"})
90+
list, err := fileinst.DescribeInstances(map[string]string{"label1": "changed1"}, false)
9191
require.NoError(t, err)
9292
require.Equal(t, []instance.Description{
9393
{
@@ -99,7 +99,7 @@ func run(t *testing.T, properties string) {
9999
err = fileinst.Destroy(*id)
100100
require.NoError(t, err)
101101

102-
list, err = fileinst.DescribeInstances(map[string]string{"label1": "changed1"})
102+
list, err = fileinst.DescribeInstances(map[string]string{"label1": "changed1"}, false)
103103
require.NoError(t, err)
104104
require.Equal(t, []instance.Description{}, list)
105105

examples/instance/maas/instance.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ func (m maasPlugin) Destroy(id instance.ID) error {
294294
}
295295

296296
// DescribeInstances returns descriptions of all instances matching all of the provided tags.
297-
func (m maasPlugin) DescribeInstances(tags map[string]string) ([]instance.Description, error) {
297+
func (m maasPlugin) DescribeInstances(tags map[string]string, properties bool) ([]instance.Description, error) {
298298
var ret []instance.Description
299299
nodeListing := m.MaasObj.GetSubObject("nodes")
300300
listNodeObjects, err := nodeListing.CallGet("list", url.Values{})

examples/instance/maas/instance_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ func TestProvision_and_Destroy(t *testing.T) {
108108
id, err := maasPlugin.Provision(instanceSpec)
109109
require.NoError(t, err)
110110

111-
list, err := maasPlugin.DescribeInstances(map[string]string{"label1": "value1"})
111+
list, err := maasPlugin.DescribeInstances(map[string]string{"label1": "value1"}, false)
112112
require.NoError(t, err)
113113
require.Equal(t, []instance.Description{
114114
{
@@ -125,7 +125,7 @@ func TestProvision_and_Destroy(t *testing.T) {
125125
})
126126
require.NoError(t, err)
127127

128-
list, err = maasPlugin.DescribeInstances(map[string]string{"label1": "value1"})
128+
list, err = maasPlugin.DescribeInstances(map[string]string{"label1": "value1"}, false)
129129
require.NoError(t, err)
130130
require.Equal(t, []instance.Description{
131131
{
@@ -137,7 +137,7 @@ func TestProvision_and_Destroy(t *testing.T) {
137137
},
138138
}, list)
139139

140-
list, err = maasPlugin.DescribeInstances(map[string]string{"label3": "changed"})
140+
list, err = maasPlugin.DescribeInstances(map[string]string{"label3": "changed"}, false)
141141
require.NoError(t, err)
142142
require.Equal(t, []instance.Description{
143143
{

examples/instance/terraform/plugin.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -556,7 +556,7 @@ func (p *plugin) Destroy(instance instance.ID) error {
556556
}
557557

558558
// DescribeInstances returns descriptions of all instances matching all of the provided tags.
559-
func (p *plugin) DescribeInstances(tags map[string]string) ([]instance.Description, error) {
559+
func (p *plugin) DescribeInstances(tags map[string]string, properties bool) ([]instance.Description, error) {
560560
log.Debugln("describe-instances", tags)
561561

562562
show, err := p.terraformShow()

0 commit comments

Comments
 (0)