feat: config.
This commit is contained in:
145
remoteconfig/kubernetes/config.go
Normal file
145
remoteconfig/kubernetes/config.go
Normal file
@@ -0,0 +1,145 @@
|
||||
package kubernetes
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
|
||||
"github.com/go-kratos/kratos/v2/config"
|
||||
)
|
||||
|
||||
// Option is kubernetes option.
|
||||
type Option func(*options)
|
||||
|
||||
type options struct {
|
||||
// kubernetes namespace
|
||||
Namespace string
|
||||
// kubernetes labelSelector example `app=test`
|
||||
LabelSelector string
|
||||
// kubernetes fieldSelector example `app=test`
|
||||
FieldSelector string
|
||||
// set KubeConfig out-of-cluster Use outside cluster
|
||||
KubeConfig string
|
||||
// set master url
|
||||
Master string
|
||||
}
|
||||
|
||||
// Namespace with kubernetes namespace.
|
||||
func Namespace(ns string) Option {
|
||||
return func(o *options) {
|
||||
o.Namespace = ns
|
||||
}
|
||||
}
|
||||
|
||||
// LabelSelector with kubernetes label selector.
|
||||
func LabelSelector(label string) Option {
|
||||
return func(o *options) {
|
||||
o.LabelSelector = label
|
||||
}
|
||||
}
|
||||
|
||||
// FieldSelector with kubernetes field selector.
|
||||
func FieldSelector(field string) Option {
|
||||
return func(o *options) {
|
||||
o.FieldSelector = field
|
||||
}
|
||||
}
|
||||
|
||||
// KubeConfig with kubernetes config.
|
||||
func KubeConfig(config string) Option {
|
||||
return func(o *options) {
|
||||
o.KubeConfig = config
|
||||
}
|
||||
}
|
||||
|
||||
// Master with kubernetes master.
|
||||
func Master(master string) Option {
|
||||
return func(o *options) {
|
||||
o.Master = master
|
||||
}
|
||||
}
|
||||
|
||||
type kube struct {
|
||||
opts options
|
||||
client *kubernetes.Clientset
|
||||
}
|
||||
|
||||
// NewSource new a kubernetes config source.
|
||||
func NewSource(opts ...Option) config.Source {
|
||||
op := options{}
|
||||
for _, o := range opts {
|
||||
o(&op)
|
||||
}
|
||||
return &kube{
|
||||
opts: op,
|
||||
}
|
||||
}
|
||||
|
||||
func (k *kube) init() (err error) {
|
||||
var config *rest.Config
|
||||
if k.opts.KubeConfig != "" {
|
||||
if config, err = clientcmd.BuildConfigFromFlags(k.opts.Master, k.opts.KubeConfig); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if config, err = rest.InClusterConfig(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if k.client, err = kubernetes.NewForConfig(config); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (k *kube) load() (kvs []*config.KeyValue, err error) {
|
||||
cmList, err := k.client.
|
||||
CoreV1().
|
||||
ConfigMaps(k.opts.Namespace).
|
||||
List(context.Background(), metav1.ListOptions{
|
||||
LabelSelector: k.opts.LabelSelector,
|
||||
FieldSelector: k.opts.FieldSelector,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, cm := range cmList.Items {
|
||||
kvs = append(kvs, k.configMap(cm)...)
|
||||
}
|
||||
return kvs, nil
|
||||
}
|
||||
|
||||
func (k *kube) configMap(cm v1.ConfigMap) (kvs []*config.KeyValue) {
|
||||
for name, val := range cm.Data {
|
||||
k := fmt.Sprintf("%s/%s/%s", k.opts.Namespace, cm.Name, name)
|
||||
|
||||
kvs = append(kvs, &config.KeyValue{
|
||||
Key: k,
|
||||
Value: []byte(val),
|
||||
Format: strings.TrimPrefix(filepath.Ext(k), "."),
|
||||
})
|
||||
}
|
||||
return kvs
|
||||
}
|
||||
|
||||
func (k *kube) Load() ([]*config.KeyValue, error) {
|
||||
if k.opts.Namespace == "" {
|
||||
return nil, errors.New("options namespace not full")
|
||||
}
|
||||
if err := k.init(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return k.load()
|
||||
}
|
||||
|
||||
func (k *kube) Watch() (config.Watcher, error) {
|
||||
return newWatcher(k)
|
||||
}
|
||||
Reference in New Issue
Block a user