<commit_before>// Copyright 2016 Factom Foundation
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.

package main

import (
	"flag"
	"fmt"
	"os"
	"strings"

	"github.com/FactomProject/cli"
	"github.com/FactomProject/factom"
	fct "github.com/FactomProject/factoid"
	"github.com/FactomProject/fctwallet/Wallet/Utility"
)

// balance prints the current balance of the specified address
var balance = func() *fctCmd {
	cmd := new(fctCmd)
	cmd.helpMsg = "factom-cli balance ADDRESS"
	cmd.description = "If this is an EC Address, returns number of Entry Credits. If this is a Factoid Address, returns the Factoid balance."
	cmd.execFunc = func(args []string) {
		os.Args = args
		flag.Parse()
		args = flag.Args()

		if len(args) < 1 {
			fmt.Println(cmd.helpMsg)
			return
		}
		addr := args[0]

		if strings.HasPrefix(addr, "FA") {
			if !Utility.IsValidAddress(addr) {
				fmt.Println("Invalid Factoid Address")
			}

			if b, err := factom.FctBalance(addr); err != nil {
				fmt.Println("Undefined or invalid address")
			} else {
				fmt.Println(addr, fct.ConvertDecimal(uint64(b)))
			}
		} else if strings.HasPrefix(addr, "EC") {
			if !Utility.IsValidAddress(addr) {
				fmt.Println("Invalid EC Address")
			}

			if b, err := factom.ECBalance(addr); err != nil {
				fmt.Println("Undefined or invalid address")
			} else {
				fmt.Println(addr, b)
			}
		} else {
			fmt.Println("Invalid address")
		}
	}
	help.Add("balance", cmd)
	return cmd
}()

// Generate a new Address
var generateaddress = func() *fctCmd {
	cmd := new(fctCmd)
	cmd.helpMsg = "factom-cli generateaddress fct|ec NAME"
	cmd.description = "Generate and name a new factoid or ec address"
	cmd.execFunc = func(args []string) {
		os.Args = args
		flag.Parse()
		args = flag.Args()

		c := cli.New()
		c.Handle("ec", ecGenerateAddr)
		c.Handle("fct", fctGenerateAddr)
		c.HandleDefaultFunc(func(args []string) {
			fmt.Println(cmd.helpMsg)
		})
		c.Execute(args)
	}
	help.Add("generateaddress", cmd)
	help.Add("newaddress", cmd)
	return cmd
}()

// Generate a new Entry Credit Address
var ecGenerateAddr = func() *fctCmd {
	cmd := new(fctCmd)
	cmd.helpMsg = "factom-cli generateaddress ec NAME"
	cmd.description = "Generate and name a new ec address"
	cmd.execFunc = func(args []string) {
		if addr, err := factom.GenerateEntryCreditAddress(args[1]); err != nil {
			fmt.Println(err)
		} else {
			fmt.Println(addr)
		}
	}
	help.Add("generateaddress ec", cmd)
	help.Add("newaddress ec", cmd)
	return cmd

}()

// Generate a new Factoid Address
var fctGenerateAddr = func() *fctCmd {
	cmd := new(fctCmd)
	cmd.helpMsg = "factom-cli generateaddress fct NAME"
	cmd.description = "Generate and name a new factoid address"
	cmd.execFunc = func(args []string) {
		if addr, err := factom.GenerateFactoidAddress(args[1]); err != nil {
			fmt.Println(err)
		} else {
			fmt.Println(addr)
		}
	}
	help.Add("generateaddress fct", cmd)
	help.Add("newaddress fct", cmd)
	return cmd
}()

var getaddresses = func() *fctCmd {
	cmd := new(fctCmd)
	cmd.helpMsg = "factom-cli getaddresses|balances"
	cmd.description = "Returns the list of addresses known to the wallet. Returns the name that can be used tied to each address, as well as the base 58 address (which is the actual address). This command also returns the balances at each address."
	cmd.execFunc = func(args []string) {
		os.Args = args
		flag.Parse()
		args = flag.Args()
		if len(args) > 0 {
			fmt.Println(cmd.helpMsg)
		}

		str := fmt.Sprintf("http://%s/v1/factoid-get-addresses/", serverFct)
		getCmd(str, "Error printing addresses")
	}
	help.Add("getaddress", cmd)
	help.Add("balances", cmd)
	return cmd
}()

// importaddr imports a Factoid or Entry Credit private key and adds the
// address to the wallet database.
var importaddr = func() *fctCmd {
	cmd := new(fctCmd)
	cmd.helpMsg = "factom-cli importaddress NAME ESKEY|FSKEY|'12WORDS'"
	cmd.description = "Import an Entry Credit or Factoid Private Key"
	cmd.execFunc = func(args []string) {
		if len(args) < 3 {
			fmt.Println(cmd.helpMsg)
			return
		}
		if strings.HasPrefix(args[2], "Fs") {
			if addr, err := factom.GenerateFactoidAddressFromHumanReadablePrivateKey(args[1], args[2]); err != nil {
				fmt.Println(err)
				fmt.Println(cmd.helpMsg)
			} else {
				fmt.Println(args[1], addr)
			}
		} else if strings.HasPrefix(args[2], "Es") {
			if addr, err := factom.GenerateEntryCreditAddressFromHumanReadablePrivateKey(args[1], args[2]); err != nil {
				fmt.Println(err)
				fmt.Println(cmd.helpMsg)
			} else {
				fmt.Println(args[1], addr)
			}
		} else {
			if addr, err := factom.GenerateFactoidAddressFromMnemonic(args[1], args[2]); err != nil {
				fmt.Println(err)
				fmt.Println(cmd.helpMsg)
			} else {
				fmt.Println(args[1], addr)
			}
		}
	}
	help.Add("importaddress", cmd)
	return cmd
}()
<commit_msg>fixed "balance" sub command for address names<commit_after>// Copyright 2016 Factom Foundation
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.

package main

import (
	"flag"
	"fmt"
	"os"
	"strings"

	"github.com/FactomProject/cli"
	"github.com/FactomProject/factom"
	fct "github.com/FactomProject/factoid"
)

// balance prints the current balance of the specified address
var balance = func() *fctCmd {
	cmd := new(fctCmd)
	cmd.helpMsg = "factom-cli balance ADDRESS"
	cmd.description = "If this is an EC Address, returns number of Entry Credits. If this is a Factoid Address, returns the Factoid balance."
	cmd.execFunc = func(args []string) {
		os.Args = args
		flag.Parse()
		args = flag.Args()

		if len(args) < 1 {
			fmt.Println(cmd.helpMsg)
			return
		}
		addr := args[0]

		if b, err := factom.FctBalance(addr); err == nil {
			fmt.Println(addr, fct.ConvertDecimal(uint64(b)))
		} else if c, err := factom.ECBalance(addr); err == nil {
			fmt.Println(addr, c)
		} else {
			fmt.Println("Undefined or invalid address")
		}
	}
	help.Add("balance", cmd)
	return cmd
}()

// Generate a new Address
var generateaddress = func() *fctCmd {
	cmd := new(fctCmd)
	cmd.helpMsg = "factom-cli generateaddress fct|ec NAME"
	cmd.description = "Generate and name a new factoid or ec address"
	cmd.execFunc = func(args []string) {
		os.Args = args
		flag.Parse()
		args = flag.Args()

		c := cli.New()
		c.Handle("ec", ecGenerateAddr)
		c.Handle("fct", fctGenerateAddr)
		c.HandleDefaultFunc(func(args []string) {
			fmt.Println(cmd.helpMsg)
		})
		c.Execute(args)
	}
	help.Add("generateaddress", cmd)
	help.Add("newaddress", cmd)
	return cmd
}()

// Generate a new Entry Credit Address
var ecGenerateAddr = func() *fctCmd {
	cmd := new(fctCmd)
	cmd.helpMsg = "factom-cli generateaddress ec NAME"
	cmd.description = "Generate and name a new ec address"
	cmd.execFunc = func(args []string) {
		if addr, err := factom.GenerateEntryCreditAddress(args[1]); err != nil {
			fmt.Println(err)
		} else {
			fmt.Println(addr)
		}
	}
	help.Add("generateaddress ec", cmd)
	help.Add("newaddress ec", cmd)
	return cmd

}()

// Generate a new Factoid Address
var fctGenerateAddr = func() *fctCmd {
	cmd := new(fctCmd)
	cmd.helpMsg = "factom-cli generateaddress fct NAME"
	cmd.description = "Generate and name a new factoid address"
	cmd.execFunc = func(args []string) {
		if addr, err := factom.GenerateFactoidAddress(args[1]); err != nil {
			fmt.Println(err)
		} else {
			fmt.Println(addr)
		}
	}
	help.Add("generateaddress fct", cmd)
	help.Add("newaddress fct", cmd)
	return cmd
}()

var getaddresses = func() *fctCmd {
	cmd := new(fctCmd)
	cmd.helpMsg = "factom-cli getaddresses|balances"
	cmd.description = "Returns the list of addresses known to the wallet. Returns the name that can be used tied to each address, as well as the base 58 address (which is the actual address). This command also returns the balances at each address."
	cmd.execFunc = func(args []string) {
		os.Args = args
		flag.Parse()
		args = flag.Args()
		if len(args) > 0 {
			fmt.Println(cmd.helpMsg)
		}

		str := fmt.Sprintf("http://%s/v1/factoid-get-addresses/", serverFct)
		getCmd(str, "Error printing addresses")
	}
	help.Add("getaddress", cmd)
	help.Add("balances", cmd)
	return cmd
}()

// importaddr imports a Factoid or Entry Credit private key and adds the
// address to the wallet database.
var importaddr = func() *fctCmd {
	cmd := new(fctCmd)
	cmd.helpMsg = "factom-cli importaddress NAME ESKEY|FSKEY|'12WORDS'"
	cmd.description = "Import an Entry Credit or Factoid Private Key"
	cmd.execFunc = func(args []string) {
		if len(args) < 3 {
			fmt.Println(cmd.helpMsg)
			return
		}
		if strings.HasPrefix(args[2], "Fs") {
			if addr, err := factom.GenerateFactoidAddressFromHumanReadablePrivateKey(args[1], args[2]); err != nil {
				fmt.Println(err)
				fmt.Println(cmd.helpMsg)
			} else {
				fmt.Println(args[1], addr)
			}
		} else if strings.HasPrefix(args[2], "Es") {
			if addr, err := factom.GenerateEntryCreditAddressFromHumanReadablePrivateKey(args[1], args[2]); err != nil {
				fmt.Println(err)
				fmt.Println(cmd.helpMsg)
			} else {
				fmt.Println(args[1], addr)
			}
		} else {
			if addr, err := factom.GenerateFactoidAddressFromMnemonic(args[1], args[2]); err != nil {
				fmt.Println(err)
				fmt.Println(cmd.helpMsg)
			} else {
				fmt.Println(args[1], addr)
			}
		}
	}
	help.Add("importaddress", cmd)
	return cmd
}()
<|endoftext|>


<commit_before>package main

import (
	"encoding/xml"
	"fmt"
	"io"
	"strings"

	"github.com/beevik/etree"
)

type aggregator struct {
	XMLName   xml.Name `xml:"EntitiesDescriptor"`
	Entities  map[string]*etree.Element
	rootAttrs map[string]etree.Attr
}

func (a *aggregator) add(r io.Reader) error {

	if a.Entities == nil {
		a.Entities = map[string]*etree.Element{}
		a.rootAttrs = map[string]etree.Attr{}
	}

	d := etree.NewDocument()
	if _, err := d.ReadFrom(r); err != nil {
		return err
	}

	root := d.Root()

	if root == nil {
		return fmt.Errorf("Nil root element")
	}

	for _, attr := range root.Attr {
		a.rootAttrs[strings.Join([]string{attr.Space, attr.Key}, ":")] = attr
	}

	fmt.Printf("root = %+v\n", root)

	switch root.Tag {
	case "EntitiesDescriptor":
		for _, child := range root.ChildElements() {
			fmt.Printf("child = %+v\n", child)
			a.addElement(child)
		}
	case "EntityDescriptor":
		a.addElement(root)
	}

	return nil
}

func (a *aggregator) addElement(e *etree.Element) {
	k := e.SelectAttrValue("entityID", "")
	if k != "" {
		a.Entities[k] = e
	}
}

func (a *aggregator) Doc() *etree.Document {
	d := etree.NewDocument()
	ele := etree.NewElement("EntitiesDescriptor")
	ele.Attr = make([]etree.Attr, 0, len(a.rootAttrs))
	for _, attr := range a.rootAttrs {
		ele.Attr = append(ele.Attr, attr)
	}

	for _, entity := range a.Entities {
		ele.AddChild(entity)
	}

	d.SetRoot(ele)

	return d
}

func (a *aggregator) WriteTo(w io.Writer) (int64, error) {
	return a.Doc().WriteTo(w)
}
<commit_msg>Only take xmlns attributes from root elements<commit_after>package main

import (
	"encoding/xml"
	"fmt"
	"io"
	"strings"

	"github.com/beevik/etree"
)

type aggregator struct {
	XMLName  xml.Name `xml:"EntitiesDescriptor"`
	Entities map[string]*etree.Element
	xmlns    map[string]etree.Attr
}

func (a *aggregator) add(r io.Reader) error {

	if a.Entities == nil {
		a.Entities = map[string]*etree.Element{}
		a.xmlns = map[string]etree.Attr{}
	}

	d := etree.NewDocument()
	if _, err := d.ReadFrom(r); err != nil {
		return err
	}

	root := d.Root()

	if root == nil {
		return fmt.Errorf("Nil root element")
	}

	for _, attr := range root.Attr {
		if attr.Key == "xmlns" || attr.Space == "xmlns" {
			a.xmlns[strings.Join([]string{attr.Space, attr.Key}, ":")] = attr
		}
	}

	fmt.Printf("root = %+v\n", root)

	switch root.Tag {
	case "EntitiesDescriptor":
		for _, child := range root.ChildElements() {
			fmt.Printf("child = %+v\n", child)
			a.addElement(child)
		}
	case "EntityDescriptor":
		a.addElement(root)
	}

	return nil
}

func (a *aggregator) addElement(e *etree.Element) {
	k := e.SelectAttrValue("entityID", "")
	if k != "" {
		a.Entities[k] = e
	}
}

func (a *aggregator) Doc() *etree.Document {
	d := etree.NewDocument()
	ele := etree.NewElement("EntitiesDescriptor")
	ele.Attr = make([]etree.Attr, 0, len(a.xmlns))
	for _, attr := range a.xmlns {
		ele.Attr = append(ele.Attr, attr)
	}

	for _, entity := range a.Entities {
		ele.AddChild(entity)
	}

	d.SetRoot(ele)

	return d
}

func (a *aggregator) WriteTo(w io.Writer) (int64, error) {
	return a.Doc().WriteTo(w)
}
<|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 e2e_node

import (
	"fmt"
	"net"
	"os/exec"
	"strings"

	"k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/sets"
	"k8s.io/apimachinery/pkg/util/uuid"
	"k8s.io/kubernetes/test/e2e/framework"

	. "github.com/onsi/ginkgo"
)

var _ = framework.KubeDescribe("Security Context", func() {
	f := framework.NewDefaultFramework("security-context-test")
	var podClient *framework.PodClient
	BeforeEach(func() {
		podClient = f.PodClient()
	})

	Context("when creating a pod in the host PID namespace", func() {
		makeHostPidPod := func(podName, image string, command []string, hostPID bool) *v1.Pod {
			return &v1.Pod{
				ObjectMeta: metav1.ObjectMeta{
					Name: podName,
				},
				Spec: v1.PodSpec{
					RestartPolicy: v1.RestartPolicyNever,
					HostPID:       hostPID,
					Containers: []v1.Container{
						{
							Image:   image,
							Name:    podName,
							Command: command,
						},
					},
				},
			}
		}
		createAndWaitHostPidPod := func(podName string, hostPID bool) {
			podClient.Create(makeHostPidPod(podName,
				"gcr.io/google_containers/busybox:1.24",
				[]string{"sh", "-c", "pidof nginx || true"},
				hostPID,
			))

			podClient.WaitForSuccess(podName, framework.PodStartTimeout)
		}

		nginxPid := ""
		BeforeEach(func() {
			nginxPodName := "nginx-hostpid-" + string(uuid.NewUUID())
			podClient.CreateSync(makeHostPidPod(nginxPodName,
				"gcr.io/google_containers/nginx-slim:0.7",
				nil,
				true,
			))

			output := f.ExecShellInContainer(nginxPodName, nginxPodName,
				"cat /var/run/nginx.pid")
			nginxPid = strings.TrimSpace(output)
		})

		It("should show its pid in the host PID namespace", func() {
			busyboxPodName := "busybox-hostpid-" + string(uuid.NewUUID())
			createAndWaitHostPidPod(busyboxPodName, true)
			logs, err := framework.GetPodLogs(f.ClientSet, f.Namespace.Name, busyboxPodName, busyboxPodName)
			if err != nil {
				framework.Failf("GetPodLogs for pod %q failed: %v", busyboxPodName, err)
			}

			pids := strings.TrimSpace(logs)
			framework.Logf("Got nginx's pid %q from pod %q", pids, busyboxPodName)
			if pids == "" {
				framework.Failf("nginx's pid should be seen by hostpid containers")
			}

			pidSets := sets.NewString(strings.Split(pids, " ")...)
			if !pidSets.Has(nginxPid) {
				framework.Failf("nginx's pid should be seen by hostpid containers")
			}
		})

		It("should not show its pid in the non-hostpid containers", func() {
			busyboxPodName := "busybox-non-hostpid-" + string(uuid.NewUUID())
			createAndWaitHostPidPod(busyboxPodName, false)
			logs, err := framework.GetPodLogs(f.ClientSet, f.Namespace.Name, busyboxPodName, busyboxPodName)
			if err != nil {
				framework.Failf("GetPodLogs for pod %q failed: %v", busyboxPodName, err)
			}

			pids := strings.TrimSpace(logs)
			framework.Logf("Got nginx's pid %q from pod %q", pids, busyboxPodName)
			pidSets := sets.NewString(strings.Split(pids, " ")...)
			if pidSets.Has(nginxPid) {
				framework.Failf("nginx's pid should not be seen by non-hostpid containers")
			}
		})
	})

	Context("when creating a pod in the host IPC namespace", func() {
		makeHostIPCPod := func(podName, image string, command []string, hostIPC bool) *v1.Pod {
			return &v1.Pod{
				ObjectMeta: metav1.ObjectMeta{
					Name: podName,
				},
				Spec: v1.PodSpec{
					RestartPolicy: v1.RestartPolicyNever,
					HostIPC:       hostIPC,
					Containers: []v1.Container{
						{
							Image:   image,
							Name:    podName,
							Command: command,
						},
					},
				},
			}
		}
		createAndWaitHostIPCPod := func(podName string, hostNetwork bool) {
			podClient.Create(makeHostIPCPod(podName,
				"gcr.io/google_containers/busybox:1.24",
				[]string{"sh", "-c", "ipcs -m | awk '{print $2}'"},
				hostNetwork,
			))

			podClient.WaitForSuccess(podName, framework.PodStartTimeout)
		}

		hostSharedMemoryID := ""
		BeforeEach(func() {
			output, err := exec.Command("sh", "-c", "ipcmk -M 1M | awk '{print $NF}'").Output()
			if err != nil {
				framework.Failf("Failed to create the shared memory on the host: %v", err)
			}
			hostSharedMemoryID = strings.TrimSpace(string(output))
			framework.Logf("Got host shared memory ID %q", hostSharedMemoryID)
		})

		It("should show the shared memory ID in the host IPC containers", func() {
			busyboxPodName := "busybox-hostipc-" + string(uuid.NewUUID())
			createAndWaitHostIPCPod(busyboxPodName, true)
			logs, err := framework.GetPodLogs(f.ClientSet, f.Namespace.Name, busyboxPodName, busyboxPodName)
			if err != nil {
				framework.Failf("GetPodLogs for pod %q failed: %v", busyboxPodName, err)
			}

			podSharedMemoryIDs := strings.TrimSpace(logs)
			framework.Logf("Got shared memory IDs %q from pod %q", podSharedMemoryIDs, busyboxPodName)
			if !strings.Contains(podSharedMemoryIDs, hostSharedMemoryID) {
				framework.Failf("hostIPC container should show shared memory IDs on host")
			}
		})

		It("should not show the shared memory ID in the non-hostIPC containers", func() {
			busyboxPodName := "busybox-non-hostipc-" + string(uuid.NewUUID())
			createAndWaitHostIPCPod(busyboxPodName, false)
			logs, err := framework.GetPodLogs(f.ClientSet, f.Namespace.Name, busyboxPodName, busyboxPodName)
			if err != nil {
				framework.Failf("GetPodLogs for pod %q failed: %v", busyboxPodName, err)
			}

			podSharedMemoryIDs := strings.TrimSpace(logs)
			framework.Logf("Got shared memory IDs %q from pod %q", podSharedMemoryIDs, busyboxPodName)
			if strings.Contains(podSharedMemoryIDs, hostSharedMemoryID) {
				framework.Failf("non-hostIPC container should not show shared memory IDs on host")
			}
		})

		AfterEach(func() {
			if hostSharedMemoryID != "" {
				_, err := exec.Command("sh", "-c", fmt.Sprintf("ipcrm -m %q", hostSharedMemoryID)).Output()
				if err != nil {
					framework.Failf("Failed to remove shared memory %q on the host: %v", hostSharedMemoryID, err)
				}
			}
		})
	})

	Context("when creating a pod in the host network namespace", func() {
		makeHostNetworkPod := func(podName, image string, command []string, hostNetwork bool) *v1.Pod {
			return &v1.Pod{
				ObjectMeta: metav1.ObjectMeta{
					Name: podName,
				},
				Spec: v1.PodSpec{
					RestartPolicy: v1.RestartPolicyNever,
					HostNetwork:   hostNetwork,
					Containers: []v1.Container{
						{
							Image:   image,
							Name:    podName,
							Command: command,
						},
					},
				},
			}
		}
		listListeningPortsCommand := []string{"sh", "-c", "netstat -ln"}
		createAndWaitHostNetworkPod := func(podName string, hostNetwork bool) {
			podClient.Create(makeHostNetworkPod(podName,
				"gcr.io/google_containers/busybox:1.24",
				listListeningPortsCommand,
				hostNetwork,
			))

			podClient.WaitForSuccess(podName, framework.PodStartTimeout)
		}

		listeningPort := ""
		var l net.Listener
		BeforeEach(func() {
			l, err := net.Listen("tcp", ":0")
			if err != nil {
				framework.Failf("Failed to open a new tcp port: %v", err)
			}
			addr := strings.Split(l.Addr().String(), ":")
			listeningPort = addr[len(addr)-1]
			framework.Logf("Opened a new tcp port %q", listeningPort)
		})

		It("should listen on same port in the host network containers", func() {
			busyboxPodName := "busybox-hostnetwork-" + string(uuid.NewUUID())
			createAndWaitHostNetworkPod(busyboxPodName, true)
			logs, err := framework.GetPodLogs(f.ClientSet, f.Namespace.Name, busyboxPodName, busyboxPodName)
			if err != nil {
				framework.Failf("GetPodLogs for pod %q failed: %v", busyboxPodName, err)
			}

			framework.Logf("Got logs for pod %q: %q", busyboxPodName, logs)
			if !strings.Contains(logs, listeningPort) {
				framework.Failf("host-networked container should listening on same port as host")
			}
		})

		It("shouldn't show the same port in the non-hostnetwork containers", func() {
			busyboxPodName := "busybox-non-hostnetwork-" + string(uuid.NewUUID())
			createAndWaitHostNetworkPod(busyboxPodName, false)
			logs, err := framework.GetPodLogs(f.ClientSet, f.Namespace.Name, busyboxPodName, busyboxPodName)
			if err != nil {
				framework.Failf("GetPodLogs for pod %q failed: %v", busyboxPodName, err)
			}

			framework.Logf("Got logs for pod %q: %q", busyboxPodName, logs)
			if strings.Contains(logs, listeningPort) {
				framework.Failf("non-hostnetworked container shouldn't show the same port as host")
			}
		})

		AfterEach(func() {
			if l != nil {
				l.Close()
			}
		})
	})

})
<commit_msg>Add node e2e tests for runAsUser<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 e2e_node

import (
	"fmt"
	"net"
	"os/exec"
	"strings"

	"k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/sets"
	"k8s.io/apimachinery/pkg/util/uuid"
	"k8s.io/kubernetes/test/e2e/framework"

	. "github.com/onsi/ginkgo"
)

var _ = framework.KubeDescribe("Security Context", func() {
	f := framework.NewDefaultFramework("security-context-test")
	var podClient *framework.PodClient
	BeforeEach(func() {
		podClient = f.PodClient()
	})

	Context("when creating a pod in the host PID namespace", func() {
		makeHostPidPod := func(podName, image string, command []string, hostPID bool) *v1.Pod {
			return &v1.Pod{
				ObjectMeta: metav1.ObjectMeta{
					Name: podName,
				},
				Spec: v1.PodSpec{
					RestartPolicy: v1.RestartPolicyNever,
					HostPID:       hostPID,
					Containers: []v1.Container{
						{
							Image:   image,
							Name:    podName,
							Command: command,
						},
					},
				},
			}
		}
		createAndWaitHostPidPod := func(podName string, hostPID bool) {
			podClient.Create(makeHostPidPod(podName,
				"gcr.io/google_containers/busybox:1.24",
				[]string{"sh", "-c", "pidof nginx || true"},
				hostPID,
			))

			podClient.WaitForSuccess(podName, framework.PodStartTimeout)
		}

		nginxPid := ""
		BeforeEach(func() {
			nginxPodName := "nginx-hostpid-" + string(uuid.NewUUID())
			podClient.CreateSync(makeHostPidPod(nginxPodName,
				"gcr.io/google_containers/nginx-slim:0.7",
				nil,
				true,
			))

			output := f.ExecShellInContainer(nginxPodName, nginxPodName,
				"cat /var/run/nginx.pid")
			nginxPid = strings.TrimSpace(output)
		})

		It("should show its pid in the host PID namespace", func() {
			busyboxPodName := "busybox-hostpid-" + string(uuid.NewUUID())
			createAndWaitHostPidPod(busyboxPodName, true)
			logs, err := framework.GetPodLogs(f.ClientSet, f.Namespace.Name, busyboxPodName, busyboxPodName)
			if err != nil {
				framework.Failf("GetPodLogs for pod %q failed: %v", busyboxPodName, err)
			}

			pids := strings.TrimSpace(logs)
			framework.Logf("Got nginx's pid %q from pod %q", pids, busyboxPodName)
			if pids == "" {
				framework.Failf("nginx's pid should be seen by hostpid containers")
			}

			pidSets := sets.NewString(strings.Split(pids, " ")...)
			if !pidSets.Has(nginxPid) {
				framework.Failf("nginx's pid should be seen by hostpid containers")
			}
		})

		It("should not show its pid in the non-hostpid containers", func() {
			busyboxPodName := "busybox-non-hostpid-" + string(uuid.NewUUID())
			createAndWaitHostPidPod(busyboxPodName, false)
			logs, err := framework.GetPodLogs(f.ClientSet, f.Namespace.Name, busyboxPodName, busyboxPodName)
			if err != nil {
				framework.Failf("GetPodLogs for pod %q failed: %v", busyboxPodName, err)
			}

			pids := strings.TrimSpace(logs)
			framework.Logf("Got nginx's pid %q from pod %q", pids, busyboxPodName)
			pidSets := sets.NewString(strings.Split(pids, " ")...)
			if pidSets.Has(nginxPid) {
				framework.Failf("nginx's pid should not be seen by non-hostpid containers")
			}
		})
	})

	Context("when creating a pod in the host IPC namespace", func() {
		makeHostIPCPod := func(podName, image string, command []string, hostIPC bool) *v1.Pod {
			return &v1.Pod{
				ObjectMeta: metav1.ObjectMeta{
					Name: podName,
				},
				Spec: v1.PodSpec{
					RestartPolicy: v1.RestartPolicyNever,
					HostIPC:       hostIPC,
					Containers: []v1.Container{
						{
							Image:   image,
							Name:    podName,
							Command: command,
						},
					},
				},
			}
		}
		createAndWaitHostIPCPod := func(podName string, hostNetwork bool) {
			podClient.Create(makeHostIPCPod(podName,
				"gcr.io/google_containers/busybox:1.24",
				[]string{"sh", "-c", "ipcs -m | awk '{print $2}'"},
				hostNetwork,
			))

			podClient.WaitForSuccess(podName, framework.PodStartTimeout)
		}

		hostSharedMemoryID := ""
		BeforeEach(func() {
			output, err := exec.Command("sh", "-c", "ipcmk -M 1M | awk '{print $NF}'").Output()
			if err != nil {
				framework.Failf("Failed to create the shared memory on the host: %v", err)
			}
			hostSharedMemoryID = strings.TrimSpace(string(output))
			framework.Logf("Got host shared memory ID %q", hostSharedMemoryID)
		})

		It("should show the shared memory ID in the host IPC containers", func() {
			busyboxPodName := "busybox-hostipc-" + string(uuid.NewUUID())
			createAndWaitHostIPCPod(busyboxPodName, true)
			logs, err := framework.GetPodLogs(f.ClientSet, f.Namespace.Name, busyboxPodName, busyboxPodName)
			if err != nil {
				framework.Failf("GetPodLogs for pod %q failed: %v", busyboxPodName, err)
			}

			podSharedMemoryIDs := strings.TrimSpace(logs)
			framework.Logf("Got shared memory IDs %q from pod %q", podSharedMemoryIDs, busyboxPodName)
			if !strings.Contains(podSharedMemoryIDs, hostSharedMemoryID) {
				framework.Failf("hostIPC container should show shared memory IDs on host")
			}
		})

		It("should not show the shared memory ID in the non-hostIPC containers", func() {
			busyboxPodName := "busybox-non-hostipc-" + string(uuid.NewUUID())
			createAndWaitHostIPCPod(busyboxPodName, false)
			logs, err := framework.GetPodLogs(f.ClientSet, f.Namespace.Name, busyboxPodName, busyboxPodName)
			if err != nil {
				framework.Failf("GetPodLogs for pod %q failed: %v", busyboxPodName, err)
			}

			podSharedMemoryIDs := strings.TrimSpace(logs)
			framework.Logf("Got shared memory IDs %q from pod %q", podSharedMemoryIDs, busyboxPodName)
			if strings.Contains(podSharedMemoryIDs, hostSharedMemoryID) {
				framework.Failf("non-hostIPC container should not show shared memory IDs on host")
			}
		})

		AfterEach(func() {
			if hostSharedMemoryID != "" {
				_, err := exec.Command("sh", "-c", fmt.Sprintf("ipcrm -m %q", hostSharedMemoryID)).Output()
				if err != nil {
					framework.Failf("Failed to remove shared memory %q on the host: %v", hostSharedMemoryID, err)
				}
			}
		})
	})

	Context("when creating a pod in the host network namespace", func() {
		makeHostNetworkPod := func(podName, image string, command []string, hostNetwork bool) *v1.Pod {
			return &v1.Pod{
				ObjectMeta: metav1.ObjectMeta{
					Name: podName,
				},
				Spec: v1.PodSpec{
					RestartPolicy: v1.RestartPolicyNever,
					HostNetwork:   hostNetwork,
					Containers: []v1.Container{
						{
							Image:   image,
							Name:    podName,
							Command: command,
						},
					},
				},
			}
		}
		listListeningPortsCommand := []string{"sh", "-c", "netstat -ln"}
		createAndWaitHostNetworkPod := func(podName string, hostNetwork bool) {
			podClient.Create(makeHostNetworkPod(podName,
				"gcr.io/google_containers/busybox:1.24",
				listListeningPortsCommand,
				hostNetwork,
			))

			podClient.WaitForSuccess(podName, framework.PodStartTimeout)
		}

		listeningPort := ""
		var l net.Listener
		BeforeEach(func() {
			l, err := net.Listen("tcp", ":0")
			if err != nil {
				framework.Failf("Failed to open a new tcp port: %v", err)
			}
			addr := strings.Split(l.Addr().String(), ":")
			listeningPort = addr[len(addr)-1]
			framework.Logf("Opened a new tcp port %q", listeningPort)
		})

		It("should listen on same port in the host network containers", func() {
			busyboxPodName := "busybox-hostnetwork-" + string(uuid.NewUUID())
			createAndWaitHostNetworkPod(busyboxPodName, true)
			logs, err := framework.GetPodLogs(f.ClientSet, f.Namespace.Name, busyboxPodName, busyboxPodName)
			if err != nil {
				framework.Failf("GetPodLogs for pod %q failed: %v", busyboxPodName, err)
			}

			framework.Logf("Got logs for pod %q: %q", busyboxPodName, logs)
			if !strings.Contains(logs, listeningPort) {
				framework.Failf("host-networked container should listening on same port as host")
			}
		})

		It("shouldn't show the same port in the non-hostnetwork containers", func() {
			busyboxPodName := "busybox-non-hostnetwork-" + string(uuid.NewUUID())
			createAndWaitHostNetworkPod(busyboxPodName, false)
			logs, err := framework.GetPodLogs(f.ClientSet, f.Namespace.Name, busyboxPodName, busyboxPodName)
			if err != nil {
				framework.Failf("GetPodLogs for pod %q failed: %v", busyboxPodName, err)
			}

			framework.Logf("Got logs for pod %q: %q", busyboxPodName, logs)
			if strings.Contains(logs, listeningPort) {
				framework.Failf("non-hostnetworked container shouldn't show the same port as host")
			}
		})

		AfterEach(func() {
			if l != nil {
				l.Close()
			}
		})
	})

	Context("When creating a container with runAsUser", func() {
		makeUserPod := func(podName, image string, command []string, userid int64) *v1.Pod {
			return &v1.Pod{
				ObjectMeta: metav1.ObjectMeta{
					Name: podName,
				},
				Spec: v1.PodSpec{
					RestartPolicy: v1.RestartPolicyNever,
					Containers: []v1.Container{
						{
							Image:   image,
							Name:    podName,
							Command: command,
							SecurityContext: &v1.SecurityContext{
								RunAsUser: &userid,
							},
						},
					},
				},
			}
		}
		createAndWaitUserPod := func(userid int64) {
			podName := fmt.Sprintf("busybox-user-%d-%s", userid, uuid.NewUUID())
			podClient.Create(makeUserPod(podName,
				"gcr.io/google_containers/busybox:1.24",
				[]string{"sh", "-c", fmt.Sprintf("test $(id -u) -eq %d", userid)},
				userid,
			))

			podClient.WaitForSuccess(podName, framework.PodStartTimeout)
		}

		It("should run the container with uid 65534", func() {
			createAndWaitUserPod(65534)
		})

		It("should run the container with uid 0", func() {
			createAndWaitUserPod(0)
		})

	})
})
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"github.com/sourcegraph/webloop"
	"log"
	"net/http"
	"os"
	"strings"
	"time"
)

var bind = flag.String("http", ":13000", "HTTP bind address")
var targetURL = flag.String("target", "http://localhost:3000", "base URL of target")
var redirectPrefixesStr = flag.String("redirect-prefixes", "/static,/api,/favicon.ico", "comma-separated list of path prefixes to redirect (not proxy and render)")

func main() {
	flag.Parse()

	log := log.New(os.Stderr, "", 0)

	var redirectPrefixes []string
	if *redirectPrefixesStr != "" {
		redirectPrefixes = strings.Split(*redirectPrefixesStr, ",")
	}

	staticRenderer := &webloop.StaticRenderer{
		TargetBaseURL: *targetURL,
		WaitTimeout:   time.Second * 3,
		Log:           log,
	}
	h := func(w http.ResponseWriter, r *http.Request) {
		for _, rp := range redirectPrefixes {
			if strings.HasPrefix(r.URL.Path, rp) {
				http.Redirect(w, r, *targetURL+r.URL.String(), http.StatusFound)
				return
			}
		}
		staticRenderer.ServeHTTP(w, r)
	}

	http.HandleFunc("/", h)
	log.Printf("Listening on %s and proxying against %s", *bind, *targetURL)
	err := http.ListenAndServe(*bind, nil)
	if err != nil {
		log.Fatalf("ListenAndServe: %s", err)
	}
}
<commit_msg>Static-reverse-proxy notes and info<commit_after>package main

import (
	"flag"
	"fmt"
	"github.com/sourcegraph/webloop"
	"log"
	"net/http"
	"os"
	"strings"
	"time"
)

var bind = flag.String("http", ":13000", "HTTP bind address")
var targetURL = flag.String("target", "http://localhost:3000", "base URL of target")
var redirectPrefixesStr = flag.String("redirect-prefixes", "/static,/api,/favicon.ico", "comma-separated list of path prefixes to redirect to the target (not proxy and render)")

func main() {
	flag.Usage = func() {
		fmt.Fprintln(os.Stderr)
		fmt.Fprintf(os.Stderr, "static-reverse-proxy proxies a dynamic JavaScript application and serves\n")
		fmt.Fprintf(os.Stderr, "an equivalent statically rendered HTML website to clients. It uses a headless\n")
		fmt.Fprintf(os.Stderr, "WebKit browser instance to render the static HTML.\n\n")
		fmt.Fprintf(os.Stderr, "Usage:\n\n")
		fmt.Fprintf(os.Stderr, "\tstatic-reverse-proxy [options]\n\n")
		fmt.Fprintf(os.Stderr, "The options are:\n\n")
		flag.PrintDefaults()
		fmt.Fprintln(os.Stderr)
		fmt.Fprintln(os.Stderr)
		fmt.Fprintf(os.Stderr, "Example usage:\n\n")
		fmt.Fprintf(os.Stderr, "\tTo proxy a dynamic application at http://example.com and serve an equivalent\n")
		fmt.Fprintf(os.Stderr, "\tstatically rendered HTML website on http://localhost:13000\n")
		fmt.Fprintf(os.Stderr, "\t    $ static-reverse-proxy -target=http://example.com -bind=:13000\n\n")
		fmt.Fprintf(os.Stderr, "Notes:\n\n")
		fmt.Fprintf(os.Stderr, "\tBecause a headless WebKit instance is used, your $DISPLAY must be set. Use\n")
		fmt.Fprintf(os.Stderr, "\tXvfb if you are running on a machine without an existing X server. See\n")
		fmt.Fprintf(os.Stderr, "\thttps://sourcegraph.com/github.com/sourcegraph/webloop/readme for more info.\n")
		fmt.Fprintln(os.Stderr)
		os.Exit(1)
	}
	flag.Parse()

	log := log.New(os.Stderr, "", 0)

	var redirectPrefixes []string
	if *redirectPrefixesStr != "" {
		redirectPrefixes = strings.Split(*redirectPrefixesStr, ",")
	}

	staticRenderer := &webloop.StaticRenderer{
		TargetBaseURL: *targetURL,
		WaitTimeout:   time.Second * 3,
		Log:           log,
	}
	h := func(w http.ResponseWriter, r *http.Request) {
		for _, rp := range redirectPrefixes {
			if strings.HasPrefix(r.URL.Path, rp) {
				http.Redirect(w, r, *targetURL+r.URL.String(), http.StatusFound)
				return
			}
		}
		staticRenderer.ServeHTTP(w, r)
	}

	http.HandleFunc("/", h)
	log.Printf("Listening on %s and proxying against %s", *bind, *targetURL)
	err := http.ListenAndServe(*bind, nil)
	if err != nil {
		log.Fatalf("ListenAndServe: %s", err)
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2015 The Camlistore 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.
*/

// Command dock builds Camlistore's various Docker images.
package main

import (
	"compress/gzip"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"runtime"

	"camlistore.org/pkg/osutil"
	"camlistore.org/third_party/golang.org/x/oauth2"
	"camlistore.org/third_party/golang.org/x/oauth2/google"
	"camlistore.org/third_party/google.golang.org/cloud"
	"camlistore.org/third_party/google.golang.org/cloud/storage"
)

var (
	rev      = flag.String("rev", "4e8413c5012c", "Camlistore revision to build (tag or commit hash)")
	localSrc = flag.String("camlisource", "", "(dev flag) Path to a local Camlistore source tree from which to build. This flag is ignored unless -rev=WORKINPROGRESS")

	doBuildServer = flag.Bool("build_server", true, "build the server")
	doUpload      = flag.Bool("upload", false, "upload a snapshot of the server tarball to http://storage.googleapis.com/camlistore-release/docker/camlistored[-VERSION].tar.gz")
)

// buildDockerImage builds a docker image from the Dockerfile located in
// imageDir, which is a path relative to dockDir. The image will be named after
// imageName. dockDir should have been set behorehand.
func buildDockerImage(imageDir, imageName string) {
	if dockDir == "" {
		panic("dockDir should be set before calling buildDockerImage")
	}
	cmd := exec.Command("docker", "build", "-t", imageName, ".")
	cmd.Dir = filepath.Join(dockDir, imageDir)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	if err := cmd.Run(); err != nil {
		log.Fatalf("Error building docker image %v: %v", imageName, err)
	}
}

var dockDir string

const (
	goDockerImage    = "camlistore/go"
	djpegDockerImage = "camlistore/djpeg"
	goCmd            = "/usr/local/go/bin/go"
	// Path to where the Camlistore builder is mounted on the camlistore/go image.
	genCamliProgram = "/usr/local/bin/build-camlistore-server.go"
)

func genCamlistore(ctxDir string) {
	check(os.Mkdir(filepath.Join(ctxDir, "/camlistore.org"), 0755))

	args := []string{
		"run",
		"--rm",
		"--volume=" + ctxDir + "/camlistore.org:/OUT",
		"--volume=" + path.Join(dockDir, "server/build-camlistore-server.go") + ":" + genCamliProgram + ":ro",
	}
	if *rev == "WORKINPROGRESS" {
		args = append(args, "--volume="+*localSrc+":/IN:ro",
			goDockerImage, goCmd, "run", genCamliProgram, "--rev="+*rev, "--camlisource=/IN")
	} else {
		args = append(args, goDockerImage, goCmd, "run", genCamliProgram, "--rev="+*rev)
	}
	cmd := exec.Command("docker", args...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	if err := cmd.Run(); err != nil {
		log.Fatalf("Error building camlistored in go container: %v", err)
	}
}

func copyFinalDockerfile(ctxDir string) {
	// Copy Dockerfile into the temp dir.
	serverDockerFile, err := ioutil.ReadFile(filepath.Join(dockDir, "server", "Dockerfile"))
	check(err)
	check(ioutil.WriteFile(filepath.Join(ctxDir, "Dockerfile"), serverDockerFile, 0644))
}

func genDjpeg(ctxDir string) {
	cmd := exec.Command("docker", "run",
		"--rm",
		"--volume="+ctxDir+":/OUT",
		djpegDockerImage, "/bin/bash", "-c", "mkdir -p /OUT && cp /src/libjpeg-turbo-1.4.0/djpeg /OUT/djpeg")
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	if err := cmd.Run(); err != nil {
		log.Fatalf("Error building djpeg in go container: %v", err)
	}
}

func buildServer(ctxDir string) {
	copyFinalDockerfile(ctxDir)
	cmd := exec.Command("docker", "build", "-t", "camlistore/server", ".")
	cmd.Dir = ctxDir
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	if err := cmd.Run(); err != nil {
		log.Fatalf("Error building camlistore/server: %v", err)
	}
}

func uploadDockerImage() {
	proj := "camlistore-website"
	bucket := "camlistore-release"
	object := "docker/camlistored.tar.gz" // TODO: this is only tip for now

	log.Printf("Uploading %s/%s ...", bucket, object)

	ts, err := tokenSource(bucket)
	if err != nil {
		log.Fatal(err)
	}

	httpClient := oauth2.NewClient(oauth2.NoContext, ts)
	ctx := cloud.NewContext(proj, httpClient)
	w := storage.NewWriter(ctx, bucket, object)
	// If you don't give the owners access, the web UI seems to
	// have a bug and doesn't have access to see that it's public, so
	// won't render the "Shared Publicly" link. So we do that, even
	// though it's dumb and unnecessary otherwise:
	w.ACL = append(w.ACL, storage.ACLRule{Entity: storage.ACLEntity("project-owners-" + proj), Role: storage.RoleOwner})
	w.ACL = append(w.ACL, storage.ACLRule{Entity: storage.AllUsers, Role: storage.RoleReader})
	w.CacheControl = "no-cache" // TODO: remove for non-tip releases? set expirations?
	w.ContentType = "application/x-gtar"

	dockerSave := exec.Command("docker", "save", "camlistore/server")
	dockerSave.Stderr = os.Stderr
	tar, err := dockerSave.StdoutPipe()
	if err != nil {
		log.Fatal(err)
	}
	targz, pw := io.Pipe()
	go func() {
		zw := gzip.NewWriter(pw)
		n, err := io.Copy(zw, tar)
		if err != nil {
			log.Fatalf("Error copying to gzip writer: after %d bytes, %v", n, err)
		}
		if err := zw.Close(); err != nil {
			log.Fatalf("gzip.Close: %v", err)
		}
		pw.CloseWithError(err)
	}()
	if err := dockerSave.Start(); err != nil {
		log.Fatalf("Error starting docker save camlistore/server: %v", err)
	}
	if _, err := io.Copy(w, targz); err != nil {
		log.Fatalf("io.Copy: %v", err)
	}
	if err := w.Close(); err != nil {
		log.Fatalf("closing GCS storage writer: %v", err)
	}
	if err := dockerSave.Wait(); err != nil {
		log.Fatalf("Error waiting for docker save camlistore/server: %v", err)
	}
	log.Printf("Uploaded tarball to %s", object)
}

func usage() {
	fmt.Fprintf(os.Stderr, "Usage:\n")
	fmt.Fprintf(os.Stderr, "%s [-rev camlistore_revision | -rev WORKINPROGRESS -camlisource dir]\n", os.Args[0])
	flag.PrintDefaults()
	os.Exit(1)
}

func checkFlags() {
	if flag.NArg() != 0 {
		usage()
	}
	if *rev == "" {
		usage()
	}
	if *rev == "WORKINPROGRESS" {
		if *localSrc == "" {
			usage()
		}
		return
	}
	if *localSrc != "" {
		fmt.Fprintf(os.Stderr, "Usage error: --camlisource can only be used with --rev WORKINPROGRESS.\n")
		usage()
	}
}

func main() {
	flag.Usage = usage
	flag.Parse()
	checkFlags()

	camDir, err := osutil.GoPackagePath("camlistore.org")
	if err != nil {
		log.Fatalf("Error looking up camlistore.org dir: %v", err)
	}
	dockDir = filepath.Join(camDir, "misc", "docker")

	if *doBuildServer {
		buildDockerImage("go", goDockerImage)
		buildDockerImage("djpeg-static", djpegDockerImage)

		// ctxDir is where we run "docker build" to produce the final
		// "FROM scratch" Docker image.
		ctxDir, err := ioutil.TempDir("", "camli-build")
		if err != nil {
			log.Fatal(err)
		}
		defer os.RemoveAll(ctxDir)

		genCamlistore(ctxDir)
		genDjpeg(ctxDir)
		buildServer(ctxDir)
	}

	if *doUpload {
		uploadDockerImage()
	}
}

func check(err error) {
	if err != nil {
		log.Fatal(err)
	}
}

func homedir() string {
	if runtime.GOOS == "windows" {
		return os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
	}
	return os.Getenv("HOME")
}

// ProjectTokenSource returns an OAuth2 TokenSource for the given Google Project ID.
func ProjectTokenSource(proj string, scopes ...string) (oauth2.TokenSource, error) {
	// TODO(bradfitz): try different strategies too, like
	// three-legged flow if the service account doesn't exist, and
	// then cache the token file on disk somewhere. Or maybe that should be an
	// option, for environments without stdin/stdout available to the user.
	// We'll figure it out as needed.
	fileName := filepath.Join(homedir(), "keys", proj+".key.json")
	jsonConf, err := ioutil.ReadFile(fileName)
	if err != nil {
		if os.IsNotExist(err) {
			return nil, fmt.Errorf("Missing JSON key configuration. Download the Service Account JSON key from https://console.developers.google.com/project/%s/apiui/credential and place it at %s", proj, fileName)
		}
		return nil, err
	}
	conf, err := google.JWTConfigFromJSON(jsonConf, scopes...)
	if err != nil {
		return nil, fmt.Errorf("reading JSON config from %s: %v", fileName, err)
	}
	return conf.TokenSource(oauth2.NoContext), nil
}

var bucketProject = map[string]string{
	"camlistore-release": "camlistore-website",
}

func tokenSource(bucket string) (oauth2.TokenSource, error) {
	proj, ok := bucketProject[bucket]
	if !ok {
		return nil, fmt.Errorf("unknown project for bucket %q", bucket)
	}
	return ProjectTokenSource(proj, storage.ScopeReadWrite)
}
<commit_msg>dock.go: upload versioned tarball<commit_after>/*
Copyright 2015 The Camlistore 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.
*/

// Command dock builds Camlistore's various Docker images.
package main

import (
	"compress/gzip"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"runtime"

	"camlistore.org/pkg/osutil"
	"camlistore.org/third_party/golang.org/x/oauth2"
	"camlistore.org/third_party/golang.org/x/oauth2/google"
	"camlistore.org/third_party/google.golang.org/cloud"
	"camlistore.org/third_party/google.golang.org/cloud/storage"
)

var (
	rev      = flag.String("rev", "4e8413c5012c", "Camlistore revision to build (tag or commit hash)")
	localSrc = flag.String("camlisource", "", "(dev flag) Path to a local Camlistore source tree from which to build. This flag is ignored unless -rev=WORKINPROGRESS")

	doBuildServer = flag.Bool("build_server", true, "build the server")
	doUpload      = flag.Bool("upload", false, "upload a snapshot of the server tarball to http://storage.googleapis.com/camlistore-release/docker/camlistored[-VERSION].tar.gz")
)

// buildDockerImage builds a docker image from the Dockerfile located in
// imageDir, which is a path relative to dockDir. The image will be named after
// imageName. dockDir should have been set behorehand.
func buildDockerImage(imageDir, imageName string) {
	if dockDir == "" {
		panic("dockDir should be set before calling buildDockerImage")
	}
	cmd := exec.Command("docker", "build", "-t", imageName, ".")
	cmd.Dir = filepath.Join(dockDir, imageDir)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	if err := cmd.Run(); err != nil {
		log.Fatalf("Error building docker image %v: %v", imageName, err)
	}
}

var dockDir string

const (
	goDockerImage    = "camlistore/go"
	djpegDockerImage = "camlistore/djpeg"
	goCmd            = "/usr/local/go/bin/go"
	// Path to where the Camlistore builder is mounted on the camlistore/go image.
	genCamliProgram = "/usr/local/bin/build-camlistore-server.go"
)

func genCamlistore(ctxDir string) {
	check(os.Mkdir(filepath.Join(ctxDir, "/camlistore.org"), 0755))

	args := []string{
		"run",
		"--rm",
		"--volume=" + ctxDir + "/camlistore.org:/OUT",
		"--volume=" + path.Join(dockDir, "server/build-camlistore-server.go") + ":" + genCamliProgram + ":ro",
	}
	if *rev == "WORKINPROGRESS" {
		args = append(args, "--volume="+*localSrc+":/IN:ro",
			goDockerImage, goCmd, "run", genCamliProgram, "--rev="+*rev, "--camlisource=/IN")
	} else {
		args = append(args, goDockerImage, goCmd, "run", genCamliProgram, "--rev="+*rev)
	}
	cmd := exec.Command("docker", args...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	if err := cmd.Run(); err != nil {
		log.Fatalf("Error building camlistored in go container: %v", err)
	}
}

func copyFinalDockerfile(ctxDir string) {
	// Copy Dockerfile into the temp dir.
	serverDockerFile, err := ioutil.ReadFile(filepath.Join(dockDir, "server", "Dockerfile"))
	check(err)
	check(ioutil.WriteFile(filepath.Join(ctxDir, "Dockerfile"), serverDockerFile, 0644))
}

func genDjpeg(ctxDir string) {
	cmd := exec.Command("docker", "run",
		"--rm",
		"--volume="+ctxDir+":/OUT",
		djpegDockerImage, "/bin/bash", "-c", "mkdir -p /OUT && cp /src/libjpeg-turbo-1.4.0/djpeg /OUT/djpeg")
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	if err := cmd.Run(); err != nil {
		log.Fatalf("Error building djpeg in go container: %v", err)
	}
}

func buildServer(ctxDir string) {
	copyFinalDockerfile(ctxDir)
	cmd := exec.Command("docker", "build", "-t", "camlistore/server", ".")
	cmd.Dir = ctxDir
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	if err := cmd.Run(); err != nil {
		log.Fatalf("Error building camlistore/server: %v", err)
	}
}

func uploadDockerImage() {
	proj := "camlistore-website"
	bucket := "camlistore-release"
	versionedTarball := "docker/camlistored-" + *rev + ".tar.gz"
	tarball := "docker/camlistored.tar.gz"

	log.Printf("Uploading %s/%s ...", bucket, versionedTarball)

	ts, err := tokenSource(bucket)
	if err != nil {
		log.Fatal(err)
	}

	httpClient := oauth2.NewClient(oauth2.NoContext, ts)
	ctx := cloud.NewContext(proj, httpClient)
	w := storage.NewWriter(ctx, bucket, versionedTarball)
	// If you don't give the owners access, the web UI seems to
	// have a bug and doesn't have access to see that it's public, so
	// won't render the "Shared Publicly" link. So we do that, even
	// though it's dumb and unnecessary otherwise:
	acl := append(w.ACL, storage.ACLRule{Entity: storage.ACLEntity("project-owners-" + proj), Role: storage.RoleOwner})
	acl = append(acl, storage.ACLRule{Entity: storage.AllUsers, Role: storage.RoleReader})
	w.ACL = acl
	w.CacheControl = "no-cache" // TODO: remove for non-tip releases? set expirations?
	w.ContentType = "application/x-gtar"

	dockerSave := exec.Command("docker", "save", "camlistore/server")
	dockerSave.Stderr = os.Stderr
	tar, err := dockerSave.StdoutPipe()
	if err != nil {
		log.Fatal(err)
	}
	targz, pw := io.Pipe()
	go func() {
		zw := gzip.NewWriter(pw)
		n, err := io.Copy(zw, tar)
		if err != nil {
			log.Fatalf("Error copying to gzip writer: after %d bytes, %v", n, err)
		}
		if err := zw.Close(); err != nil {
			log.Fatalf("gzip.Close: %v", err)
		}
		pw.CloseWithError(err)
	}()
	if err := dockerSave.Start(); err != nil {
		log.Fatalf("Error starting docker save camlistore/server: %v", err)
	}
	if _, err := io.Copy(w, targz); err != nil {
		log.Fatalf("io.Copy: %v", err)
	}
	if err := w.Close(); err != nil {
		log.Fatalf("closing GCS storage writer: %v", err)
	}
	if err := dockerSave.Wait(); err != nil {
		log.Fatalf("Error waiting for docker save camlistore/server: %v", err)
	}
	log.Printf("Uploaded tarball to %s", versionedTarball)
	log.Printf("Copying tarball to %s/%s ...", bucket, tarball)
	// TODO(mpl): 2015-05-12: update google.golang.org/cloud/storage so we
	// can specify the dest name in CopyObject, and we get the ACLs from the
	// src for free too I think.
	if _, err := storage.CopyObject(ctx, bucket, versionedTarball, bucket, storage.ObjectAttrs{
		Name:        tarball,
		ACL:         acl,
		ContentType: "application/x-gtar",
	}); err != nil {
		log.Fatalf("Error uploading %v: %v", tarball, err)
	}
	log.Printf("Uploaded tarball to %s", tarball)
}

func usage() {
	fmt.Fprintf(os.Stderr, "Usage:\n")
	fmt.Fprintf(os.Stderr, "%s [-rev camlistore_revision | -rev WORKINPROGRESS -camlisource dir]\n", os.Args[0])
	flag.PrintDefaults()
	os.Exit(1)
}

func checkFlags() {
	if flag.NArg() != 0 {
		usage()
	}
	if *rev == "" {
		usage()
	}
	if *rev == "WORKINPROGRESS" {
		if *localSrc == "" {
			usage()
		}
		return
	}
	if *localSrc != "" {
		fmt.Fprintf(os.Stderr, "Usage error: --camlisource can only be used with --rev WORKINPROGRESS.\n")
		usage()
	}
}

func main() {
	flag.Usage = usage
	flag.Parse()
	checkFlags()

	camDir, err := osutil.GoPackagePath("camlistore.org")
	if err != nil {
		log.Fatalf("Error looking up camlistore.org dir: %v", err)
	}
	dockDir = filepath.Join(camDir, "misc", "docker")

	if *doBuildServer {
		buildDockerImage("go", goDockerImage)
		buildDockerImage("djpeg-static", djpegDockerImage)

		// ctxDir is where we run "docker build" to produce the final
		// "FROM scratch" Docker image.
		ctxDir, err := ioutil.TempDir("", "camli-build")
		if err != nil {
			log.Fatal(err)
		}
		defer os.RemoveAll(ctxDir)

		genCamlistore(ctxDir)
		genDjpeg(ctxDir)
		buildServer(ctxDir)
	}

	if *doUpload {
		uploadDockerImage()
	}
}

func check(err error) {
	if err != nil {
		log.Fatal(err)
	}
}

func homedir() string {
	if runtime.GOOS == "windows" {
		return os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
	}
	return os.Getenv("HOME")
}

// ProjectTokenSource returns an OAuth2 TokenSource for the given Google Project ID.
func ProjectTokenSource(proj string, scopes ...string) (oauth2.TokenSource, error) {
	// TODO(bradfitz): try different strategies too, like
	// three-legged flow if the service account doesn't exist, and
	// then cache the token file on disk somewhere. Or maybe that should be an
	// option, for environments without stdin/stdout available to the user.
	// We'll figure it out as needed.
	fileName := filepath.Join(homedir(), "keys", proj+".key.json")
	jsonConf, err := ioutil.ReadFile(fileName)
	if err != nil {
		if os.IsNotExist(err) {
			return nil, fmt.Errorf("Missing JSON key configuration. Download the Service Account JSON key from https://console.developers.google.com/project/%s/apiui/credential and place it at %s", proj, fileName)
		}
		return nil, err
	}
	conf, err := google.JWTConfigFromJSON(jsonConf, scopes...)
	if err != nil {
		return nil, fmt.Errorf("reading JSON config from %s: %v", fileName, err)
	}
	return conf.TokenSource(oauth2.NoContext), nil
}

var bucketProject = map[string]string{
	"camlistore-release": "camlistore-website",
}

func tokenSource(bucket string) (oauth2.TokenSource, error) {
	proj, ok := bucketProject[bucket]
	if !ok {
		return nil, fmt.Errorf("unknown project for bucket %q", bucket)
	}
	return ProjectTokenSource(proj, storage.ScopeReadWrite)
}
<|endoftext|>


<commit_before>package revok

import (
	"context"
	"os"
	"time"

	"code.cloudfoundry.org/clock"
	"code.cloudfoundry.org/lager"
	"github.com/tedsuo/ifrit"

	"cred-alert/db"
	"cred-alert/kolsch"
	"cred-alert/sniff"
)

type headCredentialCounter struct {
	logger               lager.Logger
	branchRepository     db.BranchRepository
	repositoryRepository db.RepositoryRepository
	clock                clock.Clock
	interval             time.Duration
	gitClient            GitBranchCredentialsCounterClient
	sniffer              sniff.Sniffer
}

//go:generate counterfeiter . GitBranchCredentialsCounterClient

type GitBranchCredentialsCounterClient interface {
	BranchTargets(repoPath string) (map[string]string, error)
	BranchCredentialCounts(lager.Logger, string, sniff.Sniffer) (map[string]uint, error)
}

func NewHeadCredentialCounter(
	logger lager.Logger,
	branchRepository db.BranchRepository,
	repositoryRepository db.RepositoryRepository,
	clock clock.Clock,
	interval time.Duration,
	gitClient GitBranchCredentialsCounterClient,
	sniffer sniff.Sniffer,
) ifrit.Runner {
	return &headCredentialCounter{
		logger:               logger,
		branchRepository:     branchRepository,
		repositoryRepository: repositoryRepository,
		clock:                clock,
		interval:             interval,
		gitClient:            gitClient,
		sniffer:              sniffer,
	}
}

func (c *headCredentialCounter) Run(signals <-chan os.Signal, ready chan<- struct{}) error {
	logger := c.logger.Session("head-credential-counter")
	logger.Info("starting")

	close(ready)

	timer := c.clock.NewTicker(c.interval)

	ctx, cancel := context.WithCancel(context.Background())

	quietLogger := kolsch.NewLogger()

	c.work(cancel, signals, logger, quietLogger)

	for {
		select {
		case <-timer.C():
			c.work(cancel, signals, logger, quietLogger)
		case <-signals:
			cancel()
			return nil
		case <-ctx.Done():
			return nil
		}
	}
}

func (c *headCredentialCounter) work(
	cancel context.CancelFunc,
	signals <-chan os.Signal,
	logger lager.Logger,
	quietLogger lager.Logger,
) {
	repositories, err := c.repositoryRepository.All()
	if err != nil {
		logger.Error("failed-getting-all-repositories", err)
	}

	for _, repository := range repositories {
		select {
		case <-signals:
			cancel()
			return
		default:
			repoLogger := logger.WithData(lager.Data{
				"ref":  repository.DefaultBranch,
				"path": repository.Path,
			})

			if !repository.Cloned {
				repoLogger.Debug("skipping-uncloned-repository")
				continue
			}

			credentialCounts, err := c.gitClient.BranchCredentialCounts(quietLogger, repository.Path, c.sniffer)
			if err != nil {
				repoLogger.Error("failed-to-get-credential-counts", err)
				continue
			}

			branches := make([]db.Branch, 0, len(credentialCounts))
			for branchName, credentialCount := range credentialCounts {
				branches = append(branches, db.Branch{
					Name:            branchName,
					CredentialCount: credentialCount,
				})
			}

			err = c.branchRepository.UpdateBranches(repository, branches)
			if err != nil {
				repoLogger.Error("failed-to-update-credential-count", err)
				continue
			}

			repoLogger.Debug("updated-credential-count")
		}
	}
}
<commit_msg>Ensure NewHeadCredentialCounter returns a concrete type rather than some interface.<commit_after>package revok

import (
	"context"
	"os"
	"time"

	"code.cloudfoundry.org/clock"
	"code.cloudfoundry.org/lager"

	"cred-alert/db"
	"cred-alert/kolsch"
	"cred-alert/sniff"
)

//go:generate counterfeiter . GitBranchCredentialsCounterClient

type GitBranchCredentialsCounterClient interface {
	BranchTargets(repoPath string) (map[string]string, error)
	BranchCredentialCounts(lager.Logger, string, sniff.Sniffer) (map[string]uint, error)
}

type HeadCredentialCounter struct {
	logger               lager.Logger
	branchRepository     db.BranchRepository
	repositoryRepository db.RepositoryRepository
	clock                clock.Clock
	interval             time.Duration
	gitClient            GitBranchCredentialsCounterClient
	sniffer              sniff.Sniffer
}

func NewHeadCredentialCounter(
	logger lager.Logger,
	branchRepository db.BranchRepository,
	repositoryRepository db.RepositoryRepository,
	clock clock.Clock,
	interval time.Duration,
	gitClient GitBranchCredentialsCounterClient,
	sniffer sniff.Sniffer,
) *HeadCredentialCounter {
	return &HeadCredentialCounter{
		logger:               logger,
		branchRepository:     branchRepository,
		repositoryRepository: repositoryRepository,
		clock:                clock,
		interval:             interval,
		gitClient:            gitClient,
		sniffer:              sniffer,
	}
}

func (c *HeadCredentialCounter) Run(signals <-chan os.Signal, ready chan<- struct{}) error {
	logger := c.logger.Session("head-credential-counter")
	logger.Info("starting")

	close(ready)

	timer := c.clock.NewTicker(c.interval)

	ctx, cancel := context.WithCancel(context.Background())

	quietLogger := kolsch.NewLogger()

	c.work(cancel, signals, logger, quietLogger)

	for {
		select {
		case <-timer.C():
			c.work(cancel, signals, logger, quietLogger)
		case <-signals:
			cancel()
			return nil
		case <-ctx.Done():
			return nil
		}
	}
}

func (c *HeadCredentialCounter) work(
	cancel context.CancelFunc,
	signals <-chan os.Signal,
	logger lager.Logger,
	quietLogger lager.Logger,
) {
	repositories, err := c.repositoryRepository.All()
	if err != nil {
		logger.Error("failed-getting-all-repositories", err)
	}

	for _, repository := range repositories {
		select {
		case <-signals:
			cancel()
			return
		default:
			repoLogger := logger.WithData(lager.Data{
				"ref":  repository.DefaultBranch,
				"path": repository.Path,
			})

			if !repository.Cloned {
				repoLogger.Debug("skipping-uncloned-repository")
				continue
			}

			credentialCounts, err := c.gitClient.BranchCredentialCounts(quietLogger, repository.Path, c.sniffer)
			if err != nil {
				repoLogger.Error("failed-to-get-credential-counts", err)
				continue
			}

			branches := make([]db.Branch, 0, len(credentialCounts))
			for branchName, credentialCount := range credentialCounts {
				branches = append(branches, db.Branch{
					Name:            branchName,
					CredentialCount: credentialCount,
				})
			}

			err = c.branchRepository.UpdateBranches(repository, branches)
			if err != nil {
				repoLogger.Error("failed-to-update-credential-count", err)
				continue
			}

			repoLogger.Debug("updated-credential-count")
		}
	}
}
<|endoftext|>


<commit_before>package logrus

import "syscall"

const ioctlReadTermios = syscall.TIOCGETA

type Termios syscall.Termios
<commit_msg>external: remove old file that prevents build on openbsd<commit_after><|endoftext|>


<commit_before>package logstash

import (
	"encoding/json"
	"fmt"

	"github.com/Sirupsen/logrus"
)

// Formatter generates json in logstash format.
// Logstash site: http://logstash.net/
type LogstashFormatter struct {
	Type string // if not empty use for logstash type field.

	// TimestampFormat sets the format used for timestamps.
	TimestampFormat string
}

func (f *LogstashFormatter) Format(entry *logrus.Entry) ([]byte, error) {
	fields := make(logrus.Fields)
	for k, v := range entry.Data {
		fields[k] = v
	}

	fields["@version"] = 1

	if f.TimestampFormat == "" {
		f.TimestampFormat = logrus.DefaultTimestampFormat
	}

	fields["@timestamp"] = entry.Time.Format(f.TimestampFormat)

	// set message field
	v, ok := entry.Data["message"]
	if ok {
		fields["fields.message"] = v
	}
	fields["message"] = entry.Message

	// set level field
	v, ok = entry.Data["level"]
	if ok {
		fields["fields.level"] = v
	}
	fields["level"] = entry.Level.String()

	// set type field
	if f.Type != "" {
		v, ok = entry.Data["type"]
		if ok {
			fields["fields.type"] = v
		}
		fields["type"] = f.Type
	}

	serialized, err := json.Marshal(fields)
	if err != nil {
		return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err)
	}
	return append(serialized, '\n'), nil
}
<commit_msg>fix race<commit_after>package logstash

import (
	"encoding/json"
	"fmt"

	"github.com/Sirupsen/logrus"
)

// Formatter generates json in logstash format.
// Logstash site: http://logstash.net/
type LogstashFormatter struct {
	Type string // if not empty use for logstash type field.

	// TimestampFormat sets the format used for timestamps.
	TimestampFormat string
}

func (f *LogstashFormatter) Format(entry *logrus.Entry) ([]byte, error) {
	fields := make(logrus.Fields)
	for k, v := range entry.Data {
		fields[k] = v
	}

	fields["@version"] = 1

	timeStampFormat := f.TimestampFormat

	if timeStampFormat == "" {
		timeStampFormat = logrus.DefaultTimestampFormat
	}

	fields["@timestamp"] = entry.Time.Format(timeStampFormat)

	// set message field
	v, ok := entry.Data["message"]
	if ok {
		fields["fields.message"] = v
	}
	fields["message"] = entry.Message

	// set level field
	v, ok = entry.Data["level"]
	if ok {
		fields["fields.level"] = v
	}
	fields["level"] = entry.Level.String()

	// set type field
	if f.Type != "" {
		v, ok = entry.Data["type"]
		if ok {
			fields["fields.type"] = v
		}
		fields["type"] = f.Type
	}

	serialized, err := json.Marshal(fields)
	if err != nil {
		return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err)
	}
	return append(serialized, '\n'), nil
}
<|endoftext|>


<commit_before>package mock

import (
	"encoding/json"
	"fmt"
	"log"
	"math/rand"
	"net/http"
	"strings"
	"time"

	"github.com/kayac/Gunfish/apns"
)

const (
	ApplicationJSON        = "application/json"
	LimitApnsTokenByteSize = 100 // Payload byte size.
)

// StartAPNSMockServer starts HTTP/2 server for mock
func APNsMockServer(verbose bool) *http.ServeMux {
	mux := http.NewServeMux()

	mux.HandleFunc("/3/device/", func(w http.ResponseWriter, r *http.Request) {
		if verbose {
			log.Printf("proto:%s method:%s path:%s host:%s", r.Proto, r.Method, r.URL.Path, r.RemoteAddr)
		}

		// sets the response time from apns server
		time.Sleep(time.Millisecond*200 + time.Millisecond*(time.Duration(rand.Int63n(90))-45))

		// only allow path which pattern is '/3/device/:token'
		splitPath := strings.Split(r.URL.Path, "/")
		if len(splitPath) != 4 {
			w.WriteHeader(http.StatusNotFound)
			fmt.Fprintf(w, "404 Not found")
			return
		}

		w.Header().Set("Content-Type", ApplicationJSON)

		token := splitPath[len(splitPath)-1]
		if len(([]byte(token))) > LimitApnsTokenByteSize || token == "baddevicetoken" {
			w.Header().Set("apns-id", "apns-id")
			w.WriteHeader(http.StatusBadRequest)
			fmt.Fprintf(w, createErrorResponse(apns.BadDeviceToken, http.StatusBadRequest))
		} else if token == "missingtopic" {
			w.WriteHeader(http.StatusBadRequest)
			fmt.Fprintf(w, createErrorResponse(apns.MissingTopic, http.StatusBadRequest))
		} else if token == "unregistered" {
			// If the value in the :status header is 410, the value of this key is
			// the last time at which APNs confirmed that the device token was
			// no longer valid for the topic.
			//
			// Stop pushing notifications until the device registers a token with
			// a later timestamp with your provider.
			w.WriteHeader(http.StatusGone)
			fmt.Fprint(w, createErrorResponse(apns.Unregistered, http.StatusGone))
		} else if token == "expiredprovidertoken" {
			w.WriteHeader(http.StatusForbidden)
			fmt.Fprint(w, createErrorResponse(apns.ExpiredProviderToken, http.StatusForbidden))
		} else {
			w.Header().Set("apns-id", "apns-id")
			w.WriteHeader(http.StatusOK)
		}

		return
	})

	return mux
}

func createErrorResponse(ermsg apns.ErrorResponseCode, status int) string {
	var er apns.ErrorResponse
	if status == http.StatusGone {
		er = apns.ErrorResponse{
			Reason:    ermsg.String(),
			Timestamp: time.Now().Unix(),
		}
	} else {
		er = apns.ErrorResponse{
			Reason: ermsg.String(),
		}
	}
	der, _ := json.Marshal(er)
	return string(der)
}
<commit_msg>change sleep time and logging request time<commit_after>package mock

import (
	"encoding/json"
	"fmt"
	"log"
	"math/rand"
	"net/http"
	"strings"
	"time"

	"github.com/kayac/Gunfish/apns"
)

const (
	ApplicationJSON        = "application/json"
	LimitApnsTokenByteSize = 100 // Payload byte size.
)

// StartAPNSMockServer starts HTTP/2 server for mock
func APNsMockServer(verbose bool) *http.ServeMux {
	mux := http.NewServeMux()

	mux.HandleFunc("/3/device/", func(w http.ResponseWriter, r *http.Request) {
		start := time.Now()
		defer func() {
			if verbose {
				log.Printf("reqtime:%f proto:%s method:%s path:%s host:%s", reqtime(start), r.Proto, r.Method, r.URL.Path, r.RemoteAddr)
			}
		}()

		// sets the response time from apns server
		time.Sleep(time.Millisecond*200 + time.Millisecond*(time.Duration(rand.Int63n(200)-100)))

		// only allow path which pattern is '/3/device/:token'
		splitPath := strings.Split(r.URL.Path, "/")
		if len(splitPath) != 4 {
			w.WriteHeader(http.StatusNotFound)
			fmt.Fprintf(w, "404 Not found")
			return
		}

		w.Header().Set("Content-Type", ApplicationJSON)

		token := splitPath[len(splitPath)-1]
		if len(([]byte(token))) > LimitApnsTokenByteSize || token == "baddevicetoken" {
			w.Header().Set("apns-id", "apns-id")
			w.WriteHeader(http.StatusBadRequest)
			fmt.Fprintf(w, createErrorResponse(apns.BadDeviceToken, http.StatusBadRequest))
		} else if token == "missingtopic" {
			w.WriteHeader(http.StatusBadRequest)
			fmt.Fprintf(w, createErrorResponse(apns.MissingTopic, http.StatusBadRequest))
		} else if token == "unregistered" {
			// If the value in the :status header is 410, the value of this key is
			// the last time at which APNs confirmed that the device token was
			// no longer valid for the topic.
			//
			// Stop pushing notifications until the device registers a token with
			// a later timestamp with your provider.
			w.WriteHeader(http.StatusGone)
			fmt.Fprint(w, createErrorResponse(apns.Unregistered, http.StatusGone))
		} else if token == "expiredprovidertoken" {
			w.WriteHeader(http.StatusForbidden)
			fmt.Fprint(w, createErrorResponse(apns.ExpiredProviderToken, http.StatusForbidden))
		} else {
			w.Header().Set("apns-id", "apns-id")
			w.WriteHeader(http.StatusOK)
		}

		return
	})

	return mux
}

func createErrorResponse(ermsg apns.ErrorResponseCode, status int) string {
	var er apns.ErrorResponse
	if status == http.StatusGone {
		er = apns.ErrorResponse{
			Reason:    ermsg.String(),
			Timestamp: time.Now().Unix(),
		}
	} else {
		er = apns.ErrorResponse{
			Reason: ermsg.String(),
		}
	}
	der, _ := json.Marshal(er)
	return string(der)
}

func reqtime(start time.Time) float64 {
	diff := time.Now().Sub(start)
	return diff.Seconds()
}
<|endoftext|>


<commit_before>package models

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"

	"github.com/go-openapi/spec"

	"github.com/Clever/wag/swagger"

	"github.com/go-swagger/go-swagger/generator"

	"text/template"
)

// Generate writes the files to the client directories
func Generate(packageName string, swagger spec.Swagger) error {

	modifiedSpecFile, err := specWithWagPatchTypes(swagger)
	if err != nil {
		return err
	}
	defer os.Remove(modifiedSpecFile)

	// generate models with go-swagger
	if err := generator.GenerateServer("", []string{}, []string{}, generator.GenOpts{
		Spec:           modifiedSpecFile,
		ModelPackage:   "models",
		Target:         fmt.Sprintf("%s/src/%s/", os.Getenv("GOPATH"), packageName),
		IncludeModel:   true,
		IncludeHandler: false,
		IncludeSupport: false,
	}); err != nil {
		return fmt.Errorf("error generating go-swagger models: %s", err)
	}

	if err := generateOutputs(packageName, swagger.Paths); err != nil {
		return fmt.Errorf("error generating outputs: %s", err)
	}
	if err := generateInputs(packageName, swagger.Paths); err != nil {
		return fmt.Errorf("error generating inputs: %s", err)
	}
	return nil
}

// specWithWagPatchTypes takes in a swagger spec and returns a new version of the spec
// with extra type definitions for patch data types (see readme for more details on patch
// data types). The spec is returned as a file path. The caller should remove the file when
// they are finished with it.
func specWithWagPatchTypes(s spec.Swagger) (string, error) {

	definitionsToExtend, err := swagger.WagPatchDataTypes(s.Paths.Paths)
	if err != nil {
		return "", fmt.Errorf("internal error: getting wag patch data types: %s", err)
	}

	allDefinitions := make(spec.Definitions)
	for name, definition := range s.Definitions {
		allDefinitions[name] = definition
		if _, ok := definitionsToExtend[name]; ok {
			// We calculate "Patch" + name in two places. If there becomes a third we should
			// consolidate the logic.
			newName := "Patch" + name
			if _, ok := s.Definitions[newName]; ok {
				return "", fmt.Errorf("can't apply x-wag-patch extension. Conflict with name %s", newName)
			}

			// Mark all the proeprties nullable so they show up as pointers. We do this so that
			// all the fields in the patch type are optional.
			// We don't use the required field in the swagger schema since go-swagger makes optional
			// fields non-pointers (we're not sure why)
			newProps := make(map[string]spec.Schema)
			for field, prop := range definition.Properties {
				prop.AddExtension("x-isnullable", true)
				newProps[field] = prop
			}
			definition.Properties = newProps
			allDefinitions[newName] = definition

		}
	}
	s.Definitions = allDefinitions

	bytes, err := json.Marshal(s)
	if err != nil {
		return "", fmt.Errorf("internal error: wag patch type marshal failure: %s", err)
	}
	fileName := "swagger.tmp"
	if err := ioutil.WriteFile(fileName, bytes, 0644); err != nil {
		return "", err
	}
	return fileName, nil
}

func generateInputs(packageName string, paths *spec.Paths) error {

	g := swagger.Generator{PackageName: packageName}

	g.Printf(`
package models

import(
		"encoding/json"
		"strconv"

		"github.com/go-openapi/validate"
		"github.com/go-openapi/strfmt"
)

// These imports may not be used depending on the input parameters
var _ = json.Marshal
var _ = strconv.FormatInt
var _ = validate.Maximum
var _ = strfmt.NewFormats
`)

	for _, pathKey := range swagger.SortedPathItemKeys(paths.Paths) {
		path := paths.Paths[pathKey]
		pathItemOps := swagger.PathItemOperations(path)
		for _, opKey := range swagger.SortedOperationsKeys(pathItemOps) {
			op := pathItemOps[opKey]
			// Do not generate an input struct + validation for an
			// operation that has a single, schema'd input.
			// The input to these will be the model generated for
			// the schema.
			if ssbp, _ := swagger.SingleSchemaedBodyParameter(op); ssbp {
				continue
			}
			if err := printInputStruct(&g, op); err != nil {
				return err
			}
			if err := printInputValidation(&g, op); err != nil {
				return err
			}
		}
	}

	return g.WriteFile("models/inputs.go")
}

func printInputStruct(g *swagger.Generator, op *spec.Operation) error {
	capOpID := swagger.Capitalize(op.ID)
	g.Printf("// %sInput holds the input parameters for a %s operation.\n", capOpID, op.ID)
	g.Printf("type %sInput struct {\n", capOpID)

	for _, param := range op.Parameters {
		if param.In == "formData" {
			return fmt.Errorf("Input parameters with 'In' formData are not supported")
		}

		var typeName string
		var err error
		if param.In != "body" {
			typeName, err = swagger.ParamToType(param, true)
			if err != nil {
				return err
			}
		} else {
			typeName, err = swagger.TypeFromSchema(param.Schema, false)
			if err != nil {
				return err
			}
			// All schema types are pointers
			typeName = "*" + typeName
		}

		g.Printf("\t%s %s\n", swagger.StructParamName(param), typeName)
	}
	g.Printf("}\n\n")

	return nil
}

func printInputValidation(g *swagger.Generator, op *spec.Operation) error {
	capOpID := swagger.Capitalize(op.ID)
	g.Printf("// Validate returns an error if any of the %sInput parameters don't satisfy the\n",
		capOpID)
	g.Printf("// requirements from the swagger yml file.\n")
	g.Printf("func (i %sInput) Validate() error{\n", capOpID)

	for _, param := range op.Parameters {
		if param.In == "body" {
			g.Printf("\tif err := i.%s.Validate(nil); err != nil {\n", swagger.StructParamName(param))
			g.Printf("\t\treturn err\n")
			g.Printf("\t}\n\n")
		}

		validations, err := swagger.ParamToValidationCode(param)
		if err != nil {
			return err
		}
		for _, validation := range validations {
			if param.Required {
				g.Printf(errCheck(validation))
			} else {
				g.Printf("\tif i.%s != nil {\n", swagger.StructParamName(param))
				g.Printf(errCheck(validation))
				g.Printf("\t}\n")
			}
		}
	}
	g.Printf("\treturn nil\n")
	g.Printf("}\n\n")

	return nil
}

// errCheck returns an if err := ifCondition; err != nil { return err } function
func errCheck(ifCondition string) string {
	return fmt.Sprintf(
		`	if err := %s; err != nil {
		return err
	}
`, ifCondition)
}

func generateOutputs(packageName string, paths *spec.Paths) error {
	g := swagger.Generator{PackageName: packageName}

	g.Printf("package models\n\n")

	g.Printf(defaultOutputTypes())

	for _, pathKey := range swagger.SortedPathItemKeys(paths.Paths) {
		path := paths.Paths[pathKey]
		pathItemOps := swagger.PathItemOperations(path)
		for _, opKey := range swagger.SortedOperationsKeys(pathItemOps) {
			op := pathItemOps[opKey]
			capOpID := swagger.Capitalize(op.ID)

			// We classify response keys into three types:
			// 1. 200-399 - these are "success" responses and implement the Output interface
			// 	defined above
			// 2. 400-599 - these are "failure" responses and implement the error interface
			// 3. Default - this is defined as a 500
			successTypes, err := generateSuccessTypes(capOpID, op.Responses.StatusCodeResponses)
			if err != nil {
				return err
			}
			g.Printf(successTypes)
			errorTypes, err := generateErrorTypes(capOpID, op.Responses.StatusCodeResponses)
			if err != nil {
				return err
			}
			g.Printf(errorTypes)
		}
	}
	return g.WriteFile("models/outputs.go")
}

func generateSuccessTypes(capOpID string, responses map[int]spec.Response) (string, error) {
	var buf bytes.Buffer
	buf.WriteString(fmt.Sprintf("// %sOutput defines the success output interface for %s.\n",
		capOpID, capOpID))
	buf.WriteString(fmt.Sprintf("type %sOutput interface {\n", capOpID))
	buf.WriteString(fmt.Sprintf("\t%sStatusCode() int\n", capOpID))
	buf.WriteString(fmt.Sprintf("}\n\n"))

	var successStatusCodes []int
	for _, statusCode := range swagger.SortedStatusCodeKeys(responses) {
		if statusCode >= 400 {
			continue
		}
		successStatusCodes = append(successStatusCodes, statusCode)
	}

	// We don't need to generate any success types if there is one or less success responses. In that
	// case we can just use the raw type
	if len(successStatusCodes) < 2 {
		return "", nil
	}

	for _, statusCode := range successStatusCodes {
		typeString, err := generateType(capOpID, statusCode, responses[statusCode])
		if err != nil {
			return "", err
		}
		buf.WriteString(typeString)
	}
	return buf.String(), nil
}

func generateErrorTypes(capOpID string, responses map[int]spec.Response) (string, error) {
	var buf bytes.Buffer

	for _, statusCode := range swagger.SortedStatusCodeKeys(responses) {

		if statusCode >= 400 {
			typeString, err := generateType(capOpID, statusCode, responses[statusCode])
			if err != nil {
				return "", err
			}
			buf.WriteString(typeString)
		}
	}
	return buf.String(), nil
}

func generateType(capOpID string, statusCode int, response spec.Response) (string, error) {
	outputName := fmt.Sprintf("%s%dOutput", capOpID, statusCode)
	typeName, err := swagger.TypeFromSchema(response.Schema, false)
	if err != nil {
		return "", err
	}

	fields := typeTemplateFields{
		Output:     outputName,
		StatusCode: statusCode,
		OpName:     capOpID,
		Type:       typeName,
		ErrorType:  statusCode >= 400,
	}
	tmpl := template.Must(template.New("a").Parse(typeTemplate))
	var tmpBuf bytes.Buffer
	if err := tmpl.Execute(&tmpBuf, fields); err != nil {
		return "", err
	}
	return tmpBuf.String(), nil
}

type typeTemplateFields struct {
	Output     string
	StatusCode int
	OpName     string
	Type       string
	ErrorType  bool
}

var typeTemplate = `
	// {{.Output}} defines the {{.StatusCode}} status code response for {{.OpName}}.
	type {{.Output}} {{.Type}}

	{{if .ErrorType}}
	// Error returns "Status Code: X". We implemented in to satisfy the error
	// interface. For a more descriptive error message see the output type.
	func (o {{.Output}}) Error() string {
		return "Status Code: {{.StatusCode}}"
	}
	{{else}}
	// {{.OpName}}StatusCode returns the status code for the operation.
	func (o {{.Output}}) {{.OpName}}StatusCode() int {
		return {{.StatusCode}}
	}
	{{end}}
`

// defaultOutputTypes returns the string defining the default output type
func defaultOutputTypes() string {
	return fmt.Sprintf(`
// DefaultInternalError represents a generic 500 response.
type DefaultInternalError struct {
	Msg string %s
}

// Error returns the internal error that caused the 500.
func (d DefaultInternalError) Error() string {
	return d.Msg
}

// DefaultBadRequest represents a generic 400 response. It used internally by Swagger as the
// response when a request fails the validation defined in the Swagger yml file.
type DefaultBadRequest struct {
	Msg string %s
}

// Error returns the validation error that caused the 400.
func (d DefaultBadRequest) Error() string {
	return d.Msg
}

`, "`json:\"msg\"`", "`json:\"msg\"`")
}
<commit_msg>Fix typo<commit_after>package models

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"

	"github.com/go-openapi/spec"

	"github.com/Clever/wag/swagger"

	"github.com/go-swagger/go-swagger/generator"

	"text/template"
)

// Generate writes the files to the client directories
func Generate(packageName string, swagger spec.Swagger) error {

	modifiedSpecFile, err := specWithWagPatchTypes(swagger)
	if err != nil {
		return err
	}
	defer os.Remove(modifiedSpecFile)

	// generate models with go-swagger
	if err := generator.GenerateServer("", []string{}, []string{}, generator.GenOpts{
		Spec:           modifiedSpecFile,
		ModelPackage:   "models",
		Target:         fmt.Sprintf("%s/src/%s/", os.Getenv("GOPATH"), packageName),
		IncludeModel:   true,
		IncludeHandler: false,
		IncludeSupport: false,
	}); err != nil {
		return fmt.Errorf("error generating go-swagger models: %s", err)
	}

	if err := generateOutputs(packageName, swagger.Paths); err != nil {
		return fmt.Errorf("error generating outputs: %s", err)
	}
	if err := generateInputs(packageName, swagger.Paths); err != nil {
		return fmt.Errorf("error generating inputs: %s", err)
	}
	return nil
}

// specWithWagPatchTypes takes in a swagger spec and returns a new version of the spec
// with extra type definitions for patch data types (see readme for more details on patch
// data types). The spec is returned as a file path. The caller should remove the file when
// they are finished with it.
func specWithWagPatchTypes(s spec.Swagger) (string, error) {

	definitionsToExtend, err := swagger.WagPatchDataTypes(s.Paths.Paths)
	if err != nil {
		return "", fmt.Errorf("internal error: getting wag patch data types: %s", err)
	}

	allDefinitions := make(spec.Definitions)
	for name, definition := range s.Definitions {
		allDefinitions[name] = definition
		if _, ok := definitionsToExtend[name]; ok {
			// We calculate "Patch" + name in two places. If there becomes a third we should
			// consolidate the logic.
			newName := "Patch" + name
			if _, ok := s.Definitions[newName]; ok {
				return "", fmt.Errorf("can't apply x-wag-patch extension. Conflict with name %s", newName)
			}

			// Mark all the properties nullable so they show up as pointers. We do this so that
			// all the fields in the patch type are optional.
			// We don't use the required field in the swagger schema since go-swagger makes optional
			// fields non-pointers (we're not sure why)
			newProps := make(map[string]spec.Schema)
			for field, prop := range definition.Properties {
				prop.AddExtension("x-isnullable", true)
				newProps[field] = prop
			}
			definition.Properties = newProps
			allDefinitions[newName] = definition

		}
	}
	s.Definitions = allDefinitions

	bytes, err := json.Marshal(s)
	if err != nil {
		return "", fmt.Errorf("internal error: wag patch type marshal failure: %s", err)
	}
	fileName := "swagger.tmp"
	if err := ioutil.WriteFile(fileName, bytes, 0644); err != nil {
		return "", err
	}
	return fileName, nil
}

func generateInputs(packageName string, paths *spec.Paths) error {

	g := swagger.Generator{PackageName: packageName}

	g.Printf(`
package models

import(
		"encoding/json"
		"strconv"

		"github.com/go-openapi/validate"
		"github.com/go-openapi/strfmt"
)

// These imports may not be used depending on the input parameters
var _ = json.Marshal
var _ = strconv.FormatInt
var _ = validate.Maximum
var _ = strfmt.NewFormats
`)

	for _, pathKey := range swagger.SortedPathItemKeys(paths.Paths) {
		path := paths.Paths[pathKey]
		pathItemOps := swagger.PathItemOperations(path)
		for _, opKey := range swagger.SortedOperationsKeys(pathItemOps) {
			op := pathItemOps[opKey]
			// Do not generate an input struct + validation for an
			// operation that has a single, schema'd input.
			// The input to these will be the model generated for
			// the schema.
			if ssbp, _ := swagger.SingleSchemaedBodyParameter(op); ssbp {
				continue
			}
			if err := printInputStruct(&g, op); err != nil {
				return err
			}
			if err := printInputValidation(&g, op); err != nil {
				return err
			}
		}
	}

	return g.WriteFile("models/inputs.go")
}

func printInputStruct(g *swagger.Generator, op *spec.Operation) error {
	capOpID := swagger.Capitalize(op.ID)
	g.Printf("// %sInput holds the input parameters for a %s operation.\n", capOpID, op.ID)
	g.Printf("type %sInput struct {\n", capOpID)

	for _, param := range op.Parameters {
		if param.In == "formData" {
			return fmt.Errorf("Input parameters with 'In' formData are not supported")
		}

		var typeName string
		var err error
		if param.In != "body" {
			typeName, err = swagger.ParamToType(param, true)
			if err != nil {
				return err
			}
		} else {
			typeName, err = swagger.TypeFromSchema(param.Schema, false)
			if err != nil {
				return err
			}
			// All schema types are pointers
			typeName = "*" + typeName
		}

		g.Printf("\t%s %s\n", swagger.StructParamName(param), typeName)
	}
	g.Printf("}\n\n")

	return nil
}

func printInputValidation(g *swagger.Generator, op *spec.Operation) error {
	capOpID := swagger.Capitalize(op.ID)
	g.Printf("// Validate returns an error if any of the %sInput parameters don't satisfy the\n",
		capOpID)
	g.Printf("// requirements from the swagger yml file.\n")
	g.Printf("func (i %sInput) Validate() error{\n", capOpID)

	for _, param := range op.Parameters {
		if param.In == "body" {
			g.Printf("\tif err := i.%s.Validate(nil); err != nil {\n", swagger.StructParamName(param))
			g.Printf("\t\treturn err\n")
			g.Printf("\t}\n\n")
		}

		validations, err := swagger.ParamToValidationCode(param)
		if err != nil {
			return err
		}
		for _, validation := range validations {
			if param.Required {
				g.Printf(errCheck(validation))
			} else {
				g.Printf("\tif i.%s != nil {\n", swagger.StructParamName(param))
				g.Printf(errCheck(validation))
				g.Printf("\t}\n")
			}
		}
	}
	g.Printf("\treturn nil\n")
	g.Printf("}\n\n")

	return nil
}

// errCheck returns an if err := ifCondition; err != nil { return err } function
func errCheck(ifCondition string) string {
	return fmt.Sprintf(
		`	if err := %s; err != nil {
		return err
	}
`, ifCondition)
}

func generateOutputs(packageName string, paths *spec.Paths) error {
	g := swagger.Generator{PackageName: packageName}

	g.Printf("package models\n\n")

	g.Printf(defaultOutputTypes())

	for _, pathKey := range swagger.SortedPathItemKeys(paths.Paths) {
		path := paths.Paths[pathKey]
		pathItemOps := swagger.PathItemOperations(path)
		for _, opKey := range swagger.SortedOperationsKeys(pathItemOps) {
			op := pathItemOps[opKey]
			capOpID := swagger.Capitalize(op.ID)

			// We classify response keys into three types:
			// 1. 200-399 - these are "success" responses and implement the Output interface
			// 	defined above
			// 2. 400-599 - these are "failure" responses and implement the error interface
			// 3. Default - this is defined as a 500
			successTypes, err := generateSuccessTypes(capOpID, op.Responses.StatusCodeResponses)
			if err != nil {
				return err
			}
			g.Printf(successTypes)
			errorTypes, err := generateErrorTypes(capOpID, op.Responses.StatusCodeResponses)
			if err != nil {
				return err
			}
			g.Printf(errorTypes)
		}
	}
	return g.WriteFile("models/outputs.go")
}

func generateSuccessTypes(capOpID string, responses map[int]spec.Response) (string, error) {
	var buf bytes.Buffer
	buf.WriteString(fmt.Sprintf("// %sOutput defines the success output interface for %s.\n",
		capOpID, capOpID))
	buf.WriteString(fmt.Sprintf("type %sOutput interface {\n", capOpID))
	buf.WriteString(fmt.Sprintf("\t%sStatusCode() int\n", capOpID))
	buf.WriteString(fmt.Sprintf("}\n\n"))

	var successStatusCodes []int
	for _, statusCode := range swagger.SortedStatusCodeKeys(responses) {
		if statusCode >= 400 {
			continue
		}
		successStatusCodes = append(successStatusCodes, statusCode)
	}

	// We don't need to generate any success types if there is one or less success responses. In that
	// case we can just use the raw type
	if len(successStatusCodes) < 2 {
		return "", nil
	}

	for _, statusCode := range successStatusCodes {
		typeString, err := generateType(capOpID, statusCode, responses[statusCode])
		if err != nil {
			return "", err
		}
		buf.WriteString(typeString)
	}
	return buf.String(), nil
}

func generateErrorTypes(capOpID string, responses map[int]spec.Response) (string, error) {
	var buf bytes.Buffer

	for _, statusCode := range swagger.SortedStatusCodeKeys(responses) {

		if statusCode >= 400 {
			typeString, err := generateType(capOpID, statusCode, responses[statusCode])
			if err != nil {
				return "", err
			}
			buf.WriteString(typeString)
		}
	}
	return buf.String(), nil
}

func generateType(capOpID string, statusCode int, response spec.Response) (string, error) {
	outputName := fmt.Sprintf("%s%dOutput", capOpID, statusCode)
	typeName, err := swagger.TypeFromSchema(response.Schema, false)
	if err != nil {
		return "", err
	}

	fields := typeTemplateFields{
		Output:     outputName,
		StatusCode: statusCode,
		OpName:     capOpID,
		Type:       typeName,
		ErrorType:  statusCode >= 400,
	}
	tmpl := template.Must(template.New("a").Parse(typeTemplate))
	var tmpBuf bytes.Buffer
	if err := tmpl.Execute(&tmpBuf, fields); err != nil {
		return "", err
	}
	return tmpBuf.String(), nil
}

type typeTemplateFields struct {
	Output     string
	StatusCode int
	OpName     string
	Type       string
	ErrorType  bool
}

var typeTemplate = `
	// {{.Output}} defines the {{.StatusCode}} status code response for {{.OpName}}.
	type {{.Output}} {{.Type}}

	{{if .ErrorType}}
	// Error returns "Status Code: X". We implemented in to satisfy the error
	// interface. For a more descriptive error message see the output type.
	func (o {{.Output}}) Error() string {
		return "Status Code: {{.StatusCode}}"
	}
	{{else}}
	// {{.OpName}}StatusCode returns the status code for the operation.
	func (o {{.Output}}) {{.OpName}}StatusCode() int {
		return {{.StatusCode}}
	}
	{{end}}
`

// defaultOutputTypes returns the string defining the default output type
func defaultOutputTypes() string {
	return fmt.Sprintf(`
// DefaultInternalError represents a generic 500 response.
type DefaultInternalError struct {
	Msg string %s
}

// Error returns the internal error that caused the 500.
func (d DefaultInternalError) Error() string {
	return d.Msg
}

// DefaultBadRequest represents a generic 400 response. It used internally by Swagger as the
// response when a request fails the validation defined in the Swagger yml file.
type DefaultBadRequest struct {
	Msg string %s
}

// Error returns the validation error that caused the 400.
func (d DefaultBadRequest) Error() string {
	return d.Msg
}

`, "`json:\"msg\"`", "`json:\"msg\"`")
}
<|endoftext|>