<commit_before>package logs

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"net/url"
	"path/filepath"
	"strings"
	"time"

	"github.com/dokku/dokku/plugins/common"
	"github.com/joncalhoun/qson"
)

type vectorConfig struct {
	Sources map[string]vectorSource `json:"sources"`
	Sinks   map[string]vectorSink   `json:"sinks"`
}

type vectorSource struct {
	Type          string   `json:"type"`
	IncludeLabels []string `json:"include_labels,omitempty"`
}

type vectorSink map[string]interface{}

const vectorContainerName = "vector"

func killVectorContainer() error {
	if !common.ContainerExists(vectorContainerName) {
		return nil
	}

	if err := stopVectorContainer(); err != nil {
		return err
	}

	time.Sleep(10 * time.Second)
	if err := removeVectorContainer(); err != nil {
		return err
	}

	return nil
}

func removeVectorContainer() error {
	if !common.ContainerExists(vectorContainerName) {
		return nil
	}

	cmd := common.NewShellCmd(strings.Join([]string{
		common.DockerBin(), "container", "rm", "-f", vectorContainerName}, " "))

	return common.SuppressOutput(func() error {
		if cmd.Execute() {
			return nil
		}

		if common.ContainerExists(vectorContainerName) {
			return errors.New("Unable to remove vector container")
		}

		return nil
	})
}

func startVectorContainer(vectorImage string) error {
	cmd := common.NewShellCmd(strings.Join([]string{
		common.DockerBin(),
		"container",
		"run", "--detach", "--name", vectorContainerName, common.MustGetEnv("DOKKU_GLOBAL_RUN_ARGS"),
		"--restart", "unless-stopped",
		"--volume", "/var/lib/dokku/data/logs/vector.json:/etc/vector/vector.json",
		"--volume", "/var/run/docker.sock:/var/run/docker.sock",
		"--volume", common.MustGetEnv("DOKKU_LOGS_HOST_DIR") + ":/var/logs/dokku/apps",
		"--volume", common.MustGetEnv("DOKKU_LOGS_HOST_DIR") + "/apps:/var/log/dokku/apps",
		vectorImage,
		"--config", "/etc/vector/vector.json", "--watch-config"}, " "))
	cmd.ShowOutput = false

	if !cmd.Execute() {
		return errors.New("Unable to start vector container")
	}

	return nil
}

func stopVectorContainer() error {
	if !common.ContainerExists(vectorContainerName) {
		return nil
	}

	if !common.ContainerIsRunning(vectorContainerName) {
		return nil
	}

	cmd := common.NewShellCmd(strings.Join([]string{
		common.DockerBin(), "container", "stop", vectorContainerName}, " "))

	return common.SuppressOutput(func() error {
		if cmd.Execute() {
			return nil
		}

		if common.ContainerIsRunning(vectorContainerName) {
			return errors.New("Unable to stop vector container")
		}

		return nil
	})
}

func sinkValueToConfig(appName string, sinkValue string) (vectorSink, error) {
	var data vectorSink
	if strings.Contains(sinkValue, "://") {
		parts := strings.SplitN(sinkValue, "://", 2)
		parts[0] = strings.ReplaceAll(parts[0], "_", "-")
		sinkValue = strings.Join(parts, "://")
	}
	u, err := url.Parse(sinkValue)
	if err != nil {
		return data, err
	}

	if u.Query().Get("sinks") != "" {
		return data, errors.New("Invalid option sinks")
	}

	u.Scheme = strings.ReplaceAll(u.Scheme, "-", "_")

	query := u.RawQuery
	if strings.HasPrefix(query, "&") {
		query = strings.TrimPrefix(query, "&")
	}

	b, err := qson.ToJSON(query)
	if err != nil {
		return data, err
	}

	if err := json.Unmarshal(b, &data); err != nil {
		return data, err
	}

	data["type"] = u.Scheme
	data["inputs"] = []string{"docker-source:" + appName}
	if appName == "--global" {
		data["inputs"] = []string{"docker-global-source"}
	}
	if appName == "--null" {
		data["inputs"] = []string{"docker-null-source"}
	}

	return data, nil
}

func writeVectorConfig() error {
	apps, _ := common.UnfilteredDokkuApps()
	data := vectorConfig{
		Sources: map[string]vectorSource{},
		Sinks:   map[string]vectorSink{},
	}
	for _, appName := range apps {
		value := common.PropertyGet("logs", appName, "vector-sink")
		if value == "" {
			continue
		}

		appName = strings.ReplaceAll(appName, ".", "-")
		sink, err := sinkValueToConfig(appName, value)
		if err != nil {
			return err
		}

		data.Sources[fmt.Sprintf("docker-source:%s", appName)] = vectorSource{
			Type:          "docker_logs",
			IncludeLabels: []string{fmt.Sprintf("com.dokku.app-name=%s", appName)},
		}

		data.Sinks[fmt.Sprintf("docker-sink:%s", appName)] = sink
	}

	value := common.PropertyGet("logs", "--global", "vector-sink")
	if value != "" {
		sink, err := sinkValueToConfig("--global", value)
		if err != nil {
			return err
		}

		data.Sources["docker-global-source"] = vectorSource{
			Type:          "docker_logs",
			IncludeLabels: []string{"com.dokku.app-name"},
		}

		data.Sinks["docker-global-sink"] = sink
	}

	if len(data.Sources) == 0 {
		// pull from no containers
		data.Sources["docker-null-source"] = vectorSource{
			Type:          "docker_logs",
			IncludeLabels: []string{"com.dokku.vector-null"},
		}
	}

	if len(data.Sinks) == 0 {
		// write logs to a blackhole
		sink, err := sinkValueToConfig("--null", VectorDefaultSink)
		if err != nil {
			return err
		}

		data.Sinks["docker-null-sink"] = sink
	}

	b, err := json.MarshalIndent(data, "", "  ")
	if err != nil {
		return err
	}

	b = bytes.Replace(b, []byte("\\u0026"), []byte("&"), -1)

	vectorConfig := filepath.Join(common.MustGetEnv("DOKKU_LIB_ROOT"), "data", "logs", "vector.json")
	if err := common.WriteSliceToFile(vectorConfig, []string{string(b)}); err != nil {
		return err
	}

	return nil
}
<commit_msg>Revert "fix: Vector fails to start container due to --watch-config flag"<commit_after>package logs

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"net/url"
	"path/filepath"
	"strings"
	"time"

	"github.com/dokku/dokku/plugins/common"
	"github.com/joncalhoun/qson"
)

type vectorConfig struct {
	Sources map[string]vectorSource `json:"sources"`
	Sinks   map[string]vectorSink   `json:"sinks"`
}

type vectorSource struct {
	Type          string   `json:"type"`
	IncludeLabels []string `json:"include_labels,omitempty"`
}

type vectorSink map[string]interface{}

const vectorContainerName = "vector"

func killVectorContainer() error {
	if !common.ContainerExists(vectorContainerName) {
		return nil
	}

	if err := stopVectorContainer(); err != nil {
		return err
	}

	time.Sleep(10 * time.Second)
	if err := removeVectorContainer(); err != nil {
		return err
	}

	return nil
}

func removeVectorContainer() error {
	if !common.ContainerExists(vectorContainerName) {
		return nil
	}

	cmd := common.NewShellCmd(strings.Join([]string{
		common.DockerBin(), "container", "rm", "-f", vectorContainerName}, " "))

	return common.SuppressOutput(func() error {
		if cmd.Execute() {
			return nil
		}

		if common.ContainerExists(vectorContainerName) {
			return errors.New("Unable to remove vector container")
		}

		return nil
	})
}

func startVectorContainer(vectorImage string) error {
	cmd := common.NewShellCmd(strings.Join([]string{
		common.DockerBin(),
		"container",
		"run", "--detach", "--name", vectorContainerName, common.MustGetEnv("DOKKU_GLOBAL_RUN_ARGS"),
		"--restart", "unless-stopped",
		"--volume", "/var/lib/dokku/data/logs/vector.json:/etc/vector/vector.json",
		"--volume", "/var/run/docker.sock:/var/run/docker.sock",
		"--volume", common.MustGetEnv("DOKKU_LOGS_HOST_DIR") + ":/var/logs/dokku/apps",
		"--volume", common.MustGetEnv("DOKKU_LOGS_HOST_DIR") + "/apps:/var/log/dokku/apps",
		vectorImage,
		"--config", "/etc/vector/vector.json", "--watch-config", "1"}, " "))
	cmd.ShowOutput = false

	if !cmd.Execute() {
		return errors.New("Unable to start vector container")
	}

	return nil
}

func stopVectorContainer() error {
	if !common.ContainerExists(vectorContainerName) {
		return nil
	}

	if !common.ContainerIsRunning(vectorContainerName) {
		return nil
	}

	cmd := common.NewShellCmd(strings.Join([]string{
		common.DockerBin(), "container", "stop", vectorContainerName}, " "))

	return common.SuppressOutput(func() error {
		if cmd.Execute() {
			return nil
		}

		if common.ContainerIsRunning(vectorContainerName) {
			return errors.New("Unable to stop vector container")
		}

		return nil
	})
}

func sinkValueToConfig(appName string, sinkValue string) (vectorSink, error) {
	var data vectorSink
	if strings.Contains(sinkValue, "://") {
		parts := strings.SplitN(sinkValue, "://", 2)
		parts[0] = strings.ReplaceAll(parts[0], "_", "-")
		sinkValue = strings.Join(parts, "://")
	}
	u, err := url.Parse(sinkValue)
	if err != nil {
		return data, err
	}

	if u.Query().Get("sinks") != "" {
		return data, errors.New("Invalid option sinks")
	}

	u.Scheme = strings.ReplaceAll(u.Scheme, "-", "_")

	query := u.RawQuery
	if strings.HasPrefix(query, "&") {
		query = strings.TrimPrefix(query, "&")
	}

	b, err := qson.ToJSON(query)
	if err != nil {
		return data, err
	}

	if err := json.Unmarshal(b, &data); err != nil {
		return data, err
	}

	data["type"] = u.Scheme
	data["inputs"] = []string{"docker-source:" + appName}
	if appName == "--global" {
		data["inputs"] = []string{"docker-global-source"}
	}
	if appName == "--null" {
		data["inputs"] = []string{"docker-null-source"}
	}

	return data, nil
}

func writeVectorConfig() error {
	apps, _ := common.UnfilteredDokkuApps()
	data := vectorConfig{
		Sources: map[string]vectorSource{},
		Sinks:   map[string]vectorSink{},
	}
	for _, appName := range apps {
		value := common.PropertyGet("logs", appName, "vector-sink")
		if value == "" {
			continue
		}

		appName = strings.ReplaceAll(appName, ".", "-")
		sink, err := sinkValueToConfig(appName, value)
		if err != nil {
			return err
		}

		data.Sources[fmt.Sprintf("docker-source:%s", appName)] = vectorSource{
			Type:          "docker_logs",
			IncludeLabels: []string{fmt.Sprintf("com.dokku.app-name=%s", appName)},
		}

		data.Sinks[fmt.Sprintf("docker-sink:%s", appName)] = sink
	}

	value := common.PropertyGet("logs", "--global", "vector-sink")
	if value != "" {
		sink, err := sinkValueToConfig("--global", value)
		if err != nil {
			return err
		}

		data.Sources["docker-global-source"] = vectorSource{
			Type:          "docker_logs",
			IncludeLabels: []string{"com.dokku.app-name"},
		}

		data.Sinks["docker-global-sink"] = sink
	}

	if len(data.Sources) == 0 {
		// pull from no containers
		data.Sources["docker-null-source"] = vectorSource{
			Type:          "docker_logs",
			IncludeLabels: []string{"com.dokku.vector-null"},
		}
	}

	if len(data.Sinks) == 0 {
		// write logs to a blackhole
		sink, err := sinkValueToConfig("--null", VectorDefaultSink)
		if err != nil {
			return err
		}

		data.Sinks["docker-null-sink"] = sink
	}

	b, err := json.MarshalIndent(data, "", "  ")
	if err != nil {
		return err
	}

	b = bytes.Replace(b, []byte("\\u0026"), []byte("&"), -1)

	vectorConfig := filepath.Join(common.MustGetEnv("DOKKU_LIB_ROOT"), "data", "logs", "vector.json")
	if err := common.WriteSliceToFile(vectorConfig, []string{string(b)}); err != nil {
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>/*
Copyright 2017 Jetstack Ltd.
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 certificate

import (
	"flag"

	"github.com/jetstack/cert-manager/test/util/generate"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	corev1 "k8s.io/api/core/v1"
	apierrors "k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

	"github.com/jetstack/cert-manager/pkg/apis/certmanager/v1alpha1"
	cmutil "github.com/jetstack/cert-manager/pkg/util"
	"github.com/jetstack/cert-manager/test/e2e/framework"
	"github.com/jetstack/cert-manager/test/util"
)

var cloudflareEmail string
var cloudflareAPIKey string

func init() {
	flag.StringVar(&cloudflareEmail, "cloudflare-email", "", ""+
		"The cloud API email address. If not specified, DNS tests will be skipped")
	flag.StringVar(&cloudflareAPIKey, "cloudflare-api-key", "", ""+
		"The cloudflare API key. If not specified, DNS tests will be skipped")
}

var _ = framework.CertManagerDescribe("ACME Certificate (DNS01)", func() {
	f := framework.NewDefaultFramework("create-acme-certificate-dns01")

	issuerName := "test-acme-issuer"
	certificateName := "test-acme-certificate"
	certificateSecretName := "test-acme-certificate"
	cloudflareSecretName := "cloudflare-api-token"

	BeforeEach(func() {
		if cloudflareAPIKey == "" {
			framework.Skipf("Skipping DNS01 provider tests as cloudflare api key is blank")
			return
		}

		By("Verifying there is no existing ACME private key")
		_, err := f.KubeClientSet.CoreV1().Secrets(f.Namespace.Name).Get(testingACMEPrivateKey, metav1.GetOptions{})
		Expect(err).To(MatchError(apierrors.NewNotFound(corev1.Resource("secrets"), testingACMEPrivateKey)))
		By("Verifying there is no existing TLS certificate secret")
		_, err = f.KubeClientSet.CoreV1().Secrets(f.Namespace.Name).Get(certificateSecretName, metav1.GetOptions{})
		Expect(err).To(MatchError(apierrors.NewNotFound(corev1.Resource("secrets"), certificateSecretName)))

		By("Creating the cloudflare api key fixture")
		cfSecret := &corev1.Secret{
			ObjectMeta: metav1.ObjectMeta{
				Name:      cloudflareSecretName,
				Namespace: f.Namespace.Name,
			},
			Data: map[string][]byte{
				"api-key": []byte(cloudflareAPIKey),
			},
		}
		_, err = f.KubeClientSet.CoreV1().Secrets(cfSecret.Namespace).Create(cfSecret)
		Expect(err).NotTo(HaveOccurred())

		By("Creating an Issuer")
		issuer := generate.Issuer(generate.IssuerConfig{
			Name:              issuerName,
			Namespace:         f.Namespace.Name,
			ACMESkipTLSVerify: true,
			// Hardcode this to the acme staging endpoint now due to issues with pebble dns resolution
			ACMEServer: "https://acme-staging-v02.api.letsencrypt.org/directory",
			// ACMEServer:         framework.TestContext.ACMEURL,
			ACMEEmail:          testingACMEEmail,
			ACMEPrivateKeyName: testingACMEPrivateKey,
			DNS01: &v1alpha1.ACMEIssuerDNS01Config{
				Providers: []v1alpha1.ACMEIssuerDNS01Provider{
					{
						Name: "cloudflare",
						Cloudflare: &v1alpha1.ACMEIssuerDNS01ProviderCloudflare{
							Email: cloudflareEmail,
							APIKey: v1alpha1.SecretKeySelector{
								LocalObjectReference: v1alpha1.LocalObjectReference{
									Name: cloudflareSecretName,
								},
								Key: "api-key",
							},
						},
					},
				},
			},
		})
		issuer, err = f.CertManagerClientSet.CertmanagerV1alpha1().Issuers(f.Namespace.Name).Create(issuer)
		Expect(err).NotTo(HaveOccurred())
		By("Waiting for Issuer to become Ready")
		err = util.WaitForIssuerCondition(f.CertManagerClientSet.CertmanagerV1alpha1().Issuers(f.Namespace.Name),
			issuerName,
			v1alpha1.IssuerCondition{
				Type:   v1alpha1.IssuerConditionReady,
				Status: v1alpha1.ConditionTrue,
			})
		Expect(err).NotTo(HaveOccurred())
		By("Verifying the ACME account URI is set")
		err = util.WaitForIssuerStatusFunc(f.CertManagerClientSet.CertmanagerV1alpha1().Issuers(f.Namespace.Name),
			issuerName,
			func(i *v1alpha1.Issuer) (bool, error) {
				if i.GetStatus().ACMEStatus().URI == "" {
					return false, nil
				}
				return true, nil
			})
		Expect(err).NotTo(HaveOccurred())
		By("Verifying ACME account private key exists")
		secret, err := f.KubeClientSet.CoreV1().Secrets(f.Namespace.Name).Get(testingACMEPrivateKey, metav1.GetOptions{})
		Expect(err).NotTo(HaveOccurred())
		if len(secret.Data) != 1 {
			Fail("Expected 1 key in ACME account private key secret, but there was %d", len(secret.Data))
		}
	})

	AfterEach(func() {
		By("Cleaning up")
		f.CertManagerClientSet.CertmanagerV1alpha1().Issuers(f.Namespace.Name).Delete(issuerName, nil)
		f.KubeClientSet.CoreV1().Secrets(f.Namespace.Name).Delete(testingACMEPrivateKey, nil)
		f.KubeClientSet.CoreV1().Secrets(f.Namespace.Name).Delete(cloudflareSecretName, nil)
		f.KubeClientSet.CoreV1().Secrets(f.Namespace.Name).Delete(certificateSecretName, nil)
	})

	It("should obtain a signed certificate for a regular domain", func() {
		By("Creating a Certificate")
		dnsName := cmutil.RandStringRunes(5) + "." + util.ACMECloudflareDomain
		cert := generate.Certificate(generate.CertificateConfig{
			Name:       certificateName,
			Namespace:  f.Namespace.Name,
			SecretName: certificateSecretName,
			IssuerName: issuerName,
			DNSNames:   []string{dnsName},
			ACMESolverConfig: v1alpha1.ACMESolverConfig{
				DNS01: &v1alpha1.ACMECertificateDNS01Config{
					Provider: "cloudflare",
				},
			},
		})
		cert, err := f.CertManagerClientSet.CertmanagerV1alpha1().Certificates(f.Namespace.Name).Create(cert)
		Expect(err).NotTo(HaveOccurred())
		f.WaitCertificateIssuedValid(cert)
	})

	It("should obtain a signed certificate for a wildcard domain", func() {
		By("Creating a Certificate")
		dnsName := cmutil.RandStringRunes(5) + "." + util.ACMECloudflareDomain
		cert := generate.Certificate(generate.CertificateConfig{
			Name:       certificateName,
			Namespace:  f.Namespace.Name,
			SecretName: certificateSecretName,
			IssuerName: issuerName,
			DNSNames:   []string{"*." + dnsName},
			ACMESolverConfig: v1alpha1.ACMESolverConfig{
				DNS01: &v1alpha1.ACMECertificateDNS01Config{
					Provider: "cloudflare",
				},
			},
		})
		cert, err := f.CertManagerClientSet.CertmanagerV1alpha1().Certificates(f.Namespace.Name).Create(cert)
		Expect(err).NotTo(HaveOccurred())
		f.WaitCertificateIssuedValid(cert)
	})
})
<commit_msg>Add e2e test for wildcard with apex domain<commit_after>/*
Copyright 2017 Jetstack Ltd.
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 certificate

import (
	"flag"

	"github.com/jetstack/cert-manager/test/util/generate"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	corev1 "k8s.io/api/core/v1"
	apierrors "k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

	"github.com/jetstack/cert-manager/pkg/apis/certmanager/v1alpha1"
	cmutil "github.com/jetstack/cert-manager/pkg/util"
	"github.com/jetstack/cert-manager/test/e2e/framework"
	"github.com/jetstack/cert-manager/test/util"
)

var cloudflareEmail string
var cloudflareAPIKey string

func init() {
	flag.StringVar(&cloudflareEmail, "cloudflare-email", "", ""+
		"The cloud API email address. If not specified, DNS tests will be skipped")
	flag.StringVar(&cloudflareAPIKey, "cloudflare-api-key", "", ""+
		"The cloudflare API key. If not specified, DNS tests will be skipped")
}

var _ = framework.CertManagerDescribe("ACME Certificate (DNS01)", func() {
	f := framework.NewDefaultFramework("create-acme-certificate-dns01")

	issuerName := "test-acme-issuer"
	certificateName := "test-acme-certificate"
	certificateSecretName := "test-acme-certificate"
	cloudflareSecretName := "cloudflare-api-token"

	BeforeEach(func() {
		if cloudflareAPIKey == "" {
			framework.Skipf("Skipping DNS01 provider tests as cloudflare api key is blank")
			return
		}

		By("Verifying there is no existing ACME private key")
		_, err := f.KubeClientSet.CoreV1().Secrets(f.Namespace.Name).Get(testingACMEPrivateKey, metav1.GetOptions{})
		Expect(err).To(MatchError(apierrors.NewNotFound(corev1.Resource("secrets"), testingACMEPrivateKey)))
		By("Verifying there is no existing TLS certificate secret")
		_, err = f.KubeClientSet.CoreV1().Secrets(f.Namespace.Name).Get(certificateSecretName, metav1.GetOptions{})
		Expect(err).To(MatchError(apierrors.NewNotFound(corev1.Resource("secrets"), certificateSecretName)))

		By("Creating the cloudflare api key fixture")
		cfSecret := &corev1.Secret{
			ObjectMeta: metav1.ObjectMeta{
				Name:      cloudflareSecretName,
				Namespace: f.Namespace.Name,
			},
			Data: map[string][]byte{
				"api-key": []byte(cloudflareAPIKey),
			},
		}
		_, err = f.KubeClientSet.CoreV1().Secrets(cfSecret.Namespace).Create(cfSecret)
		Expect(err).NotTo(HaveOccurred())

		By("Creating an Issuer")
		issuer := generate.Issuer(generate.IssuerConfig{
			Name:              issuerName,
			Namespace:         f.Namespace.Name,
			ACMESkipTLSVerify: true,
			// Hardcode this to the acme staging endpoint now due to issues with pebble dns resolution
			ACMEServer: "https://acme-staging-v02.api.letsencrypt.org/directory",
			// ACMEServer:         framework.TestContext.ACMEURL,
			ACMEEmail:          testingACMEEmail,
			ACMEPrivateKeyName: testingACMEPrivateKey,
			DNS01: &v1alpha1.ACMEIssuerDNS01Config{
				Providers: []v1alpha1.ACMEIssuerDNS01Provider{
					{
						Name: "cloudflare",
						Cloudflare: &v1alpha1.ACMEIssuerDNS01ProviderCloudflare{
							Email: cloudflareEmail,
							APIKey: v1alpha1.SecretKeySelector{
								LocalObjectReference: v1alpha1.LocalObjectReference{
									Name: cloudflareSecretName,
								},
								Key: "api-key",
							},
						},
					},
				},
			},
		})
		issuer, err = f.CertManagerClientSet.CertmanagerV1alpha1().Issuers(f.Namespace.Name).Create(issuer)
		Expect(err).NotTo(HaveOccurred())
		By("Waiting for Issuer to become Ready")
		err = util.WaitForIssuerCondition(f.CertManagerClientSet.CertmanagerV1alpha1().Issuers(f.Namespace.Name),
			issuerName,
			v1alpha1.IssuerCondition{
				Type:   v1alpha1.IssuerConditionReady,
				Status: v1alpha1.ConditionTrue,
			})
		Expect(err).NotTo(HaveOccurred())
		By("Verifying the ACME account URI is set")
		err = util.WaitForIssuerStatusFunc(f.CertManagerClientSet.CertmanagerV1alpha1().Issuers(f.Namespace.Name),
			issuerName,
			func(i *v1alpha1.Issuer) (bool, error) {
				if i.GetStatus().ACMEStatus().URI == "" {
					return false, nil
				}
				return true, nil
			})
		Expect(err).NotTo(HaveOccurred())
		By("Verifying ACME account private key exists")
		secret, err := f.KubeClientSet.CoreV1().Secrets(f.Namespace.Name).Get(testingACMEPrivateKey, metav1.GetOptions{})
		Expect(err).NotTo(HaveOccurred())
		if len(secret.Data) != 1 {
			Fail("Expected 1 key in ACME account private key secret, but there was %d", len(secret.Data))
		}
	})

	AfterEach(func() {
		By("Cleaning up")
		f.CertManagerClientSet.CertmanagerV1alpha1().Issuers(f.Namespace.Name).Delete(issuerName, nil)
		f.KubeClientSet.CoreV1().Secrets(f.Namespace.Name).Delete(testingACMEPrivateKey, nil)
		f.KubeClientSet.CoreV1().Secrets(f.Namespace.Name).Delete(cloudflareSecretName, nil)
		f.KubeClientSet.CoreV1().Secrets(f.Namespace.Name).Delete(certificateSecretName, nil)
	})

	It("should obtain a signed certificate for a regular domain", func() {
		By("Creating a Certificate")
		dnsName := cmutil.RandStringRunes(5) + "." + util.ACMECloudflareDomain
		cert := generate.Certificate(generate.CertificateConfig{
			Name:       certificateName,
			Namespace:  f.Namespace.Name,
			SecretName: certificateSecretName,
			IssuerName: issuerName,
			DNSNames:   []string{dnsName},
			ACMESolverConfig: v1alpha1.ACMESolverConfig{
				DNS01: &v1alpha1.ACMECertificateDNS01Config{
					Provider: "cloudflare",
				},
			},
		})
		cert, err := f.CertManagerClientSet.CertmanagerV1alpha1().Certificates(f.Namespace.Name).Create(cert)
		Expect(err).NotTo(HaveOccurred())
		f.WaitCertificateIssuedValid(cert)
	})

	It("should obtain a signed certificate for a wildcard domain", func() {
		By("Creating a Certificate")
		dnsName := cmutil.RandStringRunes(5) + "." + util.ACMECloudflareDomain
		cert := generate.Certificate(generate.CertificateConfig{
			Name:       certificateName,
			Namespace:  f.Namespace.Name,
			SecretName: certificateSecretName,
			IssuerName: issuerName,
			DNSNames:   []string{"*." + dnsName},
			ACMESolverConfig: v1alpha1.ACMESolverConfig{
				DNS01: &v1alpha1.ACMECertificateDNS01Config{
					Provider: "cloudflare",
				},
			},
		})
		cert, err := f.CertManagerClientSet.CertmanagerV1alpha1().Certificates(f.Namespace.Name).Create(cert)
		Expect(err).NotTo(HaveOccurred())
		f.WaitCertificateIssuedValid(cert)
	})

	It("should obtain a signed certificate for a wildcard and apex domain", func() {
		By("Creating a Certificate")
		dnsName := cmutil.RandStringRunes(5) + "." + util.ACMECloudflareDomain
		cert := generate.Certificate(generate.CertificateConfig{
			Name:       certificateName,
			Namespace:  f.Namespace.Name,
			SecretName: certificateSecretName,
			IssuerName: issuerName,
			DNSNames:   []string{"*." + dnsName, dnsName},
			ACMESolverConfig: v1alpha1.ACMESolverConfig{
				DNS01: &v1alpha1.ACMECertificateDNS01Config{
					Provider: "cloudflare",
				},
			},
		})
		cert, err := f.CertManagerClientSet.CertmanagerV1alpha1().Certificates(f.Namespace.Name).Create(cert)
		Expect(err).NotTo(HaveOccurred())
		f.WaitCertificateIssuedValid(cert)
	})
})
<|endoftext|>


<commit_before>/*
Copyright 2015 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 network

// Tests network performance using iperf or other containers.
import (
	"fmt"
	"time"

	"github.com/onsi/ginkgo"
	v1 "k8s.io/api/core/v1"
	"k8s.io/kubernetes/test/e2e/framework"
	e2enode "k8s.io/kubernetes/test/e2e/framework/node"
	e2eservice "k8s.io/kubernetes/test/e2e/framework/service"
	e2eskipper "k8s.io/kubernetes/test/e2e/framework/skipper"
	imageutils "k8s.io/kubernetes/test/utils/image"
)

const (
	// empirically derived as a baseline for expectations from running this test using kube-up.sh.
	gceBandwidthBitsEstimate = int64(30000000000)
	// on 4 node clusters, we found this test passes very quickly, generally in less then 100 seconds.
	smallClusterTimeout = 200 * time.Second
)

// networkingIPerf test runs iperf on a container in either IPv4 or IPv6 mode.
func networkingIPerfTest(isIPv6 bool) {

	f := framework.NewDefaultFramework("network-perf")

	// A few simple bandwidth tests which are capped by nodes.
	// TODO replace the 1 with the scale option implementation
	// TODO: Make this a function parameter, once we distribute iperf endpoints, possibly via session affinity.
	numClient := 1
	numServer := 1
	maxBandwidthBits := gceBandwidthBitsEstimate

	familyStr := ""
	if isIPv6 {
		familyStr = "-V "
	}

	ginkgo.It(fmt.Sprintf("should transfer ~ 1GB onto the service endpoint %v servers (maximum of %v clients)", numServer, numClient), func() {
		nodes, err := e2enode.GetReadySchedulableNodes(f.ClientSet)
		framework.ExpectNoError(err)
		totalPods := len(nodes.Items)
		// for a single service, we expect to divide bandwidth between the network.  Very crude estimate.
		expectedBandwidth := int(float64(maxBandwidthBits) / float64(totalPods))
		appName := "iperf-e2e"
		_, err = e2eservice.CreateServiceForSimpleAppWithPods(
			f.ClientSet,
			8001,
			8002,
			f.Namespace.Name,
			appName,
			func(n v1.Node) v1.PodSpec {
				return v1.PodSpec{
					Containers: []v1.Container{{
						Name:    "iperf-server",
						Image:   imageutils.GetE2EImage(imageutils.Agnhost),
						Command: []string{"/bin/sh"},
						Args: []string{
							"-c",
							"/usr/local/bin/iperf " + familyStr + "-s -p 8001 ",
						},
						Ports: []v1.ContainerPort{{ContainerPort: 8001}},
					}},
					NodeName:      n.Name,
					RestartPolicy: v1.RestartPolicyOnFailure,
				}
			},
			// this will be used to generate the -service name which all iperf clients point at.
			numServer, // Generally should be 1 server unless we do affinity or use a version of iperf that supports LB
			true,      // Make sure we wait, otherwise all the clients will die and need to restart.
		)

		if err != nil {
			framework.Failf("Fatal error waiting for iperf server endpoint : %v", err)
		}

		iperfClientPodLabels := e2enode.CreatePodsPerNodeForSimpleApp(
			f.ClientSet,
			f.Namespace.Name,
			"iperf-e2e-cli",
			func(n v1.Node) v1.PodSpec {
				return v1.PodSpec{
					Containers: []v1.Container{
						{
							Name:    "iperf-client",
							Image:   imageutils.GetE2EImage(imageutils.Agnhost),
							Command: []string{"/bin/sh"},
							Args: []string{
								"-c",
								"/usr/local/bin/iperf " + familyStr + "-c service-for-" + appName + " -p 8002 --reportstyle C && sleep 5",
							},
						},
					},
					RestartPolicy: v1.RestartPolicyOnFailure, // let them successfully die.
				}
			},
			numClient,
		)
		expectedCli := numClient
		if len(nodes.Items) < expectedCli {
			expectedCli = len(nodes.Items)
		}

		framework.Logf("Reading all perf results to stdout.")
		framework.Logf("date,cli,cliPort,server,serverPort,id,interval,transferBits,bandwidthBits")

		// Extra 1/10 second per client.
		iperfTimeout := smallClusterTimeout + (time.Duration(expectedCli/10) * time.Second)
		iperfResults := &IPerfResults{}

		iperfClusterVerification := f.NewClusterVerification(
			f.Namespace,
			framework.PodStateVerification{
				Selectors:   iperfClientPodLabels,
				ValidPhases: []v1.PodPhase{v1.PodSucceeded},
			},
		)

		pods, err2 := iperfClusterVerification.WaitFor(expectedCli, iperfTimeout)
		if err2 != nil {
			framework.Failf("Error in wait...")
		} else if len(pods) < expectedCli {
			framework.Failf("IPerf restuls : Only got %v out of %v, after waiting %v", len(pods), expectedCli, iperfTimeout)
		} else {
			// For each builds up a collection of IPerfRecords
			iperfClusterVerification.ForEach(
				func(p v1.Pod) {
					resultS, err := framework.LookForStringInLog(f.Namespace.Name, p.Name, "iperf-client", "0-", 1*time.Second)
					if err == nil {
						framework.Logf(resultS)
						iperfResults.Add(NewIPerf(resultS))
					} else {
						framework.Failf("Unexpected error, %v when running forEach on the pods.", err)
					}
				})
		}
		fmt.Println("[begin] Node,Bandwidth CSV")
		fmt.Println(iperfResults.ToTSV())
		fmt.Println("[end] Node,Bandwidth CSV")

		for ipClient, bandwidth := range iperfResults.BandwidthMap {
			framework.Logf("%v had bandwidth %v.  Ratio to expected (%v) was %f", ipClient, bandwidth, expectedBandwidth, float64(bandwidth)/float64(expectedBandwidth))
		}
	})
}

// Declared as Flakey since it has not been proven to run in parallel on small nodes or slow networks in CI
// TODO jayunit100 : Retag this test according to semantics from #22401
var _ = SIGDescribe("Networking IPerf IPv4 [Experimental] [Feature:Networking-IPv4] [Slow] [Feature:Networking-Performance]", func() {
	networkingIPerfTest(false)
})

// Declared as Flakey since it has not been proven to run in parallel on small nodes or slow networks in CI
// TODO jayunit100 : Retag this test according to semantics from #22401
var _ = SIGDescribe("Networking IPerf IPv6 [Experimental] [Feature:Networking-IPv6] [Slow] [Feature:Networking-Performance] [LinuxOnly]", func() {
	// IPv6 is not supported on Windows.
	e2eskipper.SkipIfNodeOSDistroIs("windows")
	networkingIPerfTest(true)
})
<commit_msg>remove iperf e2e test ip family tags<commit_after>/*
Copyright 2015 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 network

// Tests network performance using iperf or other containers.
import (
	"fmt"
	"time"

	"github.com/onsi/ginkgo"
	v1 "k8s.io/api/core/v1"
	"k8s.io/kubernetes/test/e2e/framework"
	e2enode "k8s.io/kubernetes/test/e2e/framework/node"
	e2eservice "k8s.io/kubernetes/test/e2e/framework/service"
	imageutils "k8s.io/kubernetes/test/utils/image"
)

const (
	// empirically derived as a baseline for expectations from running this test using kube-up.sh.
	gceBandwidthBitsEstimate = int64(30000000000)
	// on 4 node clusters, we found this test passes very quickly, generally in less then 100 seconds.
	smallClusterTimeout = 200 * time.Second
)

// Declared as Flakey since it has not been proven to run in parallel on small nodes or slow networks in CI
var _ = SIGDescribe("Networking IPerf [Experimental] [Slow] [Feature:Networking-Performance]", func() {

	f := framework.NewDefaultFramework("network-perf")

	// A few simple bandwidth tests which are capped by nodes.
	// TODO replace the 1 with the scale option implementation
	// TODO: Make this a function parameter, once we distribute iperf endpoints, possibly via session affinity.
	numClient := 1
	numServer := 1
	maxBandwidthBits := gceBandwidthBitsEstimate

	familyStr := ""
	if framework.TestContext.ClusterIsIPv6() {
		familyStr = "-V "
	}

	ginkgo.It(fmt.Sprintf("should transfer ~ 1GB onto the service endpoint %v servers (maximum of %v clients)", numServer, numClient), func() {
		nodes, err := e2enode.GetReadySchedulableNodes(f.ClientSet)
		framework.ExpectNoError(err)
		totalPods := len(nodes.Items)
		// for a single service, we expect to divide bandwidth between the network.  Very crude estimate.
		expectedBandwidth := int(float64(maxBandwidthBits) / float64(totalPods))
		appName := "iperf-e2e"
		_, err = e2eservice.CreateServiceForSimpleAppWithPods(
			f.ClientSet,
			8001,
			8002,
			f.Namespace.Name,
			appName,
			func(n v1.Node) v1.PodSpec {
				return v1.PodSpec{
					Containers: []v1.Container{{
						Name:    "iperf-server",
						Image:   imageutils.GetE2EImage(imageutils.Agnhost),
						Command: []string{"/bin/sh"},
						Args: []string{
							"-c",
							"/usr/local/bin/iperf " + familyStr + "-s -p 8001 ",
						},
						Ports: []v1.ContainerPort{{ContainerPort: 8001}},
					}},
					NodeName:      n.Name,
					RestartPolicy: v1.RestartPolicyOnFailure,
				}
			},
			// this will be used to generate the -service name which all iperf clients point at.
			numServer, // Generally should be 1 server unless we do affinity or use a version of iperf that supports LB
			true,      // Make sure we wait, otherwise all the clients will die and need to restart.
		)

		if err != nil {
			framework.Failf("Fatal error waiting for iperf server endpoint : %v", err)
		}

		iperfClientPodLabels := e2enode.CreatePodsPerNodeForSimpleApp(
			f.ClientSet,
			f.Namespace.Name,
			"iperf-e2e-cli",
			func(n v1.Node) v1.PodSpec {
				return v1.PodSpec{
					Containers: []v1.Container{
						{
							Name:    "iperf-client",
							Image:   imageutils.GetE2EImage(imageutils.Agnhost),
							Command: []string{"/bin/sh"},
							Args: []string{
								"-c",
								"/usr/local/bin/iperf " + familyStr + "-c service-for-" + appName + " -p 8002 --reportstyle C && sleep 5",
							},
						},
					},
					RestartPolicy: v1.RestartPolicyOnFailure, // let them successfully die.
				}
			},
			numClient,
		)
		expectedCli := numClient
		if len(nodes.Items) < expectedCli {
			expectedCli = len(nodes.Items)
		}

		framework.Logf("Reading all perf results to stdout.")
		framework.Logf("date,cli,cliPort,server,serverPort,id,interval,transferBits,bandwidthBits")

		// Extra 1/10 second per client.
		iperfTimeout := smallClusterTimeout + (time.Duration(expectedCli/10) * time.Second)
		iperfResults := &IPerfResults{}

		iperfClusterVerification := f.NewClusterVerification(
			f.Namespace,
			framework.PodStateVerification{
				Selectors:   iperfClientPodLabels,
				ValidPhases: []v1.PodPhase{v1.PodSucceeded},
			},
		)

		pods, err2 := iperfClusterVerification.WaitFor(expectedCli, iperfTimeout)
		if err2 != nil {
			framework.Failf("Error in wait...")
		} else if len(pods) < expectedCli {
			framework.Failf("IPerf restuls : Only got %v out of %v, after waiting %v", len(pods), expectedCli, iperfTimeout)
		} else {
			// For each builds up a collection of IPerfRecords
			iperfClusterVerification.ForEach(
				func(p v1.Pod) {
					resultS, err := framework.LookForStringInLog(f.Namespace.Name, p.Name, "iperf-client", "0-", 1*time.Second)
					if err == nil {
						framework.Logf(resultS)
						iperfResults.Add(NewIPerf(resultS))
					} else {
						framework.Failf("Unexpected error, %v when running forEach on the pods.", err)
					}
				})
		}
		fmt.Println("[begin] Node,Bandwidth CSV")
		fmt.Println(iperfResults.ToTSV())
		fmt.Println("[end] Node,Bandwidth CSV")

		for ipClient, bandwidth := range iperfResults.BandwidthMap {
			framework.Logf("%v had bandwidth %v.  Ratio to expected (%v) was %f", ipClient, bandwidth, expectedBandwidth, float64(bandwidth)/float64(expectedBandwidth))
		}
	})
})
<|endoftext|>


<commit_before>package inbound

import (
	"sync"

	"github.com/v2ray/v2ray-core/app"
	"github.com/v2ray/v2ray-core/app/dispatcher"
	"github.com/v2ray/v2ray-core/app/proxyman"
	"github.com/v2ray/v2ray-core/common/alloc"
	v2io "github.com/v2ray/v2ray-core/common/io"
	"github.com/v2ray/v2ray-core/common/log"
	v2net "github.com/v2ray/v2ray-core/common/net"
	proto "github.com/v2ray/v2ray-core/common/protocol"
	raw "github.com/v2ray/v2ray-core/common/protocol/raw"
	"github.com/v2ray/v2ray-core/common/serial"
	"github.com/v2ray/v2ray-core/common/uuid"
	"github.com/v2ray/v2ray-core/proxy"
	"github.com/v2ray/v2ray-core/proxy/internal"
	vmessio "github.com/v2ray/v2ray-core/proxy/vmess/io"
	"github.com/v2ray/v2ray-core/transport/hub"
)

type userByEmail struct {
	sync.RWMutex
	cache           map[string]*proto.User
	defaultLevel    proto.UserLevel
	defaultAlterIDs uint16
}

func NewUserByEmail(users []*proto.User, config *DefaultConfig) *userByEmail {
	cache := make(map[string]*proto.User)
	for _, user := range users {
		cache[user.Email] = user
	}
	return &userByEmail{
		cache:           cache,
		defaultLevel:    config.Level,
		defaultAlterIDs: config.AlterIDs,
	}
}

func (this *userByEmail) Get(email string) (*proto.User, bool) {
	var user *proto.User
	var found bool
	this.RLock()
	user, found = this.cache[email]
	this.RUnlock()
	if !found {
		this.Lock()
		user, found = this.cache[email]
		if !found {
			id := proto.NewID(uuid.New())
			user = proto.NewUser(id, this.defaultLevel, this.defaultAlterIDs, email)
			this.cache[email] = user
		}
		this.Unlock()
	}
	return user, found
}

// Inbound connection handler that handles messages in VMess format.
type VMessInboundHandler struct {
	sync.Mutex
	packetDispatcher      dispatcher.PacketDispatcher
	inboundHandlerManager proxyman.InboundHandlerManager
	clients               proto.UserValidator
	usersByEmail          *userByEmail
	accepting             bool
	listener              *hub.TCPHub
	features              *FeaturesConfig
	listeningPort         v2net.Port
}

func (this *VMessInboundHandler) Port() v2net.Port {
	return this.listeningPort
}

func (this *VMessInboundHandler) Close() {
	this.accepting = false
	if this.listener != nil {
		this.Lock()
		this.listener.Close()
		this.listener = nil
		this.Unlock()
	}
}

func (this *VMessInboundHandler) GetUser(email string) *proto.User {
	user, existing := this.usersByEmail.Get(email)
	if !existing {
		this.clients.Add(user)
	}
	return user
}

func (this *VMessInboundHandler) Listen(port v2net.Port) error {
	if this.accepting {
		if this.listeningPort == port {
			return nil
		} else {
			return proxy.ErrorAlreadyListening
		}
	}
	this.listeningPort = port

	tcpListener, err := hub.ListenTCP(port, this.HandleConnection)
	if err != nil {
		log.Error("Unable to listen tcp port ", port, ": ", err)
		return err
	}
	this.accepting = true
	this.Lock()
	this.listener = tcpListener
	this.Unlock()
	return nil
}

func (this *VMessInboundHandler) HandleConnection(connection hub.Connection) {
	defer connection.Close()

	connReader := v2net.NewTimeOutReader(16, connection)
	defer connReader.Release()

	reader := v2io.NewBufferedReader(connReader)
	defer reader.Release()

	session := raw.NewServerSession(this.clients)
	defer session.Release()

	request, err := session.DecodeRequestHeader(reader)
	if err != nil {
		log.Access(connection.RemoteAddr(), serial.StringLiteral(""), log.AccessRejected, serial.StringLiteral(err.Error()))
		log.Warning("VMessIn: Invalid request from ", connection.RemoteAddr(), ": ", err)
		return
	}
	log.Access(connection.RemoteAddr(), request.Destination(), log.AccessAccepted, serial.StringLiteral(""))
	log.Debug("VMessIn: Received request for ", request.Destination())

	ray := this.packetDispatcher.DispatchToOutbound(request.Destination())
	input := ray.InboundInput()
	output := ray.InboundOutput()
	var readFinish, writeFinish sync.Mutex
	readFinish.Lock()
	writeFinish.Lock()

	userSettings := proto.GetUserSettings(request.User.Level)
	connReader.SetTimeOut(userSettings.PayloadReadTimeout)
	reader.SetCached(false)
	go func() {
		defer input.Close()
		defer readFinish.Unlock()
		bodyReader := session.DecodeRequestBody(reader)
		var requestReader v2io.Reader
		if request.Option.IsChunkStream() {
			requestReader = vmessio.NewAuthChunkReader(bodyReader)
		} else {
			requestReader = v2io.NewAdaptiveReader(bodyReader)
		}
		v2io.Pipe(requestReader, input)
		requestReader.Release()
	}()

	writer := v2io.NewBufferedWriter(connection)
	defer writer.Release()

	response := &proto.ResponseHeader{
		Command: this.generateCommand(request),
	}

	session.EncodeResponseHeader(response, writer)

	bodyWriter := session.EncodeResponseBody(writer)

	// Optimize for small response packet
	if data, err := output.Read(); err == nil {
		if request.Option.IsChunkStream() {
			vmessio.Authenticate(data)
		}
		bodyWriter.Write(data.Value)
		data.Release()

		writer.SetCached(false)
		go func(finish *sync.Mutex) {
			var writer v2io.Writer = v2io.NewAdaptiveWriter(bodyWriter)
			if request.Option.IsChunkStream() {
				writer = vmessio.NewAuthChunkWriter(writer)
			}
			v2io.Pipe(output, writer)
			if request.Option.IsChunkStream() {
				writer.Write(alloc.NewSmallBuffer().Clear())
			}
			output.Release()
			writer.Release()
			finish.Unlock()
		}(&writeFinish)
		writeFinish.Lock()
	}

	readFinish.Lock()
	writeFinish.Lock()
}

func init() {
	internal.MustRegisterInboundHandlerCreator("vmess",
		func(space app.Space, rawConfig interface{}) (proxy.InboundHandler, error) {
			if !space.HasApp(dispatcher.APP_ID) {
				return nil, internal.ErrorBadConfiguration
			}
			config := rawConfig.(*Config)

			allowedClients := proto.NewTimedUserValidator(proto.DefaultIDHash)
			for _, user := range config.AllowedUsers {
				allowedClients.Add(user)
			}

			handler := &VMessInboundHandler{
				packetDispatcher: space.GetApp(dispatcher.APP_ID).(dispatcher.PacketDispatcher),
				clients:          allowedClients,
				features:         config.Features,
				usersByEmail:     NewUserByEmail(config.AllowedUsers, config.Defaults),
			}

			if space.HasApp(proxyman.APP_ID_INBOUND_MANAGER) {
				handler.inboundHandlerManager = space.GetApp(proxyman.APP_ID_INBOUND_MANAGER).(proxyman.InboundHandlerManager)
			}

			return handler, nil
		})
}
<commit_msg>Fix a dead lock issue in VMess<commit_after>package inbound

import (
	"sync"

	"github.com/v2ray/v2ray-core/app"
	"github.com/v2ray/v2ray-core/app/dispatcher"
	"github.com/v2ray/v2ray-core/app/proxyman"
	"github.com/v2ray/v2ray-core/common/alloc"
	v2io "github.com/v2ray/v2ray-core/common/io"
	"github.com/v2ray/v2ray-core/common/log"
	v2net "github.com/v2ray/v2ray-core/common/net"
	proto "github.com/v2ray/v2ray-core/common/protocol"
	raw "github.com/v2ray/v2ray-core/common/protocol/raw"
	"github.com/v2ray/v2ray-core/common/serial"
	"github.com/v2ray/v2ray-core/common/uuid"
	"github.com/v2ray/v2ray-core/proxy"
	"github.com/v2ray/v2ray-core/proxy/internal"
	vmessio "github.com/v2ray/v2ray-core/proxy/vmess/io"
	"github.com/v2ray/v2ray-core/transport/hub"
)

type userByEmail struct {
	sync.RWMutex
	cache           map[string]*proto.User
	defaultLevel    proto.UserLevel
	defaultAlterIDs uint16
}

func NewUserByEmail(users []*proto.User, config *DefaultConfig) *userByEmail {
	cache := make(map[string]*proto.User)
	for _, user := range users {
		cache[user.Email] = user
	}
	return &userByEmail{
		cache:           cache,
		defaultLevel:    config.Level,
		defaultAlterIDs: config.AlterIDs,
	}
}

func (this *userByEmail) Get(email string) (*proto.User, bool) {
	var user *proto.User
	var found bool
	this.RLock()
	user, found = this.cache[email]
	this.RUnlock()
	if !found {
		this.Lock()
		user, found = this.cache[email]
		if !found {
			id := proto.NewID(uuid.New())
			user = proto.NewUser(id, this.defaultLevel, this.defaultAlterIDs, email)
			this.cache[email] = user
		}
		this.Unlock()
	}
	return user, found
}

// Inbound connection handler that handles messages in VMess format.
type VMessInboundHandler struct {
	sync.Mutex
	packetDispatcher      dispatcher.PacketDispatcher
	inboundHandlerManager proxyman.InboundHandlerManager
	clients               proto.UserValidator
	usersByEmail          *userByEmail
	accepting             bool
	listener              *hub.TCPHub
	features              *FeaturesConfig
	listeningPort         v2net.Port
}

func (this *VMessInboundHandler) Port() v2net.Port {
	return this.listeningPort
}

func (this *VMessInboundHandler) Close() {
	this.accepting = false
	if this.listener != nil {
		this.Lock()
		this.listener.Close()
		this.listener = nil
		this.Unlock()
	}
}

func (this *VMessInboundHandler) GetUser(email string) *proto.User {
	user, existing := this.usersByEmail.Get(email)
	if !existing {
		this.clients.Add(user)
	}
	return user
}

func (this *VMessInboundHandler) Listen(port v2net.Port) error {
	if this.accepting {
		if this.listeningPort == port {
			return nil
		} else {
			return proxy.ErrorAlreadyListening
		}
	}
	this.listeningPort = port

	tcpListener, err := hub.ListenTCP(port, this.HandleConnection)
	if err != nil {
		log.Error("Unable to listen tcp port ", port, ": ", err)
		return err
	}
	this.accepting = true
	this.Lock()
	this.listener = tcpListener
	this.Unlock()
	return nil
}

func (this *VMessInboundHandler) HandleConnection(connection hub.Connection) {
	defer connection.Close()

	connReader := v2net.NewTimeOutReader(16, connection)
	defer connReader.Release()

	reader := v2io.NewBufferedReader(connReader)
	defer reader.Release()

	session := raw.NewServerSession(this.clients)
	defer session.Release()

	request, err := session.DecodeRequestHeader(reader)
	if err != nil {
		log.Access(connection.RemoteAddr(), serial.StringLiteral(""), log.AccessRejected, serial.StringLiteral(err.Error()))
		log.Warning("VMessIn: Invalid request from ", connection.RemoteAddr(), ": ", err)
		return
	}
	log.Access(connection.RemoteAddr(), request.Destination(), log.AccessAccepted, serial.StringLiteral(""))
	log.Debug("VMessIn: Received request for ", request.Destination())

	ray := this.packetDispatcher.DispatchToOutbound(request.Destination())
	input := ray.InboundInput()
	output := ray.InboundOutput()
	var readFinish, writeFinish sync.Mutex
	readFinish.Lock()
	writeFinish.Lock()

	userSettings := proto.GetUserSettings(request.User.Level)
	connReader.SetTimeOut(userSettings.PayloadReadTimeout)
	reader.SetCached(false)
	go func() {
		defer input.Close()
		defer readFinish.Unlock()
		bodyReader := session.DecodeRequestBody(reader)
		var requestReader v2io.Reader
		if request.Option.IsChunkStream() {
			requestReader = vmessio.NewAuthChunkReader(bodyReader)
		} else {
			requestReader = v2io.NewAdaptiveReader(bodyReader)
		}
		v2io.Pipe(requestReader, input)
		requestReader.Release()
	}()

	writer := v2io.NewBufferedWriter(connection)
	defer writer.Release()

	response := &proto.ResponseHeader{
		Command: this.generateCommand(request),
	}

	session.EncodeResponseHeader(response, writer)

	bodyWriter := session.EncodeResponseBody(writer)

	// Optimize for small response packet
	if data, err := output.Read(); err == nil {
		if request.Option.IsChunkStream() {
			vmessio.Authenticate(data)
		}
		bodyWriter.Write(data.Value)
		data.Release()

		writer.SetCached(false)
		go func(finish *sync.Mutex) {
			var writer v2io.Writer = v2io.NewAdaptiveWriter(bodyWriter)
			if request.Option.IsChunkStream() {
				writer = vmessio.NewAuthChunkWriter(writer)
			}
			v2io.Pipe(output, writer)
			if request.Option.IsChunkStream() {
				writer.Write(alloc.NewSmallBuffer().Clear())
			}
			output.Release()
			writer.Release()
			finish.Unlock()
		}(&writeFinish)
		writeFinish.Lock()
	}

	readFinish.Lock()
}

func init() {
	internal.MustRegisterInboundHandlerCreator("vmess",
		func(space app.Space, rawConfig interface{}) (proxy.InboundHandler, error) {
			if !space.HasApp(dispatcher.APP_ID) {
				return nil, internal.ErrorBadConfiguration
			}
			config := rawConfig.(*Config)

			allowedClients := proto.NewTimedUserValidator(proto.DefaultIDHash)
			for _, user := range config.AllowedUsers {
				allowedClients.Add(user)
			}

			handler := &VMessInboundHandler{
				packetDispatcher: space.GetApp(dispatcher.APP_ID).(dispatcher.PacketDispatcher),
				clients:          allowedClients,
				features:         config.Features,
				usersByEmail:     NewUserByEmail(config.AllowedUsers, config.Defaults),
			}

			if space.HasApp(proxyman.APP_ID_INBOUND_MANAGER) {
				handler.inboundHandlerManager = space.GetApp(proxyman.APP_ID_INBOUND_MANAGER).(proxyman.InboundHandlerManager)
			}

			return handler, nil
		})
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the MPL
*  License. If a copy of the same was not distributed with this
*  file, You can obtain one at
*  https://github.com/AkhilHector/pubundsci/blob/master/LICENSE.
 */

package numgo

import (
	"fmt"
	"strings"
)

type NdArray struct {
	Size int
}

type NArray struct {
	Data    []float64
	Details []float64
	Index   []float64
}

func (n NdArray) Init() []float64 {
	array := make([]float64, n.Size)
	return array
}

func extract_parameters(args []float64) []float64 {
	var parameters []float64

	// store the parameters in a list
	for _, p := range args {
		parameters = append(parameters, p)
	}
	return parameters
}

func NDArrayGenElements(value float64, details ...float64) []float64 {
	parameters := extract_parameters(details)
	if len(parameters) > 0 {
		dim := parameters[0]
		rem := parameters[1:]
		arr := []float64{}
		for i := 0; i < int(dim); i++ {
			arr = append(arr, NDArrayGenElements(value, rem...)...)
		}
		return arr
	} else {
		return []float64{value}
	}
}

func NDArray(details ...float64) (n *NArray) {
	parameters := extract_parameters(details)
	n = &NArray{
		Data:    NDArrayGenElements(0, details...),
		Details: parameters,
		Index:   make([]float64, len(parameters)),
	}
	return n
}

func (n *NArray) String() (array string) {
	array = "NDArray>\n("
	if len(n.Details) == 0 {
		return "NDArray>(<nil>)"
	} else {
		var i float64 = 0
		var details []float64
		var index_number float64 = n.Details[len(n.Details)-1]
		var element float64 = index_number

		// store the rows and cols number for adding [ and ] symbols
		// at appropriate places
		for index := len(n.Details) - 1; index > 0; index-- {
			details = append(details, index_number*n.Details[index-1])
			index_number = index_number * n.Details[index-1]
		}
		for i = 0; i + element <= float64(len(n.Data)); i += element {
			var array_symbol string = ""
			// add the '[' symbol at the start of every new dimension
			for _, d := range details {
				if int(i)%int(d) == 0 {
					array_symbol += "["
				}
			}
			array += strings.Repeat(" ", len(n.Details)-len(array_symbol) - 1) + array_symbol

			// add the data between the '[' ']' symbols
			array += fmt.Sprint(n.Data[int(i):int(i + element)])

			array_symbol = ""

			// add the ']' symbol at the end of every new dimension
			for _, d := range details {
				if int((i + element))%int(d) == 0 {
					array_symbol += "]"
				}
			}
			array += array_symbol + strings.Repeat(" ", (len(n.Details)- len(array_symbol)) - 1)

			// add proper spacing for displaying arrays in presentable manner
			if i + element != float64(len(n.Data)) {
				if len(array_symbol) > 0 {
					array += "\n"
				}
				array += "\n"
			}
		}
	}
	return array + ")"
}

func (n NdArray) Range(start, end float64) []float64 {
	var array []float64
	for i := start; i < end; i++ {
		array = append(array, i)
	}
	return array
}

func (n NdArray) Xrange(args ...float64) []float64 {
	var i float64
	var array []float64
	number_of_args := len(args)
	parameters := extract_parameters(args)

	// now generate the array basiing on the number of arguments
	if number_of_args == 1 {
		for i = 0; i < parameters[0]; i++ {
			array = append(array, i)
		}
	} else if number_of_args == 2 {
		for i = parameters[0]; i < parameters[1]; i++ {
			array = append(array, i)
		}
	} else {
		for i = parameters[0]; i < parameters[1]; i++ {
			array = append(array, i)
		}
	}
	return array
}
<commit_msg>Made the following changes to arrays/arrays.go<commit_after>/* This Source Code Form is subject to the terms of the MPL
*  License. If a copy of the same was not distributed with this
*  file, You can obtain one at
*  https://github.com/AkhilHector/pubundsci/blob/master/LICENSE.
 */

package numgo

import (
	"fmt"
	"strings"
)

type NArray struct {
	Data    []float64
	Details []float64
	Index   []float64
}

func Init(length float64) (n *NArray) {
	n = &NArray{
		Data:    make([]float64, 0),
		Details: []float64{1, length},
		Index:   make([]float64, 2),
	}
	return n
}

func extract_parameters(args []float64) []float64 {
	var parameters []float64

	// store the parameters in a list
	for _, p := range args {
		parameters = append(parameters, p)
	}
	return parameters
}

func NDArrayGenElements(value float64, details ...float64) []float64 {
	parameters := extract_parameters(details)
	if len(parameters) > 0 {
		dim := parameters[0]
		rem := parameters[1:]
		arr := []float64{}
		for i := 0; i < int(dim); i++ {
			arr = append(arr, NDArrayGenElements(value, rem...)...)
		}
		return arr
	} else {
		return []float64{value}
	}
}

func NDArray(details ...float64) (n *NArray) {
	parameters := extract_parameters(details)
	n = &NArray{
		Data:    NDArrayGenElements(1, details...),
		Details: parameters,
		Index:   make([]float64, len(parameters)),
	}
	return n
}

func (n *NArray) String() (array string) {
	array = "NDArray>\n("
	if len(n.Details) == 0 {
		return "NDArray>(<nil>)"
	} else {
		var i float64 = 0
		var details []float64
		var index_number float64 = n.Details[len(n.Details)-1]
		var element float64 = index_number

		// store the rows and cols number for adding [ and ] symbols
		// at appropriate places
		for index := len(n.Details) - 1; index > 0; index-- {
			details = append(details, index_number*n.Details[index-1])
			index_number = index_number * n.Details[index-1]
		}
		for i = 0; i + element <= float64(len(n.Data)); i += element {
			var array_symbol string = ""
			// add the '[' symbol at the start of every new dimension
			for _, d := range details {
				if int(i)%int(d) == 0 {
					array_symbol += "["
				}
			}
			array += strings.Repeat(" ", len(n.Details)-len(array_symbol) - 1) + array_symbol

			// add the data between the '[' ']' symbols
			array += fmt.Sprint(n.Data[int(i):int(i + element)])

			array_symbol = ""

			// add the ']' symbol at the end of every new dimension
			for _, d := range details {
				if int((i + element))%int(d) == 0 {
					array_symbol += "]"
				}
			}
			array += array_symbol + strings.Repeat(" ", (len(n.Details)- len(array_symbol)) - 1)

			// add proper spacing for displaying arrays in presentable manner
			if i + element != float64(len(n.Data)) {
				if len(array_symbol) > 0 {
					array += "\n"
				}
				array += "\n"
			}
		}
	}
	return array + ")"
}

func Range(start, end float64) (n *NArray) {
	n = Init(end - start)
	for i := start; i < end; i++ {
		n.Data = append(n.Data, i)
	}
	return n
}

func Xrange(args ...float64) (n *NArray) {
	var i float64
	number_of_args := len(args)
	parameters := extract_parameters(args)

	// now generate the array basiing on the number of arguments
	if number_of_args == 1 {
		n = Init(parameters[0])
		for i = 0; i < parameters[0]; i++ {
			n.Data = append(n.Data, i)
		}
	} else if number_of_args == 2 {
		n = Init(parameters[1] - parameters[0])
		for i = parameters[0]; i < parameters[1]; i++ {
			n.Data = append(n.Data, i)
		}
	} else {
		n = Init(parameters[1] - parameters[0])
		for i = parameters[0]; i < parameters[1]; i++ {
			n.Data = append(n.Data, i)
		}
	}
	return n
}
<|endoftext|>


<commit_before>package main_test

import (
	"io/ioutil"
	"os"
	"os/exec"
	//	"time"
	//. "github.com/iestynpryce/goreutils/nl"

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

var _ = Describe("Nl", func() {

	It("should return no error when run on a normal file", func() {
		command := exec.Command(pathToNl)
		_, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)
		Expect(err).NotTo(HaveOccurred())
	})

	Context("when presented with an invalid file", func() {
		var command *exec.Cmd
		var session *gexec.Session

		BeforeEach(func() {
			command = exec.Command(pathToNl, "doesNotExist")
			session, _ = gexec.Start(command, GinkgoWriter,
				GinkgoWriter)
		})

		It("should return a non zero return code", func() {
			Eventually(session).Should(gexec.Exit(-1))
		})

		It("should return a useful error message", func() {
			Eventually(session.Err).Should(gbytes.Say("open doesNotExist: no such file or directory"))
		})
	})

	Context("when presented with a valid file", func() {
		var session *gexec.Session
		var fileName string
		var fileHandle *os.File

		BeforeEach(func() {
			fileHandle, _ = ioutil.TempFile("", "")
			defer fileHandle.Close()
			fileName = fileHandle.Name()

			fileHandle.WriteString("line 1\nline 2\n    \nline 3\n")
			fileHandle.Sync()

			command := exec.Command(pathToNl, fileName)
			session, _ = gexec.Start(command, GinkgoWriter,
				GinkgoWriter)
		})

		AfterEach(func() {
			os.Remove(fileName)
		})

		It("should return line numbers at the start of non-blank lines",
			func() {
				Eventually(session.Out).Should(gbytes.Say("\\s+1.*\n\\s+2"))
			})

		It("should not return line numbers at the start of blank lines",
			func() {
				Eventually(session.Out).Should(gbytes.Say("\\s+1.*\n\\s+2.*\n    \n\\s+3"))
			})
	})

	Context("when using the -i option", func() {
		var session *gexec.Session
		var fileName string
		var fileHandle *os.File

		BeforeEach(func() {
			fileHandle, _ = ioutil.TempFile("", "")
			defer fileHandle.Close()
			fileName = fileHandle.Name()

			fileHandle.WriteString("line 1\nline 2\nline 3\n")
			fileHandle.Sync()

		})

		AfterEach(func() {
			os.Remove(fileName)
		})

		It("should return line numbers incremented by 1",
			func() {
				localCommand := exec.Command(pathToNl, "-i", "1", fileName)
				session, _ = gexec.Start(localCommand, GinkgoWriter,
					GinkgoWriter)
				Eventually(session.Out).Should(gbytes.Say("\\s+1.*\n\\s+2.*\n\\s+3"))
			})

		It("should return line numbers incremented by 2",
			func() {
				localCommand := exec.Command(pathToNl, "-i", "2", fileName)
				session, _ = gexec.Start(localCommand, GinkgoWriter,
					GinkgoWriter)
				Eventually(session.Out).Should(gbytes.Say("\\s+1.*\n\\s+3.*\n\\s+5"))
			})

		It("should return line numbers incremented by 10",
			func() {
				localCommand := exec.Command(pathToNl, "-i", "10", fileName)
				session, _ = gexec.Start(localCommand, GinkgoWriter,
					GinkgoWriter)
				Eventually(session.Out).Should(gbytes.Say("\\s+1.*\n\\s+11.*\n\\s+21"))
			})

		It("should return an error when line numbers incremented by -1",
			func() {
				localCommand := exec.Command(pathToNl, "-i", "-1", fileName)
				session, _ = gexec.Start(localCommand, GinkgoWriter,
					GinkgoWriter)
				Eventually(session.Err).Should(gbytes.Say("Error: invalid line-increment value \"-1\""))
			})

		It("should return an error when line numbers incremented by 0",
			func() {
				localCommand := exec.Command(pathToNl, "-i", "0", fileName)
				session, _ = gexec.Start(localCommand, GinkgoWriter,
					GinkgoWriter)
				Eventually(session.Err).Should(gbytes.Say("Error: invalid line-increment value \"0\""))
			})
	})
})
<commit_msg>Add nl tests for the -s option<commit_after>package main_test

import (
	"io/ioutil"
	"os"
	"os/exec"
	//	"time"
	//. "github.com/iestynpryce/goreutils/nl"

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

var _ = Describe("Nl", func() {

	It("should return no error when run on a normal file", func() {
		command := exec.Command(pathToNl)
		_, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)
		Expect(err).NotTo(HaveOccurred())
	})

	Context("when presented with an invalid file", func() {
		var command *exec.Cmd
		var session *gexec.Session

		BeforeEach(func() {
			command = exec.Command(pathToNl, "doesNotExist")
			session, _ = gexec.Start(command, GinkgoWriter,
				GinkgoWriter)
		})

		It("should return a non zero return code", func() {
			Eventually(session).Should(gexec.Exit(-1))
		})

		It("should return a useful error message", func() {
			Eventually(session.Err).Should(gbytes.Say("open doesNotExist: no such file or directory"))
		})
	})

	Context("when presented with a valid file", func() {
		var session *gexec.Session
		var fileName string
		var fileHandle *os.File

		BeforeEach(func() {
			fileHandle, _ = ioutil.TempFile("", "")
			defer fileHandle.Close()
			fileName = fileHandle.Name()

			fileHandle.WriteString("line 1\nline 2\n    \nline 3\n")
			fileHandle.Sync()

			command := exec.Command(pathToNl, fileName)
			session, _ = gexec.Start(command, GinkgoWriter,
				GinkgoWriter)
		})

		AfterEach(func() {
			os.Remove(fileName)
		})

		It("should return line numbers at the start of non-blank lines",
			func() {
				Eventually(session.Out).Should(gbytes.Say("\\s+1.*\n\\s+2"))
			})

		It("should not return line numbers at the start of blank lines",
			func() {
				Eventually(session.Out).Should(gbytes.Say("\\s+1.*\n\\s+2.*\n    \n\\s+3"))
			})
	})

	Context("when using the -i option", func() {
		var session *gexec.Session
		var fileName string
		var fileHandle *os.File

		BeforeEach(func() {
			fileHandle, _ = ioutil.TempFile("", "")
			defer fileHandle.Close()
			fileName = fileHandle.Name()

			fileHandle.WriteString("line 1\nline 2\nline 3\n")
			fileHandle.Sync()

		})

		AfterEach(func() {
			os.Remove(fileName)
		})

		It("should return line numbers incremented by 1",
			func() {
				localCommand := exec.Command(pathToNl, "-i", "1", fileName)
				session, _ = gexec.Start(localCommand, GinkgoWriter,
					GinkgoWriter)
				Eventually(session.Out).Should(gbytes.Say("\\s+1.*\n\\s+2.*\n\\s+3"))
			})

		It("should return line numbers incremented by 2",
			func() {
				localCommand := exec.Command(pathToNl, "-i", "2", fileName)
				session, _ = gexec.Start(localCommand, GinkgoWriter,
					GinkgoWriter)
				Eventually(session.Out).Should(gbytes.Say("\\s+1.*\n\\s+3.*\n\\s+5"))
			})

		It("should return line numbers incremented by 10",
			func() {
				localCommand := exec.Command(pathToNl, "-i", "10", fileName)
				session, _ = gexec.Start(localCommand, GinkgoWriter,
					GinkgoWriter)
				Eventually(session.Out).Should(gbytes.Say("\\s+1.*\n\\s+11.*\n\\s+21"))
			})

		It("should return an error when line numbers incremented by -1",
			func() {
				localCommand := exec.Command(pathToNl, "-i", "-1", fileName)
				session, _ = gexec.Start(localCommand, GinkgoWriter,
					GinkgoWriter)
				Eventually(session.Err).Should(gbytes.Say("Error: invalid line-increment value \"-1\""))
			})

		It("should return an error when line numbers incremented by 0",
			func() {
				localCommand := exec.Command(pathToNl, "-i", "0", fileName)
				session, _ = gexec.Start(localCommand, GinkgoWriter,
					GinkgoWriter)
				Eventually(session.Err).Should(gbytes.Say("Error: invalid line-increment value \"0\""))
			})
	})

	Context("when using the -s option", func() {
		var session *gexec.Session
		var fileName string
		var fileHandle *os.File

		BeforeEach(func() {
			fileHandle, _ = ioutil.TempFile("", "")
			defer fileHandle.Close()
			fileName = fileHandle.Name()

			fileHandle.WriteString("line 1\nline 2\nline 3\n")
			fileHandle.Sync()

		})

		AfterEach(func() {
			os.Remove(fileName)
		})

		It("should return line numbers followed by \\t by default",
			func() {
				localCommand := exec.Command(pathToNl, fileName)
				session, _ = gexec.Start(localCommand, GinkgoWriter,
					GinkgoWriter)
				Eventually(session.Out).Should(gbytes.Say("\\s+1\t.*\n\\s+2\t.*\n\\s+3\t"))
			})

		It("should return line numbers followed by \\t",
			func() {
				localCommand := exec.Command(pathToNl, "-s", "\t", fileName)
				session, _ = gexec.Start(localCommand, GinkgoWriter,
					GinkgoWriter)
				Eventually(session.Out).Should(gbytes.Say("\\s+1\t.*\n\\s+2\t.*\n\\s+3\t"))
			})

		It("should return line numbers followed by no space",
			func() {
				localCommand := exec.Command(pathToNl, "-s", "", fileName)
				session, _ = gexec.Start(localCommand, GinkgoWriter,
					GinkgoWriter)
				Eventually(session.Out).Should(gbytes.Say("\\s+1line.*\n\\s+2line.*\n\\s+3line"))
			})

		It("should return line numbers followed by --",
			func() {
				localCommand := exec.Command(pathToNl, "-s", "--", fileName)
				session, _ = gexec.Start(localCommand, GinkgoWriter,
					GinkgoWriter)
				Eventually(session.Out).Should(gbytes.Say("\\s+1--.*\n\\s+2--.*\n\\s+3--"))
			})
	})

})
<|endoftext|>


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

import (
	"fmt"
	"strings"

	"github.com/spf13/cobra"

	"k8s.io/apimachinery/pkg/api/meta"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/cli-runtime/pkg/genericclioptions"
	"k8s.io/cli-runtime/pkg/printers"
	"k8s.io/kubectl/pkg/util/openapi"
)

// PrintFlags composes common printer flag structs
// used in the Get command.
type PrintFlags struct {
	JSONYamlPrintFlags *genericclioptions.JSONYamlPrintFlags
	NamePrintFlags     *genericclioptions.NamePrintFlags
	CustomColumnsFlags *CustomColumnsPrintFlags
	HumanReadableFlags *HumanPrintFlags
	TemplateFlags      *genericclioptions.KubeTemplatePrintFlags

	NoHeaders    *bool
	OutputFormat *string
}

// SetKind sets the Kind option of humanreadable flags
func (f *PrintFlags) SetKind(kind schema.GroupKind) {
	f.HumanReadableFlags.SetKind(kind)
}

// EnsureWithNamespace ensures that humanreadable flags return
// a printer capable of printing with a "namespace" column.
func (f *PrintFlags) EnsureWithNamespace() error {
	return f.HumanReadableFlags.EnsureWithNamespace()
}

// EnsureWithKind ensures that humanreadable flags return
// a printer capable of including resource kinds.
func (f *PrintFlags) EnsureWithKind() error {
	return f.HumanReadableFlags.EnsureWithKind()
}

// Copy returns a copy of PrintFlags for mutation
func (f *PrintFlags) Copy() PrintFlags {
	printFlags := *f
	return printFlags
}

// AllowedFormats is the list of formats in which data can be displayed
func (f *PrintFlags) AllowedFormats() []string {
	formats := f.JSONYamlPrintFlags.AllowedFormats()
	formats = append(formats, f.NamePrintFlags.AllowedFormats()...)
	formats = append(formats, f.TemplateFlags.AllowedFormats()...)
	formats = append(formats, f.CustomColumnsFlags.AllowedFormats()...)
	formats = append(formats, f.HumanReadableFlags.AllowedFormats()...)
	return formats
}

// UseOpenAPIColumns modifies the output format, as well as the
// "allowMissingKeys" option for template printers, to values
// defined in the OpenAPI schema of a resource.
func (f *PrintFlags) UseOpenAPIColumns(api openapi.Resources, mapping *meta.RESTMapping) error {
	// Found openapi metadata for this resource
	schema := api.LookupResource(mapping.GroupVersionKind)
	if schema == nil {
		// Schema not found, return empty columns
		return nil
	}

	columns, found := openapi.GetPrintColumns(schema.GetExtensions())
	if !found {
		// Extension not found, return empty columns
		return nil
	}

	parts := strings.SplitN(columns, "=", 2)
	if len(parts) < 2 {
		return nil
	}

	allowMissingKeys := true
	f.OutputFormat = &parts[0]
	f.TemplateFlags.TemplateArgument = &parts[1]
	f.TemplateFlags.AllowMissingKeys = &allowMissingKeys
	return nil
}

// ToPrinter attempts to find a composed set of PrintFlags suitable for
// returning a printer based on current flag values.
func (f *PrintFlags) ToPrinter() (printers.ResourcePrinter, error) {
	outputFormat := ""
	if f.OutputFormat != nil {
		outputFormat = *f.OutputFormat
	}

	noHeaders := false
	if f.NoHeaders != nil {
		noHeaders = *f.NoHeaders
	}
	f.HumanReadableFlags.NoHeaders = noHeaders
	f.CustomColumnsFlags.NoHeaders = noHeaders

	// for "get.go" we want to support a --template argument given, even when no --output format is provided
	if f.TemplateFlags.TemplateArgument != nil && len(*f.TemplateFlags.TemplateArgument) > 0 && len(outputFormat) == 0 {
		outputFormat = "go-template"
	}

	if p, err := f.TemplateFlags.ToPrinter(outputFormat); !genericclioptions.IsNoCompatiblePrinterError(err) {
		return p, err
	}

	if f.TemplateFlags.TemplateArgument != nil {
		f.CustomColumnsFlags.TemplateArgument = *f.TemplateFlags.TemplateArgument
	}

	if p, err := f.JSONYamlPrintFlags.ToPrinter(outputFormat); !genericclioptions.IsNoCompatiblePrinterError(err) {
		return p, err
	}

	if p, err := f.HumanReadableFlags.ToPrinter(outputFormat); !genericclioptions.IsNoCompatiblePrinterError(err) {
		return p, err
	}

	if p, err := f.CustomColumnsFlags.ToPrinter(outputFormat); !genericclioptions.IsNoCompatiblePrinterError(err) {
		return p, err
	}

	if p, err := f.NamePrintFlags.ToPrinter(outputFormat); !genericclioptions.IsNoCompatiblePrinterError(err) {
		return p, err
	}

	return nil, genericclioptions.NoCompatiblePrinterError{OutputFormat: &outputFormat, AllowedFormats: f.AllowedFormats()}
}

// AddFlags receives a *cobra.Command reference and binds
// flags related to humanreadable and template printing.
func (f *PrintFlags) AddFlags(cmd *cobra.Command) {
	f.JSONYamlPrintFlags.AddFlags(cmd)
	f.NamePrintFlags.AddFlags(cmd)
	f.TemplateFlags.AddFlags(cmd)
	f.HumanReadableFlags.AddFlags(cmd)
	f.CustomColumnsFlags.AddFlags(cmd)

	if f.OutputFormat != nil {
		cmd.Flags().StringVarP(f.OutputFormat, "output", "o", *f.OutputFormat, fmt.Sprintf("Output format. One of: %s See custom columns [https://kubernetes.io/docs/reference/kubectl/overview/#custom-columns], golang template [http://golang.org/pkg/text/template/#pkg-overview] and jsonpath template [https://kubernetes.io/docs/reference/kubectl/jsonpath/].", strings.Join(f.AllowedFormats(), "|")))
	}
	if f.NoHeaders != nil {
		cmd.Flags().BoolVar(f.NoHeaders, "no-headers", *f.NoHeaders, "When using the default or custom-column output format, don't print headers (default print headers).")
	}
}

// NewGetPrintFlags returns flags associated with humanreadable,
// template, and "name" printing, with default values set.
func NewGetPrintFlags() *PrintFlags {
	outputFormat := ""
	noHeaders := false

	return &PrintFlags{
		OutputFormat: &outputFormat,
		NoHeaders:    &noHeaders,

		JSONYamlPrintFlags: genericclioptions.NewJSONYamlPrintFlags(),
		NamePrintFlags:     genericclioptions.NewNamePrintFlags(""),
		TemplateFlags:      genericclioptions.NewKubeTemplatePrintFlags(),

		HumanReadableFlags: NewHumanPrintFlags(),
		CustomColumnsFlags: NewCustomColumnsPrintFlags(),
	}
}
<commit_msg>Add completion to the --output/-o flag<commit_after>/*
Copyright 2018 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 get

import (
	"fmt"
	"strings"

	"github.com/spf13/cobra"

	"k8s.io/apimachinery/pkg/api/meta"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/cli-runtime/pkg/genericclioptions"
	"k8s.io/cli-runtime/pkg/printers"
	"k8s.io/kubectl/pkg/cmd/util"
	"k8s.io/kubectl/pkg/util/openapi"
)

// PrintFlags composes common printer flag structs
// used in the Get command.
type PrintFlags struct {
	JSONYamlPrintFlags *genericclioptions.JSONYamlPrintFlags
	NamePrintFlags     *genericclioptions.NamePrintFlags
	CustomColumnsFlags *CustomColumnsPrintFlags
	HumanReadableFlags *HumanPrintFlags
	TemplateFlags      *genericclioptions.KubeTemplatePrintFlags

	NoHeaders    *bool
	OutputFormat *string
}

// SetKind sets the Kind option of humanreadable flags
func (f *PrintFlags) SetKind(kind schema.GroupKind) {
	f.HumanReadableFlags.SetKind(kind)
}

// EnsureWithNamespace ensures that humanreadable flags return
// a printer capable of printing with a "namespace" column.
func (f *PrintFlags) EnsureWithNamespace() error {
	return f.HumanReadableFlags.EnsureWithNamespace()
}

// EnsureWithKind ensures that humanreadable flags return
// a printer capable of including resource kinds.
func (f *PrintFlags) EnsureWithKind() error {
	return f.HumanReadableFlags.EnsureWithKind()
}

// Copy returns a copy of PrintFlags for mutation
func (f *PrintFlags) Copy() PrintFlags {
	printFlags := *f
	return printFlags
}

// AllowedFormats is the list of formats in which data can be displayed
func (f *PrintFlags) AllowedFormats() []string {
	formats := f.JSONYamlPrintFlags.AllowedFormats()
	formats = append(formats, f.NamePrintFlags.AllowedFormats()...)
	formats = append(formats, f.TemplateFlags.AllowedFormats()...)
	formats = append(formats, f.CustomColumnsFlags.AllowedFormats()...)
	formats = append(formats, f.HumanReadableFlags.AllowedFormats()...)
	return formats
}

// UseOpenAPIColumns modifies the output format, as well as the
// "allowMissingKeys" option for template printers, to values
// defined in the OpenAPI schema of a resource.
func (f *PrintFlags) UseOpenAPIColumns(api openapi.Resources, mapping *meta.RESTMapping) error {
	// Found openapi metadata for this resource
	schema := api.LookupResource(mapping.GroupVersionKind)
	if schema == nil {
		// Schema not found, return empty columns
		return nil
	}

	columns, found := openapi.GetPrintColumns(schema.GetExtensions())
	if !found {
		// Extension not found, return empty columns
		return nil
	}

	parts := strings.SplitN(columns, "=", 2)
	if len(parts) < 2 {
		return nil
	}

	allowMissingKeys := true
	f.OutputFormat = &parts[0]
	f.TemplateFlags.TemplateArgument = &parts[1]
	f.TemplateFlags.AllowMissingKeys = &allowMissingKeys
	return nil
}

// ToPrinter attempts to find a composed set of PrintFlags suitable for
// returning a printer based on current flag values.
func (f *PrintFlags) ToPrinter() (printers.ResourcePrinter, error) {
	outputFormat := ""
	if f.OutputFormat != nil {
		outputFormat = *f.OutputFormat
	}

	noHeaders := false
	if f.NoHeaders != nil {
		noHeaders = *f.NoHeaders
	}
	f.HumanReadableFlags.NoHeaders = noHeaders
	f.CustomColumnsFlags.NoHeaders = noHeaders

	// for "get.go" we want to support a --template argument given, even when no --output format is provided
	if f.TemplateFlags.TemplateArgument != nil && len(*f.TemplateFlags.TemplateArgument) > 0 && len(outputFormat) == 0 {
		outputFormat = "go-template"
	}

	if p, err := f.TemplateFlags.ToPrinter(outputFormat); !genericclioptions.IsNoCompatiblePrinterError(err) {
		return p, err
	}

	if f.TemplateFlags.TemplateArgument != nil {
		f.CustomColumnsFlags.TemplateArgument = *f.TemplateFlags.TemplateArgument
	}

	if p, err := f.JSONYamlPrintFlags.ToPrinter(outputFormat); !genericclioptions.IsNoCompatiblePrinterError(err) {
		return p, err
	}

	if p, err := f.HumanReadableFlags.ToPrinter(outputFormat); !genericclioptions.IsNoCompatiblePrinterError(err) {
		return p, err
	}

	if p, err := f.CustomColumnsFlags.ToPrinter(outputFormat); !genericclioptions.IsNoCompatiblePrinterError(err) {
		return p, err
	}

	if p, err := f.NamePrintFlags.ToPrinter(outputFormat); !genericclioptions.IsNoCompatiblePrinterError(err) {
		return p, err
	}

	return nil, genericclioptions.NoCompatiblePrinterError{OutputFormat: &outputFormat, AllowedFormats: f.AllowedFormats()}
}

// AddFlags receives a *cobra.Command reference and binds
// flags related to humanreadable and template printing.
func (f *PrintFlags) AddFlags(cmd *cobra.Command) {
	f.JSONYamlPrintFlags.AddFlags(cmd)
	f.NamePrintFlags.AddFlags(cmd)
	f.TemplateFlags.AddFlags(cmd)
	f.HumanReadableFlags.AddFlags(cmd)
	f.CustomColumnsFlags.AddFlags(cmd)

	if f.OutputFormat != nil {
		cmd.Flags().StringVarP(f.OutputFormat, "output", "o", *f.OutputFormat, fmt.Sprintf("Output format. One of: %s See custom columns [https://kubernetes.io/docs/reference/kubectl/overview/#custom-columns], golang template [http://golang.org/pkg/text/template/#pkg-overview] and jsonpath template [https://kubernetes.io/docs/reference/kubectl/jsonpath/].", strings.Join(f.AllowedFormats(), "|")))
		util.CheckErr(cmd.RegisterFlagCompletionFunc(
			"output",
			func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
				var comps []string
				for _, format := range f.AllowedFormats() {
					if strings.HasPrefix(format, toComplete) {
						comps = append(comps, format)
					}
				}
				return comps, cobra.ShellCompDirectiveNoFileComp
			},
		))
	}
	if f.NoHeaders != nil {
		cmd.Flags().BoolVar(f.NoHeaders, "no-headers", *f.NoHeaders, "When using the default or custom-column output format, don't print headers (default print headers).")
	}
}

// NewGetPrintFlags returns flags associated with humanreadable,
// template, and "name" printing, with default values set.
func NewGetPrintFlags() *PrintFlags {
	outputFormat := ""
	noHeaders := false

	return &PrintFlags{
		OutputFormat: &outputFormat,
		NoHeaders:    &noHeaders,

		JSONYamlPrintFlags: genericclioptions.NewJSONYamlPrintFlags(),
		NamePrintFlags:     genericclioptions.NewNamePrintFlags(""),
		TemplateFlags:      genericclioptions.NewKubeTemplatePrintFlags(),

		HumanReadableFlags: NewHumanPrintFlags(),
		CustomColumnsFlags: NewCustomColumnsPrintFlags(),
	}
}
<|endoftext|>


<commit_before>package HarborAPItest

import (
	"fmt"
	"github.com/stretchr/testify/assert"
	"testing"
        "github.com/vmware/harbor/tests/apitests/apilib"
)

func TestAddProject(t *testing.T) {

        fmt.Println("Test for Project Add (ProjectsPost) API\n")
	assert := assert.New(t)

	apiTest := HarborAPI.NewHarborAPI()

	//prepare for test
	adminEr := &HarborAPI.UsrInfo{"admin", "Harbor1234"}
	admin := &HarborAPI.UsrInfo{"admin", "Harbor12345"}

	prjUsr := &HarborAPI.UsrInfo{"unknown", "unknown"}

	var project HarborAPI.Project
	project.ProjectName = "testproject"
	project.Public = true

	//case 1: admin login fail, expect project creation fail.
	fmt.Println("case 1: admin login fail, expect project creation fail.")
	resault, err := apiTest.HarborLogin(*adminEr)
	if err != nil {
		t.Error("Error while admin login", err.Error())
		t.Log(err)
	} else {
		assert.Equal(resault, int(401), "Admin login status should be 401")
		//t.Log(resault)
	}

	resault, err = apiTest.ProjectsPost(*prjUsr, project)
	if err != nil {
		t.Error("Error while creat project", err.Error())
		t.Log(err)
	} else {
		assert.Equal(resault, int(401), "Case 1: Project creation status should be 401")
		//t.Log(resault)
	}

	//case 2: admin successful login, expect project creation success.
	fmt.Println("case 2: admin successful login, expect project creation success.")
	resault, err = apiTest.HarborLogin(*admin)
	if err != nil {
		t.Error("Error while admin login", err.Error())
		t.Log(err)
	} else {
		assert.Equal(resault, int(200), "Admin login status should be 200")
		//t.Log(resault)
	}
	if resault != 200 {
		t.Log(resault)
	} else {
		prjUsr = admin
	}

	resault, err = apiTest.ProjectsPost(*prjUsr, project)
	if err != nil {
		t.Error("Error while creat project", err.Error())
		t.Log(err)
	} else {
		assert.Equal(resault, int(201), "Case 2: Project creation status should be 201")
		//t.Log(resault)
	}

	//case 3: duplicate project name, create project fail
	fmt.Println("case 3: duplicate project name, create project fail")
	resault, err = apiTest.ProjectsPost(*prjUsr, project)
	if err != nil {
		t.Error("Error while creat project", err.Error())
		t.Log(err)
	} else {
		assert.Equal(resault, int(409), "Case 3: Project creation status should be 409")
		//t.Log(resault)
	}

	//resault1, err := apiTest.HarborLogout()
	//if err != nil {
	//        t.Error("Error while admin logout", err.Error())
	//        t.Log(err)
	//} else {
	//        assert.Equal(resault1, int(200), "Admin logout status")
	//        //t.Log(resault)
	//}
	//if resault1 != 200 {
	//        t.Log(resault)
	//}

}
<commit_msg>Update hbapiaddprj_test.go<commit_after>package HarborAPItest

import (
	"fmt"
	"github.com/stretchr/testify/assert"
	"testing"
        "github.com/vmware/harbor/tests/apitests/apilib"
)

func TestAddProject(t *testing.T) {

        fmt.Println("Test for Project Add (ProjectsPost) API")
	assert := assert.New(t)

	apiTest := HarborAPI.NewHarborAPI()

	//prepare for test
	adminEr := &HarborAPI.UsrInfo{"admin", "Harbor1234"}
	admin := &HarborAPI.UsrInfo{"admin", "Harbor12345"}

	prjUsr := &HarborAPI.UsrInfo{"unknown", "unknown"}

	var project HarborAPI.Project
	project.ProjectName = "testproject"
	project.Public = true

	//case 1: admin login fail, expect project creation fail.
	fmt.Println("case 1: admin login fail, expect project creation fail.")
	resault, err := apiTest.HarborLogin(*adminEr)
	if err != nil {
		t.Error("Error while admin login", err.Error())
		t.Log(err)
	} else {
		assert.Equal(resault, int(401), "Admin login status should be 401")
		//t.Log(resault)
	}

	resault, err = apiTest.ProjectsPost(*prjUsr, project)
	if err != nil {
		t.Error("Error while creat project", err.Error())
		t.Log(err)
	} else {
		assert.Equal(resault, int(401), "Case 1: Project creation status should be 401")
		//t.Log(resault)
	}

	//case 2: admin successful login, expect project creation success.
	fmt.Println("case 2: admin successful login, expect project creation success.")
	resault, err = apiTest.HarborLogin(*admin)
	if err != nil {
		t.Error("Error while admin login", err.Error())
		t.Log(err)
	} else {
		assert.Equal(resault, int(200), "Admin login status should be 200")
		//t.Log(resault)
	}
	if resault != 200 {
		t.Log(resault)
	} else {
		prjUsr = admin
	}

	resault, err = apiTest.ProjectsPost(*prjUsr, project)
	if err != nil {
		t.Error("Error while creat project", err.Error())
		t.Log(err)
	} else {
		assert.Equal(resault, int(201), "Case 2: Project creation status should be 201")
		//t.Log(resault)
	}

	//case 3: duplicate project name, create project fail
	fmt.Println("case 3: duplicate project name, create project fail")
	resault, err = apiTest.ProjectsPost(*prjUsr, project)
	if err != nil {
		t.Error("Error while creat project", err.Error())
		t.Log(err)
	} else {
		assert.Equal(resault, int(409), "Case 3: Project creation status should be 409")
		//t.Log(resault)
	}

	//resault1, err := apiTest.HarborLogout()
	//if err != nil {
	//        t.Error("Error while admin logout", err.Error())
	//        t.Log(err)
	//} else {
	//        assert.Equal(resault1, int(200), "Admin logout status")
	//        //t.Log(resault)
	//}
	//if resault1 != 200 {
	//        t.Log(resault)
	//}

}
<|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 network

import (
	v1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/util/wait"
	"k8s.io/kubernetes/test/e2e/framework"
	e2eservice "k8s.io/kubernetes/test/e2e/framework/service"
	"k8s.io/kubernetes/test/e2e/upgrades"

	"github.com/onsi/ginkgo"
)

// ServiceUpgradeTest tests that a service is available before and
// after a cluster upgrade. During a master-only upgrade, it will test
// that a service remains available during the upgrade.
type ServiceUpgradeTest struct {
	jig          *e2eservice.TestJig
	tcpService   *v1.Service
	tcpIngressIP string
	svcPort      int
}

// Name returns the tracking name of the test.
func (ServiceUpgradeTest) Name() string { return "service-upgrade" }

func shouldTestPDBs() bool { return framework.ProviderIs("gce", "gke") }

// Setup creates a service with a load balancer and makes sure it's reachable.
func (t *ServiceUpgradeTest) Setup(f *framework.Framework) {
	serviceName := "service-test"
	jig := e2eservice.NewTestJig(f.ClientSet, f.Namespace.Name, serviceName)

	ns := f.Namespace
	cs := f.ClientSet

	ginkgo.By("creating a TCP service " + serviceName + " with type=LoadBalancer in namespace " + ns.Name)
	_, err := jig.CreateTCPService(func(s *v1.Service) {
		s.Spec.Type = v1.ServiceTypeLoadBalancer
	})
	framework.ExpectNoError(err)
	tcpService, err := jig.WaitForLoadBalancer(e2eservice.GetServiceLoadBalancerCreationTimeout(cs))
	framework.ExpectNoError(err)

	// Get info to hit it with
	tcpIngressIP := e2eservice.GetIngressPoint(&tcpService.Status.LoadBalancer.Ingress[0])
	svcPort := int(tcpService.Spec.Ports[0].Port)

	ginkgo.By("creating pod to be part of service " + serviceName)
	rc, err := jig.Run(jig.AddRCAntiAffinity)
	framework.ExpectNoError(err)

	if shouldTestPDBs() {
		ginkgo.By("creating a PodDisruptionBudget to cover the ReplicationController")
		_, err = jig.CreatePDB(rc)
		framework.ExpectNoError(err)
	}

	// Hit it once before considering ourselves ready
	ginkgo.By("hitting the pod through the service's LoadBalancer")
	timeout := e2eservice.LoadBalancerLagTimeoutDefault
	if framework.ProviderIs("aws") {
		timeout = e2eservice.LoadBalancerLagTimeoutAWS
	}
	e2eservice.TestReachableHTTP(tcpIngressIP, svcPort, timeout)

	t.jig = jig
	t.tcpService = tcpService
	t.tcpIngressIP = tcpIngressIP
	t.svcPort = svcPort
}

// Test runs a connectivity check to the service.
func (t *ServiceUpgradeTest) Test(f *framework.Framework, done <-chan struct{}, upgrade upgrades.UpgradeType) {
	switch upgrade {
	case upgrades.MasterUpgrade, upgrades.ClusterUpgrade:
		t.test(f, done, true, true)
	case upgrades.NodeUpgrade:
		// Node upgrades should test during disruption only on GCE/GKE for now.
		t.test(f, done, shouldTestPDBs(), false)
	default:
		t.test(f, done, false, false)
	}
}

// Teardown cleans up any remaining resources.
func (t *ServiceUpgradeTest) Teardown(f *framework.Framework) {
	// rely on the namespace deletion to clean up everything
}

func (t *ServiceUpgradeTest) test(f *framework.Framework, done <-chan struct{}, testDuringDisruption, testFinalizer bool) {
	if testDuringDisruption {
		// Continuous validation
		ginkgo.By("continuously hitting the pod through the service's LoadBalancer")
		wait.Until(func() {
			e2eservice.TestReachableHTTP(t.tcpIngressIP, t.svcPort, e2eservice.LoadBalancerLagTimeoutDefault)
		}, framework.Poll, done)
	} else {
		// Block until upgrade is done
		ginkgo.By("waiting for upgrade to finish without checking if service remains up")
		<-done
	}

	// Hit it once more
	ginkgo.By("hitting the pod through the service's LoadBalancer")
	e2eservice.TestReachableHTTP(t.tcpIngressIP, t.svcPort, e2eservice.LoadBalancerLagTimeoutDefault)
	if testFinalizer {
		defer func() {
			ginkgo.By("Check that service can be deleted with finalizer")
			e2eservice.WaitForServiceDeletedWithFinalizer(t.jig.Client, t.tcpService.Namespace, t.tcpService.Name)
		}()
		ginkgo.By("Check that finalizer is present on loadBalancer type service")
		e2eservice.WaitForServiceUpdatedWithFinalizer(t.jig.Client, t.tcpService.Namespace, t.tcpService.Name, true)
	}
}
<commit_msg>UPSTREAM: <carry>: Always test PDB's during service upgrade test<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 network

import (
	v1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/util/wait"
	"k8s.io/kubernetes/test/e2e/framework"
	e2eservice "k8s.io/kubernetes/test/e2e/framework/service"
	"k8s.io/kubernetes/test/e2e/upgrades"

	"github.com/onsi/ginkgo"
)

// ServiceUpgradeTest tests that a service is available before and
// after a cluster upgrade. During a master-only upgrade, it will test
// that a service remains available during the upgrade.
type ServiceUpgradeTest struct {
	jig          *e2eservice.TestJig
	tcpService   *v1.Service
	tcpIngressIP string
	svcPort      int
}

// Name returns the tracking name of the test.
func (ServiceUpgradeTest) Name() string { return "service-upgrade" }

func shouldTestPDBs() bool { return true }

// Setup creates a service with a load balancer and makes sure it's reachable.
func (t *ServiceUpgradeTest) Setup(f *framework.Framework) {
	serviceName := "service-test"
	jig := e2eservice.NewTestJig(f.ClientSet, f.Namespace.Name, serviceName)

	ns := f.Namespace
	cs := f.ClientSet

	ginkgo.By("creating a TCP service " + serviceName + " with type=LoadBalancer in namespace " + ns.Name)
	_, err := jig.CreateTCPService(func(s *v1.Service) {
		s.Spec.Type = v1.ServiceTypeLoadBalancer
	})
	framework.ExpectNoError(err)
	tcpService, err := jig.WaitForLoadBalancer(e2eservice.GetServiceLoadBalancerCreationTimeout(cs))
	framework.ExpectNoError(err)

	// Get info to hit it with
	tcpIngressIP := e2eservice.GetIngressPoint(&tcpService.Status.LoadBalancer.Ingress[0])
	svcPort := int(tcpService.Spec.Ports[0].Port)

	ginkgo.By("creating pod to be part of service " + serviceName)
	rc, err := jig.Run(jig.AddRCAntiAffinity)
	framework.ExpectNoError(err)

	if shouldTestPDBs() {
		ginkgo.By("creating a PodDisruptionBudget to cover the ReplicationController")
		_, err = jig.CreatePDB(rc)
		framework.ExpectNoError(err)
	}

	// Hit it once before considering ourselves ready
	ginkgo.By("hitting the pod through the service's LoadBalancer")
	timeout := e2eservice.LoadBalancerLagTimeoutDefault
	if framework.ProviderIs("aws") {
		timeout = e2eservice.LoadBalancerLagTimeoutAWS
	}
	e2eservice.TestReachableHTTP(tcpIngressIP, svcPort, timeout)

	t.jig = jig
	t.tcpService = tcpService
	t.tcpIngressIP = tcpIngressIP
	t.svcPort = svcPort
}

// Test runs a connectivity check to the service.
func (t *ServiceUpgradeTest) Test(f *framework.Framework, done <-chan struct{}, upgrade upgrades.UpgradeType) {
	switch upgrade {
	case upgrades.MasterUpgrade, upgrades.ClusterUpgrade:
		t.test(f, done, true, true)
	case upgrades.NodeUpgrade:
		// Node upgrades should test during disruption only on GCE/GKE for now.
		t.test(f, done, shouldTestPDBs(), false)
	default:
		t.test(f, done, false, false)
	}
}

// Teardown cleans up any remaining resources.
func (t *ServiceUpgradeTest) Teardown(f *framework.Framework) {
	// rely on the namespace deletion to clean up everything
}

func (t *ServiceUpgradeTest) test(f *framework.Framework, done <-chan struct{}, testDuringDisruption, testFinalizer bool) {
	if testDuringDisruption {
		// Continuous validation
		ginkgo.By("continuously hitting the pod through the service's LoadBalancer")
		wait.Until(func() {
			e2eservice.TestReachableHTTP(t.tcpIngressIP, t.svcPort, e2eservice.LoadBalancerLagTimeoutDefault)
		}, framework.Poll, done)
	} else {
		// Block until upgrade is done
		ginkgo.By("waiting for upgrade to finish without checking if service remains up")
		<-done
	}

	// Hit it once more
	ginkgo.By("hitting the pod through the service's LoadBalancer")
	e2eservice.TestReachableHTTP(t.tcpIngressIP, t.svcPort, e2eservice.LoadBalancerLagTimeoutDefault)
	if testFinalizer {
		defer func() {
			ginkgo.By("Check that service can be deleted with finalizer")
			e2eservice.WaitForServiceDeletedWithFinalizer(t.jig.Client, t.tcpService.Namespace, t.tcpService.Name)
		}()
		ginkgo.By("Check that finalizer is present on loadBalancer type service")
		e2eservice.WaitForServiceUpdatedWithFinalizer(t.jig.Client, t.tcpService.Namespace, t.tcpService.Name, true)
	}
}
<|endoftext|>


<commit_before>package portping

import (
	"testing"
	"fmt"
	"net"
	"log"
)

const testHost = "localhost"

// TODO hopefully unused. Better ideas?
const testPort = 1234

const knownNonexistentHost = "nonexistent.janosgyerik.com"

func acceptN(host string, port int, count int) {
	ln, err := net.Listen("tcp", fmt.Sprintf("%s:%d", host, port))
	if err != nil {
		log.Fatal(err)
	}
	defer ln.Close()
	for i := 0; i < count; i++ {
		conn, err := ln.Accept()
		if err != nil {
			log.Fatal(err)
		}
		conn.Close()
	}
}

func ping(host string, port int) bool {
	err := Ping(host, port)
	fmt.Printf("%s:%d %v", host, port, err)
	return err == nil
}

func Test_ping_open_port(t*testing.T) {
	go acceptN(testHost, testPort, 1)

	if !ping(testHost, testPort) {
		t.Errorf("should be open")
	}

	// for sanity: acceptN should have shut down already
	if ping(testHost, testPort) {
		t.Errorf("should be closed")
	}
}

func Test_ping_unopen_port(t*testing.T) {
	if ping(testHost, testPort) {
		t.Errorf("should be closed")
	}
}

func Test_ping_nonexistent_host(t*testing.T) {
	if ping(knownNonexistentHost, testPort) {
		t.Errorf("should be closed")
	}
}

func Test_ping_negative_port(t*testing.T) {
	if ping(testHost, -1) {
		t.Errorf("should be closed")
	}
}

func Test_ping_too_high_port(t*testing.T) {
	if ping(testHost, 123456) {
		t.Errorf("should be closed")
	}
}
<commit_msg>log instead of print<commit_after>package portping

import (
	"testing"
	"fmt"
	"net"
	"log"
)

const testHost = "localhost"

// TODO hopefully unused. Better ideas?
const testPort = 1234

const knownNonexistentHost = "nonexistent.janosgyerik.com"

func acceptN(host string, port int, count int) {
	ln, err := net.Listen("tcp", fmt.Sprintf("%s:%d", host, port))
	if err != nil {
		log.Fatal(err)
	}
	defer ln.Close()
	for i := 0; i < count; i++ {
		conn, err := ln.Accept()
		if err != nil {
			log.Fatal(err)
		}
		conn.Close()
	}
}

func ping(host string, port int) bool {
	err := Ping(host, port)
	log.Printf("port ping %s:%d %v", host, port, err)
	return err == nil
}

func Test_ping_open_port(t*testing.T) {
	go acceptN(testHost, testPort, 1)

	if !ping(testHost, testPort) {
		t.Errorf("should be open")
	}

	// for sanity: acceptN should have shut down already
	if ping(testHost, testPort) {
		t.Errorf("should be closed")
	}
}

func Test_ping_unopen_port(t*testing.T) {
	if ping(testHost, testPort) {
		t.Errorf("should be closed")
	}
}

func Test_ping_nonexistent_host(t*testing.T) {
	if ping(knownNonexistentHost, testPort) {
		t.Errorf("should be closed")
	}
}

func Test_ping_negative_port(t*testing.T) {
	if ping(testHost, -1) {
		t.Errorf("should be closed")
	}
}

func Test_ping_too_high_port(t*testing.T) {
	if ping(testHost, 123456) {
		t.Errorf("should be closed")
	}
}
<|endoftext|>