Skip to content

Commit 41da210

Browse files
authored
Fix data-gatherers config loading (#119)
* Fix data-gatherers config loading Signed-off-by: Jose Fuentes <[email protected]> * Rework unmarshaling of Config Signed-off-by: Jose Fuentes <[email protected]>
1 parent 8d629e1 commit 41da210

File tree

6 files changed

+118
-133
lines changed

6 files changed

+118
-133
lines changed

agent.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@ endpoint:
77
data-gatherers:
88
- kind: "dummy"
99
name: "dummy"
10+
config:
11+
param-1: "bar"

pkg/agent/config.go

Lines changed: 72 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ import (
55
"strings"
66

77
"github.com/hashicorp/go-multierror"
8+
"github.com/jetstack/preflight/pkg/datagatherer"
9+
"github.com/jetstack/preflight/pkg/datagatherer/aks"
10+
"github.com/jetstack/preflight/pkg/datagatherer/eks"
11+
"github.com/jetstack/preflight/pkg/datagatherer/gke"
12+
"github.com/jetstack/preflight/pkg/datagatherer/k8s"
13+
"github.com/jetstack/preflight/pkg/datagatherer/local"
814
"github.com/pkg/errors"
915
"gopkg.in/yaml.v2"
1016
)
@@ -25,10 +31,72 @@ type Endpoint struct {
2531
}
2632

2733
type dataGatherer struct {
28-
Kind string `yaml:"kind"`
29-
Name string `yaml:"name"`
30-
DataPath string `yaml:"data-path,omitempty"`
31-
Config []byte `yaml:"config"`
34+
Kind string
35+
Name string
36+
DataPath string
37+
Config datagatherer.Config
38+
}
39+
40+
func reMarshal(rawConfig interface{}, config datagatherer.Config) error {
41+
bb, err := yaml.Marshal(rawConfig)
42+
if err != nil {
43+
return nil
44+
}
45+
46+
err = yaml.Unmarshal(bb, config)
47+
if err != nil {
48+
return nil
49+
}
50+
51+
return nil
52+
}
53+
54+
// UnmarshalYAML unmarshals a dataGatherer resolving the type according to Kind.
55+
func (dg *dataGatherer) UnmarshalYAML(unmarshal func(interface{}) error) error {
56+
aux := struct {
57+
Kind string `yaml:"kind"`
58+
Name string `yaml:"name"`
59+
DataPath string `yaml:"data-path,omitempty"`
60+
RawConfig interface{} `yaml:"config"`
61+
}{}
62+
err := unmarshal(&aux)
63+
if err != nil {
64+
return err
65+
}
66+
67+
dg.Kind = aux.Kind
68+
dg.Name = aux.Name
69+
dg.DataPath = aux.DataPath
70+
71+
var cfg datagatherer.Config
72+
73+
switch dg.Kind {
74+
case "gke":
75+
cfg = &gke.Config{}
76+
case "eks":
77+
cfg = &eks.Config{}
78+
case "aks":
79+
cfg = &aks.Config{}
80+
case "k8s":
81+
cfg = &k8s.Config{}
82+
case "local":
83+
cfg = &local.Config{}
84+
// dummy dataGatherer is just used for testing
85+
case "dummy":
86+
cfg = &dummyConfig{}
87+
default:
88+
return fmt.Errorf("cannot parse data-gatherer configuration, kind %q is not supported", dg.Kind)
89+
}
90+
91+
// we encode aux.RawConfig, which is just a map of reflect.Values, into yaml and decode it again to the right type.
92+
err = reMarshal(aux.RawConfig, cfg)
93+
if err != nil {
94+
return err
95+
}
96+
97+
dg.Config = cfg
98+
99+
return nil
32100
}
33101

34102
// Dump generates a YAML string of the Config object

pkg/agent/config_data_gatherers.go

Lines changed: 0 additions & 52 deletions
This file was deleted.

pkg/agent/config_data_gatherers_test.go

Lines changed: 0 additions & 46 deletions
This file was deleted.

pkg/agent/config_test.go

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,13 @@ func TestValidConfigLoad(t *testing.T) {
1717
schedule: "* * * * *"
1818
token: "12345"
1919
data-gatherers:
20-
- name: my-gke-cluster
21-
kind: gke
22-
- name: my-pods
23-
kind: k8s
20+
- name: d1
21+
kind: dummy
22+
config:
23+
param-1: "bar"
2424
`
2525

2626
loadedConfig, err := ParseConfig([]byte(configFileContents))
27-
2827
if err != nil {
2928
t.Errorf("unexpected error: %v", err)
3029
}
@@ -39,12 +38,11 @@ func TestValidConfigLoad(t *testing.T) {
3938
Token: "12345",
4039
DataGatherers: []dataGatherer{
4140
dataGatherer{
42-
Name: "my-gke-cluster",
43-
Kind: "gke",
44-
},
45-
dataGatherer{
46-
Name: "my-pods",
47-
Kind: "k8s",
41+
Name: "d1",
42+
Kind: "dummy",
43+
Config: &dummyConfig{
44+
Param1: "bar",
45+
},
4846
},
4947
},
5048
}
@@ -99,15 +97,14 @@ func TestPartialMissingConfigError(t *testing.T) {
9997
schedule: "* * * * *"
10098
token: "12345"
10199
data-gatherers:
102-
- foo: bar`))
100+
- kind: dummy`))
103101

104102
if parseError == nil {
105103
t.Fatalf("expected error, got nil")
106104
}
107105

108106
expectedErrorLines := []string{
109-
"2 errors occurred:",
110-
"\t* datagatherer 1/1 is missing a kind",
107+
"1 error occurred:",
111108
"\t* datagatherer 1/1 is missing a name",
112109
"\n",
113110
}
@@ -120,3 +117,22 @@ func TestPartialMissingConfigError(t *testing.T) {
120117
t.Errorf("\ngot=\n%v\nwant=\n%s\ndiff=\n%s", gotError, expectedError, diff.Diff(gotError, expectedError))
121118
}
122119
}
120+
121+
func TestInvalidDataGathered(t *testing.T) {
122+
_, parseError := ParseConfig([]byte(`
123+
endpoint:
124+
host: example.com
125+
path: /api/v1/data
126+
schedule: "* * * * *"
127+
token: "12345"
128+
data-gatherers:
129+
- kind: "foo"`))
130+
131+
if parseError == nil {
132+
t.Fatalf("expected error, got nil")
133+
}
134+
135+
if got, want := parseError.Error(), `cannot parse data-gatherer configuration, kind "foo" is not supported`; got != want {
136+
t.Errorf("\ngot=\n%v\nwant=\n%s\ndiff=\n%s", got, want, diff.Diff(got, want))
137+
}
138+
}

pkg/agent/run.go

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -58,39 +58,36 @@ func Run(cmd *cobra.Command, args []string) {
5858
log.Printf("Running data gatherer %s of type %s as Local, data-path override present", dgConfig.Name, dgConfig.Kind)
5959
}
6060

61-
dg, err := LoadDataGatherer(ctx, kind, dgConfig.Config)
61+
dg, err := dgConfig.Config.NewDataGatherer(ctx)
6262
if err != nil {
63-
log.Fatalf("Failed to load data gatherer: %s", err)
63+
log.Fatalf("failed to instantiate %s DataGatherer: %v", kind, err)
6464
}
65+
6566
dataGatherers[dgConfig.Name] = dg
6667
}
6768

6869
// Fetch from all datagatherers
69-
var information []interface{}
70+
now := time.Now()
71+
readings := []*api.DataReading{}
7072
for k, dg := range dataGatherers {
7173
i, err := dg.Fetch()
7274
if err != nil {
7375
log.Fatalf("Error fetching with DataGatherer %q: %s", k, err)
7476
}
75-
information = append(information, i)
76-
}
7777

78-
fmt.Printf("Gathered Data:\n%+v\n", information)
78+
log.Printf("Gathered data for %q:\n", k)
79+
80+
readings = append(readings, &api.DataReading{
81+
DataGatherer: k,
82+
Timestamp: api.Time{Time: now},
83+
Data: i,
84+
})
85+
}
7986

8087
for {
8188
log.Println("Running Agent...")
8289
log.Println("Posting data to ", serverURL)
83-
err = postData(serverURL, config.Token, []*api.DataReading{
84-
&api.DataReading{
85-
DataGatherer: "dummy",
86-
Timestamp: api.Time{Time: time.Now()},
87-
Data: map[string]string{
88-
"field1": "data1",
89-
"field2": "data2",
90-
"field3": "data3",
91-
},
92-
},
93-
})
90+
err = postData(serverURL, config.Token, readings)
9491
// TODO: handle errors gracefully: e.g. handle retries when it is possible
9592
if err != nil {
9693
log.Fatalf("Post to server failed: %+v", err)

0 commit comments

Comments
 (0)