mirror of https://github.com/linkerd/linkerd2.git
Add ServiceProfile support to k8s utilities (#1758)
Updates to the Kubernetes utility code in `/controller/k8s` to support interacting with ServiceProfiles. This makes use of the code generated client added in #1752 Signed-off-by: Alex Leong <alex@buoyant.io>
This commit is contained in:
parent
2d6fde274c
commit
1fe19bf3ce
|
@ -148,7 +148,7 @@ spec:
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, exp := range expectations {
|
for _, exp := range expectations {
|
||||||
k8sAPI, err := k8s.NewFakeAPI(exp.k8sRes...)
|
k8sAPI, err := k8s.NewFakeAPI("", exp.k8sRes...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("NewFakeAPI returned an error: %s", err)
|
t.Fatalf("NewFakeAPI returned an error: %s", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,7 +69,7 @@ func genEmptyResponse() pb.StatSummaryResponse {
|
||||||
|
|
||||||
func testStatSummary(t *testing.T, expectations []statSumExpected) {
|
func testStatSummary(t *testing.T, expectations []statSumExpected) {
|
||||||
for _, exp := range expectations {
|
for _, exp := range expectations {
|
||||||
k8sAPI, err := k8s.NewFakeAPI(exp.k8sConfigs...)
|
k8sAPI, err := k8s.NewFakeAPI("", exp.k8sConfigs...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("NewFakeAPI returned an error: %s", err)
|
t.Fatalf("NewFakeAPI returned an error: %s", err)
|
||||||
}
|
}
|
||||||
|
@ -728,7 +728,7 @@ status:
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Given an invalid resource type, returns error", func(t *testing.T) {
|
t.Run("Given an invalid resource type, returns error", func(t *testing.T) {
|
||||||
k8sAPI, err := k8s.NewFakeAPI()
|
k8sAPI, err := k8s.NewFakeAPI("")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("NewFakeAPI returned an error: %s", err)
|
t.Fatalf("NewFakeAPI returned an error: %s", err)
|
||||||
}
|
}
|
||||||
|
@ -787,7 +787,7 @@ status:
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Validates service stat requests", func(t *testing.T) {
|
t.Run("Validates service stat requests", func(t *testing.T) {
|
||||||
k8sAPI, err := k8s.NewFakeAPI()
|
k8sAPI, err := k8s.NewFakeAPI("")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("NewFakeAPI returned an error: %s", err)
|
t.Fatalf("NewFakeAPI returned an error: %s", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,7 +62,7 @@ func TestCertificateController(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func new(fixtures ...string) (*CertificateController, chan bool, chan struct{}, error) {
|
func new(fixtures ...string) (*CertificateController, chan bool, chan struct{}, error) {
|
||||||
k8sAPI, err := k8s.NewFakeAPI(fixtures...)
|
k8sAPI, err := k8s.NewFakeAPI("", fixtures...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, fmt.Errorf("NewFakeAPI returned an error: %s", err)
|
return nil, nil, nil, fmt.Errorf("NewFakeAPI returned an error: %s", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,9 +36,9 @@ func main() {
|
||||||
|
|
||||||
var k8sAPI *k8s.API
|
var k8sAPI *k8s.API
|
||||||
if *proxyAutoInject {
|
if *proxyAutoInject {
|
||||||
k8sAPI = k8s.NewAPI(k8sClient, restrictToNamespace, k8s.Pod, k8s.RS, k8s.MWC)
|
k8sAPI = k8s.NewAPI(k8sClient, nil, restrictToNamespace, k8s.Pod, k8s.RS, k8s.MWC)
|
||||||
} else {
|
} else {
|
||||||
k8sAPI = k8s.NewAPI(k8sClient, restrictToNamespace, k8s.Pod, k8s.RS)
|
k8sAPI = k8s.NewAPI(k8sClient, nil, restrictToNamespace, k8s.Pod, k8s.RS)
|
||||||
}
|
}
|
||||||
|
|
||||||
controller, err := ca.NewCertificateController(*controllerNamespace, k8sAPI, *proxyAutoInject)
|
controller, err := ca.NewCertificateController(*controllerNamespace, k8sAPI, *proxyAutoInject)
|
||||||
|
|
|
@ -30,17 +30,24 @@ func main() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err.Error())
|
log.Fatal(err.Error())
|
||||||
}
|
}
|
||||||
|
spClient, err := k8s.NewSpClientSet(*kubeConfigPath)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
restrictToNamespace := ""
|
restrictToNamespace := ""
|
||||||
if *singleNamespace {
|
if *singleNamespace {
|
||||||
restrictToNamespace = *controllerNamespace
|
restrictToNamespace = *controllerNamespace
|
||||||
}
|
}
|
||||||
k8sAPI := k8s.NewAPI(
|
k8sAPI := k8s.NewAPI(
|
||||||
k8sClient,
|
k8sClient,
|
||||||
|
spClient,
|
||||||
restrictToNamespace,
|
restrictToNamespace,
|
||||||
k8s.Endpoint,
|
k8s.Endpoint,
|
||||||
k8s.Pod,
|
k8s.Pod,
|
||||||
k8s.RS,
|
k8s.RS,
|
||||||
k8s.Svc,
|
k8s.Svc,
|
||||||
|
k8s.SP,
|
||||||
)
|
)
|
||||||
|
|
||||||
done := make(chan struct{})
|
done := make(chan struct{})
|
||||||
|
|
|
@ -47,6 +47,7 @@ func main() {
|
||||||
}
|
}
|
||||||
k8sAPI := k8s.NewAPI(
|
k8sAPI := k8s.NewAPI(
|
||||||
k8sClient,
|
k8sClient,
|
||||||
|
nil,
|
||||||
restrictToNamespace,
|
restrictToNamespace,
|
||||||
k8s.Deploy,
|
k8s.Deploy,
|
||||||
k8s.Pod,
|
k8s.Pod,
|
||||||
|
|
|
@ -25,7 +25,7 @@ func main() {
|
||||||
stop := make(chan os.Signal, 1)
|
stop := make(chan os.Signal, 1)
|
||||||
signal.Notify(stop, os.Interrupt, syscall.SIGTERM)
|
signal.Notify(stop, os.Interrupt, syscall.SIGTERM)
|
||||||
|
|
||||||
clientSet, err := k8s.NewClientSet(*kubeConfigPath)
|
k8sClient, err := k8s.NewClientSet(*kubeConfigPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("failed to create Kubernetes client: %s", err)
|
log.Fatalf("failed to create Kubernetes client: %s", err)
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,8 @@ func main() {
|
||||||
restrictToNamespace = *controllerNamespace
|
restrictToNamespace = *controllerNamespace
|
||||||
}
|
}
|
||||||
k8sAPI := k8s.NewAPI(
|
k8sAPI := k8s.NewAPI(
|
||||||
clientSet,
|
k8sClient,
|
||||||
|
nil,
|
||||||
restrictToNamespace,
|
restrictToNamespace,
|
||||||
k8s.Deploy,
|
k8s.Deploy,
|
||||||
k8s.Pod,
|
k8s.Pod,
|
||||||
|
|
|
@ -260,7 +260,7 @@ spec:
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
t.Run("subscribes listener to "+tt.serviceType, func(t *testing.T) {
|
t.Run("subscribes listener to "+tt.serviceType, func(t *testing.T) {
|
||||||
k8sAPI, err := k8s.NewFakeAPI(tt.k8sConfigs...)
|
k8sAPI, err := k8s.NewFakeAPI("", tt.k8sConfigs...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("NewFakeAPI returned an error: %s", err)
|
t.Fatalf("NewFakeAPI returned an error: %s", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ func (m *mockDestination_GetServer) SendMsg(x interface{}) error { return m.err
|
||||||
func (m *mockDestination_GetServer) RecvMsg(x interface{}) error { return m.errorToReturn }
|
func (m *mockDestination_GetServer) RecvMsg(x interface{}) error { return m.errorToReturn }
|
||||||
|
|
||||||
func TestBuildResolversList(t *testing.T) {
|
func TestBuildResolversList(t *testing.T) {
|
||||||
k8sAPI, err := k8s.NewFakeAPI()
|
k8sAPI, err := k8s.NewFakeAPI("")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("NewFakeAPI returned an error: %s", err)
|
t.Fatalf("NewFakeAPI returned an error: %s", err)
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,7 @@ func TestStreamResolutionUsingCorrectResolverFor(t *testing.T) {
|
||||||
stream := &mockDestination_GetServer{}
|
stream := &mockDestination_GetServer{}
|
||||||
host := "something"
|
host := "something"
|
||||||
port := 666
|
port := 666
|
||||||
k8sAPI, err := k8s.NewFakeAPI()
|
k8sAPI, err := k8s.NewFakeAPI("")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("NewFakeAPI returned an error: %s", err)
|
t.Fatalf("NewFakeAPI returned an error: %s", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,9 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
spclient "github.com/linkerd/linkerd2/controller/gen/client/clientset/versioned"
|
||||||
|
sp "github.com/linkerd/linkerd2/controller/gen/client/informers/externalversions"
|
||||||
|
spinformers "github.com/linkerd/linkerd2/controller/gen/client/informers/externalversions/serviceprofile/v1alpha1"
|
||||||
"github.com/linkerd/linkerd2/pkg/k8s"
|
"github.com/linkerd/linkerd2/pkg/k8s"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"google.golang.org/grpc/codes"
|
"google.golang.org/grpc/codes"
|
||||||
|
@ -29,11 +32,12 @@ const (
|
||||||
CM ApiResource = iota
|
CM ApiResource = iota
|
||||||
Deploy
|
Deploy
|
||||||
Endpoint
|
Endpoint
|
||||||
|
MWC // mutating webhook configuration
|
||||||
Pod
|
Pod
|
||||||
RC
|
RC
|
||||||
RS
|
RS
|
||||||
|
SP
|
||||||
Svc
|
Svc
|
||||||
MWC // mutating webhook configuration
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// API provides shared informers for all Kubernetes objects
|
// API provides shared informers for all Kubernetes objects
|
||||||
|
@ -43,22 +47,26 @@ type API struct {
|
||||||
cm coreinformers.ConfigMapInformer
|
cm coreinformers.ConfigMapInformer
|
||||||
deploy appinformers.DeploymentInformer
|
deploy appinformers.DeploymentInformer
|
||||||
endpoint coreinformers.EndpointsInformer
|
endpoint coreinformers.EndpointsInformer
|
||||||
|
mwc arinformers.MutatingWebhookConfigurationInformer
|
||||||
pod coreinformers.PodInformer
|
pod coreinformers.PodInformer
|
||||||
rc coreinformers.ReplicationControllerInformer
|
rc coreinformers.ReplicationControllerInformer
|
||||||
rs appinformers.ReplicaSetInformer
|
rs appinformers.ReplicaSetInformer
|
||||||
|
sp spinformers.ServiceProfileInformer
|
||||||
svc coreinformers.ServiceInformer
|
svc coreinformers.ServiceInformer
|
||||||
mwc arinformers.MutatingWebhookConfigurationInformer
|
|
||||||
|
|
||||||
syncChecks []cache.InformerSynced
|
syncChecks []cache.InformerSynced
|
||||||
sharedInformers informers.SharedInformerFactory
|
sharedInformers informers.SharedInformerFactory
|
||||||
|
spSharedInformers sp.SharedInformerFactory
|
||||||
namespace string
|
namespace string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAPI takes a Kubernetes client and returns an initialized API
|
// NewAPI takes a Kubernetes client and returns an initialized API
|
||||||
func NewAPI(k8sClient kubernetes.Interface, namespace string, resources ...ApiResource) *API {
|
func NewAPI(k8sClient kubernetes.Interface, spClient spclient.Interface, namespace string, resources ...ApiResource) *API {
|
||||||
var sharedInformers informers.SharedInformerFactory
|
var sharedInformers informers.SharedInformerFactory
|
||||||
|
var spSharedInformers sp.SharedInformerFactory
|
||||||
if namespace == "" {
|
if namespace == "" {
|
||||||
sharedInformers = informers.NewSharedInformerFactory(k8sClient, 10*time.Minute)
|
sharedInformers = informers.NewSharedInformerFactory(k8sClient, 10*time.Minute)
|
||||||
|
spSharedInformers = sp.NewSharedInformerFactory(spClient, 10*time.Minute)
|
||||||
} else {
|
} else {
|
||||||
sharedInformers = informers.NewFilteredSharedInformerFactory(
|
sharedInformers = informers.NewFilteredSharedInformerFactory(
|
||||||
k8sClient,
|
k8sClient,
|
||||||
|
@ -66,12 +74,19 @@ func NewAPI(k8sClient kubernetes.Interface, namespace string, resources ...ApiRe
|
||||||
namespace,
|
namespace,
|
||||||
nil,
|
nil,
|
||||||
)
|
)
|
||||||
|
spSharedInformers = sp.NewFilteredSharedInformerFactory(
|
||||||
|
spClient,
|
||||||
|
10*time.Minute,
|
||||||
|
namespace,
|
||||||
|
nil,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
api := &API{
|
api := &API{
|
||||||
Client: k8sClient,
|
Client: k8sClient,
|
||||||
syncChecks: make([]cache.InformerSynced, 0),
|
syncChecks: make([]cache.InformerSynced, 0),
|
||||||
sharedInformers: sharedInformers,
|
sharedInformers: sharedInformers,
|
||||||
|
spSharedInformers: spSharedInformers,
|
||||||
namespace: namespace,
|
namespace: namespace,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,6 +101,9 @@ func NewAPI(k8sClient kubernetes.Interface, namespace string, resources ...ApiRe
|
||||||
case Endpoint:
|
case Endpoint:
|
||||||
api.endpoint = sharedInformers.Core().V1().Endpoints()
|
api.endpoint = sharedInformers.Core().V1().Endpoints()
|
||||||
api.syncChecks = append(api.syncChecks, api.endpoint.Informer().HasSynced)
|
api.syncChecks = append(api.syncChecks, api.endpoint.Informer().HasSynced)
|
||||||
|
case MWC:
|
||||||
|
api.mwc = sharedInformers.Admissionregistration().V1beta1().MutatingWebhookConfigurations()
|
||||||
|
api.syncChecks = append(api.syncChecks, api.mwc.Informer().HasSynced)
|
||||||
case Pod:
|
case Pod:
|
||||||
api.pod = sharedInformers.Core().V1().Pods()
|
api.pod = sharedInformers.Core().V1().Pods()
|
||||||
api.syncChecks = append(api.syncChecks, api.pod.Informer().HasSynced)
|
api.syncChecks = append(api.syncChecks, api.pod.Informer().HasSynced)
|
||||||
|
@ -95,12 +113,12 @@ func NewAPI(k8sClient kubernetes.Interface, namespace string, resources ...ApiRe
|
||||||
case RS:
|
case RS:
|
||||||
api.rs = sharedInformers.Apps().V1beta2().ReplicaSets()
|
api.rs = sharedInformers.Apps().V1beta2().ReplicaSets()
|
||||||
api.syncChecks = append(api.syncChecks, api.rs.Informer().HasSynced)
|
api.syncChecks = append(api.syncChecks, api.rs.Informer().HasSynced)
|
||||||
|
case SP:
|
||||||
|
api.sp = spSharedInformers.Linkerd().V1alpha1().ServiceProfiles()
|
||||||
|
api.syncChecks = append(api.syncChecks, api.sp.Informer().HasSynced)
|
||||||
case Svc:
|
case Svc:
|
||||||
api.svc = sharedInformers.Core().V1().Services()
|
api.svc = sharedInformers.Core().V1().Services()
|
||||||
api.syncChecks = append(api.syncChecks, api.svc.Informer().HasSynced)
|
api.syncChecks = append(api.syncChecks, api.svc.Informer().HasSynced)
|
||||||
case MWC:
|
|
||||||
api.mwc = sharedInformers.Admissionregistration().V1beta1().MutatingWebhookConfigurations()
|
|
||||||
api.syncChecks = append(api.syncChecks, api.mwc.Informer().HasSynced)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,6 +130,7 @@ func NewAPI(k8sClient kubernetes.Interface, namespace string, resources ...ApiRe
|
||||||
// For testing, call this synchronously.
|
// For testing, call this synchronously.
|
||||||
func (api *API) Sync(readyCh chan<- struct{}) {
|
func (api *API) Sync(readyCh chan<- struct{}) {
|
||||||
api.sharedInformers.Start(nil)
|
api.sharedInformers.Start(nil)
|
||||||
|
api.spSharedInformers.Start(nil)
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
@ -176,6 +195,13 @@ func (api *API) CM() coreinformers.ConfigMapInformer {
|
||||||
return api.cm
|
return api.cm
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (api *API) SP() spinformers.ServiceProfileInformer {
|
||||||
|
if api.sp == nil {
|
||||||
|
panic("SP informer not configured")
|
||||||
|
}
|
||||||
|
return api.sp
|
||||||
|
}
|
||||||
|
|
||||||
func (api *API) MWC() arinformers.MutatingWebhookConfigurationInformer {
|
func (api *API) MWC() arinformers.MutatingWebhookConfigurationInformer {
|
||||||
if api.mwc == nil {
|
if api.mwc == nil {
|
||||||
panic("MWC informer not configured")
|
panic("MWC informer not configured")
|
||||||
|
|
|
@ -10,9 +10,7 @@ import (
|
||||||
"google.golang.org/grpc/codes"
|
"google.golang.org/grpc/codes"
|
||||||
"google.golang.org/grpc/status"
|
"google.golang.org/grpc/status"
|
||||||
apiv1 "k8s.io/api/core/v1"
|
apiv1 "k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/client-go/kubernetes/fake"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func newAPI(resourceConfigs []string, extraConfigs ...string) (*API, []runtime.Object, error) {
|
func newAPI(resourceConfigs []string, extraConfigs ...string) (*API, []runtime.Object, error) {
|
||||||
|
@ -32,7 +30,7 @@ func newAPI(resourceConfigs []string, extraConfigs ...string) (*API, []runtime.O
|
||||||
k8sConfigs = append(k8sConfigs, config)
|
k8sConfigs = append(k8sConfigs, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
api, err := NewFakeAPI(k8sConfigs...)
|
api, err := NewFakeAPI("", k8sConfigs...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("NewFakeAPI returned an error: %s", err)
|
return nil, nil, fmt.Errorf("NewFakeAPI returned an error: %s", err)
|
||||||
}
|
}
|
||||||
|
@ -172,19 +170,23 @@ metadata:
|
||||||
|
|
||||||
t.Run("In single-namespace mode", func(t *testing.T) {
|
t.Run("In single-namespace mode", func(t *testing.T) {
|
||||||
t.Run("Returns only the configured namespace", func(t *testing.T) {
|
t.Run("Returns only the configured namespace", func(t *testing.T) {
|
||||||
ns1 := &apiv1.Namespace{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Name: "namespace1",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
ns2 := &apiv1.Namespace{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Name: "namespace2",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
clientSet := fake.NewSimpleClientset(ns1, ns2)
|
ns1 := `
|
||||||
api := NewAPI(clientSet, "namespace1")
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: namespace1`
|
||||||
|
|
||||||
|
ns2 := `
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: namespace2`
|
||||||
|
|
||||||
|
api, err := NewFakeAPI("namespace1", ns1, ns2)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("NewFakeAPI returned an error: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
namespaces, err := api.GetObjects("", k8s.Namespace, "")
|
namespaces, err := api.GetObjects("", k8s.Namespace, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package k8s
|
package k8s
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
spclient "github.com/linkerd/linkerd2/controller/gen/client/clientset/versioned"
|
||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/client-go/rest"
|
"k8s.io/client-go/rest"
|
||||||
"k8s.io/client-go/tools/clientcmd"
|
"k8s.io/client-go/tools/clientcmd"
|
||||||
|
@ -9,6 +10,24 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewClientSet(kubeConfig string) (*kubernetes.Clientset, error) {
|
func NewClientSet(kubeConfig string) (*kubernetes.Clientset, error) {
|
||||||
|
config, err := parseConfig(kubeConfig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return kubernetes.NewForConfig(config)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSpClientSet(kubeConfig string) (*spclient.Clientset, error) {
|
||||||
|
config, err := parseConfig(kubeConfig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return spclient.NewForConfig(config)
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseConfig(kubeConfig string) (*rest.Config, error) {
|
||||||
var config *rest.Config
|
var config *rest.Config
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
|
@ -23,6 +42,5 @@ func NewClientSet(kubeConfig string) (*kubernetes.Clientset, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
return config, nil
|
||||||
return kubernetes.NewForConfig(config)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,31 +1,44 @@
|
||||||
package k8s
|
package k8s
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
spfake "github.com/linkerd/linkerd2/controller/gen/client/clientset/versioned/fake"
|
||||||
|
spscheme "github.com/linkerd/linkerd2/controller/gen/client/clientset/versioned/scheme"
|
||||||
|
"github.com/linkerd/linkerd2/pkg/k8s"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/client-go/kubernetes/fake"
|
"k8s.io/client-go/kubernetes/fake"
|
||||||
"k8s.io/client-go/kubernetes/scheme"
|
"k8s.io/client-go/kubernetes/scheme"
|
||||||
)
|
)
|
||||||
|
|
||||||
func toRuntimeObject(config string) (runtime.Object, error) {
|
func toRuntimeObject(config string) (runtime.Object, error) {
|
||||||
|
spscheme.AddToScheme(scheme.Scheme)
|
||||||
decode := scheme.Codecs.UniversalDeserializer().Decode
|
decode := scheme.Codecs.UniversalDeserializer().Decode
|
||||||
obj, _, err := decode([]byte(config), nil, nil)
|
obj, _, err := decode([]byte(config), nil, nil)
|
||||||
return obj, err
|
return obj, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewFakeAPI(configs ...string) (*API, error) {
|
func NewFakeAPI(namespace string, configs ...string) (*API, error) {
|
||||||
objs := []runtime.Object{}
|
objs := []runtime.Object{}
|
||||||
|
spObjs := []runtime.Object{}
|
||||||
for _, config := range configs {
|
for _, config := range configs {
|
||||||
obj, err := toRuntimeObject(config)
|
obj, err := toRuntimeObject(config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if strings.ToLower(obj.GetObjectKind().GroupVersionKind().Kind) == k8s.ServiceProfile {
|
||||||
|
spObjs = append(spObjs, obj)
|
||||||
|
} else {
|
||||||
objs = append(objs, obj)
|
objs = append(objs, obj)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
clientSet := fake.NewSimpleClientset(objs...)
|
clientSet := fake.NewSimpleClientset(objs...)
|
||||||
|
spClientSet := spfake.NewSimpleClientset(spObjs...)
|
||||||
return NewAPI(
|
return NewAPI(
|
||||||
clientSet,
|
clientSet,
|
||||||
"",
|
spClientSet,
|
||||||
|
namespace,
|
||||||
CM,
|
CM,
|
||||||
Deploy,
|
Deploy,
|
||||||
Endpoint,
|
Endpoint,
|
||||||
|
@ -33,6 +46,7 @@ func NewFakeAPI(configs ...string) (*API, error) {
|
||||||
RC,
|
RC,
|
||||||
RS,
|
RS,
|
||||||
Svc,
|
Svc,
|
||||||
|
SP,
|
||||||
MWC,
|
MWC,
|
||||||
), nil
|
), nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -184,7 +184,7 @@ status:
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, exp := range expectations {
|
for _, exp := range expectations {
|
||||||
k8sAPI, err := k8s.NewFakeAPI(exp.k8sRes...)
|
k8sAPI, err := k8s.NewFakeAPI("", exp.k8sRes...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("NewFakeAPI returned an error: %s", err)
|
t.Fatalf("NewFakeAPI returned an error: %s", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ const (
|
||||||
ReplicationController = "replicationcontroller"
|
ReplicationController = "replicationcontroller"
|
||||||
ReplicaSet = "replicaset"
|
ReplicaSet = "replicaset"
|
||||||
Service = "service"
|
Service = "service"
|
||||||
|
ServiceProfile = "serviceprofile"
|
||||||
StatefulSet = "statefulset"
|
StatefulSet = "statefulset"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue