Skip to content

Commit 12f7716

Browse files
authored
feat: inline Environment (#403)
1 parent 2033fc1 commit 12f7716

19 files changed

+375
-80
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
dist
2+
tk

cmd/tk/env.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ func envCmd() *cli.Command {
3636
return cmd
3737
}
3838

39-
func envSettingsFlags(env *v1alpha1.Config, fs *pflag.FlagSet) {
39+
func envSettingsFlags(env *v1alpha1.Environment, fs *pflag.FlagSet) {
4040
fs.StringVar(&env.Spec.APIServer, "server", env.Spec.APIServer, "endpoint of the Kubernetes API")
4141
fs.StringVar(&env.Spec.APIServer, "server-from-context", env.Spec.APIServer, "set the server to a known one from $KUBECONFIG")
4242
fs.StringVar(&env.Spec.Namespace, "namespace", env.Spec.Namespace, "namespace to create objects in")
@@ -61,7 +61,7 @@ func envSetCmd() *cli.Command {
6161
}
6262

6363
// flags
64-
tmp := v1alpha1.Config{}
64+
tmp := v1alpha1.Environment{}
6565
envSettingsFlags(&tmp, cmd.Flags())
6666

6767
// removed name flag
@@ -136,7 +136,7 @@ func envAddCmd() *cli.Command {
136136
}
137137

138138
// used by initCmd() as well
139-
func addEnv(dir string, cfg *v1alpha1.Config) error {
139+
func addEnv(dir string, cfg *v1alpha1.Environment) error {
140140
path, err := filepath.Abs(dir)
141141
if err != nil {
142142
return err
@@ -216,7 +216,7 @@ func envListCmd() *cli.Command {
216216
useNames := cmd.Flags().Bool("names", false, "plain names output")
217217

218218
cmd.Run = func(cmd *cli.Command, args []string) error {
219-
envs := []v1alpha1.Config{}
219+
envs := []v1alpha1.Environment{}
220220
dirs := findBaseDirs()
221221
var selector labels.Selector
222222
var err error

cmd/tk/jsonnet.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ func evalCmd() *cli.Command {
3030
jsonnetOpts.EvalPattern = *evalPattern
3131
raw, err := tanka.Eval(args[0], jsonnetOpts)
3232

33-
if err != nil {
33+
if raw == nil && err != nil {
3434
return err
3535
}
3636

cmd/tk/main.go

+14-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010

1111
"github.com/go-clix/cli"
1212

13+
"github.com/grafana/tanka/pkg/jsonnet"
1314
"github.com/grafana/tanka/pkg/jsonnet/jpath"
1415
"github.com/grafana/tanka/pkg/spec"
1516
"github.com/grafana/tanka/pkg/spec/v1alpha1"
@@ -60,7 +61,7 @@ func main() {
6061
}
6162
}
6263

63-
func setupConfiguration(baseDir string) *v1alpha1.Config {
64+
func setupConfiguration(baseDir string) *v1alpha1.Environment {
6465
_, baseDir, rootDir, err := jpath.Resolve(baseDir)
6566
if err != nil {
6667
log.Fatalln("Resolving jpath:", err)
@@ -77,6 +78,18 @@ func setupConfiguration(baseDir string) *v1alpha1.Config {
7778
if verbose {
7879
fmt.Print(err)
7980
}
81+
// no spec.json is found, try parsing main.jsonnet
82+
case spec.ErrNoSpec:
83+
config, err := tanka.EvalEnvs(baseDir, jsonnet.Opts{})
84+
if err != nil {
85+
switch err.(type) {
86+
case tanka.ErrNoEnv:
87+
return nil
88+
default:
89+
log.Fatalf("Reading main.jsonnet: %s", err)
90+
}
91+
}
92+
return config
8093
// some other error
8194
default:
8295
log.Fatalf("Reading spec.json: %s", err)

cmd/tk/other.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ func findBaseDirs() (dirs []string) {
2020
}
2121

2222
if err := filepath.Walk(".", func(path string, info os.FileInfo, err error) error {
23-
requiredFiles := []string{"main.jsonnet", "spec.json"}
23+
requiredFiles := []string{"main.jsonnet"}
2424
for _, name := range requiredFiles {
2525
if _, err := os.Stat(filepath.Join(path, name)); err != nil {
2626
// missing file, not a valid environment directory

pkg/kubernetes/kubernetes.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212

1313
// Kubernetes exposes methods to work with the Kubernetes orchestrator
1414
type Kubernetes struct {
15-
Env v1alpha1.Config
15+
Env v1alpha1.Environment
1616

1717
// Client (kubectl)
1818
ctl client.Client
@@ -26,7 +26,7 @@ type Kubernetes struct {
2626
type Differ func(manifest.List) (*string, error)
2727

2828
// New creates a new Kubernetes with an initialized client
29-
func New(env v1alpha1.Config) (*Kubernetes, error) {
29+
func New(env v1alpha1.Environment) (*Kubernetes, error) {
3030
// setup client
3131
ctl, err := client.New(env.Spec.APIServer)
3232
if err != nil {

pkg/process/process.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ const (
1818
// - tanka.dev/** labels
1919
// - filtering
2020
// - best-effort sorting
21-
func Process(raw interface{}, cfg v1alpha1.Config, exprs Matchers) (manifest.List, error) {
21+
func Process(raw interface{}, cfg v1alpha1.Environment, exprs Matchers) (manifest.List, error) {
2222
// Scan for everything that looks like a Kubernetes object
2323
extracted, err := Extract(raw)
2424
if err != nil {
@@ -56,7 +56,7 @@ func Process(raw interface{}, cfg v1alpha1.Config, exprs Matchers) (manifest.Lis
5656
}
5757

5858
// Label conditionally adds tanka.dev/** labels to each manifest in the List
59-
func Label(list manifest.List, cfg v1alpha1.Config) manifest.List {
59+
func Label(list manifest.List, cfg v1alpha1.Environment) manifest.List {
6060
for i, m := range list {
6161
// inject tanka.dev/environment label
6262
if cfg.Spec.InjectLabels {
@@ -68,7 +68,7 @@ func Label(list manifest.List, cfg v1alpha1.Config) manifest.List {
6868
return list
6969
}
7070

71-
func ResourceDefaults(list manifest.List, cfg v1alpha1.Config) manifest.List {
71+
func ResourceDefaults(list manifest.List, cfg v1alpha1.Environment) manifest.List {
7272
for i, m := range list {
7373
for k, v := range cfg.Spec.ResourceDefaults.Annotations {
7474
annotations := m.Metadata().Annotations()

pkg/process/resourceDefaults_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ func TestResourceDefaults(t *testing.T) {
5555

5656
for _, c := range cases {
5757
t.Run(c.name, func(t *testing.T) {
58-
cfg := v1alpha1.Config{
58+
cfg := v1alpha1.Environment{
5959
Spec: v1alpha1.Spec{
6060
ResourceDefaults: v1alpha1.ResourceDefaults{
6161
Annotations: c.specAnnotations,

pkg/spec/depreciations_test.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ import (
1414
func TestDeprecated(t *testing.T) {
1515
data := []byte(`
1616
{
17+
"metadata": {
18+
"name": "test"
19+
},
1720
"spec": {
1821
"namespace": "new"
1922
},
@@ -23,7 +26,7 @@ func TestDeprecated(t *testing.T) {
2326
}
2427
`)
2528

26-
got, err := Parse(data, "test")
29+
got, err := Parse(data)
2730
require.Equal(t, ErrDeprecated{
2831
{old: "server", new: "spec.apiServer"},
2932
{old: "team", new: "metadata.labels.team"},

pkg/spec/spec.go

+12-10
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ const APIGroup = "tanka.dev"
1818
// Specfile is the filename for the environment config
1919
const Specfile = "spec.json"
2020

21-
// ParseDir parses the given environments `spec.json` into a `v1alpha1.Config`
21+
// ParseDir parses the given environments `spec.json` into a `v1alpha1.Environment`
2222
// object with the name set to the directories name
23-
func ParseDir(baseDir, name string) (*v1alpha1.Config, error) {
23+
func ParseDir(baseDir, name string) (*v1alpha1.Environment, error) {
2424
fi, err := os.Stat(baseDir)
2525
if err != nil {
2626
return nil, err
@@ -39,20 +39,22 @@ func ParseDir(baseDir, name string) (*v1alpha1.Config, error) {
3939
return nil, err
4040
}
4141

42-
return Parse(data, name)
42+
c, err := Parse(data)
43+
if c != nil {
44+
// set the name field
45+
c.Metadata.Name = name
46+
}
47+
48+
return c, err
4349
}
4450

45-
// Parse parses the json `data` into a `v1alpha1.Config` object.
46-
// `name` is the name of the environment
47-
func Parse(data []byte, name string) (*v1alpha1.Config, error) {
51+
// Parse parses the json `data` into a `v1alpha1.Environment` object.
52+
func Parse(data []byte) (*v1alpha1.Environment, error) {
4853
config := v1alpha1.New()
4954
if err := json.Unmarshal(data, config); err != nil {
5055
return nil, errors.Wrap(err, "parsing spec.json")
5156
}
5257

53-
// set the name field
54-
config.Metadata.Name = name
55-
5658
if err := handleDeprecated(config, data); err != nil {
5759
return config, err
5860
}
@@ -65,7 +67,7 @@ func Parse(data []byte, name string) (*v1alpha1.Config, error) {
6567
return config, nil
6668
}
6769

68-
func handleDeprecated(c *v1alpha1.Config, data []byte) error {
70+
func handleDeprecated(c *v1alpha1.Environment, data []byte) error {
6971
var errDepr ErrDeprecated
7072

7173
var msi map[string]interface{}

pkg/spec/v1alpha1/config.go pkg/spec/v1alpha1/environment.go

+10-10
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ package v1alpha1
22

33
import "strings"
44

5-
// New creates a new Config object with internal values already set
6-
func New() *Config {
7-
c := Config{}
5+
// New creates a new Environment object with internal values already set
6+
func New() *Environment {
7+
c := Environment{}
88

99
// constants
1010
c.APIVersion = "tanka.dev/v1alpha1"
@@ -18,13 +18,13 @@ func New() *Config {
1818
return &c
1919
}
2020

21-
// Config holds the configuration variables for config version v1alpha1
22-
// ApiVersion and Kind are currently unused, this may change in the future.
23-
type Config struct {
24-
APIVersion string `json:"apiVersion"`
25-
Kind string `json:"kind"`
26-
Metadata Metadata `json:"metadata"`
27-
Spec Spec `json:"spec"`
21+
// Environment represents a set of resources in relation to its Kubernetes cluster
22+
type Environment struct {
23+
APIVersion string `json:"apiVersion"`
24+
Kind string `json:"kind"`
25+
Metadata Metadata `json:"metadata"`
26+
Spec Spec `json:"spec"`
27+
Data interface{} `json:"data,omitempty"`
2828
}
2929

3030
// Metadata is meant for humans and not parsed

pkg/tanka/errors.go

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package tanka
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
)
7+
8+
// ErrNoEnv means that the given jsonnet has no Environment object
9+
// This must not be fatal, some operations work without
10+
type ErrNoEnv struct {
11+
path string
12+
}
13+
14+
func (e ErrNoEnv) Error() string {
15+
return fmt.Sprintf("unable to find an Environment in '%s'", e.path)
16+
}
17+
18+
// ErrMultipleEnvs means that the given jsonnet has multiple Environment objects
19+
type ErrMultipleEnvs struct {
20+
path string
21+
names []string
22+
}
23+
24+
func (e ErrMultipleEnvs) Error() string {
25+
return fmt.Sprintf("found multiple Environments (%s) in '%s'", strings.Join(e.names, ", "), e.path)
26+
}

0 commit comments

Comments
 (0)