blob: 6ee92ca3b41405f4482b1b3caa4ad520759a8f6e [file] [log] [blame]
// Copyright Istio Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package kube
import (
"context"
"fmt"
"net/http"
)
import (
"google.golang.org/grpc/credentials"
istioclient "istio.io/client-go/pkg/clientset/versioned"
istioinformer "istio.io/client-go/pkg/informers/externalversions"
"istio.io/pkg/version"
v1 "k8s.io/api/core/v1"
"k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
kubeExtInformers "k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions"
kubeVersion "k8s.io/apimachinery/pkg/version"
"k8s.io/cli-runtime/pkg/resource"
"k8s.io/client-go/dynamic"
"k8s.io/client-go/dynamic/dynamicinformer"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/metadata"
"k8s.io/client-go/metadata/metadatainformer"
"k8s.io/client-go/rest"
"k8s.io/client-go/rest/fake"
cmdtesting "k8s.io/kubectl/pkg/cmd/testing"
"k8s.io/kubectl/pkg/cmd/util"
serviceapisclient "sigs.k8s.io/gateway-api/pkg/client/clientset/versioned"
serviceapisinformer "sigs.k8s.io/gateway-api/pkg/client/informers/externalversions"
mcsapisclient "sigs.k8s.io/mcs-api/pkg/client/clientset/versioned"
mcsapisinformer "sigs.k8s.io/mcs-api/pkg/client/informers/externalversions"
)
var _ ExtendedClient = MockClient{}
type MockPortForwarder struct{}
func (m MockPortForwarder) Start() error {
return nil
}
func (m MockPortForwarder) Address() string {
return "localhost:3456"
}
func (m MockPortForwarder) Close() {
}
func (m MockPortForwarder) WaitForStop() {
}
var _ PortForwarder = MockPortForwarder{}
// MockClient for tests that rely on kube.Client.
type MockClient struct {
kubernetes.Interface
RestClient *rest.RESTClient
// Results is a map of podName to the results of the expected test on the pod
Results map[string][]byte
DiscoverablePods map[string]map[string]*v1.PodList
RevisionValue string
ConfigValue *rest.Config
IstioVersions *version.MeshInfo
KubernetesVersion uint
IstiodVersion string
}
func (c MockClient) ExtInformer() kubeExtInformers.SharedInformerFactory {
panic("not used in mock")
}
func (c MockClient) Istio() istioclient.Interface {
panic("not used in mock")
}
func (c MockClient) GatewayAPI() serviceapisclient.Interface {
panic("not used in mock")
}
func (c MockClient) MCSApis() mcsapisclient.Interface {
panic("not used in mock")
}
func (c MockClient) IstioInformer() istioinformer.SharedInformerFactory {
panic("not used in mock")
}
func (c MockClient) GatewayAPIInformer() serviceapisinformer.SharedInformerFactory {
panic("not used in mock")
}
func (c MockClient) MCSApisInformer() mcsapisinformer.SharedInformerFactory {
panic("not used in mock")
}
func (c MockClient) Metadata() metadata.Interface {
panic("not used in mock")
}
func (c MockClient) KubeInformer() informers.SharedInformerFactory {
panic("not used in mock")
}
func (c MockClient) DynamicInformer() dynamicinformer.DynamicSharedInformerFactory {
panic("not used in mock")
}
func (c MockClient) MetadataInformer() metadatainformer.SharedInformerFactory {
panic("not used in mock")
}
func (c MockClient) RunAndWait(stop <-chan struct{}) {
panic("not used in mock")
}
func (c MockClient) Kube() kubernetes.Interface {
return c.Interface
}
func (c MockClient) DynamicClient() dynamic.Interface {
panic("not used in mock")
}
func (c MockClient) MetadataClient() metadata.Interface {
panic("not used in mock")
}
func (c MockClient) AllDiscoveryDo(_ context.Context, _, _ string) (map[string][]byte, error) {
return c.Results, nil
}
func (c MockClient) EnvoyDo(ctx context.Context, podName, podNamespace, method, path string) ([]byte, error) {
results, ok := c.Results[podName]
if !ok {
return nil, fmt.Errorf("unable to retrieve Pod: pods %q not found", podName)
}
return results, nil
}
func (c MockClient) EnvoyDoWithPort(ctx context.Context, podName, podNamespace, method, path string, port int) ([]byte, error) {
results, ok := c.Results[podName]
if !ok {
return nil, fmt.Errorf("unable to retrieve Pod: pods %q not found", podName)
}
return results, nil
}
func (c MockClient) RESTConfig() *rest.Config {
return c.ConfigValue
}
func (c MockClient) GetIstioVersions(_ context.Context, _ string) (*version.MeshInfo, error) {
if c.IstiodVersion != "" {
server := version.BuildInfo{}
setServerInfoWithIstiodVersionInfo(&server, c.IstiodVersion)
return &version.MeshInfo{
{
Info: server,
},
}, nil
}
return c.IstioVersions, nil
}
func (c MockClient) PodsForSelector(_ context.Context, namespace string, labelSelectors ...string) (*v1.PodList, error) {
podsForNamespace, ok := c.DiscoverablePods[namespace]
if !ok {
return &v1.PodList{}, nil
}
var allPods v1.PodList
for _, selector := range labelSelectors {
pods, ok := podsForNamespace[selector]
if !ok {
return &v1.PodList{}, nil
}
allPods.TypeMeta = pods.TypeMeta
allPods.ListMeta = pods.ListMeta
allPods.Items = append(allPods.Items, pods.Items...)
}
return &allPods, nil
}
func (c MockClient) Revision() string {
return c.RevisionValue
}
func (c MockClient) REST() rest.Interface {
panic("not implemented by mock")
}
func (c MockClient) ApplyYAMLFiles(string, ...string) error {
return nil
}
func (c MockClient) ApplyYAMLFilesDryRun(string, ...string) error {
panic("not implemented by mock")
}
// CreatePerRPCCredentials -- when implemented -- mocks per-RPC credentials (bearer token)
func (c MockClient) CreatePerRPCCredentials(ctx context.Context, tokenNamespace, tokenServiceAccount string, audiences []string,
expirationSeconds int64) (credentials.PerRPCCredentials, error) {
panic("not implemented by mock")
}
func (c MockClient) DeleteYAMLFiles(string, ...string) error {
panic("not implemented by mock")
}
func (c MockClient) DeleteYAMLFilesDryRun(string, ...string) error {
panic("not implemented by mock")
}
func (c MockClient) Ext() clientset.Interface {
panic("not implemented by mock")
}
func (c MockClient) Dynamic() dynamic.Interface {
panic("not implemented by mock")
}
func (c MockClient) GetKubernetesVersion() (*kubeVersion.Info, error) {
minor := fmt.Sprint(c.KubernetesVersion)
if c.KubernetesVersion == 0 {
minor = "16"
}
return &kubeVersion.Info{
Major: "1",
Minor: minor,
}, nil
}
func (c MockClient) GetIstioPods(_ context.Context, _ string, _ map[string]string) ([]v1.Pod, error) {
return nil, fmt.Errorf("TODO MockClient doesn't implement IstioPods")
}
func (c MockClient) PodExecCommands(podName, podNamespace, container string, commands []string) (stdout string, stderr string, err error) {
return "", "", fmt.Errorf("TODO MockClient doesn't implement exec")
}
func (c MockClient) PodExec(_, _, _ string, _ string) (string, string, error) {
return "", "", fmt.Errorf("TODO MockClient doesn't implement exec")
}
func (c MockClient) PodLogs(_ context.Context, _ string, _ string, _ string, _ bool) (string, error) {
return "", fmt.Errorf("TODO MockClient doesn't implement logs")
}
func (c MockClient) NewPortForwarder(_, _, _ string, _, _ int) (PortForwarder, error) {
return MockPortForwarder{}, nil
}
// UtilFactory mock's kubectl's utility factory. This code sets up a fake factory,
// similar to the one in https://github.com/kubernetes/kubectl/blob/master/pkg/cmd/describe/describe_test.go
func (c MockClient) UtilFactory() util.Factory {
tf := cmdtesting.NewTestFactory()
_, _, codec := cmdtesting.NewExternalScheme()
tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Resp: &http.Response{
StatusCode: http.StatusOK,
Header: cmdtesting.DefaultHeader(),
Body: cmdtesting.ObjBody(codec,
cmdtesting.NewInternalType("", "", "foo")),
},
}
return tf
}