Add some more common test componets in pkg/test (#321)

This commit is contained in:
srinivashegde86 2019-03-18 10:41:46 -07:00 committed by Knative Prow Robot
parent 374ae9eb1f
commit 46bd1f13c2
4 changed files with 172 additions and 5 deletions

View File

@ -19,8 +19,12 @@ limitations under the License.
package test
import (
"fmt"
"strings"
"github.com/knative/pkg/test/logging"
"github.com/knative/pkg/test/spoof"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
k8styped "k8s.io/client-go/kubernetes/typed/core/v1"
@ -67,7 +71,7 @@ func BuildClientConfig(kubeConfigPath string, clusterName string) (*rest.Config,
// UpdateConfigMap updates the config map for specified @name with values
func (client *KubeClient) UpdateConfigMap(name string, configName string, values map[string]string) error {
configMap, err := client.getConfigMap(name).Get(configName, metav1.GetOptions{})
configMap, err := client.GetConfigMap(name).Get(configName, metav1.GetOptions{})
if err != nil {
return err
}
@ -76,11 +80,35 @@ func (client *KubeClient) UpdateConfigMap(name string, configName string, values
configMap.Data[key] = value
}
_, err = client.getConfigMap(name).Update(configMap)
_, err = client.GetConfigMap(name).Update(configMap)
return err
}
// getConfigMap gets the knative serving config map.
func (client *KubeClient) getConfigMap(name string) k8styped.ConfigMapInterface {
// GetConfigMap gets the knative serving config map.
func (client *KubeClient) GetConfigMap(name string) k8styped.ConfigMapInterface {
return client.Kube.CoreV1().ConfigMaps(name)
}
// CreatePod will create a Pod
func (client *KubeClient) CreatePod(pod *corev1.Pod) (*corev1.Pod, error) {
pods := client.Kube.CoreV1().Pods(pod.GetNamespace())
return pods.Create(pod)
}
// PodLogs returns Pod logs for given Pod and Container
func (client *KubeClient) PodLogs(podName, containerName string) ([]byte, error) {
pods := client.Kube.CoreV1().Pods(Flags.Namespace)
podList, err := pods.List(metav1.ListOptions{})
if err != nil {
return nil, err
}
for _, pod := range podList.Items {
if strings.Contains(pod.Name, podName) {
result := pods.GetLogs(pod.Name, &corev1.PodLogOptions{
Container: containerName,
}).Do()
return result.Raw()
}
}
return nil, fmt.Errorf("Could not find logs for %s/%s", podName, containerName)
}

95
test/crd.go Normal file
View File

@ -0,0 +1,95 @@
/*
Copyright 2019 The Knative 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.
*/
// This file contains functions that construct boilerplate CRD definitions.
package test
import (
corev1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
const (
nginxPort = 80
nginxName = "nginx"
nginxImage = "nginx:1.7.9"
)
// ServiceAccount returns ServiceAccount object in given namespace
func ServiceAccount(name string, namespace string) *corev1.ServiceAccount {
return &corev1.ServiceAccount{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
},
}
}
// ClusterRoleBinding returns ClusterRoleBinding for given subject and role
func ClusterRoleBinding(name string, namespace string, serviceAccount string, role string) *rbacv1.ClusterRoleBinding {
return &rbacv1.ClusterRoleBinding{
ObjectMeta: metav1.ObjectMeta{
Name: name,
},
Subjects: []rbacv1.Subject{
{
Kind: "ServiceAccount",
Name: serviceAccount,
Namespace: namespace,
},
},
RoleRef: rbacv1.RoleRef{
Kind: "ClusterRole",
Name: role,
APIGroup: "rbac.authorization.k8s.io",
},
}
}
// CoreV1ObjectReference returns a corev1.ObjectReference for the given name, kind and apiversion
func CoreV1ObjectReference(kind, apiversion, name string) *corev1.ObjectReference {
return &corev1.ObjectReference{
Kind: kind,
APIVersion: apiversion,
Name: name,
}
}
// NginxPod returns nginx pod defined in given namespace
func NginxPod(namespace string) *corev1.Pod {
return &corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: nginxName,
Namespace: namespace,
Annotations: map[string]string{"sidecar.istio.io/inject": "true"},
},
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Name: nginxName,
Image: nginxImage,
Ports: []corev1.ContainerPort{
{
ContainerPort: nginxPort,
},
},
},
},
},
}
}

View File

@ -21,6 +21,8 @@ package test
import (
"flag"
"fmt"
"os"
"os/user"
"path"
)
@ -37,6 +39,8 @@ type EnvironmentFlags struct {
IngressEndpoint string // Host to use for ingress endpoint
LogVerbose bool // Enable verbose logging
EmitMetrics bool // Emit metrics
DockerRepo string // Docker repo (defaults to $KO_DOCKER_REPO)
Tag string // Tag for test images
}
func initializeFlags() *EnvironmentFlags {
@ -63,5 +67,16 @@ func initializeFlags() *EnvironmentFlags {
flag.BoolVar(&f.EmitMetrics, "emitmetrics", false,
"Set this flag to true if you would like tests to emit metrics, e.g. latency of resources being realized in the system.")
defaultRepo := os.Getenv("KO_DOCKER_REPO")
flag.StringVar(&f.DockerRepo, "dockerrepo", defaultRepo,
"Provide the uri of the docker repo you have uploaded the test image to using `uploadtestimage.sh`. Defaults to $KO_DOCKER_REPO")
flag.StringVar(&f.Tag, "tag", "e2e", "Provide the version tag for the test images.")
return &f
}
// ImagePath is a helper function to prefix image name with repo and suffix with tag
func ImagePath(name string) string {
return fmt.Sprintf("%s/%s:%s", Flags.DockerRepo, name, Flags.Tag)
}

View File

@ -22,6 +22,7 @@ package test
import (
"context"
"fmt"
"strings"
"time"
"github.com/knative/pkg/test/logging"
@ -35,6 +36,7 @@ import (
const (
interval = 1 * time.Second
podTimeout = 8 * time.Minute
logTimeout = 1 * time.Minute
)
// WaitForDeploymentState polls the status of the Deployment called name
@ -78,9 +80,36 @@ func GetConfigMap(client *KubeClient, namespace string) k8styped.ConfigMapInterf
return client.Kube.CoreV1().ConfigMaps(namespace)
}
// Returns a func that evaluates if a deployment has scaled to 0 pods
// DeploymentScaledToZeroFunc returns a func that evaluates if a deployment has scaled to 0 pods
func DeploymentScaledToZeroFunc() func(d *apiv1beta1.Deployment) (bool, error) {
return func(d *apiv1beta1.Deployment) (bool, error) {
return d.Status.ReadyReplicas == 0, nil
}
}
// WaitForLogContent waits until logs for given Pod/Container include the given content.
// If the content is not present within timeout it returns error.
func WaitForLogContent(client *KubeClient, podName, containerName, content string) error {
return wait.PollImmediate(interval, logTimeout, func() (bool, error) {
logs, err := client.PodLogs(podName, containerName)
if err != nil {
return true, err
}
return strings.Contains(string(logs), content), nil
})
}
// WaitForAllPodsRunning waits for all the pods to be in running state
func WaitForAllPodsRunning(client *KubeClient, namespace string) error {
return WaitForPodListState(client, PodsRunning, "PodsAreRunning", namespace)
}
// PodsRunning will check the status conditions of the pod list and return true all pods are Running
func PodsRunning(podList *corev1.PodList) (bool, error) {
for _, pod := range podList.Items {
if pod.Status.Phase != corev1.PodRunning && pod.Status.Phase != corev1.PodSucceeded {
return false, nil
}
}
return true, nil
}