feat: port stacks command from influxdb (#168)

This commit is contained in:
Daniel Moran
2021-06-30 17:21:50 -04:00
committed by GitHub
parent 8126bd8397
commit 40fc1845e9
8 changed files with 770 additions and 74 deletions

63
pkg/template/out.go Normal file
View File

@ -0,0 +1,63 @@
package template
import (
"encoding/json"
"fmt"
"io"
"os"
"path/filepath"
"github.com/influxdata/influx-cli/v2/api"
"gopkg.in/yaml.v3"
)
type OutEncoding int
const (
YamlEncoding OutEncoding = iota
JsonEncoding
)
type OutParams struct {
Out io.Writer
Encoding OutEncoding
}
func ParseOutParams(path string, fallback io.Writer) (OutParams, func(), error) {
if path == "" {
return OutParams{Out: fallback, Encoding: YamlEncoding}, nil, nil
}
f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil {
return OutParams{}, nil, fmt.Errorf("failed to open output path %q: %w", path, err)
}
params := OutParams{Out: f}
switch filepath.Ext(path) {
case ".json":
params.Encoding = JsonEncoding
default:
params.Encoding = YamlEncoding
}
return params, func() { _ = f.Close() }, nil
}
func (o OutParams) WriteTemplate(template []api.TemplateEntry) error {
switch o.Encoding {
case JsonEncoding:
enc := json.NewEncoder(o.Out)
enc.SetIndent("", "\t")
return enc.Encode(template)
case YamlEncoding:
enc := yaml.NewEncoder(o.Out)
for _, entry := range template {
if err := enc.Encode(entry); err != nil {
return err
}
}
default:
return fmt.Errorf("encoding %q is not recognized", o.Encoding)
}
return nil
}

124
pkg/template/out_test.go Normal file
View File

@ -0,0 +1,124 @@
package template_test
import (
"bytes"
"encoding/json"
"io"
"os"
"path/filepath"
"testing"
"github.com/influxdata/influx-cli/v2/api"
"github.com/influxdata/influx-cli/v2/pkg/template"
"github.com/stretchr/testify/require"
"gopkg.in/yaml.v3"
)
var tmpls = []api.TemplateEntry{
{
ApiVersion: "api1",
Kind: "Foo",
Metadata: api.TemplateEntryMetadata{
Name: "foo",
},
Spec: map[string]interface{}{
"hello": "world",
"1 + 1 =": "2",
},
},
{
ApiVersion: "api1",
Kind: "Bar",
Metadata: api.TemplateEntryMetadata{
Name: "bar",
},
Spec: map[string]interface{}{
"success?": "true",
},
},
}
func TestOutParams(t *testing.T) {
t.Parallel()
t.Run("json to file", func(t *testing.T) {
t.Parallel()
tmp, err := os.MkdirTemp("", "")
require.NoError(t, err)
defer os.RemoveAll(tmp)
out := filepath.Join(tmp, "test.json")
params, closer, err := template.ParseOutParams(out, nil)
require.NoError(t, err)
require.NotNil(t, closer)
defer closer()
require.NoError(t, params.WriteTemplate(tmpls))
contents, err := os.ReadFile(out)
require.NoError(t, err)
var written []api.TemplateEntry
dec := json.NewDecoder(bytes.NewReader(contents))
require.NoError(t, dec.Decode(&written))
require.Equal(t, tmpls, written)
})
t.Run("yaml to file", func(t *testing.T) {
t.Parallel()
tmp, err := os.MkdirTemp("", "")
require.NoError(t, err)
defer os.RemoveAll(tmp)
out := filepath.Join(tmp, "test.yaml")
params, closer, err := template.ParseOutParams(out, nil)
require.NoError(t, err)
require.NotNil(t, closer)
defer closer()
require.NoError(t, params.WriteTemplate(tmpls))
contents, err := os.ReadFile(out)
require.NoError(t, err)
var written []api.TemplateEntry
dec := yaml.NewDecoder(bytes.NewReader(contents))
for {
var e api.TemplateEntry
err := dec.Decode(&e)
if err == io.EOF {
break
}
require.NoError(t, err)
written = append(written, e)
}
require.Equal(t, tmpls, written)
})
t.Run("yaml to buffer", func(t *testing.T) {
t.Parallel()
out := bytes.Buffer{}
params, closer, err := template.ParseOutParams("", &out)
require.NoError(t, err)
require.Nil(t, closer)
require.NoError(t, params.WriteTemplate(tmpls))
var written []api.TemplateEntry
dec := yaml.NewDecoder(&out)
for {
var e api.TemplateEntry
err := dec.Decode(&e)
if err == io.EOF {
break
}
require.NoError(t, err)
written = append(written, e)
}
require.Equal(t, tmpls, written)
})
}