Skip to content

Commit

Permalink
Merge pull request #1030 from nkvoll/support-kibana-config
Browse files Browse the repository at this point in the history
Add a custom config parameter to the Kibana spec.
  • Loading branch information
nkvoll authored Jun 10, 2019
2 parents b1341d9 + 14e9160 commit 0a760c9
Show file tree
Hide file tree
Showing 21 changed files with 321 additions and 120 deletions.
3 changes: 3 additions & 0 deletions operators/config/crds/kibana_v1alpha1_kibana.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ spec:
type: object
spec:
properties:
config:
description: Config represents Kibana configuration.
type: object
elasticsearch:
description: Elasticsearch configures how Kibana connects to Elasticsearch
properties:
Expand Down
60 changes: 60 additions & 0 deletions operators/pkg/apis/common/v1alpha1/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
// or more contributor license agreements. Licensed under the Elastic License;
// you may not use this file except in compliance with the Elastic License.

package v1alpha1

import (
"encoding/json"

ucfg "github.com/elastic/go-ucfg"
)

// CfgOptions are config options for YAML config. Currently contains only support for dotted keys.
var CfgOptions = []ucfg.Option{ucfg.PathSep(".")}

// Config represents untyped YAML configuration inside a spec.
type Config struct {
// This field exists to work around https://github.com/kubernetes-sigs/kubebuilder/issues/528
Data map[string]interface{}
}

// NewConfig constructs a Config with the given unstructured configuration data.
func NewConfig(cfg map[string]interface{}) Config {
return Config{Data: cfg}
}

// MarshalJSON implements the Marshaler interface.
func (c *Config) MarshalJSON() ([]byte, error) {
return json.Marshal(c.Data)
}

// UnmarshalJSON implements the Unmarshaler interface.
func (c *Config) UnmarshalJSON(data []byte) error {
var out map[string]interface{}
err := json.Unmarshal(data, &out)
if err != nil {
return err
}
c.Data = out
return nil
}

// DeepCopyInto is an ~autogenerated~ deepcopy function, copying the receiver, writing into out. in must be non-nil.
// This exists here to work around https://github.com/kubernetes/code-generator/issues/50
func (c *Config) DeepCopyInto(out *Config) {
bytes, err := json.Marshal(c.Data)
if err != nil {
// we assume that it marshals cleanly because otherwise the resource would not have been
// created in the API server
panic(err)
}
var copy map[string]interface{}
err = json.Unmarshal(bytes, &copy)
if err != nil {
// we assume again optimistically because we just marshalled that the round trip works as well
panic(err)
}
out.Data = copy
return
}
83 changes: 83 additions & 0 deletions operators/pkg/apis/common/v1alpha1/config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
// or more contributor license agreements. Licensed under the Elastic License;
// you may not use this file except in compliance with the Elastic License.

package v1alpha1

import (
"testing"

"github.com/go-test/deep"
)

var testFixture = Config{
Data: map[string]interface{}{
"a": map[string]interface{}{
"b": map[string]interface{}{
"c": 1.0,
},
"d": 1,
},
"a.b.foo": "bar",
"e": []interface{}{1, 2, 3},
"f": true,
},
}

var expectedJSONized = Config{
Data: map[string]interface{}{
"a": map[string]interface{}{
"b": map[string]interface{}{
"c": 1.0,
},
"d": float64(1),
},
"a.b.foo": "bar",
"e": []interface{}{float64(1), float64(2), float64(3)},
"f": true,
},
}

func TestConfig_DeepCopyInto(t *testing.T) {
tests := []struct {
name string
in Config
expected Config
}{
{
name: "deep copy via JSON roundtrip changes some types",
in: testFixture,
expected: expectedJSONized,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var out Config
tt.in.DeepCopyInto(&out)
if diff := deep.Equal(out, tt.expected); diff != nil {
t.Error(diff)
}
})
}
}

func TestConfig_DeepCopy(t *testing.T) {
tests := []struct {
name string
in Config
want Config
}{
{
name: "deep copy via JSON roundtrip changes some types",
in: testFixture,
want: expectedJSONized,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if diff := deep.Equal(tt.in.DeepCopy(), &tt.want); diff != nil {
t.Error(diff)
}
})
}
}
10 changes: 10 additions & 0 deletions operators/pkg/apis/common/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

68 changes: 4 additions & 64 deletions operators/pkg/apis/elasticsearch/v1alpha1/elasticsearch_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
package v1alpha1

import (
"encoding/json"

"github.com/elastic/cloud-on-k8s/operators/pkg/apis/common/v1alpha1"
ucfg "github.com/elastic/go-ucfg"
)

Expand Down Expand Up @@ -46,76 +45,17 @@ var DefaultCfg = ElasticsearchSettings{
},
}

// CfgOptions are config options for elasticsearch.yml. Currently contains only support for dotted keys.
var CfgOptions = []ucfg.Option{ucfg.PathSep(".")}

// Config represents untyped elasticsearch.yml configuration inside the Elasticsearch spec.
type Config struct {
// This field exists to work around https://github.com/kubernetes-sigs/kubebuilder/issues/528
Data map[string]interface{}
}

// NewConfig constructs a Config with the given unstructured configuration data.
func NewConfig(cfg map[string]interface{}) Config {
return Config{Data: cfg}
}

// MarshalJSON implements the Marshaler interface.
func (c *Config) MarshalJSON() ([]byte, error) {
return json.Marshal(c.Data)
}

// UnmarshalJSON implements the Unmarshaler interface.
func (c *Config) UnmarshalJSON(data []byte) error {
var out map[string]interface{}
err := json.Unmarshal(data, &out)
if err != nil {
return err
}
c.Data = out
return nil
}

// DeepCopyInto is an ~autogenerated~ deepcopy function, copying the receiver, writing into out. in must be non-nil.
// This exists here to work around https://github.com/kubernetes/code-generator/issues/50
func (c *Config) DeepCopyInto(out *Config) {
bytes, err := json.Marshal(c.Data)
if err != nil {
// we assume that it marshals cleanly because otherwise the resource would not have been
// created in the API server
panic(err)
}
var copy map[string]interface{}
err = json.Unmarshal(bytes, &copy)
if err != nil {
// we assume again optimistically because we just marshalled that the round trip works as well
panic(err)
}
out.Data = copy
return
}

// MustUnpack returns a typed subset of the Config.
// Panics on errors.
func (c *Config) MustUnpack() ElasticsearchSettings {
cfg, err := c.Unpack()
if err != nil {
panic(err)
}
return cfg
}

// Unpack unpacks Config into a typed subset.
func (c *Config) Unpack() (ElasticsearchSettings, error) {
func UnpackConfig(c *v1alpha1.Config) (ElasticsearchSettings, error) {
esSettings := DefaultCfg // defensive copy
if c == nil {
// make this nil safe to allow a ptr value to work around Json serialization issues
return esSettings, nil
}
config, err := ucfg.NewFrom(c.Data, CfgOptions...)
config, err := ucfg.NewFrom(c.Data, v1alpha1.CfgOptions...)
if err != nil {
return esSettings, err
}
err = config.Unpack(&esSettings, CfgOptions...)
err = config.Unpack(&esSettings, v1alpha1.CfgOptions...)
return esSettings, err
}
Loading

0 comments on commit 0a760c9

Please sign in to comment.