<commit_before>// +build e2e

/*
Copyright 2018 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.
*/

package e2e

import (
	"bytes"
	"io/ioutil"
	"os"
	"os/exec"
	"strings"
	"testing"
	"time"

	"github.com/knative/pkg/test/logging"
	"github.com/knative/serving/test"
)

const (
	appYaml              = "../test_images/helloworld/helloworld.yaml"
	yamlImagePlaceholder = "github.com/knative/serving/test/test_images/helloworld"
	namespacePlaceholder = "default"
	ingressTimeout       = 5 * time.Minute
	servingTimeout       = 2 * time.Minute
	checkInterval        = 2 * time.Second
)

func noStderrShell(name string, arg ...string) string {
	var void bytes.Buffer
	cmd := exec.Command(name, arg...)
	cmd.Stderr = &void
	out, _ := cmd.Output()
	return string(out)
}

func cleanup(yamlFilename string, logger *logging.BaseLogger) {
	exec.Command("kubectl", "delete", "-f", yamlFilename).Run()
	os.Remove(yamlFilename)
}

func TestHelloWorldFromShell(t *testing.T) {
	//add test case specific name to its own logger
	logger := logging.GetContextLogger("TestHelloWorldFromShell")
	imagePath := test.ImagePath("helloworld")

	logger.Infof("Creating manifest")

	// Create manifest file.
	newYaml, err := ioutil.TempFile("", "helloworld")
	if err != nil {
		t.Fatalf("Failed to create temporary manifest: %v", err)
	}
	newYamlFilename := newYaml.Name()
	defer cleanup(newYamlFilename, logger)
	test.CleanupOnInterrupt(func() { cleanup(newYamlFilename, logger) }, logger)

	// Populate manifets file with the real path to the container
	yamlBytes, err := ioutil.ReadFile(appYaml)
	if err != nil {
		t.Fatalf("Failed to read file %s: %v", appYaml, err)
	}

	content := strings.Replace(string(yamlBytes), yamlImagePlaceholder, imagePath, -1)
	content = strings.Replace(string(content), "namespace: "+namespacePlaceholder,
		"namespace: "+test.ServingNamespace, -1)

	if _, err = newYaml.WriteString(content); err != nil {
		t.Fatalf("Failed to write new manifest: %v", err)
	}
	if err = newYaml.Close(); err != nil {
		t.Fatalf("Failed to close new manifest file: %v", err)
	}

	logger.Infof("Manifest file is '%s'", newYamlFilename)
	logger.Info("Deploying using kubectl")

	// Deploy using kubectl
	if output, err := exec.Command("kubectl", "apply", "-f", newYamlFilename).CombinedOutput(); err != nil {
		t.Fatalf("Error running kubectl: %v", strings.TrimSpace(string(output)))
	}

	logger.Info("Waiting for ingress to come up")

	// Wait for ingress to come up
	serviceIP := ""
	serviceHost := ""
	timeout := ingressTimeout
	for (serviceIP == "" || serviceHost == "") && timeout >= 0 {
		serviceHost = noStderrShell("kubectl", "get", "rt", "route-example", "-o", "jsonpath={.status.domain}", "-n", test.ServingNamespace)
		serviceIP = noStderrShell("kubectl", "get", "svc", "istio-ingressgateway", "-n", "istio-system",
			"-o", "jsonpath={.status.loadBalancer.ingress[*]['ip']}")
		time.Sleep(checkInterval)
		timeout = timeout - checkInterval
	}
	if serviceIP == "" || serviceHost == "" {
		// serviceHost or serviceIP might contain a useful error, dump them.
		t.Fatalf("Ingress not found (IP='%s', host='%s')", serviceIP, serviceHost)
	}
	logger.Infof("Ingress is at %s/%s", serviceIP, serviceHost)

	logger.Info("Accessing app using curl")

	outputString := ""
	timeout = servingTimeout
	for outputString != helloWorldExpectedOutput && timeout >= 0 {
		var cmd *exec.Cmd
		if test.ServingFlags.ResolvableDomain {
			cmd = exec.Command("curl", serviceHost)
		} else {
			cmd = exec.Command("curl", "--header", "Host:"+serviceHost, "http://"+serviceIP)
		}
		output, err := cmd.Output()
		errorString := "none"
		time.Sleep(checkInterval)
		timeout = timeout - checkInterval
		if err != nil {
			errorString = err.Error()
		}
		outputString = strings.TrimSpace(string(output))
		logger.Infof("App replied with '%s' (error: %s)", outputString, errorString)
	}

	if outputString != helloWorldExpectedOutput {
		t.Fatalf("Timeout waiting for app to start serving")
	}
	logger.Info("App is serving")
}
<commit_msg>Update helloworld shell test to hit both old & new gateways. (#2675)<commit_after>// +build e2e

/*
Copyright 2018 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.
*/

package e2e

import (
	"bytes"
	"io/ioutil"
	"os"
	"os/exec"
	"strings"
	"testing"
	"time"

	"github.com/knative/pkg/test/logging"
	"github.com/knative/serving/test"
)

const (
	appYaml              = "../test_images/helloworld/helloworld.yaml"
	yamlImagePlaceholder = "github.com/knative/serving/test/test_images/helloworld"
	namespacePlaceholder = "default"
	ingressTimeout       = 5 * time.Minute
	servingTimeout       = 2 * time.Minute
	checkInterval        = 2 * time.Second
)

func noStderrShell(name string, arg ...string) string {
	var void bytes.Buffer
	cmd := exec.Command(name, arg...)
	cmd.Stderr = &void
	out, _ := cmd.Output()
	return string(out)
}

func cleanup(yamlFilename string, logger *logging.BaseLogger) {
	exec.Command("kubectl", "delete", "-f", yamlFilename).Run()
	os.Remove(yamlFilename)
}

func TestHelloWorldFromShell(t *testing.T) {
	//add test case specific name to its own logger
	logger := logging.GetContextLogger("TestHelloWorldFromShell")
	imagePath := test.ImagePath("helloworld")

	logger.Infof("Creating manifest")

	// Create manifest file.
	newYaml, err := ioutil.TempFile("", "helloworld")
	if err != nil {
		t.Fatalf("Failed to create temporary manifest: %v", err)
	}
	newYamlFilename := newYaml.Name()
	defer cleanup(newYamlFilename, logger)
	test.CleanupOnInterrupt(func() { cleanup(newYamlFilename, logger) }, logger)

	// Populate manifets file with the real path to the container
	yamlBytes, err := ioutil.ReadFile(appYaml)
	if err != nil {
		t.Fatalf("Failed to read file %s: %v", appYaml, err)
	}

	content := strings.Replace(string(yamlBytes), yamlImagePlaceholder, imagePath, -1)
	content = strings.Replace(string(content), "namespace: "+namespacePlaceholder,
		"namespace: "+test.ServingNamespace, -1)

	if _, err = newYaml.WriteString(content); err != nil {
		t.Fatalf("Failed to write new manifest: %v", err)
	}
	if err = newYaml.Close(); err != nil {
		t.Fatalf("Failed to close new manifest file: %v", err)
	}

	logger.Infof("Manifest file is '%s'", newYamlFilename)
	logger.Info("Deploying using kubectl")

	// Deploy using kubectl
	if output, err := exec.Command("kubectl", "apply", "-f", newYamlFilename).CombinedOutput(); err != nil {
		t.Fatalf("Error running kubectl: %v", strings.TrimSpace(string(output)))
	}

	logger.Info("Waiting for ingress to come up")

	gateways := []string{"istio-ingressgateway", "knative-ingressgateway"}
	for _, gateway := range gateways {
		// Wait for ingress to come up
		serviceIP := ""
		serviceHost := ""
		timeout := ingressTimeout
		for (serviceIP == "" || serviceHost == "") && timeout >= 0 {
			if serviceHost == "" {
				serviceHost = noStderrShell("kubectl", "get", "rt", "route-example", "-o", "jsonpath={.status.domain}", "-n", test.ServingNamespace)
			}
			if serviceIP == "" {
				serviceIP = noStderrShell("kubectl", "get", "svc", gateway, "-n", "istio-system",
					"-o", "jsonpath={.status.loadBalancer.ingress[*]['ip']}")
			}
			timeout -= checkInterval
			time.Sleep(checkInterval)
		}
		if serviceIP == "" || serviceHost == "" {
			// serviceHost or serviceIP might contain a useful error, dump them.
			t.Fatalf("Ingress not found (IP='%s', host='%s')", serviceIP, serviceHost)
		}
		logger.Infof("Curling %s/%s", serviceIP, serviceHost)

		outputString := ""
		timeout = servingTimeout
		for outputString != helloWorldExpectedOutput && timeout >= 0 {
			var cmd *exec.Cmd
			if test.ServingFlags.ResolvableDomain {
				cmd = exec.Command("curl", serviceHost)
			} else {
				cmd = exec.Command("curl", "--header", "Host:"+serviceHost, "http://"+serviceIP)
			}
			output, err := cmd.Output()
			errorString := "none"
			if err != nil {
				errorString = err.Error()
			}
			outputString = strings.TrimSpace(string(output))
			logger.Infof("App replied with '%s' (error: %s)", outputString, errorString)
			timeout -= checkInterval
			time.Sleep(checkInterval)
		}

		if outputString != helloWorldExpectedOutput {
			t.Fatal("Timeout waiting for app to start serving")
		}
	}
	logger.Info("App is serving")
}
<|endoftext|>


<commit_before>// Copyright 2017 The nats-operator 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 version

var (
	OperatorVersion = "0.3.0-v1alpha2+git"
	GitSHA          = "Not provided"
)
<commit_msg>Bump version to v0.4.2<commit_after>// Copyright 2017 The nats-operator 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 version

var (
	OperatorVersion = "0.4.2-v1alpha2+git"
	GitSHA          = "Not provided"
)
<|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 scheduling

import (
	"fmt"
	"time"

	"k8s.io/api/core/v1"
	"k8s.io/api/scheduling/v1alpha1"
	"k8s.io/apimachinery/pkg/api/errors"
	"k8s.io/apimachinery/pkg/api/resource"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	clientset "k8s.io/client-go/kubernetes"
	"k8s.io/kubernetes/test/e2e/framework"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	_ "github.com/stretchr/testify/assert"
)

var _ = SIGDescribe("SchedulerPreemption [Serial] [Feature:PodPreemption]", func() {
	var cs clientset.Interface
	var nodeList *v1.NodeList
	var ns string
	f := framework.NewDefaultFramework("sched-preemption")

	lowPriority, mediumPriority, highPriority := int32(1), int32(100), int32(1000)
	lowPriorityClassName := f.BaseName + "-low-priority"
	mediumPriorityClassName := f.BaseName + "-medium-priority"
	highPriorityClassName := f.BaseName + "-high-priority"

	AfterEach(func() {
	})

	BeforeEach(func() {
		cs = f.ClientSet
		ns = f.Namespace.Name
		nodeList = &v1.NodeList{}

		_, err := f.ClientSet.SchedulingV1alpha1().PriorityClasses().Create(&v1alpha1.PriorityClass{ObjectMeta: metav1.ObjectMeta{Name: highPriorityClassName}, Value: highPriority})
		Expect(err == nil || errors.IsAlreadyExists(err)).To(Equal(true))
		_, err = f.ClientSet.SchedulingV1alpha1().PriorityClasses().Create(&v1alpha1.PriorityClass{ObjectMeta: metav1.ObjectMeta{Name: mediumPriorityClassName}, Value: mediumPriority})
		Expect(err == nil || errors.IsAlreadyExists(err)).To(Equal(true))
		_, err = f.ClientSet.SchedulingV1alpha1().PriorityClasses().Create(&v1alpha1.PriorityClass{ObjectMeta: metav1.ObjectMeta{Name: lowPriorityClassName}, Value: lowPriority})
		Expect(err == nil || errors.IsAlreadyExists(err)).To(Equal(true))

		framework.WaitForAllNodesHealthy(cs, time.Minute)
		masterNodes, nodeList = framework.GetMasterAndWorkerNodesOrDie(cs)

		err = framework.CheckTestingNSDeletedExcept(cs, ns)
		framework.ExpectNoError(err)
	})

	// This test verifies that when a higher priority pod is created and no node with
	// enough resources is found, scheduler preempts a lower priority pod to schedule
	// the high priority pod.
	It("validates basic preemption works", func() {
		var podRes v1.ResourceList
		// Create one pod per node that uses a lot of the node's resources.
		By("Create pods that use 60% of node resources.")
		pods := make([]*v1.Pod, len(nodeList.Items))
		for i, node := range nodeList.Items {
			cpuAllocatable, found := node.Status.Allocatable["cpu"]
			Expect(found).To(Equal(true))
			milliCPU := cpuAllocatable.MilliValue() * 40 / 100
			memAllocatable, found := node.Status.Allocatable["memory"]
			Expect(found).To(Equal(true))
			memory := memAllocatable.Value() * 60 / 100
			podRes = v1.ResourceList{}
			podRes[v1.ResourceCPU] = *resource.NewMilliQuantity(int64(milliCPU), resource.DecimalSI)
			podRes[v1.ResourceMemory] = *resource.NewQuantity(int64(memory), resource.BinarySI)

			// make the first pod low priority and the rest medium priority.
			priorityName := mediumPriorityClassName
			if i == 0 {
				priorityName = lowPriorityClassName
			}
			pods[i] = createPausePod(f, pausePodConfig{
				Name:              fmt.Sprintf("pod%d-%v", i, priorityName),
				PriorityClassName: priorityName,
				Resources: &v1.ResourceRequirements{
					Requests: podRes,
				},
			})
			framework.Logf("Created pod: %v", pods[i].Name)
		}
		By("Wait for pods to be scheduled.")
		for _, pod := range pods {
			framework.ExpectNoError(framework.WaitForPodRunningInNamespace(cs, pod))
		}

		By("Run a high priority pod that use 60% of a node resources.")
		// Create a high priority pod and make sure it is scheduled.
		runPausePod(f, pausePodConfig{
			Name:              "preemptor-pod",
			PriorityClassName: highPriorityClassName,
			Resources: &v1.ResourceRequirements{
				Requests: podRes,
			},
		})
		// Make sure that the lowest priority pod is deleted.
		preemptedPod, err := cs.CoreV1().Pods(pods[0].Namespace).Get(pods[0].Name, metav1.GetOptions{})
		podDeleted := (err != nil && errors.IsNotFound(err)) ||
			(err == nil && preemptedPod.DeletionTimestamp != nil)
		Expect(podDeleted).To(BeTrue())
		// Other pods (mid priority ones) should be present.
		for i := 1; i < len(pods); i++ {
			livePod, err := cs.CoreV1().Pods(pods[i].Namespace).Get(pods[i].Name, metav1.GetOptions{})
			framework.ExpectNoError(err)
			Expect(livePod.DeletionTimestamp).To(BeNil())
		}
	})
})
<commit_msg>Add more tests on pod preemption<commit_after>/*
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 scheduling

import (
	"fmt"
	"time"

	"k8s.io/api/core/v1"
	"k8s.io/api/scheduling/v1alpha1"
	"k8s.io/apimachinery/pkg/api/errors"
	"k8s.io/apimachinery/pkg/api/resource"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	clientset "k8s.io/client-go/kubernetes"
	"k8s.io/kubernetes/test/e2e/framework"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	_ "github.com/stretchr/testify/assert"
)

var _ = SIGDescribe("SchedulerPreemption [Serial] [Feature:PodPreemption]", func() {
	var cs clientset.Interface
	var nodeList *v1.NodeList
	var ns string
	f := framework.NewDefaultFramework("sched-preemption")

	lowPriority, mediumPriority, highPriority := int32(1), int32(100), int32(1000)
	lowPriorityClassName := f.BaseName + "-low-priority"
	mediumPriorityClassName := f.BaseName + "-medium-priority"
	highPriorityClassName := f.BaseName + "-high-priority"

	AfterEach(func() {
	})

	BeforeEach(func() {
		cs = f.ClientSet
		ns = f.Namespace.Name
		nodeList = &v1.NodeList{}

		_, err := f.ClientSet.SchedulingV1alpha1().PriorityClasses().Create(&v1alpha1.PriorityClass{ObjectMeta: metav1.ObjectMeta{Name: highPriorityClassName}, Value: highPriority})
		Expect(err == nil || errors.IsAlreadyExists(err)).To(Equal(true))
		_, err = f.ClientSet.SchedulingV1alpha1().PriorityClasses().Create(&v1alpha1.PriorityClass{ObjectMeta: metav1.ObjectMeta{Name: mediumPriorityClassName}, Value: mediumPriority})
		Expect(err == nil || errors.IsAlreadyExists(err)).To(Equal(true))
		_, err = f.ClientSet.SchedulingV1alpha1().PriorityClasses().Create(&v1alpha1.PriorityClass{ObjectMeta: metav1.ObjectMeta{Name: lowPriorityClassName}, Value: lowPriority})
		Expect(err == nil || errors.IsAlreadyExists(err)).To(Equal(true))

		framework.WaitForAllNodesHealthy(cs, time.Minute)
		masterNodes, nodeList = framework.GetMasterAndWorkerNodesOrDie(cs)

		err = framework.CheckTestingNSDeletedExcept(cs, ns)
		framework.ExpectNoError(err)
	})

	// This test verifies that when a higher priority pod is created and no node with
	// enough resources is found, scheduler preempts a lower priority pod to schedule
	// the high priority pod.
	It("validates basic preemption works", func() {
		var podRes v1.ResourceList
		// Create one pod per node that uses a lot of the node's resources.
		By("Create pods that use 60% of node resources.")
		pods := make([]*v1.Pod, len(nodeList.Items))
		for i, node := range nodeList.Items {
			cpuAllocatable, found := node.Status.Allocatable["cpu"]
			Expect(found).To(Equal(true))
			milliCPU := cpuAllocatable.MilliValue() * 40 / 100
			memAllocatable, found := node.Status.Allocatable["memory"]
			Expect(found).To(Equal(true))
			memory := memAllocatable.Value() * 60 / 100
			podRes = v1.ResourceList{}
			podRes[v1.ResourceCPU] = *resource.NewMilliQuantity(int64(milliCPU), resource.DecimalSI)
			podRes[v1.ResourceMemory] = *resource.NewQuantity(int64(memory), resource.BinarySI)

			// make the first pod low priority and the rest medium priority.
			priorityName := mediumPriorityClassName
			if i == 0 {
				priorityName = lowPriorityClassName
			}
			pods[i] = createPausePod(f, pausePodConfig{
				Name:              fmt.Sprintf("pod%d-%v", i, priorityName),
				PriorityClassName: priorityName,
				Resources: &v1.ResourceRequirements{
					Requests: podRes,
				},
			})
			framework.Logf("Created pod: %v", pods[i].Name)
		}
		By("Wait for pods to be scheduled.")
		for _, pod := range pods {
			framework.ExpectNoError(framework.WaitForPodRunningInNamespace(cs, pod))
		}

		By("Run a high priority pod that use 60% of a node resources.")
		// Create a high priority pod and make sure it is scheduled.
		runPausePod(f, pausePodConfig{
			Name:              "preemptor-pod",
			PriorityClassName: highPriorityClassName,
			Resources: &v1.ResourceRequirements{
				Requests: podRes,
			},
		})
		// Make sure that the lowest priority pod is deleted.
		preemptedPod, err := cs.CoreV1().Pods(pods[0].Namespace).Get(pods[0].Name, metav1.GetOptions{})
		podDeleted := (err != nil && errors.IsNotFound(err)) ||
			(err == nil && preemptedPod.DeletionTimestamp != nil)
		Expect(podDeleted).To(BeTrue())
		// Other pods (mid priority ones) should be present.
		for i := 1; i < len(pods); i++ {
			livePod, err := cs.CoreV1().Pods(pods[i].Namespace).Get(pods[i].Name, metav1.GetOptions{})
			framework.ExpectNoError(err)
			Expect(livePod.DeletionTimestamp).To(BeNil())
		}
	})

	// This test verifies that when a high priority pod is pending and its
	// scheduling violates a medium priority pod anti-affinity, the medium priority
	// pod is preempted to allow the higher priority pod schedule.
	// It also verifies that existing low priority pods are not preempted as their
	// preemption wouldn't help.
	It("validates pod anti-affinity works in preemption", func() {
		var podRes v1.ResourceList
		// Create a few pods that uses a small amount of resources.
		By("Create pods that use 10% of node resources.")
		numPods := 4
		if len(nodeList.Items) < numPods {
			numPods = len(nodeList.Items)
		}
		pods := make([]*v1.Pod, numPods)
		for i := 0; i < numPods; i++ {
			node := nodeList.Items[i]
			cpuAllocatable, found := node.Status.Allocatable["cpu"]
			Expect(found).To(BeTrue())
			milliCPU := cpuAllocatable.MilliValue() * 10 / 100
			memAllocatable, found := node.Status.Allocatable["memory"]
			Expect(found).To(BeTrue())
			memory := memAllocatable.Value() * 10 / 100
			podRes = v1.ResourceList{}
			podRes[v1.ResourceCPU] = *resource.NewMilliQuantity(int64(milliCPU), resource.DecimalSI)
			podRes[v1.ResourceMemory] = *resource.NewQuantity(int64(memory), resource.BinarySI)

			// Apply node label to each node
			framework.AddOrUpdateLabelOnNode(cs, node.Name, "node", node.Name)
			framework.ExpectNodeHasLabel(cs, node.Name, "node", node.Name)

			// make the first pod medium priority and the rest low priority.
			priorityName := lowPriorityClassName
			if i == 0 {
				priorityName = mediumPriorityClassName
			}
			pods[i] = createPausePod(f, pausePodConfig{
				Name:              fmt.Sprintf("pod%d-%v", i, priorityName),
				PriorityClassName: priorityName,
				Resources: &v1.ResourceRequirements{
					Requests: podRes,
				},
				Affinity: &v1.Affinity{
					PodAntiAffinity: &v1.PodAntiAffinity{
						RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{
							{
								LabelSelector: &metav1.LabelSelector{
									MatchExpressions: []metav1.LabelSelectorRequirement{
										{
											Key:      "service",
											Operator: metav1.LabelSelectorOpIn,
											Values:   []string{"blah", "foo"},
										},
									},
								},
								TopologyKey: "node",
							},
						},
					},
					NodeAffinity: &v1.NodeAffinity{
						RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{
							NodeSelectorTerms: []v1.NodeSelectorTerm{
								{
									MatchExpressions: []v1.NodeSelectorRequirement{
										{
											Key:      "node",
											Operator: v1.NodeSelectorOpIn,
											Values:   []string{node.Name},
										},
									},
								},
							},
						},
					},
				},
			})
			framework.Logf("Created pod: %v", pods[i].Name)
		}
		defer func() { // Remove added labels
			for i := 0; i < numPods; i++ {
				framework.RemoveLabelOffNode(cs, nodeList.Items[i].Name, "node")
			}
		}()

		By("Wait for pods to be scheduled.")
		for _, pod := range pods {
			framework.ExpectNoError(framework.WaitForPodRunningInNamespace(cs, pod))
		}

		By("Run a high priority pod with node affinity to the first node.")
		// Create a high priority pod and make sure it is scheduled.
		runPausePod(f, pausePodConfig{
			Name:              "preemptor-pod",
			PriorityClassName: highPriorityClassName,
			Labels:            map[string]string{"service": "blah"},
			Affinity: &v1.Affinity{
				NodeAffinity: &v1.NodeAffinity{
					RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{
						NodeSelectorTerms: []v1.NodeSelectorTerm{
							{
								MatchExpressions: []v1.NodeSelectorRequirement{
									{
										Key:      "node",
										Operator: v1.NodeSelectorOpIn,
										Values:   []string{nodeList.Items[0].Name},
									},
								},
							},
						},
					},
				},
			},
		})
		// Make sure that the medium priority pod on the first node is preempted.
		preemptedPod, err := cs.CoreV1().Pods(pods[0].Namespace).Get(pods[0].Name, metav1.GetOptions{})
		podDeleted := (err != nil && errors.IsNotFound(err)) ||
			(err == nil && preemptedPod.DeletionTimestamp != nil)
		Expect(podDeleted).To(BeTrue())
		// Other pods (low priority ones) should be present.
		for i := 1; i < len(pods); i++ {
			livePod, err := cs.CoreV1().Pods(pods[i].Namespace).Get(pods[i].Name, metav1.GetOptions{})
			framework.ExpectNoError(err)
			Expect(livePod.DeletionTimestamp).To(BeNil())
		}
	})
})
<|endoftext|>


<commit_before>// Copyright 2017 The LUCI 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 isolated

import (
	"bytes"
	"context"
	"crypto"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"os"
	"path/filepath"
	"runtime"
	"testing"

	"go.chromium.org/luci/client/archiver"
	"go.chromium.org/luci/common/isolated"
	"go.chromium.org/luci/common/isolatedclient"
	"go.chromium.org/luci/common/isolatedclient/isolatedfake"

	. "github.com/smartystreets/goconvey/convey"
)

func TestArchive(t *testing.T) {
	t.Parallel()
	ctx := context.Background()

	Convey(`Tests the archival of some files.`, t, func() {
		server := isolatedfake.New()
		ts := httptest.NewServer(server)
		defer ts.Close()

		// Setup temporary directory.
		//   /base/bar
		//   /base/ignored
		//   /link -> /base/bar
		//   /second/boz
		// Result:
		//   /baz.isolated
		tmpDir, err := ioutil.TempDir("", "isolated")
		So(err, ShouldBeNil)
		defer func() {
			if err := os.RemoveAll(tmpDir); err != nil {
				t.Fail()
			}
		}()
		baseDir := filepath.Join(tmpDir, "base")
		fooDir := filepath.Join(tmpDir, "foo")
		secondDir := filepath.Join(tmpDir, "second")
		So(os.Mkdir(baseDir, 0700), ShouldBeNil)
		So(os.Mkdir(fooDir, 0700), ShouldBeNil)
		So(os.Mkdir(secondDir, 0700), ShouldBeNil)

		barData := []byte("foo")
		ignoredData := []byte("ignored")
		bozData := []byte("foo2")
		So(ioutil.WriteFile(filepath.Join(baseDir, "bar"), barData, 0600), ShouldBeNil)
		So(ioutil.WriteFile(filepath.Join(baseDir, "ignored"), ignoredData, 0600), ShouldBeNil)
		So(ioutil.WriteFile(filepath.Join(secondDir, "boz"), bozData, 0600), ShouldBeNil)
		winLinkData := []byte("no link on Windows")
		if !isWindows() {
			So(os.Symlink(filepath.Join("base", "bar"), filepath.Join(tmpDir, "link")), ShouldBeNil)
		} else {
			So(ioutil.WriteFile(filepath.Join(tmpDir, "link"), winLinkData, 0600), ShouldBeNil)
		}

		var buf bytes.Buffer
		filesSC := ScatterGather{}
		So(filesSC.Add(tmpDir, "link"), ShouldBeNil)
		dirsSC := ScatterGather{}
		So(dirsSC.Add(tmpDir, "base"), ShouldBeNil)
		So(dirsSC.Add(tmpDir, "second"), ShouldBeNil)

		opts := &ArchiveOptions{
			Files:        filesSC,
			Dirs:         dirsSC,
			Blacklist:    []string{"ignored", "*.isolate"},
			Isolated:     filepath.Join(tmpDir, "baz.isolated"),
			LeakIsolated: &buf,
		}
		// TODO(maruel): Make other algorithms work too.
		for _, namespace := range []string{isolatedclient.DefaultNamespace} {
			Convey(fmt.Sprintf("Run on namespace %s", namespace), func() {
				a := archiver.New(ctx, isolatedclient.New(nil, nil, ts.URL, namespace, nil, nil), nil)
				item := Archive(ctx, a, opts)
				So(item.DisplayName, ShouldResemble, filepath.Join(tmpDir, "baz.isolated"))
				item.WaitForHashed()
				So(item.Error(), ShouldBeNil)
				So(a.Close(), ShouldBeNil)

				mode := 0600
				if isWindows() {
					mode = 0666
				}

				h := isolated.GetHash(namespace)
				baseData := oneFileArchiveExpect(h, filepath.Join("base", "bar"), mode, barData)
				secondData := oneFileArchiveExpect(h, filepath.Join("second", "boz"), mode, bozData)
				topIsolated := isolated.New(h)
				topIsolated.Includes = isolated.HexDigests{baseData.Hash, secondData.Hash}
				if !isWindows() {
					topIsolated.Files["link"] = isolated.BasicFile(isolated.HashBytes(h, barData), mode, int64(len(barData)))
				} else {
					topIsolated.Files["link"] = isolated.BasicFile(isolated.HashBytes(h, winLinkData), 0666, int64(len(winLinkData)))
				}
				isolatedData := newArchiveExpectData(h, topIsolated)
				expected := map[string]map[isolated.HexDigest]string{
					namespace: {
						isolated.HashBytes(h, barData): string(barData),
						isolated.HashBytes(h, bozData): string(bozData),
						baseData.Hash:                  baseData.String,
						isolatedData.Hash:              isolatedData.String,
						secondData.Hash:                secondData.String,
					},
				}
				if isWindows() {
					// TODO(maruel): Fix symlink support on Windows.
					expected[namespace][isolated.HashBytes(h, winLinkData)] = string(winLinkData)
				}
				actual := map[string]map[isolated.HexDigest]string{}
				for n, c := range server.Contents() {
					actual[n] = map[isolated.HexDigest]string{}
					for k, v := range c {
						actual[n][isolated.HexDigest(k)] = string(v)
					}
				}
				So(actual, ShouldResemble, expected)
				So(item.Digest(), ShouldResemble, isolatedData.Hash)
				So(server.Error(), ShouldBeNil)
				digest := isolated.HashBytes(h, buf.Bytes())
				So(digest, ShouldResemble, isolatedData.Hash)
			})
		}
	})
}

func TestArchiveFail(t *testing.T) {
	t.Parallel()
	ctx := context.Background()
	Convey(`Fails to archive a file`, t, func() {
		server := isolatedfake.New()
		ts := httptest.NewServer(server)
		defer ts.Close()

		Convey(`File missing`, func() {
			a := archiver.New(ctx, isolatedclient.New(nil, nil, ts.URL, isolatedclient.DefaultNamespace, nil, nil), nil)

			tmpDir, err := ioutil.TempDir("", "archiver")
			So(err, ShouldBeNil)
			defer func() {
				So(os.RemoveAll(tmpDir), ShouldBeNil)
			}()

			// This will trigger an eventual Cancel().
			nonexistent := filepath.Join(tmpDir, "nonexistent")
			item1 := a.PushFile("foo", nonexistent, 0)
			So(item1.DisplayName, ShouldResemble, "foo")

			fileName := filepath.Join(tmpDir, "existent")
			So(ioutil.WriteFile(fileName, []byte("foo"), 0600), ShouldBeNil)
			item2 := a.PushFile("existent", fileName, 0)
			item1.WaitForHashed()
			item2.WaitForHashed()
			msg := "no such file or directory"
			if runtime.GOOS == "windows" {
				// Warning: this string is localized.
				msg = "The system cannot find the file specified."
			}
			fileErr := fmt.Errorf("source(foo) failed: open %s%cnonexistent: %s", tmpDir, filepath.Separator, msg)
			So(a.Close(), ShouldResemble, fileErr)
			So(item1.Error(), ShouldResemble, fileErr)
			// There can be a race with item2 having time to be sent or not, but if
			// there's an error, it must be context.Canceled.
			if err := item2.Error(); err != nil {
				So(item2.Error(), ShouldResemble, context.Canceled)
			}
			So(server.Error(), ShouldBeNil)
		})

		Convey(`Server error`, func() {
			expectedErr := errors.New("expected")
			// Override the handler to fail.
			server.ServeMux = *http.NewServeMux()
			server.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
				Convey(`Return error`, t, func() {
					ioutil.ReadAll(req.Body)
					req.Body.Close()
					w.Header().Set("Content-Type", "application/json; charset=utf-8")
					w.WriteHeader(400)
					j := json.NewEncoder(w)
					out := map[string]string{"error": expectedErr.Error()}
					So(j.Encode(out), ShouldBeNil)
				})
			})
			a := archiver.New(ctx, isolatedclient.New(nil, nil, ts.URL, isolatedclient.DefaultNamespace, nil, nil), nil)

			tmpDir, err := ioutil.TempDir("", "archiver")
			So(err, ShouldBeNil)
			defer func() {
				So(os.RemoveAll(tmpDir), ShouldBeNil)
			}()

			// This will trigger an eventual Cancel().
			fileName := filepath.Join(tmpDir, "existent")
			So(ioutil.WriteFile(fileName, []byte("foo"), 0600), ShouldBeNil)
			item := a.PushFile("existent", fileName, 0)
			item.WaitForHashed()
			So(item.Error(), ShouldResemble, nil)
			// TODO(maruel): Fix isolatedclient to surface the error expectedErr.
			So(a.Close(), ShouldResemble, errors.New("contains(1) failed: gave up after 1 attempts: http request failed: Bad Request (HTTP 400)"))
		})
	})
}

func isWindows() bool {
	return runtime.GOOS == "windows"
}

type archiveExpectData struct {
	*isolated.Isolated
	String string
	Hash   isolated.HexDigest
}

func oneFileArchiveExpect(h crypto.Hash, file string, mode int, data []byte) *archiveExpectData {
	i := isolated.New(h)
	i.Files[file] = isolated.BasicFile(isolated.HashBytes(h, data), mode, int64(len(data)))
	return newArchiveExpectData(h, i)
}

func newArchiveExpectData(h crypto.Hash, i *isolated.Isolated) *archiveExpectData {
	encoded, _ := json.Marshal(i)
	str := string(encoded) + "\n"
	return &archiveExpectData{
		Isolated: i,
		String:   str,
		Hash:     isolated.HashBytes(h, []byte(str)),
	}
}
<commit_msg>[isolated] change oneArchiveExpect<commit_after>// Copyright 2017 The LUCI 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 isolated

import (
	"bytes"
	"context"
	"crypto"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"os"
	"path/filepath"
	"runtime"
	"testing"

	"go.chromium.org/luci/client/archiver"
	"go.chromium.org/luci/common/isolated"
	"go.chromium.org/luci/common/isolatedclient"
	"go.chromium.org/luci/common/isolatedclient/isolatedfake"

	. "github.com/smartystreets/goconvey/convey"
)

func TestArchive(t *testing.T) {
	t.Parallel()
	ctx := context.Background()

	Convey(`Tests the archival of some files.`, t, func() {
		server := isolatedfake.New()
		ts := httptest.NewServer(server)
		defer ts.Close()

		// Setup temporary directory.
		//   /base/bar
		//   /base/ignored
		//   /link -> /base/bar
		//   /second/boz
		// Result:
		//   /baz.isolated
		tmpDir, err := ioutil.TempDir("", "isolated")
		So(err, ShouldBeNil)
		defer func() {
			if err := os.RemoveAll(tmpDir); err != nil {
				t.Fail()
			}
		}()
		baseDir := filepath.Join(tmpDir, "base")
		fooDir := filepath.Join(tmpDir, "foo")
		secondDir := filepath.Join(tmpDir, "second")
		So(os.Mkdir(baseDir, 0700), ShouldBeNil)
		So(os.Mkdir(fooDir, 0700), ShouldBeNil)
		So(os.Mkdir(secondDir, 0700), ShouldBeNil)

		barData := []byte("foo")
		ignoredData := []byte("ignored")
		bozData := []byte("foo2")
		So(ioutil.WriteFile(filepath.Join(baseDir, "bar"), barData, 0600), ShouldBeNil)
		So(ioutil.WriteFile(filepath.Join(baseDir, "ignored"), ignoredData, 0600), ShouldBeNil)
		So(ioutil.WriteFile(filepath.Join(secondDir, "boz"), bozData, 0600), ShouldBeNil)
		winLinkData := []byte("no link on Windows")
		if !isWindows() {
			So(os.Symlink(filepath.Join("base", "bar"), filepath.Join(tmpDir, "link")), ShouldBeNil)
		} else {
			So(ioutil.WriteFile(filepath.Join(tmpDir, "link"), winLinkData, 0600), ShouldBeNil)
		}

		var buf bytes.Buffer
		filesSC := ScatterGather{}
		So(filesSC.Add(tmpDir, "link"), ShouldBeNil)
		dirsSC := ScatterGather{}
		So(dirsSC.Add(tmpDir, "base"), ShouldBeNil)
		So(dirsSC.Add(tmpDir, "second"), ShouldBeNil)

		opts := &ArchiveOptions{
			Files:        filesSC,
			Dirs:         dirsSC,
			Blacklist:    []string{"ignored", "*.isolate"},
			Isolated:     filepath.Join(tmpDir, "baz.isolated"),
			LeakIsolated: &buf,
		}
		// TODO(maruel): Make other algorithms work too.
		for _, namespace := range []string{isolatedclient.DefaultNamespace} {
			Convey(fmt.Sprintf("Run on namespace %s", namespace), func() {
				a := archiver.New(ctx, isolatedclient.New(nil, nil, ts.URL, namespace, nil, nil), nil)
				item := Archive(ctx, a, opts)
				So(item.DisplayName, ShouldResemble, filepath.Join(tmpDir, "baz.isolated"))
				item.WaitForHashed()
				So(item.Error(), ShouldBeNil)
				So(a.Close(), ShouldBeNil)

				mode := 0600
				if isWindows() {
					mode = 0666
				}

				h := isolated.GetHash(namespace)
				baseData := filesArchiveExpect(h, tmpDir, filepath.Join("base", "bar"))
				secondData := filesArchiveExpect(h, tmpDir, filepath.Join("second", "boz"))
				topIsolated := isolated.New(h)
				topIsolated.Includes = isolated.HexDigests{baseData.Hash, secondData.Hash}
				if !isWindows() {
					topIsolated.Files["link"] = isolated.BasicFile(isolated.HashBytes(h, barData), mode, int64(len(barData)))
				} else {
					topIsolated.Files["link"] = isolated.BasicFile(isolated.HashBytes(h, winLinkData), 0666, int64(len(winLinkData)))
				}
				isolatedData := newArchiveExpectData(h, topIsolated)
				expected := map[string]map[isolated.HexDigest]string{
					namespace: {
						isolated.HashBytes(h, barData): string(barData),
						isolated.HashBytes(h, bozData): string(bozData),
						baseData.Hash:                  baseData.String,
						isolatedData.Hash:              isolatedData.String,
						secondData.Hash:                secondData.String,
					},
				}
				if isWindows() {
					// TODO(maruel): Fix symlink support on Windows.
					expected[namespace][isolated.HashBytes(h, winLinkData)] = string(winLinkData)
				}
				actual := map[string]map[isolated.HexDigest]string{}
				for n, c := range server.Contents() {
					actual[n] = map[isolated.HexDigest]string{}
					for k, v := range c {
						actual[n][isolated.HexDigest(k)] = string(v)
					}
				}
				So(actual, ShouldResemble, expected)
				So(item.Digest(), ShouldResemble, isolatedData.Hash)
				So(server.Error(), ShouldBeNil)
				digest := isolated.HashBytes(h, buf.Bytes())
				So(digest, ShouldResemble, isolatedData.Hash)
			})
		}
	})
}

func TestArchiveFail(t *testing.T) {
	t.Parallel()
	ctx := context.Background()
	Convey(`Fails to archive a file`, t, func() {
		server := isolatedfake.New()
		ts := httptest.NewServer(server)
		defer ts.Close()

		Convey(`File missing`, func() {
			a := archiver.New(ctx, isolatedclient.New(nil, nil, ts.URL, isolatedclient.DefaultNamespace, nil, nil), nil)

			tmpDir, err := ioutil.TempDir("", "archiver")
			So(err, ShouldBeNil)
			defer func() {
				So(os.RemoveAll(tmpDir), ShouldBeNil)
			}()

			// This will trigger an eventual Cancel().
			nonexistent := filepath.Join(tmpDir, "nonexistent")
			item1 := a.PushFile("foo", nonexistent, 0)
			So(item1.DisplayName, ShouldResemble, "foo")

			fileName := filepath.Join(tmpDir, "existent")
			So(ioutil.WriteFile(fileName, []byte("foo"), 0600), ShouldBeNil)
			item2 := a.PushFile("existent", fileName, 0)
			item1.WaitForHashed()
			item2.WaitForHashed()
			msg := "no such file or directory"
			if runtime.GOOS == "windows" {
				// Warning: this string is localized.
				msg = "The system cannot find the file specified."
			}
			fileErr := fmt.Errorf("source(foo) failed: open %s%cnonexistent: %s", tmpDir, filepath.Separator, msg)
			So(a.Close(), ShouldResemble, fileErr)
			So(item1.Error(), ShouldResemble, fileErr)
			// There can be a race with item2 having time to be sent or not, but if
			// there's an error, it must be context.Canceled.
			if err := item2.Error(); err != nil {
				So(item2.Error(), ShouldResemble, context.Canceled)
			}
			So(server.Error(), ShouldBeNil)
		})

		Convey(`Server error`, func() {
			expectedErr := errors.New("expected")
			// Override the handler to fail.
			server.ServeMux = *http.NewServeMux()
			server.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
				Convey(`Return error`, t, func() {
					ioutil.ReadAll(req.Body)
					req.Body.Close()
					w.Header().Set("Content-Type", "application/json; charset=utf-8")
					w.WriteHeader(400)
					j := json.NewEncoder(w)
					out := map[string]string{"error": expectedErr.Error()}
					So(j.Encode(out), ShouldBeNil)
				})
			})
			a := archiver.New(ctx, isolatedclient.New(nil, nil, ts.URL, isolatedclient.DefaultNamespace, nil, nil), nil)

			tmpDir, err := ioutil.TempDir("", "archiver")
			So(err, ShouldBeNil)
			defer func() {
				So(os.RemoveAll(tmpDir), ShouldBeNil)
			}()

			// This will trigger an eventual Cancel().
			fileName := filepath.Join(tmpDir, "existent")
			So(ioutil.WriteFile(fileName, []byte("foo"), 0600), ShouldBeNil)
			item := a.PushFile("existent", fileName, 0)
			item.WaitForHashed()
			So(item.Error(), ShouldResemble, nil)
			// TODO(maruel): Fix isolatedclient to surface the error expectedErr.
			So(a.Close(), ShouldResemble, errors.New("contains(1) failed: gave up after 1 attempts: http request failed: Bad Request (HTTP 400)"))
		})
	})
}

func isWindows() bool {
	return runtime.GOOS == "windows"
}

type archiveExpectData struct {
	*isolated.Isolated
	String string
	Hash   isolated.HexDigest
}

func filesArchiveExpect(h crypto.Hash, dir string, files ...string) *archiveExpectData {
	i := isolated.New(h)

	for _, file := range files {
		path := filepath.Join(dir, file)
		fi, err := os.Stat(path)
		So(err, ShouldBeNil)
		data, err := ioutil.ReadFile(path)
		So(err, ShouldBeNil)
		mode := int(fi.Mode() & os.ModePerm)
		i.Files[file] = isolated.BasicFile(isolated.HashBytes(h, data), mode, int64(len(data)))
	}

	return newArchiveExpectData(h, i)
}

func newArchiveExpectData(h crypto.Hash, i *isolated.Isolated) *archiveExpectData {
	encoded, _ := json.Marshal(i)
	str := string(encoded) + "\n"
	return &archiveExpectData{
		Isolated: i,
		String:   str,
		Hash:     isolated.HashBytes(h, []byte(str)),
	}
}
<|endoftext|>


<commit_before>package builds

import (
	"fmt"
	"strings"

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

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

const (
	buildPrefixTS = "ruby-sample-build-ts"
	buildPrefixTD = "ruby-sample-build-td"
	buildPrefixTC = "ruby-sample-build-tc"
)

func scrapeLogs(bldPrefix string, oc *exutil.CLI) {
	// kick off the app/lang build and verify the builder image accordingly
	br, err := exutil.StartBuildAndWait(oc, bldPrefix)
	o.ExpectWithOffset(1, err).NotTo(o.HaveOccurred())

	out, err := br.Logs()
	o.Expect(err).NotTo(o.HaveOccurred())
	lines := strings.Split(out, "\n")
	found := false
	for _, line := range lines {
		if strings.Contains(line, "Pulling image") && strings.Contains(line, "centos/ruby") {
			fmt.Fprintf(g.GinkgoWriter, "\n\nfound pull image line %s\n\n", line)
			found = true
			break
		}
	}

	if !found {
		fmt.Fprintf(g.GinkgoWriter, "\n\n build log dump on failed test:  %s\n\n", out)
		o.Expect(found).To(o.BeTrue())
	}

}

func checkPodFlag(bldPrefix string, oc *exutil.CLI) {
	if bldPrefix == buildPrefixTC {
		// grant access to the custom build strategy
		err := oc.AsAdmin().Run("adm").Args("policy", "add-cluster-role-to-user", "system:build-strategy-custom", oc.Username()).Execute()
		o.Expect(err).NotTo(o.HaveOccurred())
		defer func() {
			err = oc.AsAdmin().Run("adm").Args("policy", "remove-cluster-role-from-user", "system:build-strategy-custom", oc.Username()).Execute()
			o.Expect(err).NotTo(o.HaveOccurred())
		}()
	}

	// kick off the app/lang build and verify the builder image accordingly
	_, err := exutil.StartBuildAndWait(oc, bldPrefix)
	o.ExpectWithOffset(1, err).NotTo(o.HaveOccurred())

	out, err := oc.Run("get").Args("pods", bldPrefix+"-1-build", "-o", "jsonpath='{.spec.containers[0].imagePullPolicy}'").Output()
	o.Expect(err).NotTo(o.HaveOccurred())
	o.Expect(out).To(o.Equal("'Always'"))

}

/*
If docker.io is not responding to requests in a timely manner, this test suite will be adversely affected.

If you suspect such a situation, attempt pulling some openshift images other than ruby-22-centos7
while this test is running and compare results.  Restarting your docker daemon, assuming you can ping docker.io quickly, could
be a quick fix.
*/

var _ = g.Describe("[builds] forcePull should affect pulling builder images", func() {
	defer g.GinkgoRecover()
	var oc = exutil.NewCLI("forcepull", exutil.KubeConfigPath())

	g.BeforeEach(func() {

		// grant access to the custom build strategy
		g.By("granting system:build-strategy-custom")
		err := oc.AsAdmin().Run("adm").Args("policy", "add-cluster-role-to-user", "system:build-strategy-custom", oc.Username()).Execute()
		o.Expect(err).NotTo(o.HaveOccurred())

		defer func() {
			err = oc.AsAdmin().Run("adm").Args("policy", "remove-cluster-role-from-user", "system:build-strategy-custom", oc.Username()).Execute()
			o.Expect(err).NotTo(o.HaveOccurred())
		}()

		g.By("create application build configs for 3 strategies")
		apps := exutil.FixturePath("testdata", "forcepull-test.json")
		err = exutil.CreateResource(apps, oc)
		o.Expect(err).NotTo(o.HaveOccurred())

	})

	g.Context("ForcePull test context  ", func() {

		g.JustBeforeEach(func() {
			g.By("waiting for builder service account")
			err := exutil.WaitForBuilderAccount(oc.AdminKubeClient().Core().ServiceAccounts(oc.Namespace()))
			o.Expect(err).NotTo(o.HaveOccurred())
		})

		g.It("ForcePull test case execution s2i", func() {

			g.By("when s2i force pull is true")
			// run twice to ensure the builder image gets pulled even if it already exists on the node
			scrapeLogs(buildPrefixTS, oc)
			scrapeLogs(buildPrefixTS, oc)

		})

		g.It("ForcePull test case execution docker", func() {

			g.By("docker when force pull is true")
			// run twice to ensure the builder image gets pulled even if it already exists on the node
			scrapeLogs(buildPrefixTD, oc)
			scrapeLogs(buildPrefixTD, oc)

		})

		g.It("ForcePull test case execution custom", func() {

			g.By("when custom force pull is true")

			checkPodFlag(buildPrefixTC, oc)

		})

	})

})
<commit_msg>fix-test: Wait for openshift/ruby:latest ImageStreamTag before running build forcePull test<commit_after>package builds

import (
	"fmt"
	"strings"

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

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

const (
	buildPrefixTS = "ruby-sample-build-ts"
	buildPrefixTD = "ruby-sample-build-td"
	buildPrefixTC = "ruby-sample-build-tc"
)

func scrapeLogs(bldPrefix string, oc *exutil.CLI) {
	// kick off the app/lang build and verify the builder image accordingly
	br, err := exutil.StartBuildAndWait(oc, bldPrefix)
	o.ExpectWithOffset(1, err).NotTo(o.HaveOccurred())

	out, err := br.Logs()
	o.Expect(err).NotTo(o.HaveOccurred())
	lines := strings.Split(out, "\n")
	found := false
	for _, line := range lines {
		if strings.Contains(line, "Pulling image") && strings.Contains(line, "centos/ruby") {
			fmt.Fprintf(g.GinkgoWriter, "\n\nfound pull image line %s\n\n", line)
			found = true
			break
		}
	}

	if !found {
		fmt.Fprintf(g.GinkgoWriter, "\n\n build log dump on failed test:  %s\n\n", out)
		o.Expect(found).To(o.BeTrue())
	}

}

func checkPodFlag(bldPrefix string, oc *exutil.CLI) {
	if bldPrefix == buildPrefixTC {
		// grant access to the custom build strategy
		err := oc.AsAdmin().Run("adm").Args("policy", "add-cluster-role-to-user", "system:build-strategy-custom", oc.Username()).Execute()
		o.Expect(err).NotTo(o.HaveOccurred())
		defer func() {
			err = oc.AsAdmin().Run("adm").Args("policy", "remove-cluster-role-from-user", "system:build-strategy-custom", oc.Username()).Execute()
			o.Expect(err).NotTo(o.HaveOccurred())
		}()
	}

	// kick off the app/lang build and verify the builder image accordingly
	_, err := exutil.StartBuildAndWait(oc, bldPrefix)
	o.ExpectWithOffset(1, err).NotTo(o.HaveOccurred())

	out, err := oc.Run("get").Args("pods", bldPrefix+"-1-build", "-o", "jsonpath='{.spec.containers[0].imagePullPolicy}'").Output()
	o.Expect(err).NotTo(o.HaveOccurred())
	o.Expect(out).To(o.Equal("'Always'"))

}

/*
If docker.io is not responding to requests in a timely manner, this test suite will be adversely affected.

If you suspect such a situation, attempt pulling some openshift images other than ruby-22-centos7
while this test is running and compare results.  Restarting your docker daemon, assuming you can ping docker.io quickly, could
be a quick fix.
*/

var _ = g.Describe("[builds] forcePull should affect pulling builder images", func() {
	defer g.GinkgoRecover()
	var oc = exutil.NewCLI("forcepull", exutil.KubeConfigPath())

	g.BeforeEach(func() {
		g.By("waiting for openshift/ruby:latest ImageStreamTag")
		err := exutil.WaitForAnImageStreamTag(oc, "openshift", "ruby", "latest")
		o.Expect(err).NotTo(o.HaveOccurred())

		// grant access to the custom build strategy
		g.By("granting system:build-strategy-custom")
		err = oc.AsAdmin().Run("adm").Args("policy", "add-cluster-role-to-user", "system:build-strategy-custom", oc.Username()).Execute()
		o.Expect(err).NotTo(o.HaveOccurred())

		defer func() {
			err = oc.AsAdmin().Run("adm").Args("policy", "remove-cluster-role-from-user", "system:build-strategy-custom", oc.Username()).Execute()
			o.Expect(err).NotTo(o.HaveOccurred())
		}()

		g.By("create application build configs for 3 strategies")
		apps := exutil.FixturePath("testdata", "forcepull-test.json")
		err = exutil.CreateResource(apps, oc)
		o.Expect(err).NotTo(o.HaveOccurred())

	})

	g.Context("ForcePull test context  ", func() {

		g.JustBeforeEach(func() {
			g.By("waiting for builder service account")
			err := exutil.WaitForBuilderAccount(oc.AdminKubeClient().Core().ServiceAccounts(oc.Namespace()))
			o.Expect(err).NotTo(o.HaveOccurred())
		})

		g.It("ForcePull test case execution s2i", func() {

			g.By("when s2i force pull is true")
			// run twice to ensure the builder image gets pulled even if it already exists on the node
			scrapeLogs(buildPrefixTS, oc)
			scrapeLogs(buildPrefixTS, oc)

		})

		g.It("ForcePull test case execution docker", func() {

			g.By("docker when force pull is true")
			// run twice to ensure the builder image gets pulled even if it already exists on the node
			scrapeLogs(buildPrefixTD, oc)
			scrapeLogs(buildPrefixTD, oc)

		})

		g.It("ForcePull test case execution custom", func() {

			g.By("when custom force pull is true")

			checkPodFlag(buildPrefixTC, oc)

		})

	})

})
<|endoftext|>


<commit_before>package main

import (
    "fmt"
    Logger "./logger"
    "github.com/bwmarrin/discordgo"
    "math/rand"
    "time"
    "strings"
    "regexp"
)

func onReady(session *discordgo.Session, event *discordgo.Ready) {
    Logger.INF("Connected to discord!")

    guilds, e := session.UserGuilds()
    if e == nil {
        channels := 0
        users := 0

        for _, guild := range guilds {
            channels += len(guild.Channels)
            users += len(guild.Members)
        }

        Logger.INF(fmt.Sprintf("Servers:%d | Channels:%d | Users:%d", len(guilds), channels, users))
    } else {
        Logger.ERR("Error retrieving stats")
        fmt.Println(e.Error())
    }

    fmt.Printf(
        "\n To add me to your discord server visit https://discordapp.com/oauth2/authorize?client_id=%s&scope=bot&permissions=%d\n\n",
        "249908516880515072",
        65535,
    )

    // Run async game-changer
    go changeGameInterval(session);
}

func onMessageCreate(session *discordgo.Session, message *discordgo.MessageCreate) {
    // Ignore other bots and @everyone/@here
    if (!message.Author.Bot && !message.MentionEveryone) {
        // We only do things in guilds.
        // Get a friend already and stop chatting with bots
        channel, _ := session.Channel(message.ChannelID)
        if (!channel.IsPrivate) {
            // Check if the message contains @mentions
            if (len(message.Mentions) >= 1) {
                // Check if someone is mentioning us
                if (message.Mentions[0].ID == session.State.User.ID) {
                    CCTV(message)

                    parts := strings.Split(message.Content, " ")
                    parts = append(parts[:0], parts[1:]...)

                    msg := strings.Trim(strings.Join(parts, " "), " ")

                    switch {
                    case regexp.MustCompile("^REFRESH CHAT SESSION$").Match(msg):
                        // Refresh cleverbot session
                        return

                    case regexp.MustCompile("^SET PREFIX (.){0,10}$").Match(msg):
                        // Set new prefix
                        return

                    default:
                        // Send to cleverbot
                        return
                    }
                }
            }

            // Check modules
        }
    }
}

func changeGameInterval(session *discordgo.Session) {
    for {
        session.UpdateStatus(0, games[rand.Intn(len(games))])
        time.Sleep(10 * time.Second)
    }
}

var games = []string{
    // Random stuff
    "async is the future!",
    "down with OOP!",
    "spoopy stuff",

    // Kaomoji
    "ʕ•ᴥ•ʔ",
    "༼ つ ◕_◕ ༽つ",
    "(ﾉ◕ヮ◕)ﾉ*:･ﾟ✧",
    "( ͡° ͜ʖ ͡°)",
    "¯\\_(ツ)_/¯",
    "(ง ͠° ͟ل͜ ͡°)ง",
    "ಠ_ಠ",
    "(╯°□°)╯︵ ʞooqǝɔɐɟ",
    "♪~ ᕕ(ᐛ)ᕗ",
    "\\ (•◡•) /",
    "｡◕‿◕｡",

    // actual games
    "Hearthstone",
    "Overwatch",
    "HuniePop",
    "Candy Crush",
    "Hyperdimension Neptunia",
    "Final Fantasy MCMX",
    "CIV V (forever!)",

    // software
    "with FFMPEG",
    "with libav",
    "with gophers",
    "with python",
    "with reflections",

    // names
    "with Shinobu-Chan",
    "with Ako-Chan",
    "with Nadeko",
    "with Miku",
    "with you O_o",
    "with cats",
    "with JOHN CENA",
    "with senpai",
    "with Serraniel#8978",
    "with 0xFADED#3237",
    "with C0untLizzi",
}<commit_msg>Add more random games<commit_after>package main

import (
    "fmt"
    Logger "./logger"
    "github.com/bwmarrin/discordgo"
    "math/rand"
    "time"
    "strings"
    "regexp"
)

func onReady(session *discordgo.Session, event *discordgo.Ready) {
    Logger.INF("Connected to discord!")

    guilds, e := session.UserGuilds()
    if e == nil {
        channels := 0
        users := 0

        for _, guild := range guilds {
            channels += len(guild.Channels)
            users += len(guild.Members)
        }

        Logger.INF(fmt.Sprintf("Servers:%d | Channels:%d | Users:%d", len(guilds), channels, users))
    } else {
        Logger.ERR("Error retrieving stats")
        fmt.Println(e.Error())
    }

    fmt.Printf(
        "\n To add me to your discord server visit https://discordapp.com/oauth2/authorize?client_id=%s&scope=bot&permissions=%d\n\n",
        "249908516880515072",
        65535,
    )

    // Run async game-changer
    go changeGameInterval(session);
}

func onMessageCreate(session *discordgo.Session, message *discordgo.MessageCreate) {
    // Ignore other bots and @everyone/@here
    if (!message.Author.Bot && !message.MentionEveryone) {
        // We only do things in guilds.
        // Get a friend already and stop chatting with bots
        channel, _ := session.Channel(message.ChannelID)
        if (!channel.IsPrivate) {
            // Check if the message contains @mentions
            if (len(message.Mentions) >= 1) {
                // Check if someone is mentioning us
                if (message.Mentions[0].ID == session.State.User.ID) {
                    CCTV(message)

                    parts := strings.Split(message.Content, " ")
                    parts = append(parts[:0], parts[1:]...)

                    msg := strings.Trim(strings.Join(parts, " "), " ")

                    switch {
                    case regexp.MustCompile("^REFRESH CHAT SESSION$").Match(msg):
                        // Refresh cleverbot session
                        return

                    case regexp.MustCompile("^SET PREFIX (.){0,10}$").Match(msg):
                        // Set new prefix
                        return

                    default:
                        // Send to cleverbot
                        return
                    }
                }
            }

            // Check modules
        }
    }
}

func changeGameInterval(session *discordgo.Session) {
    for {
        session.UpdateStatus(0, games[rand.Intn(len(games))])
        time.Sleep(10 * time.Second)
    }
}

var games = []string{
    // Random stuff
    "async is the future!",
    "down with OOP!",
    "spoopy stuff",
    "with human pets",
    "Planking",
    "Rare Pepe",

    // Kaomoji
    "ʕ•ᴥ•ʔ",
    "༼ つ ◕_◕ ༽つ",
    "(ﾉ◕ヮ◕)ﾉ*:･ﾟ✧",
    "( ͡° ͜ʖ ͡°)",
    "¯\\_(ツ)_/¯",
    "(ง ͠° ͟ل͜ ͡°)ง",
    "ಠ_ಠ",
    "(╯°□°)╯︵ ʞooqǝɔɐɟ",
    "♪~ ᕕ(ᐛ)ᕗ",
    "\\ (•◡•) /",
    "｡◕‿◕｡",

    // actual games
    "Hearthstone",
    "Overwatch",
    "HuniePop",
    "Candy Crush",
    "Hyperdimension Neptunia",
    "Final Fantasy MCMX",
    "CIV V (forever!)",
    "Pokemon Go",
    "Simulation Simulator 2016",
    "Half Life 3",

    // software
    "with FFMPEG",
    "with libav",
    "with gophers",
    "with python",
    "with reflections",

    // names
    "with Shinobu-Chan",
    "with Ako-Chan",
    "with Nadeko",
    "with Miku",
    "with you O_o",
    "with cats",
    "with JOHN CENA",
    "with senpai",
    "with Serraniel#8978",
    "with 0xFADED#3237",
    "with C0untLizzi",
    "with moot",
    "with your waifu",
    "with Trump",
}<|endoftext|>


<commit_before>/*
   Copyright The containerd 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 command

import (
	"fmt"
	"log"
	"os"
	"path/filepath"
	"time"
	"unsafe"

	"github.com/containerd/containerd/errdefs"
	"github.com/containerd/containerd/services/server"
	"github.com/sirupsen/logrus"
	"github.com/urfave/cli"
	exec "golang.org/x/sys/execabs"
	"golang.org/x/sys/windows"
	"golang.org/x/sys/windows/svc"
	"golang.org/x/sys/windows/svc/debug"
	"golang.org/x/sys/windows/svc/mgr"
)

var (
	serviceNameFlag       string
	registerServiceFlag   bool
	unregisterServiceFlag bool
	runServiceFlag        bool
	logFileFlag           string

	kernel32     = windows.NewLazySystemDLL("kernel32.dll")
	setStdHandle = kernel32.NewProc("SetStdHandle")
	allocConsole = kernel32.NewProc("AllocConsole")
	oldStderr    windows.Handle
	panicFile    *os.File
)

const defaultServiceName = "containerd"

// serviceFlags returns an array of flags for configuring containerd to run
// as a Windows service under control of SCM.
func serviceFlags() []cli.Flag {
	return []cli.Flag{
		cli.StringFlag{
			Name:  "service-name",
			Usage: "Set the Windows service name",
			Value: defaultServiceName,
		},
		cli.BoolFlag{
			Name:  "register-service",
			Usage: "Register the service and exit",
		},
		cli.BoolFlag{
			Name:  "unregister-service",
			Usage: "Unregister the service and exit",
		},
		cli.BoolFlag{
			Name:   "run-service",
			Usage:  "",
			Hidden: true,
		},
		cli.StringFlag{
			Name:  "log-file",
			Usage: "Path to the containerd log file",
		},
	}
}

// applyPlatformFlags applies platform-specific flags.
func applyPlatformFlags(context *cli.Context) {
	serviceNameFlag = context.GlobalString("service-name")
	if serviceNameFlag == "" {
		serviceNameFlag = defaultServiceName
	}
	for _, v := range []struct {
		name string
		d    *bool
	}{
		{
			name: "register-service",
			d:    &registerServiceFlag,
		},
		{
			name: "unregister-service",
			d:    &unregisterServiceFlag,
		},
		{
			name: "run-service",
			d:    &runServiceFlag,
		},
	} {
		*v.d = context.GlobalBool(v.name)
	}
	logFileFlag = context.GlobalString("log-file")
}

type handler struct {
	fromsvc chan error
	s       *server.Server
	done    chan struct{} // Indicates back to app main to quit
}

func getServicePath() (string, error) {
	p, err := exec.LookPath(os.Args[0])
	if err != nil {
		return "", err
	}
	return filepath.Abs(p)
}

func registerService() error {
	p, err := getServicePath()
	if err != nil {
		return err
	}
	m, err := mgr.Connect()
	if err != nil {
		return err
	}
	defer m.Disconnect()

	c := mgr.Config{
		ServiceType:  windows.SERVICE_WIN32_OWN_PROCESS,
		StartType:    mgr.StartAutomatic,
		ErrorControl: mgr.ErrorNormal,
		DisplayName:  "Containerd",
		Description:  "Container runtime",
	}

	// Configure the service to launch with the arguments that were just passed.
	args := []string{"--run-service"}
	for _, a := range os.Args[1:] {
		if a != "--register-service" && a != "--unregister-service" {
			args = append(args, a)
		}
	}

	s, err := m.CreateService(serviceNameFlag, p, c, args...)
	if err != nil {
		return err
	}
	defer s.Close()

	// See http://stackoverflow.com/questions/35151052/how-do-i-configure-failure-actions-of-a-windows-service-written-in-go
	const (
		scActionNone    = 0
		scActionRestart = 1

		serviceConfigFailureActions = 2
	)

	type serviceFailureActions struct {
		ResetPeriod  uint32
		RebootMsg    *uint16
		Command      *uint16
		ActionsCount uint32
		Actions      uintptr
	}

	type scAction struct {
		Type  uint32
		Delay uint32
	}
	t := []scAction{
		{Type: scActionRestart, Delay: uint32(15 * time.Second / time.Millisecond)},
		{Type: scActionRestart, Delay: uint32(15 * time.Second / time.Millisecond)},
		{Type: scActionNone},
	}
	lpInfo := serviceFailureActions{ResetPeriod: uint32(24 * time.Hour / time.Second), ActionsCount: uint32(3), Actions: uintptr(unsafe.Pointer(&t[0]))}
	err = windows.ChangeServiceConfig2(s.Handle, serviceConfigFailureActions, (*byte)(unsafe.Pointer(&lpInfo)))
	if err != nil {
		return err
	}

	return nil
}

func unregisterService() error {
	m, err := mgr.Connect()
	if err != nil {
		return err
	}
	defer m.Disconnect()

	s, err := m.OpenService(serviceNameFlag)
	if err != nil {
		return err
	}
	defer s.Close()

	err = s.Delete()
	if err != nil {
		return err
	}
	return nil
}

// registerUnregisterService is an entrypoint early in the daemon startup
// to handle (un-)registering against Windows Service Control Manager (SCM).
// It returns an indication to stop on successful SCM operation, and an error.
func registerUnregisterService(root string) (bool, error) {
	if unregisterServiceFlag {
		if registerServiceFlag {
			return true, fmt.Errorf("--register-service and --unregister-service cannot be used together: %w", errdefs.ErrInvalidArgument)
		}
		return true, unregisterService()
	}

	if registerServiceFlag {
		return true, registerService()
	}

	if runServiceFlag {
		// Allocate a conhost for containerd here. We don't actually use this
		// at all in containerd, but it will be inherited by any processes
		// containerd executes, so they won't need to allocate their own
		// conhosts. This is important for two reasons:
		// - Creating a conhost slows down process launch.
		// - We have seen reliability issues when launching many processes.
		//   Sometimes the process invocation will fail due to an error when
		//   creating the conhost.
		//
		// This needs to be done before initializing the panic file, as
		// AllocConsole sets the stdio handles to point to the new conhost,
		// and we want to make sure stderr goes to the panic file.
		r, _, err := allocConsole.Call()
		if r == 0 && err != nil {
			return true, fmt.Errorf("error allocating conhost: %w", err)
		}

		if err := initPanicFile(filepath.Join(root, "panic.log")); err != nil {
			return true, err
		}

		// The usual advice for Windows services is to either write to a log file or to the windows event
		// log, the former of which we've exposed here via a --log-file flag. We additionally write panic
		// stacks to a panic.log file to diagnose crashes. Below details the two different outcomes if
		// --log-file is specified or not:
		//
		// --log-file is *not* specified.
		// -------------------------------
		// -logrus, the stdlibs logging package and os.Stderr output will go to
		// NUL (Windows' /dev/null equivalent).
		// -Panics will write their stack trace to the panic.log file.
		// -Writing to the handle returned from GetStdHandle(STD_ERROR_HANDLE) will write
		// to the panic.log file as the underlying handle itself has been redirected.
		//
		// --log-file *is* specified
		// -------------------------------
		// -Logging to logrus, the stdlibs logging package or directly to
		// os.Stderr will all go to the log file specified.
		// -Panics will write their stack trace to the panic.log file.
		// -Writing to the handle returned from GetStdHandle(STD_ERROR_HANDLE) will write
		// to the panic.log file as the underlying handle itself has been redirected.
		var f *os.File
		if logFileFlag != "" {
			f, err = os.OpenFile(logFileFlag, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
			if err != nil {
				return true, fmt.Errorf("open log file %q: %w", logFileFlag, err)
			}
		} else {
			// Windows services start with NULL stdio handles, and thus os.Stderr and friends will be
			// backed by an os.File with a NULL handle. This means writes to os.Stderr will fail, which
			// isn't a huge issue as we want output to be discarded if the user doesn't ask for the log
			// file. However, writes succeeding but just going to the ether is a much better construct
			// so use devnull instead of relying on writes failing. We use devnull instead of io.Discard
			// as os.Stderr is an os.File and can't be assigned to io.Discard.
			f, err = os.OpenFile(os.DevNull, os.O_WRONLY, 0)
			if err != nil {
				return true, err
			}
		}
		// Reassign os.Stderr to the log file or NUL. Shim logs are copied to os.Stderr
		// directly so this ensures those will end up in the log file as well if specified.
		os.Stderr = f
		// Assign the stdlibs log package in case of any miscellaneous uses by
		// dependencies.
		log.SetOutput(f)
		logrus.SetOutput(f)
	}
	return false, nil
}

// launchService is the entry point for running the daemon under SCM.
func launchService(s *server.Server, done chan struct{}) error {
	if !runServiceFlag {
		return nil
	}

	h := &handler{
		fromsvc: make(chan error),
		s:       s,
		done:    done,
	}

	interactive, err := svc.IsAnInteractiveSession() // nolint:staticcheck
	if err != nil {
		return err
	}

	go func() {
		if interactive {
			err = debug.Run(serviceNameFlag, h)
		} else {
			err = svc.Run(serviceNameFlag, h)
		}
		h.fromsvc <- err
	}()

	// Wait for the first signal from the service handler.
	err = <-h.fromsvc
	if err != nil {
		return err
	}
	return nil
}

func (h *handler) Execute(_ []string, r <-chan svc.ChangeRequest, s chan<- svc.Status) (bool, uint32) {
	s <- svc.Status{State: svc.StartPending, Accepts: 0}
	// Unblock launchService()
	h.fromsvc <- nil

	s <- svc.Status{State: svc.Running, Accepts: svc.AcceptStop | svc.AcceptShutdown | svc.Accepted(windows.SERVICE_ACCEPT_PARAMCHANGE)}

Loop:
	for c := range r {
		switch c.Cmd {
		case svc.Interrogate:
			s <- c.CurrentStatus
		case svc.Stop, svc.Shutdown:
			s <- svc.Status{State: svc.StopPending, Accepts: 0}
			h.s.Stop()
			break Loop
		}
	}

	removePanicFile()
	close(h.done)
	return false, 0
}

func initPanicFile(path string) error {
	var err error
	panicFile, err = os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
	if err != nil {
		return err
	}

	st, err := panicFile.Stat()
	if err != nil {
		return err
	}

	// If there are contents in the file already, move the file out of the way
	// and replace it.
	if st.Size() > 0 {
		panicFile.Close()
		os.Rename(path, path+".old")
		panicFile, err = os.Create(path)
		if err != nil {
			return err
		}
	}

	// Update STD_ERROR_HANDLE to point to the panic file so that Go writes to
	// it when it panics. Remember the old stderr to restore it before removing
	// the panic file.
	sh := uint32(windows.STD_ERROR_HANDLE)
	h, err := windows.GetStdHandle(sh)
	if err != nil {
		return err
	}

	oldStderr = h

	r, _, err := setStdHandle.Call(uintptr(sh), panicFile.Fd())
	if r == 0 && err != nil {
		return err
	}

	return nil
}

func removePanicFile() {
	if st, err := panicFile.Stat(); err == nil {
		if st.Size() == 0 {
			sh := uint32(windows.STD_ERROR_HANDLE)
			setStdHandle.Call(uintptr(sh), uintptr(oldStderr))
			panicFile.Close()
			os.Remove(panicFile.Name())
		}
	}
}
<commit_msg>cmd/containerd: replace deprecated windows.IsAnInteractiveSession()<commit_after>/*
   Copyright The containerd 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 command

import (
	"fmt"
	"log"
	"os"
	"path/filepath"
	"time"
	"unsafe"

	"github.com/containerd/containerd/errdefs"
	"github.com/containerd/containerd/services/server"
	"github.com/sirupsen/logrus"
	"github.com/urfave/cli"
	exec "golang.org/x/sys/execabs"
	"golang.org/x/sys/windows"
	"golang.org/x/sys/windows/svc"
	"golang.org/x/sys/windows/svc/debug"
	"golang.org/x/sys/windows/svc/mgr"
)

var (
	serviceNameFlag       string
	registerServiceFlag   bool
	unregisterServiceFlag bool
	runServiceFlag        bool
	logFileFlag           string

	kernel32     = windows.NewLazySystemDLL("kernel32.dll")
	setStdHandle = kernel32.NewProc("SetStdHandle")
	allocConsole = kernel32.NewProc("AllocConsole")
	oldStderr    windows.Handle
	panicFile    *os.File
)

const defaultServiceName = "containerd"

// serviceFlags returns an array of flags for configuring containerd to run
// as a Windows service under control of SCM.
func serviceFlags() []cli.Flag {
	return []cli.Flag{
		cli.StringFlag{
			Name:  "service-name",
			Usage: "Set the Windows service name",
			Value: defaultServiceName,
		},
		cli.BoolFlag{
			Name:  "register-service",
			Usage: "Register the service and exit",
		},
		cli.BoolFlag{
			Name:  "unregister-service",
			Usage: "Unregister the service and exit",
		},
		cli.BoolFlag{
			Name:   "run-service",
			Usage:  "",
			Hidden: true,
		},
		cli.StringFlag{
			Name:  "log-file",
			Usage: "Path to the containerd log file",
		},
	}
}

// applyPlatformFlags applies platform-specific flags.
func applyPlatformFlags(context *cli.Context) {
	serviceNameFlag = context.GlobalString("service-name")
	if serviceNameFlag == "" {
		serviceNameFlag = defaultServiceName
	}
	for _, v := range []struct {
		name string
		d    *bool
	}{
		{
			name: "register-service",
			d:    &registerServiceFlag,
		},
		{
			name: "unregister-service",
			d:    &unregisterServiceFlag,
		},
		{
			name: "run-service",
			d:    &runServiceFlag,
		},
	} {
		*v.d = context.GlobalBool(v.name)
	}
	logFileFlag = context.GlobalString("log-file")
}

type handler struct {
	fromsvc chan error
	s       *server.Server
	done    chan struct{} // Indicates back to app main to quit
}

func getServicePath() (string, error) {
	p, err := exec.LookPath(os.Args[0])
	if err != nil {
		return "", err
	}
	return filepath.Abs(p)
}

func registerService() error {
	p, err := getServicePath()
	if err != nil {
		return err
	}
	m, err := mgr.Connect()
	if err != nil {
		return err
	}
	defer m.Disconnect()

	c := mgr.Config{
		ServiceType:  windows.SERVICE_WIN32_OWN_PROCESS,
		StartType:    mgr.StartAutomatic,
		ErrorControl: mgr.ErrorNormal,
		DisplayName:  "Containerd",
		Description:  "Container runtime",
	}

	// Configure the service to launch with the arguments that were just passed.
	args := []string{"--run-service"}
	for _, a := range os.Args[1:] {
		if a != "--register-service" && a != "--unregister-service" {
			args = append(args, a)
		}
	}

	s, err := m.CreateService(serviceNameFlag, p, c, args...)
	if err != nil {
		return err
	}
	defer s.Close()

	// See http://stackoverflow.com/questions/35151052/how-do-i-configure-failure-actions-of-a-windows-service-written-in-go
	const (
		scActionNone    = 0
		scActionRestart = 1

		serviceConfigFailureActions = 2
	)

	type serviceFailureActions struct {
		ResetPeriod  uint32
		RebootMsg    *uint16
		Command      *uint16
		ActionsCount uint32
		Actions      uintptr
	}

	type scAction struct {
		Type  uint32
		Delay uint32
	}
	t := []scAction{
		{Type: scActionRestart, Delay: uint32(15 * time.Second / time.Millisecond)},
		{Type: scActionRestart, Delay: uint32(15 * time.Second / time.Millisecond)},
		{Type: scActionNone},
	}
	lpInfo := serviceFailureActions{ResetPeriod: uint32(24 * time.Hour / time.Second), ActionsCount: uint32(3), Actions: uintptr(unsafe.Pointer(&t[0]))}
	err = windows.ChangeServiceConfig2(s.Handle, serviceConfigFailureActions, (*byte)(unsafe.Pointer(&lpInfo)))
	if err != nil {
		return err
	}

	return nil
}

func unregisterService() error {
	m, err := mgr.Connect()
	if err != nil {
		return err
	}
	defer m.Disconnect()

	s, err := m.OpenService(serviceNameFlag)
	if err != nil {
		return err
	}
	defer s.Close()

	err = s.Delete()
	if err != nil {
		return err
	}
	return nil
}

// registerUnregisterService is an entrypoint early in the daemon startup
// to handle (un-)registering against Windows Service Control Manager (SCM).
// It returns an indication to stop on successful SCM operation, and an error.
func registerUnregisterService(root string) (bool, error) {
	if unregisterServiceFlag {
		if registerServiceFlag {
			return true, fmt.Errorf("--register-service and --unregister-service cannot be used together: %w", errdefs.ErrInvalidArgument)
		}
		return true, unregisterService()
	}

	if registerServiceFlag {
		return true, registerService()
	}

	if runServiceFlag {
		// Allocate a conhost for containerd here. We don't actually use this
		// at all in containerd, but it will be inherited by any processes
		// containerd executes, so they won't need to allocate their own
		// conhosts. This is important for two reasons:
		// - Creating a conhost slows down process launch.
		// - We have seen reliability issues when launching many processes.
		//   Sometimes the process invocation will fail due to an error when
		//   creating the conhost.
		//
		// This needs to be done before initializing the panic file, as
		// AllocConsole sets the stdio handles to point to the new conhost,
		// and we want to make sure stderr goes to the panic file.
		r, _, err := allocConsole.Call()
		if r == 0 && err != nil {
			return true, fmt.Errorf("error allocating conhost: %w", err)
		}

		if err := initPanicFile(filepath.Join(root, "panic.log")); err != nil {
			return true, err
		}

		// The usual advice for Windows services is to either write to a log file or to the windows event
		// log, the former of which we've exposed here via a --log-file flag. We additionally write panic
		// stacks to a panic.log file to diagnose crashes. Below details the two different outcomes if
		// --log-file is specified or not:
		//
		// --log-file is *not* specified.
		// -------------------------------
		// -logrus, the stdlibs logging package and os.Stderr output will go to
		// NUL (Windows' /dev/null equivalent).
		// -Panics will write their stack trace to the panic.log file.
		// -Writing to the handle returned from GetStdHandle(STD_ERROR_HANDLE) will write
		// to the panic.log file as the underlying handle itself has been redirected.
		//
		// --log-file *is* specified
		// -------------------------------
		// -Logging to logrus, the stdlibs logging package or directly to
		// os.Stderr will all go to the log file specified.
		// -Panics will write their stack trace to the panic.log file.
		// -Writing to the handle returned from GetStdHandle(STD_ERROR_HANDLE) will write
		// to the panic.log file as the underlying handle itself has been redirected.
		var f *os.File
		if logFileFlag != "" {
			f, err = os.OpenFile(logFileFlag, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
			if err != nil {
				return true, fmt.Errorf("open log file %q: %w", logFileFlag, err)
			}
		} else {
			// Windows services start with NULL stdio handles, and thus os.Stderr and friends will be
			// backed by an os.File with a NULL handle. This means writes to os.Stderr will fail, which
			// isn't a huge issue as we want output to be discarded if the user doesn't ask for the log
			// file. However, writes succeeding but just going to the ether is a much better construct
			// so use devnull instead of relying on writes failing. We use devnull instead of io.Discard
			// as os.Stderr is an os.File and can't be assigned to io.Discard.
			f, err = os.OpenFile(os.DevNull, os.O_WRONLY, 0)
			if err != nil {
				return true, err
			}
		}
		// Reassign os.Stderr to the log file or NUL. Shim logs are copied to os.Stderr
		// directly so this ensures those will end up in the log file as well if specified.
		os.Stderr = f
		// Assign the stdlibs log package in case of any miscellaneous uses by
		// dependencies.
		log.SetOutput(f)
		logrus.SetOutput(f)
	}
	return false, nil
}

// launchService is the entry point for running the daemon under SCM.
func launchService(s *server.Server, done chan struct{}) error {
	if !runServiceFlag {
		return nil
	}

	h := &handler{
		fromsvc: make(chan error),
		s:       s,
		done:    done,
	}

	// Check if we're running as a Windows service or interactively.
	isService, err := svc.IsWindowsService()
	if err != nil {
		return err
	}

	go func() {
		if isService {
			err = svc.Run(serviceNameFlag, h)
		} else {
			err = debug.Run(serviceNameFlag, h)
		}
		h.fromsvc <- err
	}()

	// Wait for the first signal from the service handler.
	err = <-h.fromsvc
	if err != nil {
		return err
	}
	return nil
}

func (h *handler) Execute(_ []string, r <-chan svc.ChangeRequest, s chan<- svc.Status) (bool, uint32) {
	s <- svc.Status{State: svc.StartPending, Accepts: 0}
	// Unblock launchService()
	h.fromsvc <- nil

	s <- svc.Status{State: svc.Running, Accepts: svc.AcceptStop | svc.AcceptShutdown | svc.Accepted(windows.SERVICE_ACCEPT_PARAMCHANGE)}

Loop:
	for c := range r {
		switch c.Cmd {
		case svc.Interrogate:
			s <- c.CurrentStatus
		case svc.Stop, svc.Shutdown:
			s <- svc.Status{State: svc.StopPending, Accepts: 0}
			h.s.Stop()
			break Loop
		}
	}

	removePanicFile()
	close(h.done)
	return false, 0
}

func initPanicFile(path string) error {
	var err error
	panicFile, err = os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
	if err != nil {
		return err
	}

	st, err := panicFile.Stat()
	if err != nil {
		return err
	}

	// If there are contents in the file already, move the file out of the way
	// and replace it.
	if st.Size() > 0 {
		panicFile.Close()
		os.Rename(path, path+".old")
		panicFile, err = os.Create(path)
		if err != nil {
			return err
		}
	}

	// Update STD_ERROR_HANDLE to point to the panic file so that Go writes to
	// it when it panics. Remember the old stderr to restore it before removing
	// the panic file.
	sh := uint32(windows.STD_ERROR_HANDLE)
	h, err := windows.GetStdHandle(sh)
	if err != nil {
		return err
	}

	oldStderr = h

	r, _, err := setStdHandle.Call(uintptr(sh), panicFile.Fd())
	if r == 0 && err != nil {
		return err
	}

	return nil
}

func removePanicFile() {
	if st, err := panicFile.Stat(); err == nil {
		if st.Size() == 0 {
			sh := uint32(windows.STD_ERROR_HANDLE)
			setStdHandle.Call(uintptr(sh), uintptr(oldStderr))
			panicFile.Close()
			os.Remove(panicFile.Name())
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2012, 2013 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package main

import (
	gc "launchpad.net/gocheck"
	jc "github.com/juju/testing/checkers"

	jujutesting "launchpad.net/juju-core/juju/testing"
	"launchpad.net/juju-core/state"
	"launchpad.net/juju-core/state/api/params"
	"launchpad.net/juju-core/testing"
)

type resolveProvisioningErrorSuite struct {
	jujutesting.JujuConnSuite
}

var _ = gc.Suite(&resolveProvisioningErrorSuite{})

func runResolveProvisioningError(c *gc.C, args []string) error {
	_, err := testing.RunCommand(c, &ResolveProvisioningErrorCommand{}, args)
	return err
}

var resolvedMachineTests = []struct {
	args []string
	err  string
}{
	{
		err: `no machine specified`,
	}, {
		args: []string{"jeremy-fisher"},
		err:  `invalid machine "jeremy-fisher"`,
	}, {
		args: []string{"42"},
		err:  `machine 42 not found`,
	}, {
		args: []string{"1"},
		err:  `machine "machine-1" is not in an error state`,
	}, {
		args: []string{"0"},
	}, {
		args: []string{"0", "roflcopter"},
		err:  `unrecognized args: \["roflcopter"\]`,
	},
}

func (s *resolveProvisioningErrorSuite) TestResolved(c *gc.C) {
	m, err := s.State.AddOneMachine(state.MachineTemplate{
		Series:      "quantal",
		Jobs:        []state.MachineJob{state.JobManageEnviron},
	})
	c.Assert(err, gc.IsNil)
	err = m.SetStatus(params.StatusError, "broken", nil)
	c.Assert(err, gc.IsNil)
	_, err = s.State.AddOneMachine(state.MachineTemplate{
		Series:      "quantal",
		Jobs:        []state.MachineJob{state.JobHostUnits},
	})
	c.Assert(err, gc.IsNil)

	for i, t := range resolvedMachineTests {
		c.Logf("test %d: %v", i, t.args)
		err := runResolveProvisioningError(c, t.args)
		if t.err != "" {
			c.Check(err, gc.ErrorMatches, t.err)
		} else {
			status, info, data, err := m.Status()
			c.Check(err, gc.IsNil)
			c.Check(status, gc.Equals, params.StatusError)
			c.Check(info, gc.Equals, "broken")
			c.Check(data["transient"], jc.IsTrue)
		}
	}
}
<commit_msg>go fmt<commit_after>// Copyright 2012, 2013 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package main

import (
	jc "github.com/juju/testing/checkers"
	gc "launchpad.net/gocheck"

	jujutesting "launchpad.net/juju-core/juju/testing"
	"launchpad.net/juju-core/state"
	"launchpad.net/juju-core/state/api/params"
	"launchpad.net/juju-core/testing"
)

type resolveProvisioningErrorSuite struct {
	jujutesting.JujuConnSuite
}

var _ = gc.Suite(&resolveProvisioningErrorSuite{})

func runResolveProvisioningError(c *gc.C, args []string) error {
	_, err := testing.RunCommand(c, &ResolveProvisioningErrorCommand{}, args)
	return err
}

var resolvedMachineTests = []struct {
	args []string
	err  string
}{
	{
		err: `no machine specified`,
	}, {
		args: []string{"jeremy-fisher"},
		err:  `invalid machine "jeremy-fisher"`,
	}, {
		args: []string{"42"},
		err:  `machine 42 not found`,
	}, {
		args: []string{"1"},
		err:  `machine "machine-1" is not in an error state`,
	}, {
		args: []string{"0"},
	}, {
		args: []string{"0", "roflcopter"},
		err:  `unrecognized args: \["roflcopter"\]`,
	},
}

func (s *resolveProvisioningErrorSuite) TestResolved(c *gc.C) {
	m, err := s.State.AddOneMachine(state.MachineTemplate{
		Series: "quantal",
		Jobs:   []state.MachineJob{state.JobManageEnviron},
	})
	c.Assert(err, gc.IsNil)
	err = m.SetStatus(params.StatusError, "broken", nil)
	c.Assert(err, gc.IsNil)
	_, err = s.State.AddOneMachine(state.MachineTemplate{
		Series: "quantal",
		Jobs:   []state.MachineJob{state.JobHostUnits},
	})
	c.Assert(err, gc.IsNil)

	for i, t := range resolvedMachineTests {
		c.Logf("test %d: %v", i, t.args)
		err := runResolveProvisioningError(c, t.args)
		if t.err != "" {
			c.Check(err, gc.ErrorMatches, t.err)
		} else {
			status, info, data, err := m.Status()
			c.Check(err, gc.IsNil)
			c.Check(status, gc.Equals, params.StatusError)
			c.Check(info, gc.Equals, "broken")
			c.Check(data["transient"], jc.IsTrue)
		}
	}
}
<|endoftext|>


<commit_before>package ext

import (
	"errors"
	"time"

	"github.com/vmware/govmomi"
	"github.com/vmware/govmomi/vim25/methods"
	"github.com/vmware/govmomi/vim25/types"

	"github.com/lymingtonprecision/quorra/version"

	"golang.org/x/net/context"
)

const Key = "co.uk.lymingtonprecision.quorra"

type Extension struct {
	Client *govmomi.Client
	Object *types.Extension
}

func makeExtension() types.Extension {
	return types.Extension{
		Key: Key,
		Description: &types.Description{
			Label:   "Quorra",
			Summary: "A utility for managing CoreOS VMs on vSphere",
		},
		Company:                "Lymington Precision Engineers Co. Ltd.",
		LastHeartbeatTime:      time.Now(),
		Version:                version.Str(),
		ShownInSolutionManager: true,
		ExtendedProductInfo: &types.ExtExtendedProductInfo{
			CompanyUrl: "http://www.lymingtonprecision.co.uk/",
			ProductUrl: "https://github.com/lymingtonprecision/quorra",
		},
	}
}

func Register(cl *govmomi.Client) (*Extension, error) {
	_, ok := Get(cl)
	if ok {
		return nil, errors.New("extension already registered")
	}

	re := &types.RegisterExtension{
		This:      *cl.ServiceContent.ExtensionManager,
		Extension: makeExtension(),
	}

	_, err := methods.RegisterExtension(context.TODO(), cl, re)
	if err != nil {
		return nil, err
	}

	ex, ok := Get(cl)
	if !ok {
		return nil, errors.New("failed to get extension after registering")
	}

	return ex, nil
}

func Unregister(cl *govmomi.Client) error {
	ur := &types.UnregisterExtension{
		This:         *cl.ServiceContent.ExtensionManager,
		ExtensionKey: Key,
	}

	_, err := methods.UnregisterExtension(context.TODO(), cl, ur)
	if err != nil {
		return err
	}

	return nil
}

func Get(cl *govmomi.Client) (*Extension, bool) {
	fe := &types.FindExtension{
		This:         *cl.ServiceContent.ExtensionManager,
		ExtensionKey: Key,
	}

	r, err := methods.FindExtension(context.TODO(), cl, fe)
	if err != nil {
		panic(err)
	}

	if r.Returnval != nil {
		return &Extension{Client: cl, Object: r.Returnval}, true
	}

	return nil, false
}
<commit_msg>Add VirtualMachine managed entity to extension<commit_after>package ext

import (
	"errors"
	"time"

	"github.com/vmware/govmomi"
	"github.com/vmware/govmomi/vim25/methods"
	"github.com/vmware/govmomi/vim25/types"

	"github.com/lymingtonprecision/quorra/version"

	"golang.org/x/net/context"
)

const Key = "co.uk.lymingtonprecision.quorra"

type Extension struct {
	Client *govmomi.Client
	Object *types.Extension
}

func makeExtension() types.Extension {
	return types.Extension{
		Key: Key,
		Description: &types.Description{
			Label:   "Quorra",
			Summary: "A utility for managing CoreOS VMs on vSphere",
		},
		Company:                "Lymington Precision Engineers Co. Ltd.",
		LastHeartbeatTime:      time.Now(),
		Version:                version.Str(),
		ShownInSolutionManager: true,
		ExtendedProductInfo: &types.ExtExtendedProductInfo{
			CompanyUrl: "http://www.lymingtonprecision.co.uk/",
			ProductUrl: "https://github.com/lymingtonprecision/quorra",
		},
		ManagedEntityInfo: []types.ExtManagedEntityInfo{
			types.ExtManagedEntityInfo{
				Type:        "VirtualMachine",
				Description: "Virtual Machine",
			},
		},
	}
}

func Register(cl *govmomi.Client) (*Extension, error) {
	_, ok := Get(cl)
	if ok {
		return nil, errors.New("extension already registered")
	}

	re := &types.RegisterExtension{
		This:      *cl.ServiceContent.ExtensionManager,
		Extension: makeExtension(),
	}

	_, err := methods.RegisterExtension(context.TODO(), cl, re)
	if err != nil {
		return nil, err
	}

	ex, ok := Get(cl)
	if !ok {
		return nil, errors.New("failed to get extension after registering")
	}

	return ex, nil
}

func Unregister(cl *govmomi.Client) error {
	ur := &types.UnregisterExtension{
		This:         *cl.ServiceContent.ExtensionManager,
		ExtensionKey: Key,
	}

	_, err := methods.UnregisterExtension(context.TODO(), cl, ur)
	if err != nil {
		return err
	}

	return nil
}

func Get(cl *govmomi.Client) (*Extension, bool) {
	fe := &types.FindExtension{
		This:         *cl.ServiceContent.ExtensionManager,
		ExtensionKey: Key,
	}

	r, err := methods.FindExtension(context.TODO(), cl, fe)
	if err != nil {
		panic(err)
	}

	if r.Returnval != nil {
		return &Extension{Client: cl, Object: r.Returnval}, true
	}

	return nil, false
}
<|endoftext|>