* build: install the multus binary in an init container Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com> * build: generate kubeconfig via go Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com> * build: generate multus cni configuration via golang Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com> * build: provide a docker img for daemon based deployments We will have 2 different images (only on amd64 archs): - legacy entrypoint script based - daemonized process The `image-build` docker action is updated, to build these 2 images. There will be 2 different deployment specs, along with e2e test lanes, one for each of the aforementioned alternatives. Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com> * build: delegate CNI config watch loop via golang For the thick-plugin alternative, provide the watch loop for configuration regeneration via a golang binary. Over time, this binary is expected to run the control loop to watch out for pod updates. To enable current multus users to chose when they upgrade to this new deployment setup, these changes are provided in separate multus images, having a different yaml spec files. Both of these alternatives are tested e2e, since a new lane is introduced. The following libraries are introduced, along with the motivation for adding them: - dproxy: allows traversing the default network configuration arbitrarily, similar to what an X path / JSON path tool provides. Repo is available at [0]. - fsnotify: watch for changes in the default CNI configuration file. Repo is available at [1]. The config map providing the default network CNI configuration is not copied over, since originally, the user was not required to install a default network CNI plugin first, but, nowadays, this is a required step of multus. As such, it is no longer required to provide a default CNI configuration. [0] - https://github.com/koron/go-dproxy [1] - https://github.com/fsnotify/fsnotify Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com> * run gofmt Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com> * refactor: make the builder pattern more idiomatic to golang Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com> * build: update github actions to release new imgs Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
dProxy - document proxy
dProxy is a proxy to access interface{}
(document) by simple query.
It is intented to be used with json.Unmarshal()
or json.NewDecorder()
.
See codes for overview.
import (
"encoding/json"
"github.com/koron/go-dproxy"
)
var v interface{}
json.Unmarshal([]byte(`{
"cities": [ "tokyo", 100, "osaka", 200, "hakata", 300 ],
"data": {
"custom": [ "male", 23, "female", 24 ]
}
}`), &v)
// s == "tokyo", got a string.
s, _ := dproxy.New(v).M("cities").A(0).String()
// err != nil, type not matched.
_, err := dproxy.New(v).M("cities").A(0).Float64()
// n == 200, got a float64
n, _ := dproxy.New(v).M("cities").A(3).Float64()
// can be chained.
dproxy.New(v).M("data").M("custom").A(0).String()
// err.Error() == "not found: data.kustom", wrong query can be verified.
_, err = dproxy.New(v).M("data").M("kustom").String()
Getting started
Proxy
-
Wrap a value (
interface{}
) withdproxy.New()
getdproxy.Proxy
.p := dproxy.New(v) // v should be a value of interface{}
-
Query as a map (
map[string]interface{}
)byM()
, returnsdproxy.Proxy
.p.M("cities")
-
Query as an array (
[]interface{}
) withA()
, returnsdproxy.Proxy
.p.A(3)
-
Therefore, can be chained queries.
p.M("cities").A(3)
-
Get a value finally.
n, _ := p.M("cities").A(3).Int64()
-
You'll get an error when getting a value, if there were some mistakes.
// OOPS! "kustom" is typo, must be "custom" _, err := p.M("data").M("kustom").A(3).Int64() // "not found: data.kustom" fmt.Println(err)
-
If you tried to get a value as different type, get an error.
// OOPS! "cities[3]" (=200) should be float64 or int64. _, err := p.M("cities").A(3).String() // "not matched types: expected=string actual=float64: cities[3]" fmt.Println(err)
-
You can verify queries easily.
Drain
Getting value and error from Proxy/ProxySet multiple times, is very awful. It must check error when every getting values.
p := dproxy.New(v)
v1, err := p.M("cities").A(3).Int64()
if err != nil {
return err
}
v2, err := p.M("data").M("kustom").A(3).Int64()
if err != nil {
return err
}
v3, err := p.M("cities").A(3).String()
if err != nil {
return err
}
It can be rewrite as simple like below with dproxy.Drain
var d Drain
p := dproxy.New(v)
v1 := d.Int64(p.M("cities").A(3))
v2 := d.Int64(p.M("data").M("kustom").A(3))
v3 := d.String(p.M("cities").A(3))
if err := d.CombineErrors(); err != nil {
return err
}
JSON Pointer
JSON Pointer can be used to query interface{}
v1, err := dproxy.New(v).P("/cities/0").Int64()
or
v1, err := dproxy.Pointer(v, "/cities/0").Int64()
See RFC6901 for details of JSON Pointer.
LICENSE
MIT license. See LICENSE.