<commit_before>/*
Copyright 2016 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 framework

import (
	"flag"
	"os"

	"github.com/onsi/ginkgo/config"

	"k8s.io/client-go/tools/clientcmd"
)

const (
	RecommendedConfigPathEnvVar = "CERTMANAGERCONFIG"
)

type TestContextType struct {
	KubeHost    string
	KubeConfig  string
	KubeContext string

	CertManagerHost    string
	CertManagerConfig  string
	CertManagerContext string

	BoulderImageRepo string
	BoulderImageTag  string
	ACMEURL          string

	ReportDir string
}

var TestContext TestContextType

// Register flags common to all e2e test suites.
func RegisterCommonFlags() {
	// Turn on verbose by default to get spec names
	config.DefaultReporterConfig.Verbose = true

	// Turn on EmitSpecProgress to get spec progress (especially on interrupt)
	config.GinkgoConfig.EmitSpecProgress = true

	// Randomize specs as well as suites
	config.GinkgoConfig.RandomizeAllSpecs = true

	flag.StringVar(&TestContext.KubeHost, "kubernetes-host", "http://127.0.0.1:8080", "The kubernetes host, or apiserver, to connect to")
	flag.StringVar(&TestContext.KubeConfig, "kubernetes-config", os.Getenv(clientcmd.RecommendedConfigPathEnvVar), "Path to config containing embedded authinfo for kubernetes. Default value is from environment variable "+clientcmd.RecommendedConfigPathEnvVar)
	flag.StringVar(&TestContext.KubeContext, "kubernetes-context", "", "config context to use for kuberentes. If unset, will use value from 'current-context'")
	flag.StringVar(&TestContext.CertManagerHost, "cert-manager-host", "http://127.0.0.1:30000", "The cert-manager host, or apiserver, to connect to")
	flag.StringVar(&TestContext.CertManagerConfig, "cert-manager-config", os.Getenv(RecommendedConfigPathEnvVar), "Path to config containing embedded authinfo for cert-manager. Default value is from environment variable "+RecommendedConfigPathEnvVar)
	flag.StringVar(&TestContext.CertManagerContext, "cert-manager-context", "", "config context to use for cert-manager. If unset, will use value from 'current-context'")
	flag.StringVar(&TestContext.BoulderImageRepo, "boulder-image-repo", "", "The container image repository for boulder to use in e2e tests")
	flag.StringVar(&TestContext.BoulderImageTag, "boulder-image-tag", "", "The container image tag for boulder to use in e2e tests")
	flag.StringVar(&TestContext.ACMEURL, "acme-url", "http://boulder.boulder.svc.cluster.local:4000/directory", "The ACME test server to use in e2e tests")
	flag.StringVar(&TestContext.ReportDir, "report-dir", "", "Optional directory to store junit output in. If not specified, no junit file will be output")
}

func RegisterParseFlags() {
	RegisterCommonFlags()
	flag.Parse()
}
<commit_msg>Update acme e2e testing endpoint<commit_after>/*
Copyright 2016 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 framework

import (
	"flag"
	"os"

	"github.com/onsi/ginkgo/config"

	"k8s.io/client-go/tools/clientcmd"
)

const (
	RecommendedConfigPathEnvVar = "CERTMANAGERCONFIG"
)

type TestContextType struct {
	KubeHost    string
	KubeConfig  string
	KubeContext string

	CertManagerHost    string
	CertManagerConfig  string
	CertManagerContext string

	BoulderImageRepo string
	BoulderImageTag  string
	ACMEURL          string

	ReportDir string
}

var TestContext TestContextType

// Register flags common to all e2e test suites.
func RegisterCommonFlags() {
	// Turn on verbose by default to get spec names
	config.DefaultReporterConfig.Verbose = true

	// Turn on EmitSpecProgress to get spec progress (especially on interrupt)
	config.GinkgoConfig.EmitSpecProgress = true

	// Randomize specs as well as suites
	config.GinkgoConfig.RandomizeAllSpecs = true

	flag.StringVar(&TestContext.KubeHost, "kubernetes-host", "http://127.0.0.1:8080", "The kubernetes host, or apiserver, to connect to")
	flag.StringVar(&TestContext.KubeConfig, "kubernetes-config", os.Getenv(clientcmd.RecommendedConfigPathEnvVar), "Path to config containing embedded authinfo for kubernetes. Default value is from environment variable "+clientcmd.RecommendedConfigPathEnvVar)
	flag.StringVar(&TestContext.KubeContext, "kubernetes-context", "", "config context to use for kuberentes. If unset, will use value from 'current-context'")
	flag.StringVar(&TestContext.CertManagerHost, "cert-manager-host", "http://127.0.0.1:30000", "The cert-manager host, or apiserver, to connect to")
	flag.StringVar(&TestContext.CertManagerConfig, "cert-manager-config", os.Getenv(RecommendedConfigPathEnvVar), "Path to config containing embedded authinfo for cert-manager. Default value is from environment variable "+RecommendedConfigPathEnvVar)
	flag.StringVar(&TestContext.CertManagerContext, "cert-manager-context", "", "config context to use for cert-manager. If unset, will use value from 'current-context'")
	flag.StringVar(&TestContext.BoulderImageRepo, "boulder-image-repo", "", "The container image repository for boulder to use in e2e tests")
	flag.StringVar(&TestContext.BoulderImageTag, "boulder-image-tag", "", "The container image tag for boulder to use in e2e tests")
	flag.StringVar(&TestContext.ACMEURL, "acme-url", "http://boulder.boulder.svc.cluster.local:4000/dir", "The ACME test server to use in e2e tests")
	flag.StringVar(&TestContext.ReportDir, "report-dir", "", "Optional directory to store junit output in. If not specified, no junit file will be output")
}

func RegisterParseFlags() {
	RegisterCommonFlags()
	flag.Parse()
}
<|endoftext|>


<commit_before>/*
Copyright 2017 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package scheduling

import (
	"os"
	"time"

	"k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/resource"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/uuid"
	extensionsinternal "k8s.io/kubernetes/pkg/apis/extensions"
	"k8s.io/kubernetes/test/e2e/framework"
	imageutils "k8s.io/kubernetes/test/utils/image"

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

const (
	testPodNamePrefix = "nvidia-gpu-"
	// Nvidia driver installation can take upwards of 5 minutes.
	driverInstallTimeout = 10 * time.Minute
)

var (
	gpuResourceName v1.ResourceName
	dsYamlUrl       string
)

func makeCudaAdditionDevicePluginTestPod() *v1.Pod {
	podName := testPodNamePrefix + string(uuid.NewUUID())
	testPod := &v1.Pod{
		ObjectMeta: metav1.ObjectMeta{
			Name: podName,
		},
		Spec: v1.PodSpec{
			RestartPolicy: v1.RestartPolicyNever,
			Containers: []v1.Container{
				{
					Name:  "vector-addition",
					Image: imageutils.GetE2EImage(imageutils.CudaVectorAdd),
					Resources: v1.ResourceRequirements{
						Limits: v1.ResourceList{
							gpuResourceName: *resource.NewQuantity(1, resource.DecimalSI),
						},
					},
				},
			},
		},
	}
	return testPod
}

func logOSImages(f *framework.Framework) {
	nodeList, err := f.ClientSet.CoreV1().Nodes().List(metav1.ListOptions{})
	framework.ExpectNoError(err, "getting node list")
	for _, node := range nodeList.Items {
		framework.Logf("Nodename: %v, OS Image: %v", node.Name, node.Status.NodeInfo.OSImage)
	}
}

func areGPUsAvailableOnAllSchedulableNodes(f *framework.Framework) bool {
	framework.Logf("Getting list of Nodes from API server")
	nodeList, err := f.ClientSet.CoreV1().Nodes().List(metav1.ListOptions{})
	framework.ExpectNoError(err, "getting node list")
	for _, node := range nodeList.Items {
		if node.Spec.Unschedulable {
			continue
		}
		framework.Logf("gpuResourceName %s", gpuResourceName)
		if val, ok := node.Status.Capacity[gpuResourceName]; !ok || val.Value() == 0 {
			framework.Logf("Nvidia GPUs not available on Node: %q", node.Name)
			return false
		}
	}
	framework.Logf("Nvidia GPUs exist on all schedulable nodes")
	return true
}

func getGPUsAvailable(f *framework.Framework) int64 {
	nodeList, err := f.ClientSet.CoreV1().Nodes().List(metav1.ListOptions{})
	framework.ExpectNoError(err, "getting node list")
	var gpusAvailable int64
	for _, node := range nodeList.Items {
		if val, ok := node.Status.Capacity[gpuResourceName]; ok {
			gpusAvailable += (&val).Value()
		}
	}
	return gpusAvailable
}

func SetupNVIDIAGPUNode(f *framework.Framework, setupResourceGatherer bool) *framework.ContainerResourceGatherer {
	logOSImages(f)

	dsYamlUrlFromEnv := os.Getenv("NVIDIA_DRIVER_INSTALLER_DAEMONSET")
	if dsYamlUrlFromEnv != "" {
		dsYamlUrl = dsYamlUrlFromEnv
	} else {
		dsYamlUrl = "https://raw.githubusercontent.com/GoogleCloudPlatform/container-engine-accelerators/master/daemonset.yaml"
	}
	gpuResourceName = framework.NVIDIAGPUResourceName

	framework.Logf("Using %v", dsYamlUrl)
	// Creates the DaemonSet that installs Nvidia Drivers.
	ds, err := framework.DsFromManifest(dsYamlUrl)
	Expect(err).NotTo(HaveOccurred())
	ds.Namespace = f.Namespace.Name
	_, err = f.ClientSet.AppsV1().DaemonSets(f.Namespace.Name).Create(ds)
	framework.ExpectNoError(err, "failed to create nvidia-driver-installer daemonset")
	framework.Logf("Successfully created daemonset to install Nvidia drivers.")

	pods, err := framework.WaitForControlledPods(f.ClientSet, ds.Namespace, ds.Name, extensionsinternal.Kind("DaemonSet"))
	framework.ExpectNoError(err, "failed to get pods controlled by the nvidia-driver-installer daemonset")

	devicepluginPods, err := framework.WaitForControlledPods(f.ClientSet, "kube-system", "nvidia-gpu-device-plugin", extensionsinternal.Kind("DaemonSet"))
	if err == nil {
		framework.Logf("Adding deviceplugin addon pod.")
		pods.Items = append(pods.Items, devicepluginPods.Items...)
	}

	var rsgather *framework.ContainerResourceGatherer
	if setupResourceGatherer {
		framework.Logf("Starting ResourceUsageGather for the created DaemonSet pods.")
		rsgather, err = framework.NewResourceUsageGatherer(f.ClientSet, framework.ResourceGathererOptions{InKubemark: false, MasterOnly: false, ResourceDataGatheringPeriod: 2 * time.Second, ProbeDuration: 2 * time.Second, PrintVerboseLogs: true}, pods)
		framework.ExpectNoError(err, "creating ResourceUsageGather for the daemonset pods")
		go rsgather.StartGatheringData()
	}

	// Wait for Nvidia GPUs to be available on nodes
	framework.Logf("Waiting for drivers to be installed and GPUs to be available in Node Capacity...")
	Eventually(func() bool {
		return areGPUsAvailableOnAllSchedulableNodes(f)
	}, driverInstallTimeout, time.Second).Should(BeTrue())

	return rsgather
}

func testNvidiaGPUs(f *framework.Framework) {
	rsgather := SetupNVIDIAGPUNode(f, true)
	framework.Logf("Creating as many pods as there are Nvidia GPUs and have the pods run a CUDA app")
	podList := []*v1.Pod{}
	for i := int64(0); i < getGPUsAvailable(f); i++ {
		podList = append(podList, f.PodClient().Create(makeCudaAdditionDevicePluginTestPod()))
	}
	framework.Logf("Wait for all test pods to succeed")
	// Wait for all pods to succeed
	for _, po := range podList {
		f.PodClient().WaitForSuccess(po.Name, 5*time.Minute)
	}

	framework.Logf("Stopping ResourceUsageGather")
	constraints := make(map[string]framework.ResourceConstraint)
	// For now, just gets summary. Can pass valid constraints in the future.
	summary, err := rsgather.StopAndSummarize([]int{50, 90, 100}, constraints)
	f.TestSummaries = append(f.TestSummaries, summary)
	framework.ExpectNoError(err, "getting resource usage summary")
}

var _ = SIGDescribe("[Feature:GPUDevicePlugin]", func() {
	f := framework.NewDefaultFramework("device-plugin-gpus")
	It("run Nvidia GPU Device Plugin tests", func() {
		testNvidiaGPUs(f)
	})
})
<commit_msg>Got allocatable GPUs.<commit_after>/*
Copyright 2017 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package scheduling

import (
	"os"
	"time"

	"k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/resource"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/uuid"
	extensionsinternal "k8s.io/kubernetes/pkg/apis/extensions"
	"k8s.io/kubernetes/test/e2e/framework"
	imageutils "k8s.io/kubernetes/test/utils/image"

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

const (
	testPodNamePrefix = "nvidia-gpu-"
	// Nvidia driver installation can take upwards of 5 minutes.
	driverInstallTimeout = 10 * time.Minute
)

var (
	gpuResourceName v1.ResourceName
	dsYamlUrl       string
)

func makeCudaAdditionDevicePluginTestPod() *v1.Pod {
	podName := testPodNamePrefix + string(uuid.NewUUID())
	testPod := &v1.Pod{
		ObjectMeta: metav1.ObjectMeta{
			Name: podName,
		},
		Spec: v1.PodSpec{
			RestartPolicy: v1.RestartPolicyNever,
			Containers: []v1.Container{
				{
					Name:  "vector-addition",
					Image: imageutils.GetE2EImage(imageutils.CudaVectorAdd),
					Resources: v1.ResourceRequirements{
						Limits: v1.ResourceList{
							gpuResourceName: *resource.NewQuantity(1, resource.DecimalSI),
						},
					},
				},
			},
		},
	}
	return testPod
}

func logOSImages(f *framework.Framework) {
	nodeList, err := f.ClientSet.CoreV1().Nodes().List(metav1.ListOptions{})
	framework.ExpectNoError(err, "getting node list")
	for _, node := range nodeList.Items {
		framework.Logf("Nodename: %v, OS Image: %v", node.Name, node.Status.NodeInfo.OSImage)
	}
}

func areGPUsAvailableOnAllSchedulableNodes(f *framework.Framework) bool {
	framework.Logf("Getting list of Nodes from API server")
	nodeList, err := f.ClientSet.CoreV1().Nodes().List(metav1.ListOptions{})
	framework.ExpectNoError(err, "getting node list")
	for _, node := range nodeList.Items {
		if node.Spec.Unschedulable {
			continue
		}
		framework.Logf("gpuResourceName %s", gpuResourceName)
		if val, ok := node.Status.Capacity[gpuResourceName]; !ok || val.Value() == 0 {
			framework.Logf("Nvidia GPUs not available on Node: %q", node.Name)
			return false
		}
	}
	framework.Logf("Nvidia GPUs exist on all schedulable nodes")
	return true
}

func getGPUsAvailable(f *framework.Framework) int64 {
	nodeList, err := f.ClientSet.CoreV1().Nodes().List(metav1.ListOptions{})
	framework.ExpectNoError(err, "getting node list")
	var gpusAvailable int64
	for _, node := range nodeList.Items {
		if val, ok := node.Status.Allocatable[gpuResourceName]; ok {
			gpusAvailable += (&val).Value()
		}
	}
	return gpusAvailable
}

func SetupNVIDIAGPUNode(f *framework.Framework, setupResourceGatherer bool) *framework.ContainerResourceGatherer {
	logOSImages(f)

	dsYamlUrlFromEnv := os.Getenv("NVIDIA_DRIVER_INSTALLER_DAEMONSET")
	if dsYamlUrlFromEnv != "" {
		dsYamlUrl = dsYamlUrlFromEnv
	} else {
		dsYamlUrl = "https://raw.githubusercontent.com/GoogleCloudPlatform/container-engine-accelerators/master/daemonset.yaml"
	}
	gpuResourceName = framework.NVIDIAGPUResourceName

	framework.Logf("Using %v", dsYamlUrl)
	// Creates the DaemonSet that installs Nvidia Drivers.
	ds, err := framework.DsFromManifest(dsYamlUrl)
	Expect(err).NotTo(HaveOccurred())
	ds.Namespace = f.Namespace.Name
	_, err = f.ClientSet.AppsV1().DaemonSets(f.Namespace.Name).Create(ds)
	framework.ExpectNoError(err, "failed to create nvidia-driver-installer daemonset")
	framework.Logf("Successfully created daemonset to install Nvidia drivers.")

	pods, err := framework.WaitForControlledPods(f.ClientSet, ds.Namespace, ds.Name, extensionsinternal.Kind("DaemonSet"))
	framework.ExpectNoError(err, "failed to get pods controlled by the nvidia-driver-installer daemonset")

	devicepluginPods, err := framework.WaitForControlledPods(f.ClientSet, "kube-system", "nvidia-gpu-device-plugin", extensionsinternal.Kind("DaemonSet"))
	if err == nil {
		framework.Logf("Adding deviceplugin addon pod.")
		pods.Items = append(pods.Items, devicepluginPods.Items...)
	}

	var rsgather *framework.ContainerResourceGatherer
	if setupResourceGatherer {
		framework.Logf("Starting ResourceUsageGather for the created DaemonSet pods.")
		rsgather, err = framework.NewResourceUsageGatherer(f.ClientSet, framework.ResourceGathererOptions{InKubemark: false, MasterOnly: false, ResourceDataGatheringPeriod: 2 * time.Second, ProbeDuration: 2 * time.Second, PrintVerboseLogs: true}, pods)
		framework.ExpectNoError(err, "creating ResourceUsageGather for the daemonset pods")
		go rsgather.StartGatheringData()
	}

	// Wait for Nvidia GPUs to be available on nodes
	framework.Logf("Waiting for drivers to be installed and GPUs to be available in Node Capacity...")
	Eventually(func() bool {
		return areGPUsAvailableOnAllSchedulableNodes(f)
	}, driverInstallTimeout, time.Second).Should(BeTrue())

	return rsgather
}

func testNvidiaGPUs(f *framework.Framework) {
	rsgather := SetupNVIDIAGPUNode(f, true)
	framework.Logf("Creating as many pods as there are Nvidia GPUs and have the pods run a CUDA app")
	podList := []*v1.Pod{}
	for i := int64(0); i < getGPUsAvailable(f); i++ {
		podList = append(podList, f.PodClient().Create(makeCudaAdditionDevicePluginTestPod()))
	}
	framework.Logf("Wait for all test pods to succeed")
	// Wait for all pods to succeed
	for _, po := range podList {
		f.PodClient().WaitForSuccess(po.Name, 5*time.Minute)
	}

	framework.Logf("Stopping ResourceUsageGather")
	constraints := make(map[string]framework.ResourceConstraint)
	// For now, just gets summary. Can pass valid constraints in the future.
	summary, err := rsgather.StopAndSummarize([]int{50, 90, 100}, constraints)
	f.TestSummaries = append(f.TestSummaries, summary)
	framework.ExpectNoError(err, "getting resource usage summary")
}

var _ = SIGDescribe("[Feature:GPUDevicePlugin]", func() {
	f := framework.NewDefaultFramework("device-plugin-gpus")
	It("run Nvidia GPU Device Plugin tests", func() {
		testNvidiaGPUs(f)
	})
})
<|endoftext|>


<commit_before>package libgodelbrot

import (
    "encoding/json"
    "io"
    "math/big"
    "github.com/johnny-morrice/godelbrot/internal/bigbase"
)

type ZoomTarget struct {
    Xmin uint
    Xmax uint
    Ymin uint
    Ymax uint
    // Reconsider numerical system and render modes as appropriate.
    Reconfigure bool
    // Increase precision.  With Reconfigure, this should automatically engage arbitrary
    // precision mode.
    UpPrec bool
}

// Zoom into a portion of the previous image.
type Zoom struct {
    Prev Info
    ZoomTarget
}

type distort struct {
    prev big.Float
    next big.Float
}

func (d distort) para(time *big.Float) *big.Float {
    prec := d.next.Prec()
    delta := bigbase.MakeBigFloat(0.0, prec)
    delta.Sub(&d.prev, &d.next)
    delta.Abs(&delta)
    delta.Mul(&delta, time)
    if d.prev.Cmp(&d.next) > 0 {
        return delta.Sub(&d.prev, &delta)
    } else {
        return delta.Add(&d.prev, &delta)
    }
}

// Frame zooms towards the target coordinates.  Degree = 1 is a complete zoom.
func (z *Zoom) rescope(degree float64) (*Info, error) {
    info := z.lens(degree)

    if z.Reconfigure {
        return Configure(&info.UserRequest)
    } else {
        return info, nil
    }
}

func (z *Zoom) Magnify(degree float64) (*Info, error) {
    info := z.lens(degree)

    if z.UpPrec {
        for !info.IsAccurate() {
            z.Prev.AddPrec(1)
            z.Prev.UserRequest = z.Prev.GenRequest()
            info = z.lens(degree)
        }
    }

    if z.Reconfigure {
        return Configure(&info.UserRequest)
    } else {
        return info, nil
    }
}

func (z *Zoom) lens(degree float64) *Info {
    baseapp := makeBaseFacade(&z.Prev)
    app := makeBigBaseFacade(&z.Prev, baseapp)
    num := bigbase.Make(app)

    req := new(Request)
    *req = z.Prev.UserRequest

    time := bigbase.MakeBigFloat(degree, num.Precision)

    // Flip Y axis
    min := num.PixelToPlane(int(z.Xmin), int(z.Ymin))
    max := num.PixelToPlane(int(z.Xmax), int(z.Ymax))

    target := []big.Float{
        min.R,
        min.I,
        max.R,
        max.I,
    }

    bounds := []big.Float{
        z.Prev.RealMin,
        z.Prev.ImagMin,
        z.Prev.RealMax,
        z.Prev.ImagMax,
    }
    zoom := make([]*big.Float, len(bounds))
    for i, b := range bounds {
        d := distort{
            prev: b,
            next: target[i],
        }

        zoom[i] = d.para(&time)
    }

    req.RealMin = emitBig(zoom[0])
    req.ImagMin = emitBig(zoom[1])
    req.RealMax = emitBig(zoom[2])
    req.ImagMax = emitBig(zoom[3])

    info := new(Info)
    *info = z.Prev
    info.UserRequest = *req
    info.RealMin = *zoom[0]
    info.ImagMin = *zoom[1]
    info.RealMax = *zoom[2]
    info.ImagMax = *zoom[3]

    return info
}

// Movie is a parametric expansion of frames.
func (z *Zoom) Movie(count uint) ([]*Info, error) {
    if count == 0 {
        return []*Info{}, nil
    }

    // Compute last frame first to encourage numerical stability
    const fullZoom = 1.0
    last, lerr := z.Magnify(fullZoom)
    if lerr != nil {
        return nil, lerr
    }

    // Compute intervening frames
    interval := 1.0 / float64(count)
    time := 0.0
    frames := make([]*Info, count)
    for i := uint(0); i < count - 1; i++ {
        time += interval
        info, err := z.rescope(time)
        if err != nil {
            return nil, err
        }
        frames[i] = info
    }

    frames[count - 1] = last
    return frames, nil
}

type UserZoom struct {
    Prev UserInfo
    ZoomTarget
}

func ReadZoom(r io.Reader) (*Zoom, error) {
    uz := &UserZoom{}
    dec := json.NewDecoder(r)
    decerr := dec.Decode(uz)
    if decerr != nil {
        return nil, decerr
    }

    info, inferr := Unfriendly(&uz.Prev)
    if inferr != nil {
        return nil, inferr
    }

    z := &Zoom{}
    z.Prev = *info
    z.ZoomTarget = uz.ZoomTarget
    return z, nil
}

func WriteZoom(w io.Writer, z *Zoom) error {
    uz := &UserZoom{}
    uz.Prev = *Friendly(&z.Prev)
    uz.ZoomTarget = z.ZoomTarget

    enc := json.NewEncoder(w)
    err := enc.Encode(uz)
    if err != nil {
        return err
    }
    return nil
}<commit_msg>Tidy up zoom code<commit_after>package libgodelbrot

import (
    "encoding/json"
    "io"
    "math/big"
    "github.com/johnny-morrice/godelbrot/internal/bigbase"
)

type ZoomTarget struct {
    Xmin uint
    Xmax uint
    Ymin uint
    Ymax uint
    // Reconsider numerical system and render modes as appropriate.
    Reconfigure bool
    // Increase precision.  With Reconfigure, this should automatically engage arbitrary
    // precision mode.
    UpPrec bool
}

// Zoom into a portion of the previous image.
type Zoom struct {
    Prev Info
    ZoomTarget
}

type distort struct {
    prev big.Float
    next big.Float
}

func (d distort) para(time *big.Float) *big.Float {
    prec := d.next.Prec()
    delta := bigbase.MakeBigFloat(0.0, prec)
    delta.Sub(&d.prev, &d.next)
    delta.Abs(&delta)
    delta.Mul(&delta, time)
    if d.prev.Cmp(&d.next) > 0 {
        return delta.Sub(&d.prev, &delta)
    } else {
        return delta.Add(&d.prev, &delta)
    }
}

// Frame zooms towards the target coordinates.  Degree = 1 is a complete zoom.
func (z *Zoom) rescope(degree float64) (*Info, error) {
    info := z.lens(degree)

    if z.Reconfigure {
        return Configure(&info.UserRequest)
    } else {
        return info, nil
    }
}

func (z *Zoom) lens(degree float64) *Info {
    baseapp := makeBaseFacade(&z.Prev)
    app := makeBigBaseFacade(&z.Prev, baseapp)
    num := bigbase.Make(app)

    time := bigbase.MakeBigFloat(degree, num.Precision)

    min := num.PixelToPlane(int(z.Xmin), int(z.Ymin))
    max := num.PixelToPlane(int(z.Xmax), int(z.Ymax))

    target := []big.Float{
        min.R,
        min.I,
        max.R,
        max.I,
    }

    bounds := []big.Float{
        z.Prev.RealMin,
        z.Prev.ImagMin,
        z.Prev.RealMax,
        z.Prev.ImagMax,
    }
    zoom := make([]*big.Float, len(bounds))
    for i, b := range bounds {
        d := distort{
            prev: b,
            next: target[i],
        }

        zoom[i] = d.para(&time)
    }

    info := new(Info)
    *info = z.Prev
    info.RealMin = *zoom[0]
    info.ImagMin = *zoom[1]
    info.RealMax = *zoom[2]
    info.ImagMax = *zoom[3]
    info.UserRequest = info.GenRequest()

    return info
}

func (z *Zoom) Magnify(degree float64) (*Info, error) {
    info := z.lens(degree)

    if z.UpPrec {
        for !info.IsAccurate() {
            z.Prev.AddPrec(1)
            z.Prev.UserRequest = z.Prev.GenRequest()
            info = z.lens(degree)
        }
    }

    if z.Reconfigure {
        return Configure(&info.UserRequest)
    } else {
        return info, nil
    }
}

// Movie is a parametric expansion of frames.
func (z *Zoom) Movie(count uint) ([]*Info, error) {
    if count == 0 {
        return []*Info{}, nil
    }

    // Compute last frame first to encourage numerical stability
    const fullZoom = 1.0
    last, lerr := z.Magnify(fullZoom)
    if lerr != nil {
        return nil, lerr
    }

    // Compute intervening frames
    interval := 1.0 / float64(count)
    time := 0.0
    frames := make([]*Info, count)
    for i := uint(0); i < count - 1; i++ {
        time += interval
        info, err := z.rescope(time)
        if err != nil {
            return nil, err
        }
        frames[i] = info
    }

    frames[count - 1] = last
    return frames, nil
}

type UserZoom struct {
    Prev UserInfo
    ZoomTarget
}

func ReadZoom(r io.Reader) (*Zoom, error) {
    uz := &UserZoom{}
    dec := json.NewDecoder(r)
    decerr := dec.Decode(uz)
    if decerr != nil {
        return nil, decerr
    }

    info, inferr := Unfriendly(&uz.Prev)
    if inferr != nil {
        return nil, inferr
    }

    z := &Zoom{}
    z.Prev = *info
    z.ZoomTarget = uz.ZoomTarget
    return z, nil
}

func WriteZoom(w io.Writer, z *Zoom) error {
    uz := &UserZoom{}
    uz.Prev = *Friendly(&z.Prev)
    uz.ZoomTarget = z.ZoomTarget

    enc := json.NewEncoder(w)
    err := enc.Encode(uz)
    if err != nil {
        return err
    }
    return nil
}<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"sort"
	"strings"

	"github.com/tobstarr/wlcli/Godeps/_workspace/src/github.com/dynport/gocli"
	"github.com/tobstarr/wlcli/wlclient"
)

type listInboxAction struct {
	listID int
	Tag    string `cli:"opt --tag"`
}

func (r *listInboxAction) Run() error {
	cl, err := loadClient()
	if err != nil {
		return err
	}
	listID := r.listID
	if listID == 0 {
		ib, err := cl.Inbox()
		if err != nil {
			return err
		}
		listID = ib.ID
	}

	tasks, err := cl.Tasks(wlclient.ListID(listID))
	if err != nil {
		return err
	}

	if len(tasks) == 0 {
		fmt.Printf("no tasks found. use `wlcli push` to create one\n")
		return nil
	}
	sort.Sort(tasks)
	t := gocli.NewTable()
	for _, task := range tasks {
		if r.Tag != "" && !matchesTag(task.Title, r.Tag) {
			continue
		}
		t.Add(task.CreatedAt.Format("2006-02-01 15:04:05"), task.ID, task.Title)
	}
	fmt.Println(t)
	return nil
}

func matchesTag(text, tag string) bool {
	tag = strings.ToLower(tag)
	for _, f := range strings.Fields(strings.ToLower(text)) {
		if f == "#"+tag {
			return true
		}
	}
	return false
}
<commit_msg>add --limit --all and --full flags<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"sort"
	"strings"

	"github.com/tobstarr/wlcli/Godeps/_workspace/src/github.com/dynport/gocli"
	"github.com/tobstarr/wlcli/wlclient"
)

type listInboxAction struct {
	listID int
	Tag    string `cli:"opt --tag"`
	Limit  int    `cli:"opt --limit default=25"`
	All    bool   `cli:"opt --all"`
	Full   bool   `cli:"opt --full"`
}

// this should be a generic inbox action
func (r *listInboxAction) Run() error {
	cl, err := loadClient()
	if err != nil {
		return err
	}
	listID := r.listID
	if listID == 0 {
		ib, err := cl.Inbox()
		if err != nil {
			return err
		}
		listID = ib.ID
	}

	if dataOnStdin() {
		b, err := ioutil.ReadAll(os.Stdin)
		if err != nil {
			return err
		}
		task, err := cl.CreateTask(&wlclient.Task{ListID: listID, Title: strings.TrimSpace(string(b))})
		if err != nil {
			return err
		}
		return json.NewEncoder(os.Stdout).Encode(task)
		return nil
	}
	tasks, err := cl.Tasks(wlclient.ListID(listID))
	if err != nil {
		return err
	}

	pos, err := cl.TaskPositions(listID)
	if err != nil {
		return err
	}
	if len(pos) == 0 {
		return fmt.Errorf("unable to get positions for list %d", listID)
	}

	if len(tasks) == 0 {
		fmt.Printf("no tasks found. use `wlcli push` to create one\n")
		return nil
	}
	sort.Sort(tasks)
	t := gocli.NewTable()
	tm := map[int]*wlclient.Task{}
	for _, t := range tasks {
		tm[t.ID] = t
	}

	positions := pos[0].Values
	for i, p := range positions {
		task, ok := tm[p]
		if !ok {
			continue
		}
		delete(tm, p)
		if r.Tag != "" && !matchesTag(task.Title, r.Tag) {
			continue
		}
		title := task.Title
		if !r.Full {
			title = truncate(title, 64)
		}
		if i < r.Limit && !r.All {
			t.Add(task.ID, title)
		}
	}
	for _, task := range tm {
		if r.Tag != "" && !matchesTag(task.Title, r.Tag) {
			continue
		}
		t.Add(task.ID, truncate(task.Title, 64))
	}
	fmt.Println(t)
	return nil
}

func dataOnStdin() bool {
	stat, err := os.Stdin.Stat()
	if err != nil {
		return false
	}
	return (stat.Mode() & os.ModeCharDevice) == 0
}

// this is naive!!!
func truncate(in string, max int) string {
	parts := strings.Split(in, "")
	if len(parts) < max {
		return in
	}
	return strings.Join(parts[0:max], "")
}

func matchesTag(text, tag string) bool {
	tag = strings.ToLower(tag)
	for _, f := range strings.Fields(strings.ToLower(text)) {
		if f == "#"+tag {
			return true
		}
	}
	return false
}
<|endoftext|>


<commit_before>/*
   Copyright 2020 Docker Compose CLI 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 compose

import (
	"context"
	"fmt"
	"io"
	"os"

	"github.com/compose-spec/compose-go/types"
	"github.com/docker/compose-cli/api/compose"
	convert "github.com/docker/compose-cli/local/moby"
	apitypes "github.com/docker/docker/api/types"
	moby "github.com/docker/docker/pkg/stringid"
)

func (s *composeService) RunOneOffContainer(ctx context.Context, project *types.Project, opts compose.RunOptions) (string, error) {
	originalServices := project.Services
	var requestedService types.ServiceConfig
	for _, service := range originalServices {
		if service.Name == opts.Name {
			requestedService = service
		}
	}

	project.Services = originalServices
	if len(opts.Command) > 0 {
		requestedService.Command = opts.Command
	}
	requestedService.Scale = 1
	requestedService.Tty = true
	requestedService.StdinOpen = true

	slug := moby.GenerateRandomID()
	requestedService.ContainerName = fmt.Sprintf("%s_%s_run_%s", project.Name, requestedService.Name, moby.TruncateID(slug))
	requestedService.Labels = requestedService.Labels.Add(slugLabel, slug)
	requestedService.Labels = requestedService.Labels.Add(oneoffLabel, "True")

	if err := s.waitDependencies(ctx, project, requestedService); err != nil {
		return "", err
	}
	err := s.createContainer(ctx, project, requestedService, requestedService.ContainerName, 1)
	if err != nil {
		return "", err
	}

	containerID := requestedService.ContainerName

	if opts.Detach {
		return containerID, s.apiClient.ContainerStart(ctx, containerID, apitypes.ContainerStartOptions{})
	}

	cnx, err := s.apiClient.ContainerAttach(ctx, containerID, apitypes.ContainerAttachOptions{
		Stream: true,
		Stdin:  true,
		Stdout: true,
		Stderr: true,
		Logs:   true,
	})
	if err != nil {
		return containerID, err
	}
	defer cnx.Close()

	stdout := convert.ContainerStdout{HijackedResponse: cnx}
	stdin := convert.ContainerStdin{HijackedResponse: cnx}

	readChannel := make(chan error, 10)
	writeChannel := make(chan error, 10)

	go func() {
		_, err := io.Copy(os.Stdout, cnx.Reader)
		readChannel <- err
	}()

	go func() {
		_, err := io.Copy(stdin, os.Stdin)
		writeChannel <- err
	}()

	go func() {
		<-ctx.Done()
		stdout.Close() //nolint:errcheck
		stdin.Close()  //nolint:errcheck
	}()

	// start container
	err = s.apiClient.ContainerStart(ctx, containerID, apitypes.ContainerStartOptions{})
	if err != nil {
		return containerID, err
	}

	for {
		select {
		case err := <-readChannel:
			return containerID, err
		case err := <-writeChannel:
			return containerID, err
		}
	}
}
<commit_msg>Attach to container using compose attach<commit_after>/*
   Copyright 2020 Docker Compose CLI 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 compose

import (
	"context"
	"fmt"
	"os"

	"github.com/compose-spec/compose-go/types"
	"github.com/docker/compose-cli/api/compose"
	"github.com/docker/compose-cli/utils"
	apitypes "github.com/docker/docker/api/types"
	"github.com/docker/docker/api/types/filters"
	"golang.org/x/sync/errgroup"

	moby "github.com/docker/docker/pkg/stringid"
)

func (s *composeService) RunOneOffContainer(ctx context.Context, project *types.Project, opts compose.RunOptions) (string, error) {
	originalServices := project.Services
	var requestedService types.ServiceConfig
	for _, service := range originalServices {
		if service.Name == opts.Name {
			requestedService = service
		}
	}

	project.Services = originalServices
	if len(opts.Command) > 0 {
		requestedService.Command = opts.Command
	}
	requestedService.Scale = 1
	requestedService.Tty = true
	requestedService.StdinOpen = true

	slug := moby.GenerateRandomID()
	requestedService.ContainerName = fmt.Sprintf("%s_%s_run_%s", project.Name, requestedService.Name, moby.TruncateID(slug))
	requestedService.Labels = requestedService.Labels.Add(slugLabel, slug)
	requestedService.Labels = requestedService.Labels.Add(oneoffLabel, "True")

	if err := s.waitDependencies(ctx, project, requestedService); err != nil {
		return "", err
	}
	err := s.createContainer(ctx, project, requestedService, requestedService.ContainerName, 1)
	if err != nil {
		return "", err
	}

	containerID := requestedService.ContainerName

	if opts.Detach {
		return containerID, s.apiClient.ContainerStart(ctx, containerID, apitypes.ContainerStartOptions{})
	}

	containers, err := s.apiClient.ContainerList(ctx, apitypes.ContainerListOptions{
		Filters: filters.NewArgs(
			projectFilter(project.Name),
		),
		All: true,
	})
	if err != nil {
		return "", err
	}
	var oneoffContainer apitypes.Container
	for _, container := range containers {
		if utils.StringContains(container.Names, "/"+containerID) {
			oneoffContainer = container
		}
	}
	eg := errgroup.Group{}
	eg.Go(func() error {
		return s.attachContainerStreams(ctx, oneoffContainer, true, os.Stdin, os.Stdout)
	})
	if err != nil {
		return "", err
	}

	err = s.apiClient.ContainerStart(ctx, containerID, apitypes.ContainerStartOptions{})
	if err != nil {
		return "", err
	}
	err = eg.Wait()
	return containerID, err
}
<|endoftext|>


<commit_before>package tui

type Color int

const (
	ColorDefault Color = iota
	ColorBlack
	ColorWhite
	ColorRed
	ColorGreen
	ColorBlue
	ColorCyan
	ColorMagenta
	ColorYellow
)

type Style struct {
	Fg Color
	Bg Color
}

type Theme struct {
	styles map[string]Style
}

var DefaultTheme = &Theme{
	styles: map[string]Style{
		"normal":              {ColorDefault, ColorDefault},
		"list.item.selected":  {ColorWhite, ColorBlue},
		"table.cell.selected": {ColorWhite, ColorBlue},
		"button.focused":      {ColorWhite, ColorBlue},
		"box.focused":         {ColorWhite, ColorBlue},
	},
}

func NewTheme() *Theme {
	return &Theme{
		styles: make(map[string]Style),
	}
}

func (p *Theme) SetStyle(n string, i Style) {
	p.styles[n] = i
}

func (p *Theme) Style(name string) Style {
	if c, ok := p.styles[name]; ok {
		return c
	}
	return Style{ColorDefault, ColorDefault}
}
<commit_msg>better default for `box.focused`<commit_after>package tui

type Color int

const (
	ColorDefault Color = iota
	ColorBlack
	ColorWhite
	ColorRed
	ColorGreen
	ColorBlue
	ColorCyan
	ColorMagenta
	ColorYellow
)

type Style struct {
	Fg Color
	Bg Color
}

type Theme struct {
	styles map[string]Style
}

var DefaultTheme = &Theme{
	styles: map[string]Style{
		"normal":              {ColorDefault, ColorDefault},
		"list.item.selected":  {ColorWhite, ColorBlue},
		"table.cell.selected": {ColorWhite, ColorBlue},
		"button.focused":      {ColorWhite, ColorBlue},
		"box.focused":         {ColorYellow, ColorDefault},
	},
}

func NewTheme() *Theme {
	return &Theme{
		styles: make(map[string]Style),
	}
}

func (p *Theme) SetStyle(n string, i Style) {
	p.styles[n] = i
}

func (p *Theme) Style(name string) Style {
	if c, ok := p.styles[name]; ok {
		return c
	}
	return Style{ColorDefault, ColorDefault}
}
<|endoftext|>


<commit_before>package main

import (
	cli "github.com/spf13/cobra"

	"github.com/tmrts/tmplt/pkg/cmd"
)

func main() {
	mainCmd := &cli.Command{
		Use: "tmplt",
	}

	mainCmd.AddCommand(cmd.Use)
	mainCmd.AddCommand(cmd.Save)
	mainCmd.AddCommand(cmd.Verify)
	mainCmd.AddCommand(cmd.Version)

	mainCmd.Execute()
}
<commit_msg>Trim down main pkg<commit_after>package main

import "github.com/tmrts/tmplt/pkg/cmd"

func main() {
	cmd.Run()
}
<|endoftext|>


<commit_before>/*
*  Copyright (c) WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
*  WSO2 Inc. licenses this file to you 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 cmd

import (
	"fmt"

	"bytes"
	"crypto/tls"
	"io"
	"mime/multipart"
	"net/http"
	"os"
	"path/filepath"

	"github.com/renstrom/dedent"
	"github.com/spf13/cobra"
	"github.com/wso2/product-apim-tooling/import-export-cli/utils"
	"regexp"
	"strings"
	"time"
)

var flagImportApiFile string
var flagImportApiEnvironment string
var importAPICmdUsername string
var importAPICmdPassword string
var flagImportApiCmdToken string

// ImportAPI command related usage info
const importAPICmdLiteral = "import-api"
const importAPICmdShortDesc = "Import API"

var importAPICmdLongDesc = "Import an API to an environment"

var importAPICmdExamples = dedent.Dedent(`
		Examples:
		` + utils.ProjectName + ` ` + importAPICmdLiteral + ` -n qa/TwitterAPI.zip -e dev
		` + utils.ProjectName + ` ` + importAPICmdLiteral + ` -n staging/FacebookAPI.zip -e production
	`)

// ImportAPICmd represents the importAPI command
var ImportAPICmd = &cobra.Command{
	Use: importAPICmdLiteral + " (--file <api-zip-file> --environment " +
		"<environment-to-which-the-api-should-be-imported>)",
	Short: importAPICmdShortDesc,
	Long:  importAPICmdLongDesc + importAPICmdExamples,
	Run: func(cmd *cobra.Command, args []string) {
		utils.Logln(utils.LogPrefixInfo + importAPICmdLiteral + " called")
		executeImportApiCmd(utils.MainConfigFilePath, utils.EnvKeysAllFilePath, utils.ExportDirectory)
	},
}

func executeImportApiCmd(mainConfigFilePath, keysAllFilePath, exportDirectory string) {
	if flagExportAPICmdToken != "" {
		// token provided with --token (-t) flag
		if exportAPICmdUsername != "" || exportAPICmdPassword != "" {
			// username and/or password provided with -u and/or -p flags
			// Error
			utils.HandleErrorAndExit("username/password provided with OAuth token.", nil)
		} else {
			// token only, proceed with token
		}
	} else {
		// no token provided with --token (-t) flag
		// proceed with username and password
		accessToken, apiManagerEndpoint, preCommandErr := utils.ExecutePreCommand(flagImportApiEnvironment,
			importAPICmdUsername, importAPICmdPassword, mainConfigFilePath, keysAllFilePath)

		if preCommandErr == nil {
			resp, err := ImportAPI(flagImportApiFile, apiManagerEndpoint, accessToken, exportDirectory)

			if err != nil {
				utils.HandleErrorAndExit("error importing API", err)
			}

			if resp.StatusCode == 200 {
				utils.Logln("Header:", resp.Header)
				fmt.Println("Succesfully imported API!")
			} else {
				fmt.Println("Error importing API")
				utils.Logln(utils.LogPrefixError + resp.Status)
			}

		} else {
			// env_endpoints file is not configured properly by the user
			fmt.Println("Error:", preCommandErr)
			utils.Logln(utils.LogPrefixError + preCommandErr.Error())
		}
	}
}

// ImportAPI function is used with import-api command
// @param name: name of the API (zipped file) to be imported
// @param apiManagerEndpoint: API Manager endpoint for the environment
// @param accessToken: OAuth2.0 access token for the resource being accessed
func ImportAPI(query string, apiManagerEndpoint string, accessToken string, exportDirectory string) (*http.Response, error) {
	// append '/' to the end if there isn't one already
	if string(apiManagerEndpoint[len(apiManagerEndpoint)-1]) != "/" {
		apiManagerEndpoint += "/"
	}
	apiManagerEndpoint += "import/apis"

	sourceEnv := strings.Split(query, utils.PathSeparator_)[0] // environment from which the API was exported
	utils.Logln(utils.LogPrefixInfo + "Source Environment: " + sourceEnv)

	//sourceEnvDirExists, _ := utils.IsDirExist(filepath.Join(utils.exportDirPath, sourceEnv))
	//if !sourceEnvDirExists {
	//	return nil, errors.New("wrong directory '"+sourceEnv+"'")
	//}

	fileName := query // ex:- fileName = dev/twitterapi_1.0.0.zip

	zipFilePath := filepath.Join(exportDirectory, fileName)
	fmt.Println("ZipFilePath:", zipFilePath)

	// check if '.zip' exists in the input 'fileName'
	hasZipExtension, _ := regexp.MatchString(`^\S+\.zip$`, fileName)

	if !hasZipExtension {
		//fmt.Println("hasZipExtension: ", false)
		// search for a directory with the given fileName
		destination := filepath.Join(utils.ExportDirPath, fileName+".zip")
		err := utils.ZipDir(zipFilePath, destination)
		if err != nil {
			utils.HandleErrorAndExit("Error creating zip archive", err)
		}
		zipFilePath += ".zip"
	}

	extraParams := map[string]string{}
	// TODO:: Add extraParams as necessary

	req, err := NewFileUploadRequest(apiManagerEndpoint, extraParams, "file", zipFilePath, accessToken)
	if err != nil {
		utils.HandleErrorAndExit("Error creating request.", err)
	}

	var tr *http.Transport
	if utils.Insecure {
		tr = &http.Transport{
			TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, // to bypass errors in SSL certificates
		}
	} else {
		tr = &http.Transport{}
	}

	client := &http.Client{
		Transport: tr,
		Timeout:   time.Duration(utils.HttpRequestTimeout) * time.Second,
	}

	resp, err := client.Do(req)

	if err != nil {
		utils.Logln(utils.LogPrefixError, err)
	} else {
		//var bodyContent []byte

		if resp.StatusCode == http.StatusCreated || resp.StatusCode == http.StatusOK {
			fmt.Println("Successfully imported API '" + fileName + "'")
		} else {
			fmt.Println("Error importing API.")
			fmt.Println("Status: " + resp.Status)
		}

		//fmt.Println(resp.Header)
		//resp.Body.Read(bodyContent)
		//resp.Body.Close()
		//fmt.Println(bodyContent)
	}

	return resp, err
}

// NewFileUploadRequest form an HTTP Put request
// Helper function for forming multi-part form data
// Returns the formed http request and errors
func NewFileUploadRequest(uri string, params map[string]string, paramName, path string,
	accessToken string) (*http.Request, error) {
	file, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer file.Close()

	body := &bytes.Buffer{}
	writer := multipart.NewWriter(body)
	part, err := writer.CreateFormFile(paramName, filepath.Base(path))
	if err != nil {
		return nil, err
	}
	_, err = io.Copy(part, file)

	for key, val := range params {
		_ = writer.WriteField(key, val)
	}
	err = writer.Close()
	if err != nil {
		return nil, err
	}

	request, err := http.NewRequest(http.MethodPut, uri, body)
	request.Header.Add(utils.HeaderAuthorization, utils.HeaderValueAuthPrefixBearer+" "+accessToken)
	request.Header.Add(utils.HeaderContentType, writer.FormDataContentType())
	request.Header.Add(utils.HeaderAccept, "*/*")
	request.Header.Add(utils.HeaderConnection, utils.HeaderValueKeepAlive)

	return request, err
}

// init using Cobra
func init() {
	RootCmd.AddCommand(ImportAPICmd)
	ImportAPICmd.Flags().StringVarP(&flagImportApiFile, "file", "f", "",
		"Name of the API to be imported")
	ImportAPICmd.Flags().StringVarP(&flagImportApiEnvironment, "environment", "e",
		utils.DefaultEnvironmentName, "Environment from the which the API should be imported")
	ImportAPICmd.Flags().StringVarP(&flagImportApiCmdToken, "token", "t",
		"", "OAuth token to be used instead of username and password")
	ImportAPICmd.Flags().StringVarP(&importAPICmdUsername, "username", "u", "", "Username")
	ImportAPICmd.Flags().StringVarP(&importAPICmdPassword, "password", "p", "", "Password")
}
<commit_msg>Fixing #34<commit_after>/*
*  Copyright (c) WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
*  WSO2 Inc. licenses this file to you 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 cmd

import (
	"fmt"

	"bytes"
	"crypto/tls"
	"io"
	"mime/multipart"
	"net/http"
	"os"
	"path/filepath"

	"github.com/renstrom/dedent"
	"github.com/spf13/cobra"
	"github.com/wso2/product-apim-tooling/import-export-cli/utils"
	"regexp"
	"strings"
	"time"
)

var flagImportApiFile string
var flagImportApiEnvironment string
var importAPICmdUsername string
var importAPICmdPassword string
var flagImportApiCmdToken string

// ImportAPI command related usage info
const importAPICmdLiteral = "import-api"
const importAPICmdShortDesc = "Import API"

var importAPICmdLongDesc = "Import an API to an environment"

var importAPICmdExamples = dedent.Dedent(`
		Examples:
		` + utils.ProjectName + ` ` + importAPICmdLiteral + ` -n qa/TwitterAPI.zip -e dev
		` + utils.ProjectName + ` ` + importAPICmdLiteral + ` -n staging/FacebookAPI.zip -e production
	`)

// ImportAPICmd represents the importAPI command
var ImportAPICmd = &cobra.Command{
	Use: importAPICmdLiteral + " (--file <api-zip-file> --environment " +
		"<environment-to-which-the-api-should-be-imported>)",
	Short: importAPICmdShortDesc,
	Long:  importAPICmdLongDesc + importAPICmdExamples,
	Run: func(cmd *cobra.Command, args []string) {
		utils.Logln(utils.LogPrefixInfo + importAPICmdLiteral + " called")
		executeImportApiCmd(utils.MainConfigFilePath, utils.EnvKeysAllFilePath, utils.ExportDirectory)
	},
}

func executeImportApiCmd(mainConfigFilePath, keysAllFilePath, exportDirectory string) {
	if flagExportAPICmdToken != "" {
		// token provided with --token (-t) flag
		if exportAPICmdUsername != "" || exportAPICmdPassword != "" {
			// username and/or password provided with -u and/or -p flags
			// Error
			utils.HandleErrorAndExit("username/password provided with OAuth token.", nil)
		} else {
			// token only, proceed with token
		}
	} else {
		// no token provided with --token (-t) flag
		// proceed with username and password
		accessToken, apiManagerEndpoint, preCommandErr := utils.ExecutePreCommand(flagImportApiEnvironment,
			importAPICmdUsername, importAPICmdPassword, mainConfigFilePath, keysAllFilePath)

		if preCommandErr == nil {
			resp, err := ImportAPI(flagImportApiFile, apiManagerEndpoint, accessToken, exportDirectory)

			if err != nil {
				utils.HandleErrorAndExit("error importing API", err)
			}

			if resp.StatusCode == 200 {
				utils.Logln("Header:", resp.Header)
				fmt.Println("Succesfully imported API!")
			} else {
				fmt.Println("Error importing API")
				utils.Logln(utils.LogPrefixError + resp.Status)
			}

		} else {
			// env_endpoints file is not configured properly by the user
			fmt.Println("Error:", preCommandErr)
			utils.Logln(utils.LogPrefixError + preCommandErr.Error())
		}
	}
}

// ImportAPI function is used with import-api command
// @param name: name of the API (zipped file) to be imported
// @param apiManagerEndpoint: API Manager endpoint for the environment
// @param accessToken: OAuth2.0 access token for the resource being accessed
func ImportAPI(query string, apiManagerEndpoint string, accessToken string, exportDirectory string) (*http.Response, error) {
	// append '/' to the end if there isn't one already
	if string(apiManagerEndpoint[len(apiManagerEndpoint)-1]) != "/" {
		apiManagerEndpoint += "/"
	}
	apiManagerEndpoint += "import/apis"

	sourceEnv := strings.Split(query, utils.PathSeparator_)[0] // environment from which the API was exported
	utils.Logln(utils.LogPrefixInfo + "Source Environment: " + sourceEnv)

	//sourceEnvDirExists, _ := utils.IsDirExist(filepath.Join(utils.exportDirPath, sourceEnv))
	//if !sourceEnvDirExists {
	//	return nil, errors.New("wrong directory '"+sourceEnv+"'")
	//}

	fileName := query // ex:- fileName = dev/twitterapi_1.0.0.zip

	zipFilePath := filepath.Join(exportDirectory, fileName)
	fmt.Println("ZipFilePath:", zipFilePath)

	// check if '.zip' exists in the input 'fileName'
	hasZipExtension, _ := regexp.MatchString(`^\S+\.zip$`, fileName)

	if !hasZipExtension {
		//fmt.Println("hasZipExtension: ", false)
		// search for a directory with the given fileName
		destination := filepath.Join(utils.ExportDirPath, fileName+".zip")
		err := utils.ZipDir(zipFilePath, destination)
		if err != nil {
			utils.HandleErrorAndExit("Error creating zip archive", err)
		}
		zipFilePath += ".zip"
	}

	extraParams := map[string]string{}
	// TODO:: Add extraParams as necessary

	req, err := NewFileUploadRequest(apiManagerEndpoint, extraParams, "file", zipFilePath, accessToken)
	if err != nil {
		utils.HandleErrorAndExit("Error creating request.", err)
	}

	var tr *http.Transport
	if utils.Insecure {
		tr = &http.Transport{
			TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, // to bypass errors in SSL certificates
		}
	} else {
		tr = &http.Transport{}
	}

	client := &http.Client{
		Transport: tr,
		Timeout:   time.Duration(utils.HttpRequestTimeout) * time.Second,
	}

	resp, err := client.Do(req)

	if err != nil {
		utils.Logln(utils.LogPrefixError, err)
	} else {
		//var bodyContent []byte

		if resp.StatusCode == http.StatusCreated || resp.StatusCode == http.StatusOK {
			fmt.Println("Successfully imported API '" + fileName + "'")
		} else {
			fmt.Println("Error importing API.")
			fmt.Println("Status: " + resp.Status)
		}

		//fmt.Println(resp.Header)
		//resp.Body.Read(bodyContent)
		//resp.Body.Close()
		//fmt.Println(bodyContent)
	}

	return resp, err
}

// NewFileUploadRequest form an HTTP Put request
// Helper function for forming multi-part form data
// Returns the formed http request and errors
func NewFileUploadRequest(uri string, params map[string]string, paramName, path string,
	accessToken string) (*http.Request, error) {
	file, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer file.Close()

	body := &bytes.Buffer{}
	writer := multipart.NewWriter(body)
	part, err := writer.CreateFormFile(paramName, filepath.Base(path))
	if err != nil {
		return nil, err
	}
	_, err = io.Copy(part, file)

	for key, val := range params {
		_ = writer.WriteField(key, val)
	}
	err = writer.Close()
	if err != nil {
		return nil, err
	}

	request, err := http.NewRequest(http.MethodPost, uri, body)
	request.Header.Add(utils.HeaderAuthorization, utils.HeaderValueAuthPrefixBearer+" "+accessToken)
	request.Header.Add(utils.HeaderContentType, writer.FormDataContentType())
	request.Header.Add(utils.HeaderAccept, "*/*")
	request.Header.Add(utils.HeaderConnection, utils.HeaderValueKeepAlive)

	return request, err
}

// init using Cobra
func init() {
	RootCmd.AddCommand(ImportAPICmd)
	ImportAPICmd.Flags().StringVarP(&flagImportApiFile, "file", "f", "",
		"Name of the API to be imported")
	ImportAPICmd.Flags().StringVarP(&flagImportApiEnvironment, "environment", "e",
		utils.DefaultEnvironmentName, "Environment from the which the API should be imported")
	ImportAPICmd.Flags().StringVarP(&flagImportApiCmdToken, "token", "t",
		"", "OAuth token to be used instead of username and password")
	ImportAPICmd.Flags().StringVarP(&importAPICmdUsername, "username", "u", "", "Username")
	ImportAPICmd.Flags().StringVarP(&importAPICmdPassword, "password", "p", "", "Password")
}
<|endoftext|>


<commit_before>// Copyright (C) 2014 Jakob Borg and Contributors (see the CONTRIBUTORS file).
// All rights reserved. Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.

package config

import (
	"os"
	"reflect"
	"testing"

	"github.com/syncthing/syncthing/protocol"
)

var node1, node2, node3, node4 protocol.NodeID

func init() {
	node1, _ = protocol.NodeIDFromString("AIR6LPZ7K4PTTUXQSMUUCPQ5YWOEDFIIQJUG7772YQXXR5YD6AWQ")
	node2, _ = protocol.NodeIDFromString("GYRZZQB-IRNPV4Z-T7TC52W-EQYJ3TT-FDQW6MW-DFLMU42-SSSU6EM-FBK2VAY")
	node3, _ = protocol.NodeIDFromString("LGFPDIT-7SKNNJL-VJZA4FC-7QNCRKA-CE753K7-2BW5QDK-2FOZ7FR-FEP57QJ")
	node4, _ = protocol.NodeIDFromString("P56IOI7-MZJNU2Y-IQGDREY-DM2MGTI-MGL3BXN-PQ6W5BM-TBBZ4TJ-XZWICQ2")
}

func TestDefaultValues(t *testing.T) {
	expected := OptionsConfiguration{
		ListenAddress:      []string{"0.0.0.0:22000"},
		GlobalAnnServer:    "announce.syncthing.net:22026",
		GlobalAnnEnabled:   true,
		LocalAnnEnabled:    true,
		LocalAnnPort:       21025,
		LocalAnnMCAddr:     "[ff32::5222]:21026",
		ParallelRequests:   16,
		MaxSendKbps:        0,
		ReconnectIntervalS: 60,
		StartBrowser:       true,
		UPnPEnabled:        true,
		UPnPLease:          0,
		UPnPRenewal:        30,
	}

	cfg := New("test", node1)

	if !reflect.DeepEqual(cfg.Options, expected) {
		t.Errorf("Default config differs;\n  E: %#v\n  A: %#v", expected, cfg.Options)
	}
}

func TestNodeConfig(t *testing.T) {
	for i, ver := range []string{"v1", "v2", "v3", "v4"} {
		cfg, err := Load("testdata/"+ver+".xml", node1)
		if err != nil {
			t.Error(err)
		}

		expectedRepos := []RepositoryConfiguration{
			{
				ID:              "test",
				Directory:       "~/Sync",
				Nodes:           []RepositoryNodeConfiguration{{NodeID: node1}, {NodeID: node4}},
				ReadOnly:        true,
				RescanIntervalS: 600,
			},
		}
		expectedNodes := []NodeConfiguration{
			{
				NodeID:      node1,
				Name:        "node one",
				Addresses:   []string{"a"},
				Compression: true,
			},
			{
				NodeID:      node4,
				Name:        "node two",
				Addresses:   []string{"b"},
				Compression: true,
			},
		}
		expectedNodeIDs := []protocol.NodeID{node1, node4}

		if cfg.Version != 4 {
			t.Errorf("%d: Incorrect version %d != 3", i, cfg.Version)
		}
		if !reflect.DeepEqual(cfg.Repositories, expectedRepos) {
			t.Errorf("%d: Incorrect Repositories\n  A: %#v\n  E: %#v", i, cfg.Repositories, expectedRepos)
		}
		if !reflect.DeepEqual(cfg.Nodes, expectedNodes) {
			t.Errorf("%d: Incorrect Nodes\n  A: %#v\n  E: %#v", i, cfg.Nodes, expectedNodes)
		}
		if !reflect.DeepEqual(cfg.Repositories[0].NodeIDs(), expectedNodeIDs) {
			t.Errorf("%d: Incorrect NodeIDs\n  A: %#v\n  E: %#v", i, cfg.Repositories[0].NodeIDs(), expectedNodeIDs)
		}

		if len(cfg.NodeMap()) != len(expectedNodes) {
			t.Errorf("Unexpected number of NodeMap() entries")
		}
		if len(cfg.RepoMap()) != len(expectedRepos) {
			t.Errorf("Unexpected number of RepoMap() entries")
		}
	}
}

func TestNoListenAddress(t *testing.T) {
	cfg, err := Load("testdata/nolistenaddress.xml", node1)
	if err != nil {
		t.Error(err)
	}

	expected := []string{""}
	if !reflect.DeepEqual(cfg.Options.ListenAddress, expected) {
		t.Errorf("Unexpected ListenAddress %#v", cfg.Options.ListenAddress)
	}
}

func TestOverriddenValues(t *testing.T) {
	expected := OptionsConfiguration{
		ListenAddress:      []string{":23000"},
		GlobalAnnServer:    "syncthing.nym.se:22026",
		GlobalAnnEnabled:   false,
		LocalAnnEnabled:    false,
		LocalAnnPort:       42123,
		LocalAnnMCAddr:     "quux:3232",
		ParallelRequests:   32,
		MaxSendKbps:        1234,
		ReconnectIntervalS: 6000,
		StartBrowser:       false,
		UPnPEnabled:        false,
		UPnPLease:          60,
		UPnPRenewal:        15,
	}

	cfg, err := Load("testdata/overridenvalues.xml", node1)
	if err != nil {
		t.Error(err)
	}

	if !reflect.DeepEqual(cfg.Options, expected) {
		t.Errorf("Overridden config differs;\n  E: %#v\n  A: %#v", expected, cfg.Options)
	}
}

func TestNodeAddressesDynamic(t *testing.T) {
	name, _ := os.Hostname()
	expected := []NodeConfiguration{
		{
			NodeID:      node1,
			Addresses:   []string{"dynamic"},
			Compression: true,
		},
		{
			NodeID:      node2,
			Addresses:   []string{"dynamic"},
			Compression: true,
		},
		{
			NodeID:      node3,
			Addresses:   []string{"dynamic"},
			Compression: true,
		},
		{
			NodeID:    node4,
			Name:      name, // Set when auto created
			Addresses: []string{"dynamic"},
		},
	}

	cfg, err := Load("testdata/nodeaddressesdynamic.xml", node4)
	if err != nil {
		t.Error(err)
	}

	if !reflect.DeepEqual(cfg.Nodes, expected) {
		t.Errorf("Nodes differ;\n  E: %#v\n  A: %#v", expected, cfg.Nodes)
	}
}

func TestNodeAddressesStatic(t *testing.T) {
	name, _ := os.Hostname()
	expected := []NodeConfiguration{
		{
			NodeID:    node1,
			Addresses: []string{"192.0.2.1", "192.0.2.2"},
		},
		{
			NodeID:    node2,
			Addresses: []string{"192.0.2.3:6070", "[2001:db8::42]:4242"},
		},
		{
			NodeID:    node3,
			Addresses: []string{"[2001:db8::44]:4444", "192.0.2.4:6090"},
		},
		{
			NodeID:    node4,
			Name:      name, // Set when auto created
			Addresses: []string{"dynamic"},
		},
	}

	cfg, err := Load("testdata/nodeaddressesstatic.xml", node4)
	if err != nil {
		t.Error(err)
	}

	if !reflect.DeepEqual(cfg.Nodes, expected) {
		t.Errorf("Nodes differ;\n  E: %#v\n  A: %#v", expected, cfg.Nodes)
	}
}

func TestVersioningConfig(t *testing.T) {
	cfg, err := Load("testdata/versioningconfig.xml", node4)
	if err != nil {
		t.Error(err)
	}

	vc := cfg.Repositories[0].Versioning
	if vc.Type != "simple" {
		t.Errorf(`vc.Type %q != "simple"`, vc.Type)
	}
	if l := len(vc.Params); l != 2 {
		t.Errorf("len(vc.Params) %d != 2", l)
	}

	expected := map[string]string{
		"foo": "bar",
		"baz": "quux",
	}
	if !reflect.DeepEqual(vc.Params, expected) {
		t.Errorf("vc.Params differ;\n  E: %#v\n  A: %#v", expected, vc.Params)
	}
}
<commit_msg>Add tests<commit_after>// Copyright (C) 2014 Jakob Borg and Contributors (see the CONTRIBUTORS file).
// All rights reserved. Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.

package config

import (
	"os"
	"reflect"
	"testing"

	"github.com/syncthing/syncthing/protocol"
)

var node1, node2, node3, node4 protocol.NodeID

func init() {
	node1, _ = protocol.NodeIDFromString("AIR6LPZ7K4PTTUXQSMUUCPQ5YWOEDFIIQJUG7772YQXXR5YD6AWQ")
	node2, _ = protocol.NodeIDFromString("GYRZZQB-IRNPV4Z-T7TC52W-EQYJ3TT-FDQW6MW-DFLMU42-SSSU6EM-FBK2VAY")
	node3, _ = protocol.NodeIDFromString("LGFPDIT-7SKNNJL-VJZA4FC-7QNCRKA-CE753K7-2BW5QDK-2FOZ7FR-FEP57QJ")
	node4, _ = protocol.NodeIDFromString("P56IOI7-MZJNU2Y-IQGDREY-DM2MGTI-MGL3BXN-PQ6W5BM-TBBZ4TJ-XZWICQ2")
}

func TestDefaultValues(t *testing.T) {
	expected := OptionsConfiguration{
		ListenAddress:      []string{"0.0.0.0:22000"},
		GlobalAnnServer:    "announce.syncthing.net:22026",
		GlobalAnnEnabled:   true,
		LocalAnnEnabled:    true,
		LocalAnnPort:       21025,
		LocalAnnMCAddr:     "[ff32::5222]:21026",
		ParallelRequests:   16,
		MaxSendKbps:        0,
		ReconnectIntervalS: 60,
		StartBrowser:       true,
		UPnPEnabled:        true,
		UPnPLease:          0,
		UPnPRenewal:        30,
	}

	cfg := New("test", node1)

	if !reflect.DeepEqual(cfg.Options, expected) {
		t.Errorf("Default config differs;\n  E: %#v\n  A: %#v", expected, cfg.Options)
	}
}

func TestNodeConfig(t *testing.T) {
	for i, ver := range []string{"v1", "v2", "v3", "v4"} {
		cfg, err := Load("testdata/"+ver+".xml", node1)
		if err != nil {
			t.Error(err)
		}

		expectedRepos := []RepositoryConfiguration{
			{
				ID:              "test",
				Directory:       "~/Sync",
				Nodes:           []RepositoryNodeConfiguration{{NodeID: node1}, {NodeID: node4}},
				ReadOnly:        true,
				RescanIntervalS: 600,
			},
		}
		expectedNodes := []NodeConfiguration{
			{
				NodeID:      node1,
				Name:        "node one",
				Addresses:   []string{"a"},
				Compression: true,
			},
			{
				NodeID:      node4,
				Name:        "node two",
				Addresses:   []string{"b"},
				Compression: true,
			},
		}
		expectedNodeIDs := []protocol.NodeID{node1, node4}

		if cfg.Version != 4 {
			t.Errorf("%d: Incorrect version %d != 3", i, cfg.Version)
		}
		if !reflect.DeepEqual(cfg.Repositories, expectedRepos) {
			t.Errorf("%d: Incorrect Repositories\n  A: %#v\n  E: %#v", i, cfg.Repositories, expectedRepos)
		}
		if !reflect.DeepEqual(cfg.Nodes, expectedNodes) {
			t.Errorf("%d: Incorrect Nodes\n  A: %#v\n  E: %#v", i, cfg.Nodes, expectedNodes)
		}
		if !reflect.DeepEqual(cfg.Repositories[0].NodeIDs(), expectedNodeIDs) {
			t.Errorf("%d: Incorrect NodeIDs\n  A: %#v\n  E: %#v", i, cfg.Repositories[0].NodeIDs(), expectedNodeIDs)
		}

		if len(cfg.NodeMap()) != len(expectedNodes) {
			t.Errorf("Unexpected number of NodeMap() entries")
		}
		if len(cfg.RepoMap()) != len(expectedRepos) {
			t.Errorf("Unexpected number of RepoMap() entries")
		}
	}
}

func TestNoListenAddress(t *testing.T) {
	cfg, err := Load("testdata/nolistenaddress.xml", node1)
	if err != nil {
		t.Error(err)
	}

	expected := []string{""}
	if !reflect.DeepEqual(cfg.Options.ListenAddress, expected) {
		t.Errorf("Unexpected ListenAddress %#v", cfg.Options.ListenAddress)
	}
}

func TestOverriddenValues(t *testing.T) {
	expected := OptionsConfiguration{
		ListenAddress:      []string{":23000"},
		GlobalAnnServer:    "syncthing.nym.se:22026",
		GlobalAnnEnabled:   false,
		LocalAnnEnabled:    false,
		LocalAnnPort:       42123,
		LocalAnnMCAddr:     "quux:3232",
		ParallelRequests:   32,
		MaxSendKbps:        1234,
		ReconnectIntervalS: 6000,
		StartBrowser:       false,
		UPnPEnabled:        false,
		UPnPLease:          60,
		UPnPRenewal:        15,
	}

	cfg, err := Load("testdata/overridenvalues.xml", node1)
	if err != nil {
		t.Error(err)
	}

	if !reflect.DeepEqual(cfg.Options, expected) {
		t.Errorf("Overridden config differs;\n  E: %#v\n  A: %#v", expected, cfg.Options)
	}
}

func TestNodeAddressesDynamic(t *testing.T) {
	name, _ := os.Hostname()
	expected := []NodeConfiguration{
		{
			NodeID:      node1,
			Addresses:   []string{"dynamic"},
			Compression: true,
		},
		{
			NodeID:      node2,
			Addresses:   []string{"dynamic"},
			Compression: true,
		},
		{
			NodeID:      node3,
			Addresses:   []string{"dynamic"},
			Compression: true,
		},
		{
			NodeID:    node4,
			Name:      name, // Set when auto created
			Addresses: []string{"dynamic"},
		},
	}

	cfg, err := Load("testdata/nodeaddressesdynamic.xml", node4)
	if err != nil {
		t.Error(err)
	}

	if !reflect.DeepEqual(cfg.Nodes, expected) {
		t.Errorf("Nodes differ;\n  E: %#v\n  A: %#v", expected, cfg.Nodes)
	}
}

func TestNodeAddressesStatic(t *testing.T) {
	name, _ := os.Hostname()
	expected := []NodeConfiguration{
		{
			NodeID:    node1,
			Addresses: []string{"192.0.2.1", "192.0.2.2"},
		},
		{
			NodeID:    node2,
			Addresses: []string{"192.0.2.3:6070", "[2001:db8::42]:4242"},
		},
		{
			NodeID:    node3,
			Addresses: []string{"[2001:db8::44]:4444", "192.0.2.4:6090"},
		},
		{
			NodeID:    node4,
			Name:      name, // Set when auto created
			Addresses: []string{"dynamic"},
		},
	}

	cfg, err := Load("testdata/nodeaddressesstatic.xml", node4)
	if err != nil {
		t.Error(err)
	}

	if !reflect.DeepEqual(cfg.Nodes, expected) {
		t.Errorf("Nodes differ;\n  E: %#v\n  A: %#v", expected, cfg.Nodes)
	}
}

func TestVersioningConfig(t *testing.T) {
	cfg, err := Load("testdata/versioningconfig.xml", node4)
	if err != nil {
		t.Error(err)
	}

	vc := cfg.Repositories[0].Versioning
	if vc.Type != "simple" {
		t.Errorf(`vc.Type %q != "simple"`, vc.Type)
	}
	if l := len(vc.Params); l != 2 {
		t.Errorf("len(vc.Params) %d != 2", l)
	}

	expected := map[string]string{
		"foo": "bar",
		"baz": "quux",
	}
	if !reflect.DeepEqual(vc.Params, expected) {
		t.Errorf("vc.Params differ;\n  E: %#v\n  A: %#v", expected, vc.Params)
	}
}

func TestNewSaveLoad(t *testing.T) {
	path := "testdata/temp.xml"
	os.Remove(path)

	exists := func(path string) bool {
		_, err := os.Stat(path)
		return err == nil
	}

	cfg := New(path, node1)

	// To make the equality pass later
	cfg.XMLName.Local = "configuration"

	if exists(path) {
		t.Error(path, "exists")
	}

	err := cfg.Save()
	if err != nil {
		t.Error(err)
	}
	if !exists(path) {
		t.Error(path, "does not exist")
	}

	cfg2, err := Load(path, node1)
	if err != nil {
		t.Error(err)
	}

	if !reflect.DeepEqual(cfg, cfg2) {
		t.Errorf("Configs are not equal;\n  E:  %#v\n  A:  %#v", cfg, cfg2)
	}

	cfg.GUI.User = "test"
	cfg.Save()

	cfg2, err = Load(path, node1)
	if err != nil {
		t.Error(err)
	}

	if cfg2.GUI.User != "test" || !reflect.DeepEqual(cfg, cfg2) {
		t.Errorf("Configs are not equal;\n  E:  %#v\n  A:  %#v", cfg, cfg2)
	}

	os.Remove(path)
}

func TestPrepare(t *testing.T) {
	var cfg Configuration

	if cfg.Repositories != nil || cfg.Nodes != nil || cfg.Options.ListenAddress != nil {
		t.Error("Expected nil")
	}

	cfg.prepare(node1)

	if cfg.Repositories == nil || cfg.Nodes == nil || cfg.Options.ListenAddress == nil {
		t.Error("Unexpected nil")
	}
}
<|endoftext|>


<commit_before>//
package config

import (
	"fmt"
	"testing"
)

// tests if appNameToIP works as intended
func TestappNameToIP(t *testing.T) {
	name := "test-app"
	target := "172.16.7.24" // pre-calculated IP for "test-app"
	actual := appNameToIP(name)

	if actual != target {
		t.Error(fmt.Sprintf("Expected IP '%s' got '%s'", target, actual))
	}
}

// tests to ensure that IPs generated by appNameToIP are unique for similar names
func TestAppNameToIPUnique(t *testing.T) {
	var name string

	name = "test-app"
	first := appNameToIP(name)

	name = "app-test"
	second := appNameToIP(name)

	if first == second {
		t.Error("IPs arent unique")
	}
}
<commit_msg>fixing test func name<commit_after>//
package config

import (
	"fmt"
	"testing"
)

// tests if appNameToIP works as intended
func TestAppNameToIP(t *testing.T) {
	name := "test-app"
	target := "172.16.7.24" // pre-calculated IP for "test-app"
	actual := appNameToIP(name)

	if actual != target {
		t.Error(fmt.Sprintf("Expected IP '%s' got '%s'", target, actual))
	}
}

// tests to ensure that IPs generated by appNameToIP are unique for similar names
func TestAppNameToIPUnique(t *testing.T) {
	var name string

	name = "test-app"
	first := appNameToIP(name)

	name = "app-test"
	second := appNameToIP(name)

	if first == second {
		t.Error("IPs arent unique")
	}
}
<|endoftext|>


<commit_before>package container // import "github.com/docker/docker/integration/container"

import (
	"context"
	"testing"
	"time"

	containertypes "github.com/docker/docker/api/types/container"
	"github.com/docker/docker/integration/internal/container"
	"github.com/docker/docker/integration/internal/request"
	"github.com/docker/docker/pkg/archive"
	"github.com/gotestyourself/gotestyourself/poll"
	"github.com/gotestyourself/gotestyourself/skip"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

// ensure that an added file shows up in docker diff
func TestDiffFilenameShownInOutput(t *testing.T) {
	defer setupTest(t)()
	client := request.NewAPIClient(t)
	ctx := context.Background()

	cID := container.Run(t, ctx, client, container.WithCmd("sh", "-c", `mkdir /foo; echo xyzzy > /foo/bar`))

	// Wait for it to exit as cannot diff a running container on Windows, and
	// it will take a few seconds to exit. Also there's no way in Windows to
	// differentiate between an Add or a Modify, and all files are under
	// a "Files/" prefix.
	lookingFor := containertypes.ContainerChangeResponseItem{Kind: archive.ChangeAdd, Path: "/foo/bar"}
	if testEnv.OSType == "windows" {
		poll.WaitOn(t, container.IsInState(ctx, client, cID, "exited"), poll.WithDelay(100*time.Millisecond), poll.WithTimeout(60*time.Second))
		lookingFor = containertypes.ContainerChangeResponseItem{Kind: archive.ChangeModify, Path: "Files/foo/bar"}
	}

	items, err := client.ContainerDiff(ctx, cID)
	require.NoError(t, err)
	assert.Contains(t, items, lookingFor)
}

// test to ensure GH #3840 doesn't occur any more
func TestDiffEnsureInitLayerFilesAreIgnored(t *testing.T) {
	skip.If(t, testEnv.DaemonInfo.OSType != "linux")

	defer setupTest(t)()
	client := request.NewAPIClient(t)
	ctx := context.Background()

	// this is a list of files which shouldn't show up in `docker diff`
	initLayerFiles := []string{"/etc/resolv.conf", "/etc/hostname", "/etc/hosts", "/.dockerenv"}
	containerCount := 5

	// we might not run into this problem from the first run, so start a few containers
	for i := 0; i < containerCount; i++ {
		cID := container.Run(t, ctx, client, container.WithCmd("sh", "-c", `echo foo > /root/bar`))

		items, err := client.ContainerDiff(ctx, cID)
		require.NoError(t, err)
		for _, item := range items {
			assert.NotContains(t, initLayerFiles, item.Path)
		}
	}
}

func TestDiffEnsureDefaultDevs(t *testing.T) {
	skip.If(t, testEnv.DaemonInfo.OSType != "linux")

	defer setupTest(t)()
	client := request.NewAPIClient(t)
	ctx := context.Background()

	cID := container.Run(t, ctx, client, container.WithCmd("sleep", "0"))

	items, err := client.ContainerDiff(ctx, cID)
	require.NoError(t, err)

	expected := []containertypes.ContainerChangeResponseItem{
		{Kind: archive.ChangeModify, Path: "/dev"},
		{Kind: archive.ChangeAdd, Path: "/dev/full"},    // busybox
		{Kind: archive.ChangeModify, Path: "/dev/ptmx"}, // libcontainer
		{Kind: archive.ChangeAdd, Path: "/dev/mqueue"},
		{Kind: archive.ChangeAdd, Path: "/dev/kmsg"},
		{Kind: archive.ChangeAdd, Path: "/dev/fd"},
		{Kind: archive.ChangeAdd, Path: "/dev/ptmx"},
		{Kind: archive.ChangeAdd, Path: "/dev/null"},
		{Kind: archive.ChangeAdd, Path: "/dev/random"},
		{Kind: archive.ChangeAdd, Path: "/dev/stdout"},
		{Kind: archive.ChangeAdd, Path: "/dev/stderr"},
		{Kind: archive.ChangeAdd, Path: "/dev/tty1"},
		{Kind: archive.ChangeAdd, Path: "/dev/stdin"},
		{Kind: archive.ChangeAdd, Path: "/dev/tty"},
		{Kind: archive.ChangeAdd, Path: "/dev/urandom"},
	}

	for _, item := range items {
		assert.Contains(t, expected, item)
	}
}
<commit_msg>Remove unnecessary diff tests<commit_after>package container // import "github.com/docker/docker/integration/container"

import (
	"context"
	"testing"
	"time"

	containertypes "github.com/docker/docker/api/types/container"
	"github.com/docker/docker/integration/internal/container"
	"github.com/docker/docker/integration/internal/request"
	"github.com/docker/docker/pkg/archive"
	"github.com/gotestyourself/gotestyourself/poll"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

func TestDiff(t *testing.T) {
	defer setupTest(t)()
	client := request.NewAPIClient(t)
	ctx := context.Background()

	cID := container.Run(t, ctx, client, container.WithCmd("sh", "-c", `mkdir /foo; echo xyzzy > /foo/bar`))

	// Wait for it to exit as cannot diff a running container on Windows, and
	// it will take a few seconds to exit. Also there's no way in Windows to
	// differentiate between an Add or a Modify, and all files are under
	// a "Files/" prefix.
	expected := []containertypes.ContainerChangeResponseItem{
		{Kind: archive.ChangeAdd, Path: "/foo"},
		{Kind: archive.ChangeAdd, Path: "/foo/bar"},
	}
	if testEnv.OSType == "windows" {
		poll.WaitOn(t, container.IsInState(ctx, client, cID, "exited"), poll.WithDelay(100*time.Millisecond), poll.WithTimeout(60*time.Second))
		expected = []containertypes.ContainerChangeResponseItem{
			{Kind: archive.ChangeModify, Path: "Files/foo"},
			{Kind: archive.ChangeModify, Path: "Files/foo/bar"},
		}
	}

	items, err := client.ContainerDiff(ctx, cID)
	require.NoError(t, err)
	assert.Equal(t, expected, items)
}
<|endoftext|>


<commit_before>// Copyright 2012 Junqing Tan <ivan@mysqlab.net> and The Go Authors
// Use of this source code is governed by a BSD-style
// Part of source code is from Go fcgi package

package fcgiclient

import (
	"bufio"
	"bytes"
	"encoding/binary"
	"errors"
	"io"
	"io/ioutil"
	"mime/multipart"
	"net"
	"net/http"
	"net/http/httputil"
	"net/textproto"
	"net/url"
	"os"
	"path/filepath"
	"strconv"
	"sync"
	"time"
)

const FCGI_LISTENSOCK_FILENO uint8 = 0
const FCGI_HEADER_LEN uint8 = 8
const VERSION_1 uint8 = 1
const FCGI_NULL_REQUEST_ID uint8 = 0
const FCGI_KEEP_CONN uint8 = 1
const doubleCRLF = "\r\n\r\n"

const (
	FCGI_BEGIN_REQUEST uint8 = iota + 1
	FCGI_ABORT_REQUEST
	FCGI_END_REQUEST
	FCGI_PARAMS
	FCGI_STDIN
	FCGI_STDOUT
	FCGI_STDERR
	FCGI_DATA
	FCGI_GET_VALUES
	FCGI_GET_VALUES_RESULT
	FCGI_UNKNOWN_TYPE
	FCGI_MAXTYPE = FCGI_UNKNOWN_TYPE
)

const (
	FCGI_RESPONDER uint8 = iota + 1
	FCGI_AUTHORIZER
	FCGI_FILTER
)

const (
	FCGI_REQUEST_COMPLETE uint8 = iota
	FCGI_CANT_MPX_CONN
	FCGI_OVERLOADED
	FCGI_UNKNOWN_ROLE
)

const (
	FCGI_MAX_CONNS  string = "MAX_CONNS"
	FCGI_MAX_REQS   string = "MAX_REQS"
	FCGI_MPXS_CONNS string = "MPXS_CONNS"
)

const (
	maxWrite = 65500 // 65530 may work, but for compatibility
	maxPad   = 255
)

type header struct {
	Version       uint8
	Type          uint8
	Id            uint16
	ContentLength uint16
	PaddingLength uint8
	Reserved      uint8
}

// for padding so we don't have to allocate all the time
// not synchronized because we don't care what the contents are
var pad [maxPad]byte

func (h *header) init(recType uint8, reqId uint16, contentLength int) {
	h.Version = 1
	h.Type = recType
	h.Id = reqId
	h.ContentLength = uint16(contentLength)
	h.PaddingLength = uint8(-contentLength & 7)
}

type record struct {
	h    header
	rbuf []byte
}

func (rec *record) read(r io.Reader) (buf []byte, err error) {
	if err = binary.Read(r, binary.BigEndian, &rec.h); err != nil {
		return
	}
	if rec.h.Version != 1 {
		err = errors.New("fcgi: invalid header version")
		return
	}
	if rec.h.Type == FCGI_END_REQUEST {
		err = io.EOF
		return
	}
	n := int(rec.h.ContentLength) + int(rec.h.PaddingLength)
	if len(rec.rbuf) < n {
		rec.rbuf = make([]byte, n)
	}
	if n, err = io.ReadFull(r, rec.rbuf[:n]); err != nil {
		return
	}
	buf = rec.rbuf[:int(rec.h.ContentLength)]

	return
}

type FCGIClient struct {
	mutex     sync.Mutex
	rwc       io.ReadWriteCloser
	h         header
	buf       bytes.Buffer
	keepAlive bool
	reqId     uint16
}

// Connects to the fcgi responder at the specified network address.
// See func net.Dial for a description of the network and address parameters.
func Dial(network, address string) (fcgi *FCGIClient, err error) {
	var conn net.Conn

	conn, err = net.Dial(network, address)
	if err != nil {
		return
	}

	fcgi = &FCGIClient{
		rwc:       conn,
		keepAlive: false,
		reqId:     1,
	}

	return
}

// Connects to the fcgi responder at the specified network address with timeout
// See func net.DialTimeout for a description of the network, address and timeout parameters.
func DialTimeout(network, address string, timeout time.Duration) (fcgi *FCGIClient, err error) {

	var conn net.Conn

	conn, err = net.DialTimeout(network, address, timeout)
	if err != nil {
		return
	}

	fcgi = &FCGIClient{
		rwc:       conn,
		keepAlive: false,
		reqId:     1,
	}

	return
}

// Close fcgi connnection
func (this *FCGIClient) Close() {
	this.rwc.Close()
}

func (this *FCGIClient) writeRecord(recType uint8, content []byte) (err error) {
	this.mutex.Lock()
	defer this.mutex.Unlock()
	this.buf.Reset()
	this.h.init(recType, this.reqId, len(content))
	if err := binary.Write(&this.buf, binary.BigEndian, this.h); err != nil {
		return err
	}
	if _, err := this.buf.Write(content); err != nil {
		return err
	}
	if _, err := this.buf.Write(pad[:this.h.PaddingLength]); err != nil {
		return err
	}
	_, err = this.rwc.Write(this.buf.Bytes())
	return err
}

func (this *FCGIClient) writeBeginRequest(role uint16, flags uint8) error {
	b := [8]byte{byte(role >> 8), byte(role), flags}
	return this.writeRecord(FCGI_BEGIN_REQUEST, b[:])
}

func (this *FCGIClient) writeEndRequest(appStatus int, protocolStatus uint8) error {
	b := make([]byte, 8)
	binary.BigEndian.PutUint32(b, uint32(appStatus))
	b[4] = protocolStatus
	return this.writeRecord(FCGI_END_REQUEST, b)
}

func (this *FCGIClient) writePairs(recType uint8, pairs map[string]string) error {
	w := newWriter(this, recType)
	b := make([]byte, 8)
	nn := 0
	for k, v := range pairs {
		m := 8 + len(k) + len(v)
		if m > maxWrite {
			// param data size exceed 65535 bytes"
			vl := maxWrite - 8 - len(k)
			v = v[:vl]
		}
		n := encodeSize(b, uint32(len(k)))
		n += encodeSize(b[n:], uint32(len(v)))
		m = n + len(k) + len(v)
		if (nn + m) > maxWrite {
			w.Flush()
			nn = 0
		}
		nn += m
		if _, err := w.Write(b[:n]); err != nil {
			return err
		}
		if _, err := w.WriteString(k); err != nil {
			return err
		}
		if _, err := w.WriteString(v); err != nil {
			return err
		}
	}
	w.Close()
	return nil
}

func readSize(s []byte) (uint32, int) {
	if len(s) == 0 {
		return 0, 0
	}
	size, n := uint32(s[0]), 1
	if size&(1<<7) != 0 {
		if len(s) < 4 {
			return 0, 0
		}
		n = 4
		size = binary.BigEndian.Uint32(s)
		size &^= 1 << 31
	}
	return size, n
}

func readString(s []byte, size uint32) string {
	if size > uint32(len(s)) {
		return ""
	}
	return string(s[:size])
}

func encodeSize(b []byte, size uint32) int {
	if size > 127 {
		size |= 1 << 31
		binary.BigEndian.PutUint32(b, size)
		return 4
	}
	b[0] = byte(size)
	return 1
}

// bufWriter encapsulates bufio.Writer but also closes the underlying stream when
// Closed.
type bufWriter struct {
	closer io.Closer
	*bufio.Writer
}

func (w *bufWriter) Close() error {
	if err := w.Writer.Flush(); err != nil {
		w.closer.Close()
		return err
	}
	return w.closer.Close()
}

func newWriter(c *FCGIClient, recType uint8) *bufWriter {
	s := &streamWriter{c: c, recType: recType}
	w := bufio.NewWriterSize(s, maxWrite)
	return &bufWriter{s, w}
}

// streamWriter abstracts out the separation of a stream into discrete records.
// It only writes maxWrite bytes at a time.
type streamWriter struct {
	c       *FCGIClient
	recType uint8
}

func (w *streamWriter) Write(p []byte) (int, error) {
	nn := 0
	for len(p) > 0 {
		n := len(p)
		if n > maxWrite {
			n = maxWrite
		}
		if err := w.c.writeRecord(w.recType, p[:n]); err != nil {
			return nn, err
		}
		nn += n
		p = p[n:]
	}
	return nn, nil
}

func (w *streamWriter) Close() error {
	// send empty record to close the stream
	return w.c.writeRecord(w.recType, nil)
}

type streamReader struct {
	c   *FCGIClient
	buf []byte
}

func (w *streamReader) Read(p []byte) (n int, err error) {

	if len(p) > 0 {
		if len(w.buf) == 0 {
			rec := &record{}
			w.buf, err = rec.read(w.c.rwc)
			if err != nil {
				return
			}
		}

		n = len(p)
		if n > len(w.buf) {
			n = len(w.buf)
		}
		copy(p, w.buf[:n])
		w.buf = w.buf[n:]
	}

	return
}

// Do made the request and returns a io.Reader that translates the data read
// from fcgi responder out of fcgi packet before returning it.
func (this *FCGIClient) Do(p map[string]string, req io.Reader) (r io.Reader, err error) {
	err = this.writeBeginRequest(uint16(FCGI_RESPONDER), FCGI_KEEP_CONN)
	if err != nil {
		return
	}

	err = this.writePairs(FCGI_PARAMS, p)
	if err != nil {
		return
	}

	body := newWriter(this, FCGI_STDIN)
	if req != nil {
		io.Copy(body, req)
	}
	body.Close()

	r = &streamReader{c: this}
	return
}

// Request returns a HTTP Response with Header and Body
// from fcgi responder
func (this *FCGIClient) Request(p map[string]string, req io.Reader) (resp *http.Response, err error) {

	r, err := this.Do(p, req)
	if err != nil {
		return
	}

	rb := bufio.NewReader(r)
	tp := textproto.NewReader(rb)
	resp = new(http.Response)

	// Parse the response headers.
	mimeHeader, err := tp.ReadMIMEHeader()
	if err != nil {
		return
	}
	resp.Header = http.Header(mimeHeader)

	// TODO: fixTransferEncoding ?
	resp.TransferEncoding = resp.Header["Transfer-Encoding"]
	resp.ContentLength, _ = strconv.ParseInt(resp.Header.Get("Content-Length"), 10, 64)

	if chunked(resp.TransferEncoding) {
		resp.Body = ioutil.NopCloser(httputil.NewChunkedReader(rb))
	} else {
		resp.Body = ioutil.NopCloser(rb)
	}

	return
}

// Get issues a GET request to the fcgi responder.
func (this *FCGIClient) Get(p map[string]string) (resp *http.Response, err error) {

	p["REQUEST_METHOD"] = "GET"
	p["CONTENT_LENGTH"] = "0"

	return this.Request(p, nil)
}

// Get issues a Post request to the fcgi responder. with request body
// in the format that bodyType specified
func (this *FCGIClient) Post(p map[string]string, bodyType string, body io.Reader, l int) (resp *http.Response, err error) {

	if len(p["REQUEST_METHOD"]) == 0 || p["REQUEST_METHOD"] == "GET" {
		p["REQUEST_METHOD"] = "POST"
	}
	p["CONTENT_LENGTH"] = strconv.Itoa(l)
	if len(bodyType) > 0 {
		p["CONTENT_TYPE"] = bodyType
	} else {
		p["CONTENT_TYPE"] = "application/x-www-form-urlencoded"
	}

	return this.Request(p, body)
}

// PostForm issues a POST to the fcgi responder, with form
// as a string key to a list values (url.Values)
func (this *FCGIClient) PostForm(p map[string]string, data url.Values) (resp *http.Response, err error) {
	body := bytes.NewReader([]byte(data.Encode()))
	return this.Post(p, "application/x-www-form-urlencoded", body, body.Len())
}

// PostFile issues a POST to the fcgi responder in multipart(RFC 2046) standard,
// with form as a string key to a list values (url.Values),
// and/or with file as a string key to a list file path.
func (this *FCGIClient) PostFile(p map[string]string, data url.Values, file map[string]string) (resp *http.Response, err error) {
	buf := &bytes.Buffer{}
	writer := multipart.NewWriter(buf)
	bodyType := writer.FormDataContentType()

	for key, val := range data {
		for _, v0 := range val {
			err = writer.WriteField(key, v0)
			if err != nil {
				return
			}
		}
	}

	for key, val := range file {
		fd, e := os.Open(val)
		if e != nil {
			return nil, e
		}
		defer fd.Close()

		part, e := writer.CreateFormFile(key, filepath.Base(val))
		if e != nil {
			return nil, e
		}
		_, err = io.Copy(part, fd)
	}

	err = writer.Close()
	if err != nil {
		return
	}

	return this.Post(p, bodyType, buf, buf.Len())
}

// Checks whether chunked is part of the encodings stack
func chunked(te []string) bool { return len(te) > 0 && te[0] == "chunked" }
<commit_msg>remove unused functions and actually use keepalive value<commit_after>// Copyright 2012 Junqing Tan <ivan@mysqlab.net> and The Go Authors
// Use of this source code is governed by a BSD-style
// Part of source code is from Go fcgi package

package fcgiclient

import (
	"bufio"
	"bytes"
	"encoding/binary"
	"errors"
	"io"
	"io/ioutil"
	"net"
	"net/http"
	"net/http/httputil"
	"net/textproto"
	"strconv"
	"sync"
	"time"
)

const FCGI_LISTENSOCK_FILENO uint8 = 0
const FCGI_HEADER_LEN uint8 = 8
const VERSION_1 uint8 = 1
const FCGI_NULL_REQUEST_ID uint8 = 0
const FCGI_KEEP_CONN uint8 = 1
const doubleCRLF = "\r\n\r\n"

const (
	FCGI_BEGIN_REQUEST uint8 = iota + 1
	FCGI_ABORT_REQUEST
	FCGI_END_REQUEST
	FCGI_PARAMS
	FCGI_STDIN
	FCGI_STDOUT
	FCGI_STDERR
	FCGI_DATA
	FCGI_GET_VALUES
	FCGI_GET_VALUES_RESULT
	FCGI_UNKNOWN_TYPE
	FCGI_MAXTYPE = FCGI_UNKNOWN_TYPE
)

const (
	FCGI_RESPONDER uint8 = iota + 1
	FCGI_AUTHORIZER
	FCGI_FILTER
)

const (
	FCGI_REQUEST_COMPLETE uint8 = iota
	FCGI_CANT_MPX_CONN
	FCGI_OVERLOADED
	FCGI_UNKNOWN_ROLE
)

const (
	FCGI_MAX_CONNS  string = "MAX_CONNS"
	FCGI_MAX_REQS   string = "MAX_REQS"
	FCGI_MPXS_CONNS string = "MPXS_CONNS"
)

const (
	maxWrite = 65500 // 65530 may work, but for compatibility
	maxPad   = 255
)

type header struct {
	Version       uint8
	Type          uint8
	Id            uint16
	ContentLength uint16
	PaddingLength uint8
	Reserved      uint8
}

// for padding so we don't have to allocate all the time
// not synchronized because we don't care what the contents are
var pad [maxPad]byte

func (h *header) init(recType uint8, reqId uint16, contentLength int) {
	h.Version = 1
	h.Type = recType
	h.Id = reqId
	h.ContentLength = uint16(contentLength)
	h.PaddingLength = uint8(-contentLength & 7)
}

type record struct {
	h    header
	rbuf []byte
}

func (rec *record) read(r io.Reader) (buf []byte, err error) {
	if err = binary.Read(r, binary.BigEndian, &rec.h); err != nil {
		return
	}
	if rec.h.Version != 1 {
		err = errors.New("fcgi: invalid header version")
		return
	}
	if rec.h.Type == FCGI_END_REQUEST {
		err = io.EOF
		return
	}
	n := int(rec.h.ContentLength) + int(rec.h.PaddingLength)
	if len(rec.rbuf) < n {
		rec.rbuf = make([]byte, n)
	}
	if n, err = io.ReadFull(r, rec.rbuf[:n]); err != nil {
		return
	}
	buf = rec.rbuf[:int(rec.h.ContentLength)]

	return
}

type FCGIClient struct {
	mutex     sync.Mutex
	rwc       io.ReadWriteCloser
	h         header
	buf       bytes.Buffer
	keepAlive bool
	reqId     uint16
}

// Connects to the fcgi responder at the specified network address.
// See func net.Dial for a description of the network and address parameters.
func Dial(network, address string) (fcgi *FCGIClient, err error) {
	var conn net.Conn

	conn, err = net.Dial(network, address)
	if err != nil {
		return
	}

	fcgi = &FCGIClient{
		rwc:       conn,
		keepAlive: true,
		reqId:     1,
	}

	return
}

// Connects to the fcgi responder at the specified network address with timeout
// See func net.DialTimeout for a description of the network, address and timeout parameters.
func DialTimeout(network, address string, timeout time.Duration) (fcgi *FCGIClient, err error) {

	var conn net.Conn

	conn, err = net.DialTimeout(network, address, timeout)
	if err != nil {
		return
	}

	fcgi = &FCGIClient{
		rwc:       conn,
		keepAlive: true,
		reqId:     1,
	}

	return
}

// Close fcgi connnection
func (this *FCGIClient) Close() {
	this.rwc.Close()
}

func (this *FCGIClient) writeRecord(recType uint8, content []byte) (err error) {
	this.mutex.Lock()
	defer this.mutex.Unlock()
	this.buf.Reset()
	this.h.init(recType, this.reqId, len(content))
	if err := binary.Write(&this.buf, binary.BigEndian, this.h); err != nil {
		return err
	}
	if _, err := this.buf.Write(content); err != nil {
		return err
	}
	if _, err := this.buf.Write(pad[:this.h.PaddingLength]); err != nil {
		return err
	}
	_, err = this.rwc.Write(this.buf.Bytes())
	return err
}

func (this *FCGIClient) writeBeginRequest(role uint16, flags uint8) error {
	b := [8]byte{byte(role >> 8), byte(role), flags}
	return this.writeRecord(FCGI_BEGIN_REQUEST, b[:])
}

func (this *FCGIClient) writeEndRequest(appStatus int, protocolStatus uint8) error {
	b := make([]byte, 8)
	binary.BigEndian.PutUint32(b, uint32(appStatus))
	b[4] = protocolStatus
	return this.writeRecord(FCGI_END_REQUEST, b)
}

func (this *FCGIClient) writePairs(recType uint8, pairs map[string]string) error {
	w := newWriter(this, recType)
	b := make([]byte, 8)
	nn := 0
	for k, v := range pairs {
		m := 8 + len(k) + len(v)
		if m > maxWrite {
			// param data size exceed 65535 bytes"
			vl := maxWrite - 8 - len(k)
			v = v[:vl]
		}
		n := encodeSize(b, uint32(len(k)))
		n += encodeSize(b[n:], uint32(len(v)))
		m = n + len(k) + len(v)
		if (nn + m) > maxWrite {
			w.Flush()
			nn = 0
		}
		nn += m
		if _, err := w.Write(b[:n]); err != nil {
			return err
		}
		if _, err := w.WriteString(k); err != nil {
			return err
		}
		if _, err := w.WriteString(v); err != nil {
			return err
		}
	}
	w.Close()
	return nil
}

func readSize(s []byte) (uint32, int) {
	if len(s) == 0 {
		return 0, 0
	}
	size, n := uint32(s[0]), 1
	if size&(1<<7) != 0 {
		if len(s) < 4 {
			return 0, 0
		}
		n = 4
		size = binary.BigEndian.Uint32(s)
		size &^= 1 << 31
	}
	return size, n
}

func readString(s []byte, size uint32) string {
	if size > uint32(len(s)) {
		return ""
	}
	return string(s[:size])
}

func encodeSize(b []byte, size uint32) int {
	if size > 127 {
		size |= 1 << 31
		binary.BigEndian.PutUint32(b, size)
		return 4
	}
	b[0] = byte(size)
	return 1
}

// bufWriter encapsulates bufio.Writer but also closes the underlying stream when
// Closed.
type bufWriter struct {
	closer io.Closer
	*bufio.Writer
}

func (w *bufWriter) Close() error {
	if err := w.Writer.Flush(); err != nil {
		w.closer.Close()
		return err
	}
	return w.closer.Close()
}

func newWriter(c *FCGIClient, recType uint8) *bufWriter {
	s := &streamWriter{c: c, recType: recType}
	w := bufio.NewWriterSize(s, maxWrite)
	return &bufWriter{s, w}
}

// streamWriter abstracts out the separation of a stream into discrete records.
// It only writes maxWrite bytes at a time.
type streamWriter struct {
	c       *FCGIClient
	recType uint8
}

func (w *streamWriter) Write(p []byte) (int, error) {
	nn := 0
	for len(p) > 0 {
		n := len(p)
		if n > maxWrite {
			n = maxWrite
		}
		if err := w.c.writeRecord(w.recType, p[:n]); err != nil {
			return nn, err
		}
		nn += n
		p = p[n:]
	}
	return nn, nil
}

func (w *streamWriter) Close() error {
	// send empty record to close the stream
	return w.c.writeRecord(w.recType, nil)
}

type streamReader struct {
	c   *FCGIClient
	buf []byte
}

func (w *streamReader) Read(p []byte) (n int, err error) {

	if len(p) > 0 {
		if len(w.buf) == 0 {
			rec := &record{}
			w.buf, err = rec.read(w.c.rwc)
			if err != nil {
				return
			}
		}

		n = len(p)
		if n > len(w.buf) {
			n = len(w.buf)
		}
		copy(p, w.buf[:n])
		w.buf = w.buf[n:]
	}

	return
}

// Do made the request and returns a io.Reader that translates the data read
// from fcgi responder out of fcgi packet before returning it.
func (this *FCGIClient) Do(p map[string]string, req io.Reader) (r io.Reader, err error) {
	var flags uint8
	if this.keepAlive {
		flags = FCGI_KEEP_CONN
	}
	err = this.writeBeginRequest(uint16(FCGI_RESPONDER), flags)
	if err != nil {
		return
	}

	err = this.writePairs(FCGI_PARAMS, p)
	if err != nil {
		return
	}

	body := newWriter(this, FCGI_STDIN)
	if req != nil {
		io.Copy(body, req)
	}
	body.Close()

	r = &streamReader{c: this}
	return
}

// Request returns a HTTP Response with Header and Body
// from fcgi responder
func (this *FCGIClient) Request(p map[string]string, req io.Reader) (resp *http.Response, err error) {

	r, err := this.Do(p, req)
	if err != nil {
		return
	}

	rb := bufio.NewReader(r)
	tp := textproto.NewReader(rb)
	resp = new(http.Response)

	// Parse the response headers.
	mimeHeader, err := tp.ReadMIMEHeader()
	if err != nil {
		return
	}
	resp.Header = http.Header(mimeHeader)

	// TODO: fixTransferEncoding ?
	resp.TransferEncoding = resp.Header["Transfer-Encoding"]
	resp.ContentLength, _ = strconv.ParseInt(resp.Header.Get("Content-Length"), 10, 64)

	if chunked(resp.TransferEncoding) {
		resp.Body = ioutil.NopCloser(httputil.NewChunkedReader(rb))
	} else {
		resp.Body = ioutil.NopCloser(rb)
	}

	return
}

// Checks whether chunked is part of the encodings stack
func chunked(te []string) bool { return len(te) > 0 && te[0] == "chunked" }
<|endoftext|>