<commit_before>/*
Copyright 2015 The Kubernetes Authors All rights reserved.

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 e2e

import (
	"fmt"
	"strings"
	"time"

	"k8s.io/kubernetes/pkg/api"
	client "k8s.io/kubernetes/pkg/client/unversioned"
	"k8s.io/kubernetes/pkg/util"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

// How long to wait for a log pod to be displayed
const podLogTimeout = 45 * time.Second

// utility function for gomega Eventually
func getPodLogs(c *client.Client, namespace, podName, containerName string) (string, error) {
	logs, err := c.Get().Resource("pods").Namespace(namespace).Name(podName).SubResource("log").Param("container", containerName).Do().Raw()
	if err != nil {
		return "", err
	}
	if err == nil && strings.Contains(string(logs), "Internal Error") {
		return "", fmt.Errorf("Internal Error")
	}
	return string(logs), err
}

var _ = Describe("Downward API volume", func() {
	f := NewFramework("downward-api")
	It("should provide podname only [Conformance]", func() {
		podName := "downwardapi-volume-" + string(util.NewUUID())
		pod := downwardAPIVolumePod(podName, map[string]string{}, map[string]string{}, "/etc/podname")

		testContainerOutput("downward API volume plugin", f.Client, pod, 0, []string{
			fmt.Sprintf("%s\n", podName),
		}, f.Namespace.Name)
	})

	It("should provide podname as non-root with fsgroup [Conformance] [Skipped]", func() {
		podName := "metadata-volume-" + string(util.NewUUID())
		uid := int64(1001)
		gid := int64(1234)
		pod := downwardAPIVolumePod(podName, map[string]string{}, map[string]string{}, "/etc/podname")
		pod.Spec.SecurityContext = &api.PodSecurityContext{
			RunAsUser: &uid,
			FSGroup:   &gid,
		}
		testContainerOutput("downward API volume plugin", f.Client, pod, 0, []string{
			fmt.Sprintf("%s\n", podName),
		}, f.Namespace.Name)
	})

	It("should update labels on modification [Conformance]", func() {
		labels := map[string]string{}
		labels["key1"] = "value1"
		labels["key2"] = "value2"

		podName := "labelsupdate" + string(util.NewUUID())
		pod := downwardAPIVolumePod(podName, labels, map[string]string{}, "/etc/labels")
		containerName := "client-container"
		defer func() {
			By("Deleting the pod")
			f.Client.Pods(f.Namespace.Name).Delete(pod.Name, api.NewDeleteOptions(0))
		}()
		By("Creating the pod")
		_, err := f.Client.Pods(f.Namespace.Name).Create(pod)
		Expect(err).NotTo(HaveOccurred())

		expectNoError(waitForPodRunningInNamespace(f.Client, pod.Name, f.Namespace.Name))

		pod, err = f.Client.Pods(f.Namespace.Name).Get(pod.Name)
		Expect(err).NotTo(HaveOccurred())

		Eventually(func() (string, error) {
			return getPodLogs(f.Client, f.Namespace.Name, pod.Name, containerName)
		},
			podLogTimeout, poll).Should(ContainSubstring("key1=\"value1\"\n"))

		//modify labels
		pod.Labels["key3"] = "value3"
		_, err = f.Client.Pods(f.Namespace.Name).Update(pod)
		Expect(err).NotTo(HaveOccurred())

		Eventually(func() (string, error) {
			return getPodLogs(f.Client, f.Namespace.Name, pod.Name, containerName)
		},
			podLogTimeout, poll).Should(ContainSubstring("key3=\"value3\"\n"))

	})

	It("should update annotations on modification [Conformance]", func() {
		annotations := map[string]string{}
		annotations["builder"] = "bar"
		podName := "annotationupdate" + string(util.NewUUID())
		pod := downwardAPIVolumePod(podName, map[string]string{}, annotations, "/etc/annotations")

		containerName := "client-container"
		defer func() {
			By("Deleting the pod")
			f.Client.Pods(f.Namespace.Name).Delete(pod.Name, api.NewDeleteOptions(0))
		}()
		By("Creating the pod")
		_, err := f.Client.Pods(f.Namespace.Name).Create(pod)
		Expect(err).NotTo(HaveOccurred())
		expectNoError(waitForPodRunningInNamespace(f.Client, pod.Name, f.Namespace.Name))

		pod, err = f.Client.Pods(f.Namespace.Name).Get(pod.Name)
		Expect(err).NotTo(HaveOccurred())

		Eventually(func() (string, error) {
			return getPodLogs(f.Client, f.Namespace.Name, pod.Name, containerName)
		},
			podLogTimeout, poll).Should(ContainSubstring("builder=\"bar\"\n"))

		//modify annotations
		pod.Annotations["builder"] = "foo"
		_, err = f.Client.Pods(f.Namespace.Name).Update(pod)
		Expect(err).NotTo(HaveOccurred())

		Eventually(func() (string, error) {
			return getPodLogs(f.Client, f.Namespace.Name, pod.Name, containerName)
		},
			podLogTimeout, poll).Should(ContainSubstring("builder=\"foo\"\n"))

	})
})

func downwardAPIVolumePod(name string, labels, annotations map[string]string, filePath string) *api.Pod {
	pod := &api.Pod{
		ObjectMeta: api.ObjectMeta{
			Name:        name,
			Labels:      labels,
			Annotations: annotations,
		},
		Spec: api.PodSpec{
			Containers: []api.Container{
				{
					Name:    "client-container",
					Image:   "gcr.io/google_containers/mounttest:0.6",
					Command: []string{"/mt", "--break_on_expected_content=false", "--retry_time=10", "--file_content_in_loop=" + filePath},
					VolumeMounts: []api.VolumeMount{
						{
							Name:      "podinfo",
							MountPath: "/etc",
							ReadOnly:  false,
						},
					},
				},
			},
			Volumes: []api.Volume{
				{
					Name: "podinfo",
					VolumeSource: api.VolumeSource{
						DownwardAPI: &api.DownwardAPIVolumeSource{
							Items: []api.DownwardAPIVolumeFile{
								{
									Path: "podname",
									FieldRef: api.ObjectFieldSelector{
										APIVersion: "v1",
										FieldPath:  "metadata.name",
									},
								},
							},
						},
					},
				},
			},
			RestartPolicy: api.RestartPolicyNever,
		},
	}

	if len(labels) > 0 {
		pod.Spec.Volumes[0].DownwardAPI.Items = append(pod.Spec.Volumes[0].DownwardAPI.Items, api.DownwardAPIVolumeFile{
			Path: "labels",
			FieldRef: api.ObjectFieldSelector{
				APIVersion: "v1",
				FieldPath:  "metadata.labels",
			},
		})
	}

	if len(annotations) > 0 {
		pod.Spec.Volumes[0].DownwardAPI.Items = append(pod.Spec.Volumes[0].DownwardAPI.Items, api.DownwardAPIVolumeFile{
			Path: "annotations",
			FieldRef: api.ObjectFieldSelector{
				APIVersion: "v1",
				FieldPath:  "metadata.annotations",
			},
		})
	}
	return pod
}

// TODO: add test-webserver example as pointed out in https://github.com/kubernetes/kubernetes/pull/5093#discussion-diff-37606771
<commit_msg>rising timeout for mount-tester image<commit_after>/*
Copyright 2015 The Kubernetes Authors All rights reserved.

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 e2e

import (
	"fmt"
	"strings"
	"time"

	"k8s.io/kubernetes/pkg/api"
	client "k8s.io/kubernetes/pkg/client/unversioned"
	"k8s.io/kubernetes/pkg/util"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

// How long to wait for a log pod to be displayed
const podLogTimeout = 45 * time.Second

// utility function for gomega Eventually
func getPodLogs(c *client.Client, namespace, podName, containerName string) (string, error) {
	logs, err := c.Get().Resource("pods").Namespace(namespace).Name(podName).SubResource("log").Param("container", containerName).Do().Raw()
	if err != nil {
		return "", err
	}
	if err == nil && strings.Contains(string(logs), "Internal Error") {
		return "", fmt.Errorf("Internal Error")
	}
	return string(logs), err
}

var _ = Describe("Downward API volume", func() {
	f := NewFramework("downward-api")
	It("should provide podname only [Conformance]", func() {
		podName := "downwardapi-volume-" + string(util.NewUUID())
		pod := downwardAPIVolumePod(podName, map[string]string{}, map[string]string{}, "/etc/podname")

		testContainerOutput("downward API volume plugin", f.Client, pod, 0, []string{
			fmt.Sprintf("%s\n", podName),
		}, f.Namespace.Name)
	})

	It("should provide podname as non-root with fsgroup [Conformance] [Skipped]", func() {
		podName := "metadata-volume-" + string(util.NewUUID())
		uid := int64(1001)
		gid := int64(1234)
		pod := downwardAPIVolumePod(podName, map[string]string{}, map[string]string{}, "/etc/podname")
		pod.Spec.SecurityContext = &api.PodSecurityContext{
			RunAsUser: &uid,
			FSGroup:   &gid,
		}
		testContainerOutput("downward API volume plugin", f.Client, pod, 0, []string{
			fmt.Sprintf("%s\n", podName),
		}, f.Namespace.Name)
	})

	It("should update labels on modification [Conformance]", func() {
		labels := map[string]string{}
		labels["key1"] = "value1"
		labels["key2"] = "value2"

		podName := "labelsupdate" + string(util.NewUUID())
		pod := downwardAPIVolumePod(podName, labels, map[string]string{}, "/etc/labels")
		containerName := "client-container"
		defer func() {
			By("Deleting the pod")
			f.Client.Pods(f.Namespace.Name).Delete(pod.Name, api.NewDeleteOptions(0))
		}()
		By("Creating the pod")
		_, err := f.Client.Pods(f.Namespace.Name).Create(pod)
		Expect(err).NotTo(HaveOccurred())

		expectNoError(waitForPodRunningInNamespace(f.Client, pod.Name, f.Namespace.Name))

		pod, err = f.Client.Pods(f.Namespace.Name).Get(pod.Name)
		Expect(err).NotTo(HaveOccurred())

		Eventually(func() (string, error) {
			return getPodLogs(f.Client, f.Namespace.Name, pod.Name, containerName)
		},
			podLogTimeout, poll).Should(ContainSubstring("key1=\"value1\"\n"))

		//modify labels
		pod.Labels["key3"] = "value3"
		_, err = f.Client.Pods(f.Namespace.Name).Update(pod)
		Expect(err).NotTo(HaveOccurred())

		Eventually(func() (string, error) {
			return getPodLogs(f.Client, f.Namespace.Name, pod.Name, containerName)
		},
			podLogTimeout, poll).Should(ContainSubstring("key3=\"value3\"\n"))

	})

	It("should update annotations on modification [Conformance]", func() {
		annotations := map[string]string{}
		annotations["builder"] = "bar"
		podName := "annotationupdate" + string(util.NewUUID())
		pod := downwardAPIVolumePod(podName, map[string]string{}, annotations, "/etc/annotations")

		containerName := "client-container"
		defer func() {
			By("Deleting the pod")
			f.Client.Pods(f.Namespace.Name).Delete(pod.Name, api.NewDeleteOptions(0))
		}()
		By("Creating the pod")
		_, err := f.Client.Pods(f.Namespace.Name).Create(pod)
		Expect(err).NotTo(HaveOccurred())
		expectNoError(waitForPodRunningInNamespace(f.Client, pod.Name, f.Namespace.Name))

		pod, err = f.Client.Pods(f.Namespace.Name).Get(pod.Name)
		Expect(err).NotTo(HaveOccurred())

		Eventually(func() (string, error) {
			return getPodLogs(f.Client, f.Namespace.Name, pod.Name, containerName)
		},
			podLogTimeout, poll).Should(ContainSubstring("builder=\"bar\"\n"))

		//modify annotations
		pod.Annotations["builder"] = "foo"
		_, err = f.Client.Pods(f.Namespace.Name).Update(pod)
		Expect(err).NotTo(HaveOccurred())

		Eventually(func() (string, error) {
			return getPodLogs(f.Client, f.Namespace.Name, pod.Name, containerName)
		},
			podLogTimeout, poll).Should(ContainSubstring("builder=\"foo\"\n"))

	})
})

func downwardAPIVolumePod(name string, labels, annotations map[string]string, filePath string) *api.Pod {
	pod := &api.Pod{
		ObjectMeta: api.ObjectMeta{
			Name:        name,
			Labels:      labels,
			Annotations: annotations,
		},
		Spec: api.PodSpec{
			Containers: []api.Container{
				{
					Name:    "client-container",
					Image:   "gcr.io/google_containers/mounttest:0.6",
					Command: []string{"/mt", "--break_on_expected_content=false", "--retry_time=120", "--file_content_in_loop=" + filePath},
					VolumeMounts: []api.VolumeMount{
						{
							Name:      "podinfo",
							MountPath: "/etc",
							ReadOnly:  false,
						},
					},
				},
			},
			Volumes: []api.Volume{
				{
					Name: "podinfo",
					VolumeSource: api.VolumeSource{
						DownwardAPI: &api.DownwardAPIVolumeSource{
							Items: []api.DownwardAPIVolumeFile{
								{
									Path: "podname",
									FieldRef: api.ObjectFieldSelector{
										APIVersion: "v1",
										FieldPath:  "metadata.name",
									},
								},
							},
						},
					},
				},
			},
			RestartPolicy: api.RestartPolicyNever,
		},
	}

	if len(labels) > 0 {
		pod.Spec.Volumes[0].DownwardAPI.Items = append(pod.Spec.Volumes[0].DownwardAPI.Items, api.DownwardAPIVolumeFile{
			Path: "labels",
			FieldRef: api.ObjectFieldSelector{
				APIVersion: "v1",
				FieldPath:  "metadata.labels",
			},
		})
	}

	if len(annotations) > 0 {
		pod.Spec.Volumes[0].DownwardAPI.Items = append(pod.Spec.Volumes[0].DownwardAPI.Items, api.DownwardAPIVolumeFile{
			Path: "annotations",
			FieldRef: api.ObjectFieldSelector{
				APIVersion: "v1",
				FieldPath:  "metadata.annotations",
			},
		})
	}
	return pod
}

// TODO: add test-webserver example as pointed out in https://github.com/kubernetes/kubernetes/pull/5093#discussion-diff-37606771
<|endoftext|>


<commit_before>/*
Copyright 2017 The Kubernetes 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 apimock contains temporary definitions of Vertical Pod Autoscaler related objects - to be replaced with real implementation
// Definitions based on VPA design doc : https://github.com/kubernetes/community/pull/338
package apimock

import (
	"math/rand"
	"time"

	apiv1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/resource"
)

// VerticalPodAutoscaler Represents Vertical Pod Autoscaler configuration - to be replaced by real implementation
type VerticalPodAutoscaler struct {
	// Specification
	Spec Spec
	// Current state of VPA
	Status Status
}

// Spec holds Vertical Pod Autoscaler configuration
type Spec struct {
	// Defines which pods this Autoscaler should watch and update
	Target Target
	// Policy for pod updates
	UpdatePolicy UpdatePolicy
	// Policy for container resources updates
	ResourcesPolicy ResourcesPolicy
}

// Status holds current Vertical Pod Autoscaler state
type Status struct {
	// Recommended resources allocation
	Recommendation *Recommendation
}

// Target Specifies pods to be managed by Vertical Pod Autoscaler
type Target struct {
	// label query over pods. The string will be in the same format as the query-param syntax.
	// More info about label selectors: http://kubernetes.io/docs/user-guide/labels#label-selectors
	// +optional
	Selector string `json:"selector,omitempty" protobuf:"bytes,2,opt,name=selector"`
}

// UpdatePolicy defines policy for Pod updates
type UpdatePolicy struct {
	// Mode for update policy
	Mode Mode
}

// Mode of update policy
type Mode struct {
}

// ResourcesPolicy represents Resources allocation policy
type ResourcesPolicy struct {
	// Resources allocation policy for containers
	Containers []ContainerPolicy
}

// Recommendation represents resources allocation recommended by Vertical Pod Autoscaler
type Recommendation struct {
	// Recommended resources allocation for containers
	Containers []ContainerRecommendation
}

// ContainerPolicy hold resources allocation policy for single container
type ContainerPolicy struct {
	// Name of the container
	Name string
	// Memory allocation policy
	ResourcePolicy map[apiv1.ResourceName]Policy
}

// Policy holds resource allocation policy
type Policy struct {
	// Minimal resource quantity
	Min resource.Quantity
	// Maximal resource quantity
	Max resource.Quantity
}

// ContainerRecommendation holds resource allocation recommendation for container
type ContainerRecommendation struct {
	// Name of the container
	Name string
	// Resources allocation recommended
	Resources map[apiv1.ResourceName]resource.Quantity
}

// VerticalPodAutoscalerLister provides list of all configured Vertical Pod Autoscalers
type VerticalPodAutoscalerLister interface {
	// List returns all configured Vertical Pod Autoscalers
	List() (ret []*VerticalPodAutoscaler, err error)
}

type vpaLister struct{}

// List Mock implementation of Vertical Pod Autoscaler Lister - to be replaced with real implementation
func (lister *vpaLister) List() (ret []*VerticalPodAutoscaler, err error) {
	return []*VerticalPodAutoscaler{fake()}, nil
}

// NewVpaLister returns mock VerticalPodAutoscalerLister - to be replaced with real implementation
func NewVpaLister(_ interface{}) VerticalPodAutoscalerLister {
	return &vpaLister{}
}

// RecommenderAPI defines api returning Vertical Pod Autoscaler recommendations for pods
type RecommenderAPI interface {
	// GetRecommendation returns Vertical Pod Autoscaler recommendation for given pod
	GetRecommendation(spec *apiv1.PodSpec) (*Recommendation, error)
}

type recommenderAPIImpl struct {
}

// NewRecommenderAPI return mock RecommenderAPI - to be replaced with real implementation
func NewRecommenderAPI() RecommenderAPI {
	return &recommenderAPIImpl{}
}

// GetRecommendation Returns random recommendation of resources increase / decrease by 0 - 100 %
// To be replaced with real implementation of recommender request
func (rec *recommenderAPIImpl) GetRecommendation(spec *apiv1.PodSpec) (*Recommendation, error) {
	rand.Seed(time.Now().UTC().UnixNano())
	result := make([]ContainerRecommendation, len(spec.Containers))
	for i, podContainer := range spec.Containers {

		// scale memory and cpu by random factor [0, 2]

		diffFactor := 2 * rand.Float64()
		memory := podContainer.Resources.Requests.Memory().DeepCopy()
		memory.Set(int64(float64(memory.Value()) * diffFactor))

		diffFactor = 2 * rand.Float64()
		cpu := podContainer.Resources.Requests.Cpu().DeepCopy()
		cpu.Set(int64(float64(cpu.Value()) * diffFactor))

		result[i] = ContainerRecommendation{
			Name: podContainer.Name,
			Resources: map[apiv1.ResourceName]resource.Quantity{
				apiv1.ResourceCPU: cpu, apiv1.ResourceMemory: memory}}
	}
	return &Recommendation{Containers: result}, nil
}

func fake() *VerticalPodAutoscaler {
	minCpu, _ := resource.ParseQuantity("1")
	maxCpu, _ := resource.ParseQuantity("4")
	minMem, _ := resource.ParseQuantity("10M")
	maxMem, _ := resource.ParseQuantity("5G")
	return &VerticalPodAutoscaler{
		Spec: Spec{
			Target:       Target{Selector: "app = redis"},
			UpdatePolicy: UpdatePolicy{Mode: Mode{}},
			ResourcesPolicy: ResourcesPolicy{Containers: []ContainerPolicy{{
				Name: "slave",
				ResourcePolicy: map[apiv1.ResourceName]Policy{
					apiv1.ResourceCPU:    {minCpu, maxCpu},
					apiv1.ResourceMemory: {minMem, maxMem}},
			}}}},
	}
}
<commit_msg>apimock removed.<commit_after><|endoftext|>


<commit_before>package cgo

import (
	"go/ast"
	"go/token"
	"go/types"
)

// ArrayWrapper is a wrapper for the
type SliceWrapper struct {
	elem types.Type
}

// NewSliceWrapper wraps types.Slice to provide a consistent comparison
func NewSliceWrapper(elem types.Type) SliceWrapper {
	return SliceWrapper{
		elem: elem,
	}
}

// Underlying returns the underlying type of the Slice (types.Type)
func (t SliceWrapper) Underlying() types.Type {
	return t
}

// Underlying returns the string representation of the type (types.Type)
func (t SliceWrapper) String() string {
	return types.TypeString(types.NewSlice(t.elem), nil)
}

// ToCgoAst returns the go/ast representation of the CGo wrapper of the Slice type
func (s SliceWrapper) ToCgoAst() []ast.Decl {
	decls := s.NewAst()
	decls = append(decls, s.StringAst()...)
	decls = append(decls, s.ItemAst()...)
	decls = append(decls, s.ItemSetAst()...)
	return decls
}

func (s SliceWrapper) GoName() string {
	return "[]" + s.elem.String()
}

func (s SliceWrapper) CGoName() string {
	return "slice_of_" + s.elem.String()
}

// NewAst produces the []ast.Decl to construct a slice type and increment it's reference count
func (s SliceWrapper) NewAst() []ast.Decl {
	functionName := s.CGoName() + "_new"
	localVarIdent := NewIdent("o")
	goTypeIdent := NewIdent(s.GoName())
	target := &ast.UnaryExpr{
		Op: token.AND,
		X:  localVarIdent,
	}

	goType := &ast.ArrayType{
		Elt: NewIdent(s.elem.String()),
	}

	funcDecl := &ast.FuncDecl{
		Doc: &ast.CommentGroup{
			List: ExportComments(functionName),
		},
		Name: NewIdent(functionName),
		Type: &ast.FuncType{
			Results: &ast.FieldList{
				List: []*ast.Field{
					{Type: goTypeIdent},
				},
			},
		},
		Body: &ast.BlockStmt{
			List: []ast.Stmt{
				DeclareVar(localVarIdent, goType),
				IncrementRef(target),
				CastReturn(goTypeIdent, target),
			},
		},
	}

	return []ast.Decl{funcDecl}
}

// StringAst produces the []ast.Decl to provide a string representation of the slice
func (s SliceWrapper) StringAst() []ast.Decl {
	functionName := s.CGoName() + "_str"
	selfIdent := NewIdent("self")
	goTypeIdent := NewIdent(s.GoName())
	stringIdent := NewIdent("string")

	castExpression := CastUnsafePtr(DeRef(goTypeIdent), selfIdent)
	deRef := DeRef(castExpression)
	sprintf := FormatSprintf("%#v", deRef)

	funcDecl := &ast.FuncDecl{
		Doc: &ast.CommentGroup{
			List: ExportComments(functionName),
		},
		Name: NewIdent(functionName),
		Type: &ast.FuncType{
			Params: &ast.FieldList{
				List: []*ast.Field{
					{
						Names: []*ast.Ident{selfIdent},
						Type:  goTypeIdent,
					},
				},
			},
			Results: &ast.FieldList{
				List: []*ast.Field{
					{Type: stringIdent},
				},
			},
		},
		Body: &ast.BlockStmt{
			List: []ast.Stmt{
				Return(sprintf),
			},
		},
	}

	return []ast.Decl{funcDecl}
}

func (s SliceWrapper) ItemAst() []ast.Decl {
	functionName := s.CGoName() + "_item"
	selfIdent := NewIdent("self")
	indexIdent := NewIdent("i")
	indexTypeIdent := NewIdent("int")
	goTypeIdent := NewIdent(s.GoName())
	elementTypeIdent := NewIdent(s.elem.String())
	itemsIdent := NewIdent("items")
	itemIdent := NewIdent("item")

	castExpression := CastUnsafePtr(DeRef(goTypeIdent), selfIdent)

	funcDecl := &ast.FuncDecl{
		Doc: &ast.CommentGroup{
			List: ExportComments(functionName),
		},
		Name: NewIdent(functionName),
		Type: &ast.FuncType{
			Params: InstanceMethodParams(goTypeIdent,
				[]*ast.Field{
					{
						Names: []*ast.Ident{indexIdent},
						Type:  indexTypeIdent,
					},
				}...),
			Results: &ast.FieldList{
				List: []*ast.Field{
					{Type: elementTypeIdent},
				},
			},
		},
		Body: &ast.BlockStmt{
			List: []ast.Stmt{
				&ast.AssignStmt{
					Lhs: []ast.Expr{
						itemsIdent,
					},
					Rhs: []ast.Expr{
						castExpression,
					},
					Tok: token.DEFINE,
				},
				&ast.AssignStmt{
					Lhs: []ast.Expr{
						itemIdent,
					},
					Rhs: []ast.Expr{
						&ast.IndexExpr{
							X: &ast.ParenExpr{
								X: &ast.StarExpr{
									X: itemsIdent,
								},
							},
							Index: indexIdent,
						},
					},
					Tok: token.DEFINE,
				},
				Return(itemIdent),
			},
		},
	}

	return []ast.Decl{funcDecl}
}

func (s SliceWrapper) ItemSetAst() []ast.Decl {
	functionName := s.CGoName() + "_item_set"
	selfIdent := NewIdent("self")
	indexIdent := NewIdent("i")
	indexTypeIdent := NewIdent("int")
	goTypeIdent := NewIdent(s.GoName())
	elementTypeIdent := NewIdent(s.elem.String())
	itemsIdent := NewIdent("items")
	itemIdent := NewIdent("item")

	castExpression := CastUnsafePtr(DeRef(goTypeIdent), selfIdent)

	funcDecl := &ast.FuncDecl{
		Doc: &ast.CommentGroup{
			List: ExportComments(functionName),
		},
		Name: NewIdent(functionName),
		Type: &ast.FuncType{
			Params: InstanceMethodParams(goTypeIdent,
				[]*ast.Field{
					{
						Names: []*ast.Ident{indexIdent},
						Type:  indexTypeIdent,
					},
					{
						Names: []*ast.Ident{itemIdent},
						Type:  elementTypeIdent,
					},
				}...),
		},
		Body: &ast.BlockStmt{
			List: []ast.Stmt{
				&ast.AssignStmt{
					Lhs: []ast.Expr{
						itemsIdent,
					},
					Rhs: []ast.Expr{
						castExpression,
					},
					Tok: token.DEFINE,
				},
				&ast.AssignStmt{
					Lhs: []ast.Expr{
						&ast.IndexExpr{
							X: &ast.ParenExpr{
								X: &ast.StarExpr{
									X: itemsIdent,
								},
							},
							Index: indexIdent,
						},
					},
					Rhs: []ast.Expr{
						itemIdent,
					},
					Tok: token.ASSIGN,
				},
			},
		},
	}

	return []ast.Decl{funcDecl}
}
<commit_msg>add slice append<commit_after>package cgo

import (
	"go/ast"
	"go/token"
	"go/types"
)

// ArrayWrapper is a wrapper for the
type SliceWrapper struct {
	elem types.Type
}

// NewSliceWrapper wraps types.Slice to provide a consistent comparison
func NewSliceWrapper(elem types.Type) SliceWrapper {
	return SliceWrapper{
		elem: elem,
	}
}

// Underlying returns the underlying type of the Slice (types.Type)
func (t SliceWrapper) Underlying() types.Type {
	return t
}

// Underlying returns the string representation of the type (types.Type)
func (t SliceWrapper) String() string {
	return types.TypeString(types.NewSlice(t.elem), nil)
}

// ToCgoAst returns the go/ast representation of the CGo wrapper of the Slice type
func (s SliceWrapper) ToCgoAst() []ast.Decl {
	decls := s.NewAst()
	decls = append(decls, s.StringAst()...)
	decls = append(decls, s.ItemAst()...)
	decls = append(decls, s.ItemSetAst()...)
	decls = append(decls, s.ItemAppendAst()...)
	return decls
}

func (s SliceWrapper) GoName() string {
	return "[]" + s.elem.String()
}

func (s SliceWrapper) CGoName() string {
	return "slice_of_" + s.elem.String()
}

// NewAst produces the []ast.Decl to construct a slice type and increment it's reference count
func (s SliceWrapper) NewAst() []ast.Decl {
	functionName := s.CGoName() + "_new"
	localVarIdent := NewIdent("o")
	goTypeIdent := NewIdent(s.GoName())
	target := &ast.UnaryExpr{
		Op: token.AND,
		X:  localVarIdent,
	}

	goType := &ast.ArrayType{
		Elt: NewIdent(s.elem.String()),
	}

	funcDecl := &ast.FuncDecl{
		Doc: &ast.CommentGroup{
			List: ExportComments(functionName),
		},
		Name: NewIdent(functionName),
		Type: &ast.FuncType{
			Results: &ast.FieldList{
				List: []*ast.Field{
					{Type: goTypeIdent},
				},
			},
		},
		Body: &ast.BlockStmt{
			List: []ast.Stmt{
				DeclareVar(localVarIdent, goType),
				IncrementRef(target),
				CastReturn(goTypeIdent, target),
			},
		},
	}

	return []ast.Decl{funcDecl}
}

// StringAst produces the []ast.Decl to provide a string representation of the slice
func (s SliceWrapper) StringAst() []ast.Decl {
	functionName := s.CGoName() + "_str"
	selfIdent := NewIdent("self")
	goTypeIdent := NewIdent(s.GoName())
	stringIdent := NewIdent("string")

	castExpression := CastUnsafePtr(DeRef(goTypeIdent), selfIdent)
	deRef := DeRef(castExpression)
	sprintf := FormatSprintf("%#v", deRef)

	funcDecl := &ast.FuncDecl{
		Doc: &ast.CommentGroup{
			List: ExportComments(functionName),
		},
		Name: NewIdent(functionName),
		Type: &ast.FuncType{
			Params: &ast.FieldList{
				List: []*ast.Field{
					{
						Names: []*ast.Ident{selfIdent},
						Type:  goTypeIdent,
					},
				},
			},
			Results: &ast.FieldList{
				List: []*ast.Field{
					{Type: stringIdent},
				},
			},
		},
		Body: &ast.BlockStmt{
			List: []ast.Stmt{
				Return(sprintf),
			},
		},
	}

	return []ast.Decl{funcDecl}
}

func (s SliceWrapper) ItemAst() []ast.Decl {
	functionName := s.CGoName() + "_item"
	selfIdent := NewIdent("self")
	indexIdent := NewIdent("i")
	indexTypeIdent := NewIdent("int")
	goTypeIdent := NewIdent(s.GoName())
	elementTypeIdent := NewIdent(s.elem.String())
	itemsIdent := NewIdent("items")
	itemIdent := NewIdent("item")

	castExpression := CastUnsafePtr(DeRef(goTypeIdent), selfIdent)

	funcDecl := &ast.FuncDecl{
		Doc: &ast.CommentGroup{
			List: ExportComments(functionName),
		},
		Name: NewIdent(functionName),
		Type: &ast.FuncType{
			Params: InstanceMethodParams(goTypeIdent,
				[]*ast.Field{
					{
						Names: []*ast.Ident{indexIdent},
						Type:  indexTypeIdent,
					},
				}...),
			Results: &ast.FieldList{
				List: []*ast.Field{
					{Type: elementTypeIdent},
				},
			},
		},
		Body: &ast.BlockStmt{
			List: []ast.Stmt{
				&ast.AssignStmt{
					Lhs: []ast.Expr{
						itemsIdent,
					},
					Rhs: []ast.Expr{
						castExpression,
					},
					Tok: token.DEFINE,
				},
				&ast.AssignStmt{
					Lhs: []ast.Expr{
						itemIdent,
					},
					Rhs: []ast.Expr{
						&ast.IndexExpr{
							X: &ast.ParenExpr{
								X: &ast.StarExpr{
									X: itemsIdent,
								},
							},
							Index: indexIdent,
						},
					},
					Tok: token.DEFINE,
				},
				Return(itemIdent),
			},
		},
	}

	return []ast.Decl{funcDecl}
}

func (s SliceWrapper) ItemSetAst() []ast.Decl {
	functionName := s.CGoName() + "_item_set"
	selfIdent := NewIdent("self")
	indexIdent := NewIdent("i")
	indexTypeIdent := NewIdent("int")
	goTypeIdent := NewIdent(s.GoName())
	elementTypeIdent := NewIdent(s.elem.String())
	itemsIdent := NewIdent("items")
	itemIdent := NewIdent("item")

	castExpression := CastUnsafePtr(DeRef(goTypeIdent), selfIdent)

	funcDecl := &ast.FuncDecl{
		Doc: &ast.CommentGroup{
			List: ExportComments(functionName),
		},
		Name: NewIdent(functionName),
		Type: &ast.FuncType{
			Params: InstanceMethodParams(goTypeIdent,
				[]*ast.Field{
					{
						Names: []*ast.Ident{indexIdent},
						Type:  indexTypeIdent,
					},
					{
						Names: []*ast.Ident{itemIdent},
						Type:  elementTypeIdent,
					},
				}...),
		},
		Body: &ast.BlockStmt{
			List: []ast.Stmt{
				&ast.AssignStmt{
					Lhs: []ast.Expr{
						itemsIdent,
					},
					Rhs: []ast.Expr{
						castExpression,
					},
					Tok: token.DEFINE,
				},
				&ast.AssignStmt{
					Lhs: []ast.Expr{
						&ast.IndexExpr{
							X: &ast.ParenExpr{
								X: &ast.StarExpr{
									X: itemsIdent,
								},
							},
							Index: indexIdent,
						},
					},
					Rhs: []ast.Expr{
						itemIdent,
					},
					Tok: token.ASSIGN,
				},
			},
		},
	}

	return []ast.Decl{funcDecl}
}

func (s SliceWrapper) ItemAppendAst() []ast.Decl {
	functionName := s.CGoName() + "_item_append"
	selfIdent := NewIdent("self")
	goTypeIdent := NewIdent(s.GoName())
	elementTypeIdent := NewIdent(s.elem.String())
	itemsIdent := NewIdent("items")
	itemIdent := NewIdent("item")

	castExpression := CastUnsafePtr(DeRef(goTypeIdent), selfIdent)

	funcDecl := &ast.FuncDecl{
		Doc: &ast.CommentGroup{
			List: ExportComments(functionName),
		},
		Name: NewIdent(functionName),
		Type: &ast.FuncType{
			Params: InstanceMethodParams(goTypeIdent,
				[]*ast.Field{
					{
						Names: []*ast.Ident{itemIdent},
						Type:  elementTypeIdent,
					},
				}...),
		},
		Body: &ast.BlockStmt{
			List: []ast.Stmt{
				&ast.AssignStmt{
					Lhs: []ast.Expr{
						itemsIdent,
					},
					Rhs: []ast.Expr{
						castExpression,
					},
					Tok: token.DEFINE,
				},
				&ast.AssignStmt{
					Lhs: []ast.Expr{
						DeRef(itemsIdent),
					},
					Rhs: []ast.Expr{
						&ast.CallExpr{
							Fun: NewIdent("append"),
							Args: []ast.Expr{
								DeRef(itemsIdent),
								itemIdent,
							},
						},
					},
					Tok: token.ASSIGN,
				},
			},
		},
	}

	return []ast.Decl{funcDecl}
}
<|endoftext|>


<commit_before>package images

import (
	"fmt"
	"net/http"
	"strconv"
	"strings"
	"time"

	g "github.com/onsi/ginkgo"
	o "github.com/onsi/gomega"

	kapi "k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/util/wait"
	e2e "k8s.io/kubernetes/test/e2e/framework"

	exutil "github.com/openshift/origin/test/extended/util"
)

const changeTimeoutSeconds = 3 * 60

var _ = g.Describe("[networking][router] openshift routers", func() {
	defer g.GinkgoRecover()
	var (
		configPath = exutil.FixturePath("testdata", "scoped-router.yaml")
		oc         = exutil.NewCLI("scoped-router", exutil.KubeConfigPath())
	)

	g.BeforeEach(func() {
		// defer oc.Run("delete").Args("-f", configPath).Execute()
		err := oc.AsAdmin().Run("adm").Args("policy", "add-cluster-role-to-user", "system:router", oc.Username()).Execute()
		o.Expect(err).NotTo(o.HaveOccurred())
		err = oc.Run("create").Args("-f", configPath).Execute()
		o.Expect(err).NotTo(o.HaveOccurred())
	})

	g.Describe("The HAProxy router", func() {
		g.It("should serve the correct routes when scoped to a single namespace and label set", func() {
			oc.SetOutputDir(exutil.TestContext.OutputDir)
			ns := oc.KubeFramework().Namespace.Name
			execPodName := exutil.CreateExecPodOrFail(oc.AdminKubeClient().Core(), ns, "execpod")
			defer func() { oc.AdminKubeClient().Core().Pods(ns).Delete(execPodName, kapi.NewDeleteOptions(1)) }()

			g.By(fmt.Sprintf("creating a scoped router from a config file %q", configPath))

			var routerIP string
			err := wait.Poll(time.Second, changeTimeoutSeconds*time.Second, func() (bool, error) {
				pod, err := oc.KubeFramework().ClientSet.Core().Pods(oc.KubeFramework().Namespace.Name).Get("scoped-router")
				if err != nil {
					return false, err
				}
				if len(pod.Status.PodIP) == 0 {
					return false, nil
				}
				routerIP = pod.Status.PodIP
				return true, nil
			})
			o.Expect(err).NotTo(o.HaveOccurred())

			// router expected to listen on port 80
			routerURL := fmt.Sprintf("http://%s", routerIP)

			g.By("waiting for the healthz endpoint to respond")
			healthzURI := fmt.Sprintf("http://%s:1936/healthz", routerIP)
			err = waitForRouterOKResponseExec(ns, execPodName, healthzURI, routerIP, changeTimeoutSeconds)
			o.Expect(err).NotTo(o.HaveOccurred())

			g.By("waiting for the valid route to respond")
			err = waitForRouterOKResponseExec(ns, execPodName, routerURL, "first.example.com", changeTimeoutSeconds)
			o.Expect(err).NotTo(o.HaveOccurred())

			for _, host := range []string{"second.example.com", "third.example.com"} {
				g.By(fmt.Sprintf("checking that %s does not match a route", host))
				err = expectRouteStatusCodeExec(ns, execPodName, routerURL, host, http.StatusServiceUnavailable)
				o.Expect(err).NotTo(o.HaveOccurred())
			}
		})

		g.It("should override the route host with a custom value", func() {
			oc.SetOutputDir(exutil.TestContext.OutputDir)
			ns := oc.KubeFramework().Namespace.Name
			execPodName := exutil.CreateExecPodOrFail(oc.AdminKubeClient().Core(), ns, "execpod")
			defer func() { oc.AdminKubeClient().Core().Pods(ns).Delete(execPodName, kapi.NewDeleteOptions(1)) }()

			g.By(fmt.Sprintf("creating a scoped router from a config file %q", configPath))

			var routerIP string
			err := wait.Poll(time.Second, changeTimeoutSeconds*time.Second, func() (bool, error) {
				pod, err := oc.KubeFramework().ClientSet.Core().Pods(ns).Get("router-override")
				if err != nil {
					return false, err
				}
				if len(pod.Status.PodIP) == 0 {
					return false, nil
				}
				routerIP = pod.Status.PodIP
				return true, nil
			})

			o.Expect(err).NotTo(o.HaveOccurred())

			// router expected to listen on port 80
			routerURL := fmt.Sprintf("http://%s", routerIP)
			pattern := "%s-%s.myapps.mycompany.com"

			g.By("waiting for the healthz endpoint to respond")
			healthzURI := fmt.Sprintf("http://%s:1936/healthz", routerIP)
			err = waitForRouterOKResponseExec(ns, execPodName, healthzURI, routerIP, changeTimeoutSeconds)
			o.Expect(err).NotTo(o.HaveOccurred())

			g.By("waiting for the valid route to respond")
			err = waitForRouterOKResponseExec(ns, execPodName, routerURL, fmt.Sprintf(pattern, "route-1", ns), changeTimeoutSeconds)
			o.Expect(err).NotTo(o.HaveOccurred())

			g.By("checking that the stored domain name does not match a route")
			host := "first.example.com"
			err = expectRouteStatusCodeExec(ns, execPodName, routerURL, host, http.StatusServiceUnavailable)
			o.Expect(err).NotTo(o.HaveOccurred())

			for _, host := range []string{"route-1", "route-2"} {
				host = fmt.Sprintf(pattern, host, ns)
				g.By(fmt.Sprintf("checking that %s matches a route", host))
				err = expectRouteStatusCodeExec(ns, execPodName, routerURL, host, http.StatusOK)
				o.Expect(err).NotTo(o.HaveOccurred())
			}
		})
	})
})

func waitForRouterOKResponseExec(ns, execPodName, url, host string, timeoutSeconds int) error {
	cmd := fmt.Sprintf(`
		set -e
		for i in $(seq 1 %d); do
			code=$( curl -s -o /dev/null -w '%%{http_code}\n' --header 'Host: %s' %q )
			echo $code
			if [[ $code -eq 200 ]]; then
				exit 0
			fi
			if [[ $code -ne 503 ]]; then
				exit 1
			fi
			sleep 1
		done
		`, timeoutSeconds, host, url)
	output, err := e2e.RunHostCmd(ns, execPodName, cmd)
	if err != nil {
		return fmt.Errorf("host command failed: %v\n%s", err, output)
	}
	lines := strings.Split(strings.TrimSpace(output), "\n")
	if lines[len(lines)-1] != "200" {
		return fmt.Errorf("last response from server was not 200:\n%s", output)
	}
	return nil
}

func expectRouteStatusCodeRepeatedExec(ns, execPodName, url, host string, statusCode int, times int) error {
	cmd := fmt.Sprintf(`
		set -e
		for i in $(seq 1 %d); do
			code=$( curl -s -o /dev/null -w '%%{http_code}\n' --header 'Host: %s' %q )
			echo $code
			if [[ $code -ne %d ]]; then
				exit 1
			fi
		done
		`, times, host, url, statusCode)
	output, err := e2e.RunHostCmd(ns, execPodName, cmd)
	if err != nil {
		return fmt.Errorf("host command failed: %v\n%s", err, output)
	}
	return nil
}

func expectRouteStatusCodeExec(ns, execPodName, url, host string, statusCode int) error {
	cmd := fmt.Sprintf("curl -s -o /dev/null -w '%%{http_code}' --header 'Host: %s' %q", host, url)
	output, err := e2e.RunHostCmd(ns, execPodName, cmd)
	if err != nil {
		return fmt.Errorf("host command failed: %v\n%s", err, output)
	}
	if output != strconv.Itoa(statusCode) {
		return fmt.Errorf("last response from server was not %d: %s", statusCode, output)
	}
	return nil
}

func getAuthenticatedRouteURLViaPod(ns, execPodName, url, host, user, pass string) (string, error) {
	cmd := fmt.Sprintf("curl -s -u %s:%s --header 'Host: %s' %q", user, pass, host, url)
	output, err := e2e.RunHostCmd(ns, execPodName, cmd)
	if err != nil {
		return "", fmt.Errorf("host command failed: %v\n%s", err, output)
	}
	return output, nil
}
<commit_msg>Router tests should check for curl errors<commit_after>package images

import (
	"fmt"
	"net/http"
	"strconv"
	"strings"
	"time"

	g "github.com/onsi/ginkgo"
	o "github.com/onsi/gomega"

	kapi "k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/util/wait"
	e2e "k8s.io/kubernetes/test/e2e/framework"

	exutil "github.com/openshift/origin/test/extended/util"
)

const changeTimeoutSeconds = 3 * 60

var _ = g.Describe("[networking][router] openshift routers", func() {
	defer g.GinkgoRecover()
	var (
		configPath = exutil.FixturePath("testdata", "scoped-router.yaml")
		oc         = exutil.NewCLI("scoped-router", exutil.KubeConfigPath())
	)

	g.BeforeEach(func() {
		// defer oc.Run("delete").Args("-f", configPath).Execute()
		err := oc.AsAdmin().Run("adm").Args("policy", "add-cluster-role-to-user", "system:router", oc.Username()).Execute()
		o.Expect(err).NotTo(o.HaveOccurred())
		err = oc.Run("create").Args("-f", configPath).Execute()
		o.Expect(err).NotTo(o.HaveOccurred())
	})

	g.Describe("The HAProxy router", func() {
		g.It("should serve the correct routes when scoped to a single namespace and label set", func() {
			oc.SetOutputDir(exutil.TestContext.OutputDir)
			ns := oc.KubeFramework().Namespace.Name
			execPodName := exutil.CreateExecPodOrFail(oc.AdminKubeClient().Core(), ns, "execpod")
			defer func() { oc.AdminKubeClient().Core().Pods(ns).Delete(execPodName, kapi.NewDeleteOptions(1)) }()

			g.By(fmt.Sprintf("creating a scoped router from a config file %q", configPath))

			var routerIP string
			err := wait.Poll(time.Second, changeTimeoutSeconds*time.Second, func() (bool, error) {
				pod, err := oc.KubeFramework().ClientSet.Core().Pods(oc.KubeFramework().Namespace.Name).Get("scoped-router")
				if err != nil {
					return false, err
				}
				if len(pod.Status.PodIP) == 0 {
					return false, nil
				}
				routerIP = pod.Status.PodIP
				return true, nil
			})
			o.Expect(err).NotTo(o.HaveOccurred())

			// router expected to listen on port 80
			routerURL := fmt.Sprintf("http://%s", routerIP)

			g.By("waiting for the healthz endpoint to respond")
			healthzURI := fmt.Sprintf("http://%s:1936/healthz", routerIP)
			err = waitForRouterOKResponseExec(ns, execPodName, healthzURI, routerIP, changeTimeoutSeconds)
			o.Expect(err).NotTo(o.HaveOccurred())

			g.By("waiting for the valid route to respond")
			err = waitForRouterOKResponseExec(ns, execPodName, routerURL, "first.example.com", changeTimeoutSeconds)
			o.Expect(err).NotTo(o.HaveOccurred())

			for _, host := range []string{"second.example.com", "third.example.com"} {
				g.By(fmt.Sprintf("checking that %s does not match a route", host))
				err = expectRouteStatusCodeExec(ns, execPodName, routerURL, host, http.StatusServiceUnavailable)
				o.Expect(err).NotTo(o.HaveOccurred())
			}
		})

		g.It("should override the route host with a custom value", func() {
			oc.SetOutputDir(exutil.TestContext.OutputDir)
			ns := oc.KubeFramework().Namespace.Name
			execPodName := exutil.CreateExecPodOrFail(oc.AdminKubeClient().Core(), ns, "execpod")
			defer func() { oc.AdminKubeClient().Core().Pods(ns).Delete(execPodName, kapi.NewDeleteOptions(1)) }()

			g.By(fmt.Sprintf("creating a scoped router from a config file %q", configPath))

			var routerIP string
			err := wait.Poll(time.Second, changeTimeoutSeconds*time.Second, func() (bool, error) {
				pod, err := oc.KubeFramework().ClientSet.Core().Pods(ns).Get("router-override")
				if err != nil {
					return false, err
				}
				if len(pod.Status.PodIP) == 0 {
					return false, nil
				}
				routerIP = pod.Status.PodIP
				return true, nil
			})

			o.Expect(err).NotTo(o.HaveOccurred())

			// router expected to listen on port 80
			routerURL := fmt.Sprintf("http://%s", routerIP)
			pattern := "%s-%s.myapps.mycompany.com"

			g.By("waiting for the healthz endpoint to respond")
			healthzURI := fmt.Sprintf("http://%s:1936/healthz", routerIP)
			err = waitForRouterOKResponseExec(ns, execPodName, healthzURI, routerIP, changeTimeoutSeconds)
			o.Expect(err).NotTo(o.HaveOccurred())

			g.By("waiting for the valid route to respond")
			err = waitForRouterOKResponseExec(ns, execPodName, routerURL, fmt.Sprintf(pattern, "route-1", ns), changeTimeoutSeconds)
			o.Expect(err).NotTo(o.HaveOccurred())

			g.By("checking that the stored domain name does not match a route")
			host := "first.example.com"
			err = expectRouteStatusCodeExec(ns, execPodName, routerURL, host, http.StatusServiceUnavailable)
			o.Expect(err).NotTo(o.HaveOccurred())

			for _, host := range []string{"route-1", "route-2"} {
				host = fmt.Sprintf(pattern, host, ns)
				g.By(fmt.Sprintf("checking that %s matches a route", host))
				err = expectRouteStatusCodeExec(ns, execPodName, routerURL, host, http.StatusOK)
				o.Expect(err).NotTo(o.HaveOccurred())
			}
		})
	})
})

func waitForRouterOKResponseExec(ns, execPodName, url, host string, timeoutSeconds int) error {
	cmd := fmt.Sprintf(`
		set -e
		for i in $(seq 1 %d); do
			code=$( curl -s -o /dev/null -w '%%{http_code}\n' --header 'Host: %s' %q ) || rc=$?
			if [[ "${rc:-0}" -eq 0 ]]; then
				echo $code
				if [[ $code -eq 200 ]]; then
					exit 0
				fi
				if [[ $code -ne 503 ]]; then
					exit 1
				fi
			else
				echo "error ${rc}" 1>&2
			fi
			sleep 1
		done
		`, timeoutSeconds, host, url)
	output, err := e2e.RunHostCmd(ns, execPodName, cmd)
	if err != nil {
		return fmt.Errorf("host command failed: %v\n%s", err, output)
	}
	lines := strings.Split(strings.TrimSpace(output), "\n")
	if lines[len(lines)-1] != "200" {
		return fmt.Errorf("last response from server was not 200:\n%s", output)
	}
	return nil
}

func expectRouteStatusCodeRepeatedExec(ns, execPodName, url, host string, statusCode int, times int) error {
	cmd := fmt.Sprintf(`
		set -e
		for i in $(seq 1 %d); do
			code=$( curl -s -o /dev/null -w '%%{http_code}\n' --header 'Host: %s' %q ) || rc=$?
			if [[ "${rc:-0}" -eq 0 ]]; then
				echo $code
				if [[ $code -ne %d ]]; then
					exit 1
				fi
			else
				echo "error ${rc}" 1>&2
			fi
		done
		`, times, host, url, statusCode)
	output, err := e2e.RunHostCmd(ns, execPodName, cmd)
	if err != nil {
		return fmt.Errorf("host command failed: %v\n%s", err, output)
	}
	return nil
}

func expectRouteStatusCodeExec(ns, execPodName, url, host string, statusCode int) error {
	cmd := fmt.Sprintf("curl -s -o /dev/null -w '%%{http_code}' --header 'Host: %s' %q", host, url)
	output, err := e2e.RunHostCmd(ns, execPodName, cmd)
	if err != nil {
		return fmt.Errorf("host command failed: %v\n%s", err, output)
	}
	if output != strconv.Itoa(statusCode) {
		return fmt.Errorf("last response from server was not %d: %s", statusCode, output)
	}
	return nil
}

func getAuthenticatedRouteURLViaPod(ns, execPodName, url, host, user, pass string) (string, error) {
	cmd := fmt.Sprintf("curl -s -u %s:%s --header 'Host: %s' %q", user, pass, host, url)
	output, err := e2e.RunHostCmd(ns, execPodName, cmd)
	if err != nil {
		return "", fmt.Errorf("host command failed: %v\n%s", err, output)
	}
	return output, nil
}
<|endoftext|>