<commit_before>/*
Copyright 2019 The Tekton 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 test

import (
	"os"
	"regexp"
	"runtime"
	"testing"

	"k8s.io/apimachinery/pkg/util/sets"
)

var (
	imageNames      = initImageNames()
	excludedTests   = initExcludedTests()
	imagesMappingRE map[*regexp.Regexp][]byte
)

const (
	// Busybox image with specific sha
	busyboxImage = iota
	// Registry image
	registryImage
	// kubectl image
	kanikoImage
	// dockerize image
	dockerizeImage
)

func init() {
	imagesMappingRE = getImagesMappingRE()
}

// getTestArch returns architecture of the cluster where test suites will be executed.
// default value is similar to build architecture, TEST_RUNTIME_ARCH is used when test target cluster has another architecture
func getTestArch() string {
	val, ok := os.LookupEnv("TEST_RUNTIME_ARCH")
	if ok {
		return val
	}
	return runtime.GOARCH
}

// initImageNames returns the map with arch dependent image names for e2e tests
func initImageNames() map[int]string {
	switch getTestArch() {
	case "s390x":
		return map[int]string{
			busyboxImage:   "busybox@sha256:4f47c01fa91355af2865ac10fef5bf6ec9c7f42ad2321377c21e844427972977",
			registryImage:  "ibmcom/registry:2.6.2.5",
			kanikoImage:    "gcr.io/kaniko-project/executor:s390x-9ed158c1f63a059cde4fd5f8b95af51d452d9aa7",
			dockerizeImage: "ibmcom/dockerize-s390x",
		}
	case "ppc64le":
		return map[int]string{
			busyboxImage:   "busybox@sha256:4f47c01fa91355af2865ac10fef5bf6ec9c7f42ad2321377c21e844427972977",
			registryImage:  "ppc64le/registry:2",
			kanikoImage:    "ibmcom/kaniko-project-executor-ppc64le:v0.17.1",
			dockerizeImage: "ibmcom/dockerize-ppc64le",
		}
	default:
		return map[int]string{
			busyboxImage:   "busybox@sha256:895ab622e92e18d6b461d671081757af7dbaa3b00e3e28e12505af7817f73649",
			registryImage:  "registry",
			kanikoImage:    "gcr.io/kaniko-project/executor:v1.3.0",
			dockerizeImage: "jwilder/dockerize",
		}
	}
}

// getImagesMappingRE generates the map ready to search and replace image names with regexp for examples files.
// search is done using "image: <name>" pattern.
func getImagesMappingRE() map[*regexp.Regexp][]byte {
	imageNamesMapping := imageNamesMapping()
	imageMappingRE := make(map[*regexp.Regexp][]byte, len(imageNamesMapping))

	for existingImage, archSpecificImage := range imageNamesMapping {
		imageMappingRE[regexp.MustCompile("(?im)image: "+existingImage+"$")] = []byte("image: " + archSpecificImage)
		imageMappingRE[regexp.MustCompile("(?im)default: "+existingImage+"$")] = []byte("default: " + archSpecificImage)
	}

	return imageMappingRE
}

// imageNamesMapping provides mapping between image name in the examples yaml files and desired image name for specific arch.
// by default empty map is returned.
func imageNamesMapping() map[string]string {

	switch getTestArch() {
	case "s390x":
		return map[string]string{
			"registry":                              getTestImage(registryImage),
			"node":                                  "node:alpine3.11",
			"gcr.io/cloud-builders/git":             "alpine/git:latest",
			"docker:dind":                           "ibmcom/docker-s390x:dind",
			"docker":                                "docker:18.06.3",
			"mikefarah/yq:3":                        "danielxlee/yq:2.4.0",
			"stedolan/jq":                           "ibmcom/jq-s390x:latest",
			"gcr.io/kaniko-project/executor:v1.3.0": getTestImage(kanikoImage),
		}
	case "ppc64le":
		return map[string]string{
			"registry":                              getTestImage(registryImage),
			"node":                                  "node:alpine3.11",
			"gcr.io/cloud-builders/git":             "alpine/git:latest",
			"docker:dind":                           "ibmcom/docker-ppc64le:19.03-dind",
			"docker":                                "docker:18.06.3",
			"mikefarah/yq:3":                        "danielxlee/yq:2.4.0",
			"stedolan/jq":                           "ibmcom/jq-ppc64le:latest",
			"gcr.io/kaniko-project/executor:v1.3.0": getTestImage(kanikoImage),
		}

	}

	return make(map[string]string)
}

// initExcludedTests provides list of excluded tests for e2e and exanples tests
func initExcludedTests() sets.String {

	switch getTestArch() {
	case "s390x":
		return sets.NewString(
			// examples
			"TestExamples/v1alpha1/taskruns/gcs-resource",
			"TestExamples/v1beta1/taskruns/gcs-resource",
			"TestExamples/v1beta1/taskruns/creds-init-only-mounts-provided-credentials",
		)
	case "ppc64le":
		return sets.NewString(
			// examples
			"TestExamples/v1alpha1/taskruns/gcs-resource",
			"TestExamples/v1beta1/taskruns/gcs-resource",
		)
	}

	return sets.NewString()
}

// getTestImage gets test image based on unique id
func getTestImage(image int) string {
	return imageNames[image]
}

// skipIfExcluded checks if test name is in the excluded list and skip it
func skipIfExcluded(t *testing.T) {
	if excludedTests.Has(t.Name()) {
		t.Skipf("skip for %s architecture", getTestArch())
	}
}
<commit_msg>Add image replacement for amd64 specific image<commit_after>/*
Copyright 2019 The Tekton 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 test

import (
	"os"
	"regexp"
	"runtime"
	"testing"

	"k8s.io/apimachinery/pkg/util/sets"
)

var (
	imageNames      = initImageNames()
	excludedTests   = initExcludedTests()
	imagesMappingRE map[*regexp.Regexp][]byte
)

const (
	// Busybox image with specific sha
	busyboxImage = iota
	// Registry image
	registryImage
	// kubectl image
	kanikoImage
	// dockerize image
	dockerizeImage
)

func init() {
	imagesMappingRE = getImagesMappingRE()
}

// getTestArch returns architecture of the cluster where test suites will be executed.
// default value is similar to build architecture, TEST_RUNTIME_ARCH is used when test target cluster has another architecture
func getTestArch() string {
	val, ok := os.LookupEnv("TEST_RUNTIME_ARCH")
	if ok {
		return val
	}
	return runtime.GOARCH
}

// initImageNames returns the map with arch dependent image names for e2e tests
func initImageNames() map[int]string {
	switch getTestArch() {
	case "s390x":
		return map[int]string{
			busyboxImage:   "busybox@sha256:4f47c01fa91355af2865ac10fef5bf6ec9c7f42ad2321377c21e844427972977",
			registryImage:  "ibmcom/registry:2.6.2.5",
			kanikoImage:    "gcr.io/kaniko-project/executor:s390x-9ed158c1f63a059cde4fd5f8b95af51d452d9aa7",
			dockerizeImage: "ibmcom/dockerize-s390x",
		}
	case "ppc64le":
		return map[int]string{
			busyboxImage:   "busybox@sha256:4f47c01fa91355af2865ac10fef5bf6ec9c7f42ad2321377c21e844427972977",
			registryImage:  "ppc64le/registry:2",
			kanikoImage:    "ibmcom/kaniko-project-executor-ppc64le:v0.17.1",
			dockerizeImage: "ibmcom/dockerize-ppc64le",
		}
	default:
		return map[int]string{
			busyboxImage:   "busybox@sha256:895ab622e92e18d6b461d671081757af7dbaa3b00e3e28e12505af7817f73649",
			registryImage:  "registry",
			kanikoImage:    "gcr.io/kaniko-project/executor:v1.3.0",
			dockerizeImage: "jwilder/dockerize",
		}
	}
}

// getImagesMappingRE generates the map ready to search and replace image names with regexp for examples files.
// search is done using "image: <name>" pattern.
func getImagesMappingRE() map[*regexp.Regexp][]byte {
	imageNamesMapping := imageNamesMapping()
	imageMappingRE := make(map[*regexp.Regexp][]byte, len(imageNamesMapping))

	for existingImage, archSpecificImage := range imageNamesMapping {
		imageMappingRE[regexp.MustCompile("(?im)image: "+existingImage+"$")] = []byte("image: " + archSpecificImage)
		imageMappingRE[regexp.MustCompile("(?im)default: "+existingImage+"$")] = []byte("default: " + archSpecificImage)
	}

	return imageMappingRE
}

// imageNamesMapping provides mapping between image name in the examples yaml files and desired image name for specific arch.
// by default empty map is returned.
func imageNamesMapping() map[string]string {

	switch getTestArch() {
	case "s390x":
		return map[string]string{
			"registry":                              getTestImage(registryImage),
			"node":                                  "node:alpine3.11",
			"gcr.io/cloud-builders/git":             "alpine/git:latest",
			"docker:dind":                           "ibmcom/docker-s390x:dind",
			"docker":                                "docker:18.06.3",
			"mikefarah/yq:3":                        "danielxlee/yq:2.4.0",
			"stedolan/jq":                           "ibmcom/jq-s390x:latest",
			"amd64/ubuntu":                          "s390x/ubuntu",
			"gcr.io/kaniko-project/executor:v1.3.0": getTestImage(kanikoImage),
		}
	case "ppc64le":
		return map[string]string{
			"registry":                              getTestImage(registryImage),
			"node":                                  "node:alpine3.11",
			"gcr.io/cloud-builders/git":             "alpine/git:latest",
			"docker:dind":                           "ibmcom/docker-ppc64le:19.03-dind",
			"docker":                                "docker:18.06.3",
			"mikefarah/yq:3":                        "danielxlee/yq:2.4.0",
			"stedolan/jq":                           "ibmcom/jq-ppc64le:latest",
			"gcr.io/kaniko-project/executor:v1.3.0": getTestImage(kanikoImage),
		}

	}

	return make(map[string]string)
}

// initExcludedTests provides list of excluded tests for e2e and exanples tests
func initExcludedTests() sets.String {

	switch getTestArch() {
	case "s390x":
		return sets.NewString(
			// examples
			"TestExamples/v1alpha1/taskruns/gcs-resource",
			"TestExamples/v1beta1/taskruns/gcs-resource",
			"TestExamples/v1beta1/taskruns/creds-init-only-mounts-provided-credentials",
		)
	case "ppc64le":
		return sets.NewString(
			// examples
			"TestExamples/v1alpha1/taskruns/gcs-resource",
			"TestExamples/v1beta1/taskruns/gcs-resource",
		)
	}

	return sets.NewString()
}

// getTestImage gets test image based on unique id
func getTestImage(image int) string {
	return imageNames[image]
}

// skipIfExcluded checks if test name is in the excluded list and skip it
func skipIfExcluded(t *testing.T) {
	if excludedTests.Has(t.Name()) {
		t.Skipf("skip for %s architecture", getTestArch())
	}
}
<|endoftext|>


<commit_before>package cli

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"sort"
	"strings"
	"time"

	"github.com/micro/cli"
	"github.com/micro/go-micro/cmd"
	"github.com/micro/go-micro/registry"
	proto "github.com/micro/go-micro/server/debug/proto"
	"github.com/serenize/snaker"

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

func formatEndpoint(v *registry.Value, r int) string {
	// default format is tabbed plus the value plus new line
	fparts := []string{"", "%s %s", "\n"}
	for i := 0; i < r+1; i++ {
		fparts[0] += "\t"
	}
	// its just a primitive of sorts so return
	if len(v.Values) == 0 {
		return fmt.Sprintf(strings.Join(fparts, ""), snaker.CamelToSnake(v.Name), v.Type)
	}

	// this thing has more things, it's complex
	fparts[1] += " {"

	vals := []interface{}{snaker.CamelToSnake(v.Name), v.Type}

	for _, val := range v.Values {
		fparts = append(fparts, "%s")
		vals = append(vals, formatEndpoint(val, r+1))
	}

	// at the end
	l := len(fparts) - 1
	for i := 0; i < r+1; i++ {
		fparts[l] += "\t"
	}
	fparts = append(fparts, "}\n")

	return fmt.Sprintf(strings.Join(fparts, ""), vals...)
}

func get(url string, v interface{}) error {
	if !strings.HasPrefix(url, "http") && !strings.HasPrefix(url, "https") {
		url = "http://" + url
	}

	rsp, err := http.Get(url)
	if err != nil {
		return err
	}
	defer rsp.Body.Close()

	b, err := ioutil.ReadAll(rsp.Body)
	if err != nil {
		return err
	}

	return json.Unmarshal(b, v)
}

func post(url string, b []byte, v interface{}) error {
	if !strings.HasPrefix(url, "http") && !strings.HasPrefix(url, "https") {
		url = "http://" + url
	}

	buf := bytes.NewBuffer(b)
	defer buf.Reset()

	rsp, err := http.Post(url, "application/json", buf)
	if err != nil {
		return err
	}
	defer rsp.Body.Close()

	bu, err := ioutil.ReadAll(rsp.Body)
	if err != nil {
		return err
	}

	if v == nil {
		return nil
	}

	return json.Unmarshal(bu, v)
}

func del(url string, b []byte, v interface{}) error {
	if !strings.HasPrefix(url, "http") && !strings.HasPrefix(url, "https") {
		url = "http://" + url
	}

	buf := bytes.NewBuffer(b)
	defer buf.Reset()

	req, err := http.NewRequest("DELETE", url, buf)
	if err != nil {
		return err
	}

	rsp, err := http.DefaultClient.Do(req)
	if err != nil {
		return err
	}
	defer rsp.Body.Close()

	bu, err := ioutil.ReadAll(rsp.Body)
	if err != nil {
		return err
	}

	if v == nil {
		return nil
	}

	return json.Unmarshal(bu, v)
}

func listServices(c *cli.Context) {
	var rsp []*registry.Service
	var err error

	if p := c.GlobalString("proxy_address"); len(p) > 0 {
		if err := get(p+"/registry", &rsp); err != nil {
			fmt.Println(err.Error())
			return
		}
	} else {
		rsp, err = (*cmd.DefaultOptions().Registry).ListServices()
		if err != nil {
			fmt.Println(err.Error())
			return
		}
	}

	ss := sortedServices{rsp}
	sort.Sort(ss)

	for _, service := range ss.services {
		fmt.Println(service.Name)
	}
}

func registerService(c *cli.Context) {
	if len(c.Args()) != 1 {
		fmt.Println("require service definition")
		return
	}

	if p := c.GlobalString("proxy_address"); len(p) > 0 {
		if err := post(p+"/registry", []byte(c.Args().First()), nil); err != nil {
			fmt.Println(err.Error())
		}
		return
	}

	var service *registry.Service

	if err := json.Unmarshal([]byte(c.Args().First()), &service); err != nil {
		fmt.Println(err.Error())
		return
	}

	if err := (*cmd.DefaultOptions().Registry).Register(service); err != nil {
		fmt.Println(err.Error())
	}
}

func deregisterService(c *cli.Context) {
	if len(c.Args()) != 1 {
		fmt.Println("require service definition")
		return
	}

	if p := c.GlobalString("proxy_address"); len(p) > 0 {
		if err := del(p+"/registry", []byte(c.Args().First()), nil); err != nil {
			fmt.Println(err.Error())
		}
		return
	}

	var service *registry.Service
	if err := json.Unmarshal([]byte(c.Args().First()), &service); err != nil {
		fmt.Println(err.Error())
		return
	}
	if err := (*cmd.DefaultOptions().Registry).Deregister(service); err != nil {
		fmt.Println(err.Error())
		return
	}
}

func getService(c *cli.Context) {
	if !c.Args().Present() {
		fmt.Println("Service required")
		return
	}

	var service []*registry.Service
	var err error

	if p := c.GlobalString("proxy_address"); len(p) > 0 {
		if err := get(p+"/registry?service="+c.Args().First(), &service); err != nil {
			fmt.Println(err.Error())
			return
		}
	} else {
		service, err = (*cmd.DefaultOptions().Registry).GetService(c.Args().First())
	}

	if err != nil {
		fmt.Println(err.Error())
		return
	}
	if len(service) == 0 {
		fmt.Println("Service not found")
		return
	}

	fmt.Printf("service  %s\n", service[0].Name)
	for _, serv := range service {
		fmt.Println("\nversion ", serv.Version)
		fmt.Println("\nId\tAddress\tPort\tMetadata")
		for _, node := range serv.Nodes {
			var meta []string
			for k, v := range node.Metadata {
				meta = append(meta, k+"="+v)
			}
			fmt.Printf("%s\t%s\t%d\t%s\n", node.Id, node.Address, node.Port, strings.Join(meta, ","))
		}
	}

	for _, e := range service[0].Endpoints {
		var request, response string
		var meta []string
		for k, v := range e.Metadata {
			meta = append(meta, k+"="+v)
		}
		if e.Request != nil && len(e.Request.Values) > 0 {
			request = "{\n"
			for _, v := range e.Request.Values {
				request += formatEndpoint(v, 0)
			}
			request += "}"
		} else {
			request = "{}"
		}
		if e.Response != nil && len(e.Response.Values) > 0 {
			response = "{\n"
			for _, v := range e.Response.Values {
				response += formatEndpoint(v, 0)
			}
			response += "}"
		} else {
			response = "{}"
		}
		fmt.Printf("\nEndpoint: %s\nMetadata: %s\n", e.Name, strings.Join(meta, ","))
		fmt.Printf("Request: %s\n\nResponse: %s\n", request, response)
	}
}

func queryService(c *cli.Context) {
	if len(c.Args()) < 2 {
		fmt.Println("require service and method")
		return
	}
	service := c.Args()[0]
	method := c.Args()[1]
	var request map[string]interface{}
	var response map[string]interface{}

	if p := c.GlobalString("proxy_address"); len(p) > 0 {
		request = map[string]interface{}{
			"service": service,
			"method":  method,
			"request": []byte(strings.Join(c.Args()[2:], " ")),
		}

		b, err := json.Marshal(request)
		if err != nil {
			fmt.Println(err.Error())
			return
		}

		if err := post(p+"/rpc", b, &response); err != nil {
			fmt.Println(err.Error())
			return
		}

	} else {
		json.Unmarshal([]byte(strings.Join(c.Args()[2:], " ")), &request)

		req := (*cmd.DefaultOptions().Client).NewJsonRequest(service, method, request)
		err := (*cmd.DefaultOptions().Client).Call(context.Background(), req, &response)
		if err != nil {
			fmt.Printf("error calling %s.%s: %v\n", service, method, err)
			return
		}
	}

	b, _ := json.MarshalIndent(response, "", "\t")
	fmt.Println(string(b))
}

// TODO: stream via HTTP
func streamService(c *cli.Context) {
	if len(c.Args()) < 2 {
		fmt.Println("require service and method")
		return
	}
	service := c.Args()[0]
	method := c.Args()[1]
	var request map[string]interface{}
	json.Unmarshal([]byte(strings.Join(c.Args()[2:], " ")), &request)
	req := (*cmd.DefaultOptions().Client).NewJsonRequest(service, method, request)
	stream, err := (*cmd.DefaultOptions().Client).Stream(context.Background(), req)
	if err != nil {
		fmt.Printf("error calling %s.%s: %v\n", service, method, err)
		return
	}

	if err := stream.Send(request); err != nil {
		fmt.Printf("error sending to %s.%s: %v\n", service, method, err)
		return
	}

	for {
		var response map[string]interface{}
		if err := stream.Recv(&response); err != nil {
			fmt.Printf("error receiving from %s.%s: %v\n", service, method, err)
			return
		}

		b, _ := json.MarshalIndent(response, "", "\t")
		fmt.Println(string(b))

		// artificial delay
		time.Sleep(time.Millisecond * 10)
	}
}

func queryHealth(c *cli.Context) {
	if !c.Args().Present() {
		fmt.Println("require service name")
		return
	}
	service, err := (*cmd.DefaultOptions().Registry).GetService(c.Args().First())
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	if service == nil || len(service) == 0 {
		fmt.Println("Service not found")
		return
	}

	req := (*cmd.DefaultOptions().Client).NewRequest(service[0].Name, "Debug.Health", &proto.HealthRequest{})

	// print things
	fmt.Printf("service  %s\n\n", service[0].Name)

	for _, serv := range service {
		// print things
		fmt.Println("\nversion ", serv.Version)
		fmt.Println("\nnode\t\taddress:port\t\tstatus")

		// query health for every node
		for _, node := range serv.Nodes {
			address := node.Address
			if node.Port > 0 {
				address = fmt.Sprintf("%s:%d", address, node.Port)
			}
			rsp := &proto.HealthResponse{}

			var err error

			if p := c.GlobalString("proxy_address"); len(p) > 0 {
				// call using proxy
				request := map[string]interface{}{
					"service": service[0].Name,
					"method":  "Debug.Health",
					"address": address,
				}

				b, err := json.Marshal(request)
				if err != nil {
					fmt.Println(err.Error())
					return
				}

				if err := post(p+"/rpc", b, &rsp); err != nil {
					fmt.Println(err.Error())
					return
				}
			} else {
				// call using client
				err = (*cmd.DefaultOptions().Client).CallRemote(context.Background(), address, req, rsp)
			}

			var status string
			if err != nil {
				status = err.Error()
			} else {
				status = rsp.Status
			}
			fmt.Printf("%s\t\t%s:%d\t\t%s\n", node.Id, node.Address, node.Port, status)
		}
	}
}
<commit_msg>Why the heck I was turning that into bytes...<commit_after>package cli

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"sort"
	"strings"
	"time"

	"github.com/micro/cli"
	"github.com/micro/go-micro/cmd"
	"github.com/micro/go-micro/registry"
	proto "github.com/micro/go-micro/server/debug/proto"
	"github.com/serenize/snaker"

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

func formatEndpoint(v *registry.Value, r int) string {
	// default format is tabbed plus the value plus new line
	fparts := []string{"", "%s %s", "\n"}
	for i := 0; i < r+1; i++ {
		fparts[0] += "\t"
	}
	// its just a primitive of sorts so return
	if len(v.Values) == 0 {
		return fmt.Sprintf(strings.Join(fparts, ""), snaker.CamelToSnake(v.Name), v.Type)
	}

	// this thing has more things, it's complex
	fparts[1] += " {"

	vals := []interface{}{snaker.CamelToSnake(v.Name), v.Type}

	for _, val := range v.Values {
		fparts = append(fparts, "%s")
		vals = append(vals, formatEndpoint(val, r+1))
	}

	// at the end
	l := len(fparts) - 1
	for i := 0; i < r+1; i++ {
		fparts[l] += "\t"
	}
	fparts = append(fparts, "}\n")

	return fmt.Sprintf(strings.Join(fparts, ""), vals...)
}

func get(url string, v interface{}) error {
	if !strings.HasPrefix(url, "http") && !strings.HasPrefix(url, "https") {
		url = "http://" + url
	}

	rsp, err := http.Get(url)
	if err != nil {
		return err
	}
	defer rsp.Body.Close()

	b, err := ioutil.ReadAll(rsp.Body)
	if err != nil {
		return err
	}

	return json.Unmarshal(b, v)
}

func post(url string, b []byte, v interface{}) error {
	if !strings.HasPrefix(url, "http") && !strings.HasPrefix(url, "https") {
		url = "http://" + url
	}

	buf := bytes.NewBuffer(b)
	defer buf.Reset()

	rsp, err := http.Post(url, "application/json", buf)
	if err != nil {
		return err
	}
	defer rsp.Body.Close()

	bu, err := ioutil.ReadAll(rsp.Body)
	if err != nil {
		return err
	}

	if v == nil {
		return nil
	}

	return json.Unmarshal(bu, v)
}

func del(url string, b []byte, v interface{}) error {
	if !strings.HasPrefix(url, "http") && !strings.HasPrefix(url, "https") {
		url = "http://" + url
	}

	buf := bytes.NewBuffer(b)
	defer buf.Reset()

	req, err := http.NewRequest("DELETE", url, buf)
	if err != nil {
		return err
	}

	rsp, err := http.DefaultClient.Do(req)
	if err != nil {
		return err
	}
	defer rsp.Body.Close()

	bu, err := ioutil.ReadAll(rsp.Body)
	if err != nil {
		return err
	}

	if v == nil {
		return nil
	}

	return json.Unmarshal(bu, v)
}

func listServices(c *cli.Context) {
	var rsp []*registry.Service
	var err error

	if p := c.GlobalString("proxy_address"); len(p) > 0 {
		if err := get(p+"/registry", &rsp); err != nil {
			fmt.Println(err.Error())
			return
		}
	} else {
		rsp, err = (*cmd.DefaultOptions().Registry).ListServices()
		if err != nil {
			fmt.Println(err.Error())
			return
		}
	}

	ss := sortedServices{rsp}
	sort.Sort(ss)

	for _, service := range ss.services {
		fmt.Println(service.Name)
	}
}

func registerService(c *cli.Context) {
	if len(c.Args()) != 1 {
		fmt.Println("require service definition")
		return
	}

	if p := c.GlobalString("proxy_address"); len(p) > 0 {
		if err := post(p+"/registry", []byte(c.Args().First()), nil); err != nil {
			fmt.Println(err.Error())
		}
		return
	}

	var service *registry.Service

	if err := json.Unmarshal([]byte(c.Args().First()), &service); err != nil {
		fmt.Println(err.Error())
		return
	}

	if err := (*cmd.DefaultOptions().Registry).Register(service); err != nil {
		fmt.Println(err.Error())
	}
}

func deregisterService(c *cli.Context) {
	if len(c.Args()) != 1 {
		fmt.Println("require service definition")
		return
	}

	if p := c.GlobalString("proxy_address"); len(p) > 0 {
		if err := del(p+"/registry", []byte(c.Args().First()), nil); err != nil {
			fmt.Println(err.Error())
		}
		return
	}

	var service *registry.Service
	if err := json.Unmarshal([]byte(c.Args().First()), &service); err != nil {
		fmt.Println(err.Error())
		return
	}
	if err := (*cmd.DefaultOptions().Registry).Deregister(service); err != nil {
		fmt.Println(err.Error())
		return
	}
}

func getService(c *cli.Context) {
	if !c.Args().Present() {
		fmt.Println("Service required")
		return
	}

	var service []*registry.Service
	var err error

	if p := c.GlobalString("proxy_address"); len(p) > 0 {
		if err := get(p+"/registry?service="+c.Args().First(), &service); err != nil {
			fmt.Println(err.Error())
			return
		}
	} else {
		service, err = (*cmd.DefaultOptions().Registry).GetService(c.Args().First())
	}

	if err != nil {
		fmt.Println(err.Error())
		return
	}
	if len(service) == 0 {
		fmt.Println("Service not found")
		return
	}

	fmt.Printf("service  %s\n", service[0].Name)
	for _, serv := range service {
		fmt.Println("\nversion ", serv.Version)
		fmt.Println("\nId\tAddress\tPort\tMetadata")
		for _, node := range serv.Nodes {
			var meta []string
			for k, v := range node.Metadata {
				meta = append(meta, k+"="+v)
			}
			fmt.Printf("%s\t%s\t%d\t%s\n", node.Id, node.Address, node.Port, strings.Join(meta, ","))
		}
	}

	for _, e := range service[0].Endpoints {
		var request, response string
		var meta []string
		for k, v := range e.Metadata {
			meta = append(meta, k+"="+v)
		}
		if e.Request != nil && len(e.Request.Values) > 0 {
			request = "{\n"
			for _, v := range e.Request.Values {
				request += formatEndpoint(v, 0)
			}
			request += "}"
		} else {
			request = "{}"
		}
		if e.Response != nil && len(e.Response.Values) > 0 {
			response = "{\n"
			for _, v := range e.Response.Values {
				response += formatEndpoint(v, 0)
			}
			response += "}"
		} else {
			response = "{}"
		}
		fmt.Printf("\nEndpoint: %s\nMetadata: %s\n", e.Name, strings.Join(meta, ","))
		fmt.Printf("Request: %s\n\nResponse: %s\n", request, response)
	}
}

func queryService(c *cli.Context) {
	if len(c.Args()) < 2 {
		fmt.Println("require service and method")
		return
	}
	service := c.Args()[0]
	method := c.Args()[1]
	var request map[string]interface{}
	var response map[string]interface{}

	if p := c.GlobalString("proxy_address"); len(p) > 0 {
		request = map[string]interface{}{
			"service": service,
			"method":  method,
			"request": strings.Join(c.Args()[2:], " "),
		}

		b, err := json.Marshal(request)
		if err != nil {
			fmt.Println(err.Error())
			return
		}

		if err := post(p+"/rpc", b, &response); err != nil {
			fmt.Println(err.Error())
			return
		}

	} else {
		json.Unmarshal([]byte(strings.Join(c.Args()[2:], " ")), &request)

		req := (*cmd.DefaultOptions().Client).NewJsonRequest(service, method, request)
		err := (*cmd.DefaultOptions().Client).Call(context.Background(), req, &response)
		if err != nil {
			fmt.Printf("error calling %s.%s: %v\n", service, method, err)
			return
		}
	}

	b, _ := json.MarshalIndent(response, "", "\t")
	fmt.Println(string(b))
}

// TODO: stream via HTTP
func streamService(c *cli.Context) {
	if len(c.Args()) < 2 {
		fmt.Println("require service and method")
		return
	}
	service := c.Args()[0]
	method := c.Args()[1]
	var request map[string]interface{}
	json.Unmarshal([]byte(strings.Join(c.Args()[2:], " ")), &request)
	req := (*cmd.DefaultOptions().Client).NewJsonRequest(service, method, request)
	stream, err := (*cmd.DefaultOptions().Client).Stream(context.Background(), req)
	if err != nil {
		fmt.Printf("error calling %s.%s: %v\n", service, method, err)
		return
	}

	if err := stream.Send(request); err != nil {
		fmt.Printf("error sending to %s.%s: %v\n", service, method, err)
		return
	}

	for {
		var response map[string]interface{}
		if err := stream.Recv(&response); err != nil {
			fmt.Printf("error receiving from %s.%s: %v\n", service, method, err)
			return
		}

		b, _ := json.MarshalIndent(response, "", "\t")
		fmt.Println(string(b))

		// artificial delay
		time.Sleep(time.Millisecond * 10)
	}
}

func queryHealth(c *cli.Context) {
	if !c.Args().Present() {
		fmt.Println("require service name")
		return
	}
	service, err := (*cmd.DefaultOptions().Registry).GetService(c.Args().First())
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	if service == nil || len(service) == 0 {
		fmt.Println("Service not found")
		return
	}

	req := (*cmd.DefaultOptions().Client).NewRequest(service[0].Name, "Debug.Health", &proto.HealthRequest{})

	// print things
	fmt.Printf("service  %s\n\n", service[0].Name)

	for _, serv := range service {
		// print things
		fmt.Println("\nversion ", serv.Version)
		fmt.Println("\nnode\t\taddress:port\t\tstatus")

		// query health for every node
		for _, node := range serv.Nodes {
			address := node.Address
			if node.Port > 0 {
				address = fmt.Sprintf("%s:%d", address, node.Port)
			}
			rsp := &proto.HealthResponse{}

			var err error

			if p := c.GlobalString("proxy_address"); len(p) > 0 {
				// call using proxy
				request := map[string]interface{}{
					"service": service[0].Name,
					"method":  "Debug.Health",
					"address": address,
				}

				b, err := json.Marshal(request)
				if err != nil {
					fmt.Println(err.Error())
					return
				}

				if err := post(p+"/rpc", b, &rsp); err != nil {
					fmt.Println(err.Error())
					return
				}
			} else {
				// call using client
				err = (*cmd.DefaultOptions().Client).CallRemote(context.Background(), address, req, rsp)
			}

			var status string
			if err != nil {
				status = err.Error()
			} else {
				status = rsp.Status
			}
			fmt.Printf("%s\t\t%s:%d\t\t%s\n", node.Id, node.Address, node.Port, status)
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2014 go-dockerclient authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package docker

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"reflect"
	"strconv"
	"strings"
	"testing"
)

func TestNewAPIClient(t *testing.T) {
	endpoint := "http://localhost:4243"
	client, err := NewClient(endpoint)
	if err != nil {
		t.Fatal(err)
	}
	if client.endpoint != endpoint {
		t.Errorf("Expected endpoint %s. Got %s.", endpoint, client.endpoint)
	}
	if client.HTTPClient != http.DefaultClient {
		t.Errorf("Expected http.Client %#v. Got %#v.", http.DefaultClient, client.HTTPClient)
	}
	// test unix socket endpoints
	endpoint = "unix:///var/run/docker.sock"
	client, err = NewClient(endpoint)
	if err != nil {
		t.Fatal(err)
	}
	if client.endpoint != endpoint {
		t.Errorf("Expected endpoint %s. Got %s.", endpoint, client.endpoint)
	}
	if !client.SkipServerVersionCheck {
		t.Error("Expected SkipServerVersionCheck to be true, got false")
	}
	if client.requestedApiVersion != nil {
		t.Errorf("Expected requestedApiVersion to be nil, got %#v.", client.requestedApiVersion)
	}
}

func newTLSClient(endpoint string) (*Client, error) {
	return NewTLSClient(endpoint,
		"testing/data/cert.pem",
		"testing/data/key.pem",
		"testing/data/ca.pem")
}

func TestNewTSLAPIClient(t *testing.T) {
	endpoint := "https://localhost:4243"
	client, err := newTLSClient(endpoint)
	if err != nil {
		t.Fatal(err)
	}
	if client.endpoint != endpoint {
		t.Errorf("Expected endpoint %s. Got %s.", endpoint, client.endpoint)
	}
	if !client.SkipServerVersionCheck {
		t.Error("Expected SkipServerVersionCheck to be true, got false")
	}
	if client.requestedApiVersion != nil {
		t.Errorf("Expected requestedApiVersion to be nil, got %#v.", client.requestedApiVersion)
	}
}

func TestNewVersionedClient(t *testing.T) {
	endpoint := "http://localhost:4243"
	client, err := NewVersionedClient(endpoint, "1.12")
	if err != nil {
		t.Fatal(err)
	}
	if client.endpoint != endpoint {
		t.Errorf("Expected endpoint %s. Got %s.", endpoint, client.endpoint)
	}
	if client.HTTPClient != http.DefaultClient {
		t.Errorf("Expected http.Client %#v. Got %#v.", http.DefaultClient, client.HTTPClient)
	}
	if reqVersion := client.requestedApiVersion.String(); reqVersion != "1.12" {
		t.Errorf("Wrong requestApiVersion. Want %q. Got %q.", "1.12", reqVersion)
	}
	if client.SkipServerVersionCheck {
		t.Error("Expected SkipServerVersionCheck to be false, got true")
	}
}

func TestNewTLSVersionedClient(t *testing.T) {
	certPath := "testing/data/cert.pem"
	keyPath := "testing/data/key.pem"
	caPath := "testing/data/ca.pem"
	endpoint := "https://localhost:4243"
	client, err := NewVersionnedTLSClient(endpoint, certPath, keyPath, caPath, "1.14")
	if err != nil {
		t.Fatal(err)
	}
	if client.endpoint != endpoint {
		t.Errorf("Expected endpoint %s. Got %s.", endpoint, client.endpoint)
	}
	if reqVersion := client.requestedApiVersion.String(); reqVersion != "1.14" {
		t.Errorf("Wrong requestApiVersion. Want %q. Got %q.", "1.14", reqVersion)
	}
	if client.SkipServerVersionCheck {
		t.Error("Expected SkipServerVersionCheck to be false, got true")
	}
}

func TestNewTLSVersionedClientInvalidCA(t *testing.T) {
	certPath := "testing/data/cert.pem"
	keyPath := "testing/data/key.pem"
	caPath := "testing/data/key.pem"
	endpoint := "https://localhost:4243"
	_, err := NewVersionnedTLSClient(endpoint, certPath, keyPath, caPath, "1.14")
	if err == nil {
		t.Errorf("Expected invalid ca at %s", caPath)
	}
}

func TestNewClientInvalidEndpoint(t *testing.T) {
	cases := []string{
		"htp://localhost:3243", "http://localhost:a", "localhost:8080",
		"", "localhost", "http://localhost:8080:8383", "http://localhost:65536",
		"https://localhost:-20",
	}
	for _, c := range cases {
		client, err := NewClient(c)
		if client != nil {
			t.Errorf("Want <nil> client for invalid endpoint, got %#v.", client)
		}
		if !reflect.DeepEqual(err, ErrInvalidEndpoint) {
			t.Errorf("NewClient(%q): Got invalid error for invalid endpoint. Want %#v. Got %#v.", c, ErrInvalidEndpoint, err)
		}
	}
}

func TestNewTLSClient2736(t *testing.T) {
	var tests = []struct {
		endpoint string
		expected string
	}{
		{"tcp://localhost:2376", "https"},
		{"tcp://localhost:2375", "http"},
		{"tcp://localhost:4000", "http"},
	}

	for _, tt := range tests {
		client, err := newTLSClient(tt.endpoint)
		if err != nil {
			t.Error(err)
		}
		got := client.endpointURL.Scheme
		if got != tt.expected {
			t.Errorf("endpointURL.Scheme: Got %s. Want %s.", got, tt.expected)
		}
	}
}

func TestGetURL(t *testing.T) {
	var tests = []struct {
		endpoint string
		path     string
		expected string
	}{
		{"http://localhost:4243/", "/", "http://localhost:4243/"},
		{"http://localhost:4243", "/", "http://localhost:4243/"},
		{"http://localhost:4243", "/containers/ps", "http://localhost:4243/containers/ps"},
		{"tcp://localhost:4243", "/containers/ps", "http://localhost:4243/containers/ps"},
		{"http://localhost:4243/////", "/", "http://localhost:4243/"},
		{"unix:///var/run/docker.socket", "/containers", "/containers"},
	}
	for _, tt := range tests {
		client, _ := NewClient(tt.endpoint)
		client.endpoint = tt.endpoint
		client.SkipServerVersionCheck = true
		got := client.getURL(tt.path)
		if got != tt.expected {
			t.Errorf("getURL(%q): Got %s. Want %s.", tt.path, got, tt.expected)
		}
	}
}

func TestError(t *testing.T) {
	err := newError(400, []byte("bad parameter"))
	expected := Error{Status: 400, Message: "bad parameter"}
	if !reflect.DeepEqual(expected, *err) {
		t.Errorf("Wrong error type. Want %#v. Got %#v.", expected, *err)
	}
	message := "API error (400): bad parameter"
	if err.Error() != message {
		t.Errorf("Wrong error message. Want %q. Got %q.", message, err.Error())
	}
}

func TestQueryString(t *testing.T) {
	v := float32(2.4)
	f32QueryString := fmt.Sprintf("w=%s&x=10&y=10.35", strconv.FormatFloat(float64(v), 'f', -1, 64))
	jsonPerson := url.QueryEscape(`{"Name":"gopher","age":4}`)
	var tests = []struct {
		input interface{}
		want  string
	}{
		{&ListContainersOptions{All: true}, "all=1"},
		{ListContainersOptions{All: true}, "all=1"},
		{ListContainersOptions{Before: "something"}, "before=something"},
		{ListContainersOptions{Before: "something", Since: "other"}, "before=something&since=other"},
		{dumb{X: 10, Y: 10.35000}, "x=10&y=10.35"},
		{dumb{W: v, X: 10, Y: 10.35000}, f32QueryString},
		{dumb{X: 10, Y: 10.35000, Z: 10}, "x=10&y=10.35&zee=10"},
		{dumb{v: 4, X: 10, Y: 10.35000}, "x=10&y=10.35"},
		{dumb{T: 10, Y: 10.35000}, "y=10.35"},
		{dumb{Person: &person{Name: "gopher", Age: 4}}, "p=" + jsonPerson},
		{nil, ""},
		{10, ""},
		{"not_a_struct", ""},
	}
	for _, tt := range tests {
		got := queryString(tt.input)
		if got != tt.want {
			t.Errorf("queryString(%v). Want %q. Got %q.", tt.input, tt.want, got)
		}
	}
}

func TestNewApiVersionFailures(t *testing.T) {
	var tests = []struct {
		input         string
		expectedError string
	}{
		{"1-0", `Unable to parse version "1-0"`},
		{"1.0-beta", `Unable to parse version "1.0-beta": "0-beta" is not an integer`},
	}
	for _, tt := range tests {
		v, err := NewApiVersion(tt.input)
		if v != nil {
			t.Errorf("Expected <nil> version, got %v.", v)
		}
		if err.Error() != tt.expectedError {
			t.Errorf("NewApiVersion(%q): wrong error. Want %q. Got %q", tt.input, tt.expectedError, err.Error())
		}
	}
}

func TestApiVersions(t *testing.T) {
	var tests = []struct {
		a                              string
		b                              string
		expectedALessThanB             bool
		expectedALessThanOrEqualToB    bool
		expectedAGreaterThanB          bool
		expectedAGreaterThanOrEqualToB bool
	}{
		{"1.11", "1.11", false, true, false, true},
		{"1.10", "1.11", true, true, false, false},
		{"1.11", "1.10", false, false, true, true},

		{"1.9", "1.11", true, true, false, false},
		{"1.11", "1.9", false, false, true, true},

		{"1.1.1", "1.1", false, false, true, true},
		{"1.1", "1.1.1", true, true, false, false},

		{"2.1", "1.1.1", false, false, true, true},
		{"2.1", "1.3.1", false, false, true, true},
		{"1.1.1", "2.1", true, true, false, false},
		{"1.3.1", "2.1", true, true, false, false},
	}

	for _, tt := range tests {
		a, _ := NewApiVersion(tt.a)
		b, _ := NewApiVersion(tt.b)

		if tt.expectedALessThanB && !a.LessThan(b) {
			t.Errorf("Expected %#v < %#v", a, b)
		}
		if tt.expectedALessThanOrEqualToB && !a.LessThanOrEqualTo(b) {
			t.Errorf("Expected %#v <= %#v", a, b)
		}
		if tt.expectedAGreaterThanB && !a.GreaterThan(b) {
			t.Errorf("Expected %#v > %#v", a, b)
		}
		if tt.expectedAGreaterThanOrEqualToB && !a.GreaterThanOrEqualTo(b) {
			t.Errorf("Expected %#v >= %#v", a, b)
		}
	}
}

func TestPing(t *testing.T) {
	fakeRT := &FakeRoundTripper{message: "", status: http.StatusOK}
	client := newTestClient(fakeRT)
	err := client.Ping()
	if err != nil {
		t.Fatal(err)
	}
}

func TestPingFailing(t *testing.T) {
	fakeRT := &FakeRoundTripper{message: "", status: http.StatusInternalServerError}
	client := newTestClient(fakeRT)
	err := client.Ping()
	if err == nil {
		t.Fatal("Expected non nil error, got nil")
	}
	expectedErrMsg := "API error (500): "
	if err.Error() != expectedErrMsg {
		t.Fatalf("Expected error to be %q, got: %q", expectedErrMsg, err.Error())
	}
}

func TestPingFailingWrongStatus(t *testing.T) {
	fakeRT := &FakeRoundTripper{message: "", status: http.StatusAccepted}
	client := newTestClient(fakeRT)
	err := client.Ping()
	if err == nil {
		t.Fatal("Expected non nil error, got nil")
	}
	expectedErrMsg := "API error (202): "
	if err.Error() != expectedErrMsg {
		t.Fatalf("Expected error to be %q, got: %q", expectedErrMsg, err.Error())
	}
}

type FakeRoundTripper struct {
	message  string
	status   int
	header   map[string]string
	requests []*http.Request
}

func (rt *FakeRoundTripper) RoundTrip(r *http.Request) (*http.Response, error) {
	body := strings.NewReader(rt.message)
	rt.requests = append(rt.requests, r)
	res := &http.Response{
		StatusCode: rt.status,
		Body:       ioutil.NopCloser(body),
		Header:     make(http.Header),
	}
	for k, v := range rt.header {
		res.Header.Set(k, v)
	}
	return res, nil
}

func (rt *FakeRoundTripper) Reset() {
	rt.requests = nil
}

type person struct {
	Name string
	Age  int `json:"age"`
}

type dumb struct {
	T      int `qs:"-"`
	v      int
	W      float32
	X      int
	Y      float64
	Z      int     `qs:"zee"`
	Person *person `qs:"p"`
}

type fakeEndpointURL struct {
	Scheme string
}
<commit_msg>Fix test name typo<commit_after>// Copyright 2014 go-dockerclient authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package docker

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"reflect"
	"strconv"
	"strings"
	"testing"
)

func TestNewAPIClient(t *testing.T) {
	endpoint := "http://localhost:4243"
	client, err := NewClient(endpoint)
	if err != nil {
		t.Fatal(err)
	}
	if client.endpoint != endpoint {
		t.Errorf("Expected endpoint %s. Got %s.", endpoint, client.endpoint)
	}
	if client.HTTPClient != http.DefaultClient {
		t.Errorf("Expected http.Client %#v. Got %#v.", http.DefaultClient, client.HTTPClient)
	}
	// test unix socket endpoints
	endpoint = "unix:///var/run/docker.sock"
	client, err = NewClient(endpoint)
	if err != nil {
		t.Fatal(err)
	}
	if client.endpoint != endpoint {
		t.Errorf("Expected endpoint %s. Got %s.", endpoint, client.endpoint)
	}
	if !client.SkipServerVersionCheck {
		t.Error("Expected SkipServerVersionCheck to be true, got false")
	}
	if client.requestedApiVersion != nil {
		t.Errorf("Expected requestedApiVersion to be nil, got %#v.", client.requestedApiVersion)
	}
}

func newTLSClient(endpoint string) (*Client, error) {
	return NewTLSClient(endpoint,
		"testing/data/cert.pem",
		"testing/data/key.pem",
		"testing/data/ca.pem")
}

func TestNewTSLAPIClient(t *testing.T) {
	endpoint := "https://localhost:4243"
	client, err := newTLSClient(endpoint)
	if err != nil {
		t.Fatal(err)
	}
	if client.endpoint != endpoint {
		t.Errorf("Expected endpoint %s. Got %s.", endpoint, client.endpoint)
	}
	if !client.SkipServerVersionCheck {
		t.Error("Expected SkipServerVersionCheck to be true, got false")
	}
	if client.requestedApiVersion != nil {
		t.Errorf("Expected requestedApiVersion to be nil, got %#v.", client.requestedApiVersion)
	}
}

func TestNewVersionedClient(t *testing.T) {
	endpoint := "http://localhost:4243"
	client, err := NewVersionedClient(endpoint, "1.12")
	if err != nil {
		t.Fatal(err)
	}
	if client.endpoint != endpoint {
		t.Errorf("Expected endpoint %s. Got %s.", endpoint, client.endpoint)
	}
	if client.HTTPClient != http.DefaultClient {
		t.Errorf("Expected http.Client %#v. Got %#v.", http.DefaultClient, client.HTTPClient)
	}
	if reqVersion := client.requestedApiVersion.String(); reqVersion != "1.12" {
		t.Errorf("Wrong requestApiVersion. Want %q. Got %q.", "1.12", reqVersion)
	}
	if client.SkipServerVersionCheck {
		t.Error("Expected SkipServerVersionCheck to be false, got true")
	}
}

func TestNewTLSVersionedClient(t *testing.T) {
	certPath := "testing/data/cert.pem"
	keyPath := "testing/data/key.pem"
	caPath := "testing/data/ca.pem"
	endpoint := "https://localhost:4243"
	client, err := NewVersionnedTLSClient(endpoint, certPath, keyPath, caPath, "1.14")
	if err != nil {
		t.Fatal(err)
	}
	if client.endpoint != endpoint {
		t.Errorf("Expected endpoint %s. Got %s.", endpoint, client.endpoint)
	}
	if reqVersion := client.requestedApiVersion.String(); reqVersion != "1.14" {
		t.Errorf("Wrong requestApiVersion. Want %q. Got %q.", "1.14", reqVersion)
	}
	if client.SkipServerVersionCheck {
		t.Error("Expected SkipServerVersionCheck to be false, got true")
	}
}

func TestNewTLSVersionedClientInvalidCA(t *testing.T) {
	certPath := "testing/data/cert.pem"
	keyPath := "testing/data/key.pem"
	caPath := "testing/data/key.pem"
	endpoint := "https://localhost:4243"
	_, err := NewVersionnedTLSClient(endpoint, certPath, keyPath, caPath, "1.14")
	if err == nil {
		t.Errorf("Expected invalid ca at %s", caPath)
	}
}

func TestNewClientInvalidEndpoint(t *testing.T) {
	cases := []string{
		"htp://localhost:3243", "http://localhost:a", "localhost:8080",
		"", "localhost", "http://localhost:8080:8383", "http://localhost:65536",
		"https://localhost:-20",
	}
	for _, c := range cases {
		client, err := NewClient(c)
		if client != nil {
			t.Errorf("Want <nil> client for invalid endpoint, got %#v.", client)
		}
		if !reflect.DeepEqual(err, ErrInvalidEndpoint) {
			t.Errorf("NewClient(%q): Got invalid error for invalid endpoint. Want %#v. Got %#v.", c, ErrInvalidEndpoint, err)
		}
	}
}

func TestNewTLSClient2376(t *testing.T) {
	var tests = []struct {
		endpoint string
		expected string
	}{
		{"tcp://localhost:2376", "https"},
		{"tcp://localhost:2375", "http"},
		{"tcp://localhost:4000", "http"},
	}

	for _, tt := range tests {
		client, err := newTLSClient(tt.endpoint)
		if err != nil {
			t.Error(err)
		}
		got := client.endpointURL.Scheme
		if got != tt.expected {
			t.Errorf("endpointURL.Scheme: Got %s. Want %s.", got, tt.expected)
		}
	}
}

func TestGetURL(t *testing.T) {
	var tests = []struct {
		endpoint string
		path     string
		expected string
	}{
		{"http://localhost:4243/", "/", "http://localhost:4243/"},
		{"http://localhost:4243", "/", "http://localhost:4243/"},
		{"http://localhost:4243", "/containers/ps", "http://localhost:4243/containers/ps"},
		{"tcp://localhost:4243", "/containers/ps", "http://localhost:4243/containers/ps"},
		{"http://localhost:4243/////", "/", "http://localhost:4243/"},
		{"unix:///var/run/docker.socket", "/containers", "/containers"},
	}
	for _, tt := range tests {
		client, _ := NewClient(tt.endpoint)
		client.endpoint = tt.endpoint
		client.SkipServerVersionCheck = true
		got := client.getURL(tt.path)
		if got != tt.expected {
			t.Errorf("getURL(%q): Got %s. Want %s.", tt.path, got, tt.expected)
		}
	}
}

func TestError(t *testing.T) {
	err := newError(400, []byte("bad parameter"))
	expected := Error{Status: 400, Message: "bad parameter"}
	if !reflect.DeepEqual(expected, *err) {
		t.Errorf("Wrong error type. Want %#v. Got %#v.", expected, *err)
	}
	message := "API error (400): bad parameter"
	if err.Error() != message {
		t.Errorf("Wrong error message. Want %q. Got %q.", message, err.Error())
	}
}

func TestQueryString(t *testing.T) {
	v := float32(2.4)
	f32QueryString := fmt.Sprintf("w=%s&x=10&y=10.35", strconv.FormatFloat(float64(v), 'f', -1, 64))
	jsonPerson := url.QueryEscape(`{"Name":"gopher","age":4}`)
	var tests = []struct {
		input interface{}
		want  string
	}{
		{&ListContainersOptions{All: true}, "all=1"},
		{ListContainersOptions{All: true}, "all=1"},
		{ListContainersOptions{Before: "something"}, "before=something"},
		{ListContainersOptions{Before: "something", Since: "other"}, "before=something&since=other"},
		{dumb{X: 10, Y: 10.35000}, "x=10&y=10.35"},
		{dumb{W: v, X: 10, Y: 10.35000}, f32QueryString},
		{dumb{X: 10, Y: 10.35000, Z: 10}, "x=10&y=10.35&zee=10"},
		{dumb{v: 4, X: 10, Y: 10.35000}, "x=10&y=10.35"},
		{dumb{T: 10, Y: 10.35000}, "y=10.35"},
		{dumb{Person: &person{Name: "gopher", Age: 4}}, "p=" + jsonPerson},
		{nil, ""},
		{10, ""},
		{"not_a_struct", ""},
	}
	for _, tt := range tests {
		got := queryString(tt.input)
		if got != tt.want {
			t.Errorf("queryString(%v). Want %q. Got %q.", tt.input, tt.want, got)
		}
	}
}

func TestNewApiVersionFailures(t *testing.T) {
	var tests = []struct {
		input         string
		expectedError string
	}{
		{"1-0", `Unable to parse version "1-0"`},
		{"1.0-beta", `Unable to parse version "1.0-beta": "0-beta" is not an integer`},
	}
	for _, tt := range tests {
		v, err := NewApiVersion(tt.input)
		if v != nil {
			t.Errorf("Expected <nil> version, got %v.", v)
		}
		if err.Error() != tt.expectedError {
			t.Errorf("NewApiVersion(%q): wrong error. Want %q. Got %q", tt.input, tt.expectedError, err.Error())
		}
	}
}

func TestApiVersions(t *testing.T) {
	var tests = []struct {
		a                              string
		b                              string
		expectedALessThanB             bool
		expectedALessThanOrEqualToB    bool
		expectedAGreaterThanB          bool
		expectedAGreaterThanOrEqualToB bool
	}{
		{"1.11", "1.11", false, true, false, true},
		{"1.10", "1.11", true, true, false, false},
		{"1.11", "1.10", false, false, true, true},

		{"1.9", "1.11", true, true, false, false},
		{"1.11", "1.9", false, false, true, true},

		{"1.1.1", "1.1", false, false, true, true},
		{"1.1", "1.1.1", true, true, false, false},

		{"2.1", "1.1.1", false, false, true, true},
		{"2.1", "1.3.1", false, false, true, true},
		{"1.1.1", "2.1", true, true, false, false},
		{"1.3.1", "2.1", true, true, false, false},
	}

	for _, tt := range tests {
		a, _ := NewApiVersion(tt.a)
		b, _ := NewApiVersion(tt.b)

		if tt.expectedALessThanB && !a.LessThan(b) {
			t.Errorf("Expected %#v < %#v", a, b)
		}
		if tt.expectedALessThanOrEqualToB && !a.LessThanOrEqualTo(b) {
			t.Errorf("Expected %#v <= %#v", a, b)
		}
		if tt.expectedAGreaterThanB && !a.GreaterThan(b) {
			t.Errorf("Expected %#v > %#v", a, b)
		}
		if tt.expectedAGreaterThanOrEqualToB && !a.GreaterThanOrEqualTo(b) {
			t.Errorf("Expected %#v >= %#v", a, b)
		}
	}
}

func TestPing(t *testing.T) {
	fakeRT := &FakeRoundTripper{message: "", status: http.StatusOK}
	client := newTestClient(fakeRT)
	err := client.Ping()
	if err != nil {
		t.Fatal(err)
	}
}

func TestPingFailing(t *testing.T) {
	fakeRT := &FakeRoundTripper{message: "", status: http.StatusInternalServerError}
	client := newTestClient(fakeRT)
	err := client.Ping()
	if err == nil {
		t.Fatal("Expected non nil error, got nil")
	}
	expectedErrMsg := "API error (500): "
	if err.Error() != expectedErrMsg {
		t.Fatalf("Expected error to be %q, got: %q", expectedErrMsg, err.Error())
	}
}

func TestPingFailingWrongStatus(t *testing.T) {
	fakeRT := &FakeRoundTripper{message: "", status: http.StatusAccepted}
	client := newTestClient(fakeRT)
	err := client.Ping()
	if err == nil {
		t.Fatal("Expected non nil error, got nil")
	}
	expectedErrMsg := "API error (202): "
	if err.Error() != expectedErrMsg {
		t.Fatalf("Expected error to be %q, got: %q", expectedErrMsg, err.Error())
	}
}

type FakeRoundTripper struct {
	message  string
	status   int
	header   map[string]string
	requests []*http.Request
}

func (rt *FakeRoundTripper) RoundTrip(r *http.Request) (*http.Response, error) {
	body := strings.NewReader(rt.message)
	rt.requests = append(rt.requests, r)
	res := &http.Response{
		StatusCode: rt.status,
		Body:       ioutil.NopCloser(body),
		Header:     make(http.Header),
	}
	for k, v := range rt.header {
		res.Header.Set(k, v)
	}
	return res, nil
}

func (rt *FakeRoundTripper) Reset() {
	rt.requests = nil
}

type person struct {
	Name string
	Age  int `json:"age"`
}

type dumb struct {
	T      int `qs:"-"`
	v      int
	W      float32
	X      int
	Y      float64
	Z      int     `qs:"zee"`
	Person *person `qs:"p"`
}

type fakeEndpointURL struct {
	Scheme string
}
<|endoftext|>


<commit_before>package marionette_client

import (
	"fmt"
	"testing"
)

var client *Client

func init() {
	client = NewClient()
	client.Transport(&MarionetteTransport{})
}

func TestNewSession(t *testing.T) {
	err := client.Connect("", 0)
	if err != nil {
		t.Error(err)
	}

	r, err := client.NewSession("", nil)
	if err != nil {
		t.Error(err)
	}

	fmt.Println(r.Value)
	//client.Close()
}

// working
func TestGetSessionID(t *testing.T) {
	if client.SessionId != client.GetSessionID() {
		fmt.Println("SessionId differ...")
		t.FailNow()
	}

	fmt.Println("session is : ", client.SessionId)
}

func TestGetPage(t *testing.T) {
	r, err := client.Get("http://www.abola.pt/")
	if err != nil {
		fmt.Println(err)
		t.FailNow()
	}

	fmt.Println(r.Value)
}

//func TestConnectWithActiveConnection(t *testing.T) {
//	err := client.Connect("", 0)
//	if err == nil {
//		fmt.Println(err)
//	}
//
//	fmt.Println("No Error..")
//}

// working
func TestGetSessionCapabilities(t *testing.T) {
	r, err := client.GetSessionCapabilities()
	if err != nil {
		fmt.Println(err)
		t.FailNow()
	}

	fmt.Println(r.BrowserName)
}

func TestScreenshot(t *testing.T) {
	r, err := client.Screenshot()
	if err != nil {
		t.Log(err)
		t.FailNow()
	}

	println(r.MessageID)
	println(r.ResponseError)
	println(r.Size)
	//this print ise a problem for travis builds, since it can surpass the 4 MB of log size.
	// don't print the base64 encoded image.
	//println(r.Value)
}

// working
func TestLog(t *testing.T) {
	r, err := client.Log("message testing", "warning")
	if err != nil {
		fmt.Println(err)
		t.FailNow()
	}

	fmt.Println(r.Value)
}

// working
func TestGetLogs(t *testing.T) {
	r, err := client.GetLogs()
	if err != nil {
		fmt.Println(err)
		t.FailNow()
	}

	fmt.Println(r.Value)
}

func TestSetContext(t *testing.T) {
	r, err := client.SetContext(CONTEXT_CHROME)
	if err != nil {
		fmt.Println(err)
		t.FailNow()
	}

	fmt.Println(r.Value)

	r, err = client.SetContext(CONTEXT_CONTENT)
	if err != nil {
		fmt.Println(err)
		t.FailNow()
	}

	fmt.Println(r.Value)
}

func TestGetContext(t *testing.T) {
	r, err := client.GetContext()
	if err != nil {
		fmt.Println(err)
		t.FailNow()
	}

	fmt.Println(r.Value)
}

func TestSetScriptTimout(t *testing.T) {
	r, err := client.SetScriptTimeout(1000)
	if err != nil {
		fmt.Println(err)
		t.FailNow()
	}

	fmt.Println(r.Value)
}

func TestSetPageTimout(t *testing.T) {
	r, err := client.SetPageTimeout(1000)
	if err != nil {
		fmt.Println(err)
		t.FailNow()
	}

	fmt.Println(r.Value)
}

func TestSetSearchTimout(t *testing.T) {
	r, err := client.SetSearchTimeout(1000)
	if err != nil {
		fmt.Println(err)
		t.FailNow()
	}

	fmt.Println(r.Value)
}

func TestExecuteScript(t *testing.T) {
	script := "function testMyGoMarionetteClient() { alert('yes'); } testMyGoMarionetteClient();"
	args := []interface{}{}
	r, err := client.ExecuteScript(script, args, 1000, false)
	if err != nil {
		fmt.Println(err)
		t.FailNow()
	}

	fmt.Println(r.Value)

	client.DismissDialog()
}

func TestExecuteScriptWithArgs(t *testing.T) {
	script := "function testMyGoMarionetteClientArgs(a, b) { alert(a + b); }; testMyGoMarionetteClientArgs(arguments[0], arguments[1]);"
	args := []interface{}{1, 3}
	r, err := client.ExecuteScript(script, args, 1000, false)
	if err != nil {
		fmt.Println(err)
		t.FailNow()
	}

	fmt.Println(r.Value)

	client.DismissDialog()
}

func TestGetTitle(t *testing.T) {
	title, err := client.GetTitle()
	if err != nil {
		fmt.Println(err)
		t.FailNow()
	}

	fmt.Println(title)

}
func TestFindElement(t *testing.T) {
	element, err := client.FindElement("id", "clubes-hp", nil)
	if err != nil {
		fmt.Println(err)
		t.FailNow()
	}

	fmt.Println(element.Id())
	fmt.Println(element.IsEnabled())
	fmt.Println(element.IsSelected())
	fmt.Println(element.IsDisplayed())
	fmt.Println(element.TagName())
	fmt.Println(element.Text())
	fmt.Println(element.Attribute("id"))
	fmt.Println(element.CssValue("text-decoration"))
	fmt.Println(element.Rect())

	collection, err := element.FindElements("css selector", "li")
	if 18 != len(collection) {
		t.FailNow()
	}
}

func TestSendKeys(t *testing.T) {
	e, err := client.FindElement("id", "topo_txtPesquisa", nil)
	if err != nil {
		fmt.Println(err)
	}

	e.SendKeys("teste")
}

func TestFindElements(t *testing.T) {
	elements, err := client.FindElements("css selector", "li", nil)
	if err != nil {
		fmt.Println(err)
		t.FailNow()
	}

	fmt.Println(len(elements))
}

func TestCurrentWindowHandle(t *testing.T) {
	r, err := client.GetCurrentWindowHandle()
	if err != nil {
		fmt.Println(err)
		t.FailNow()
	}

	fmt.Println(r.Value)
}

func TestCurrentChromeWindowHandle(t *testing.T) {
	r, err := client.GetCurrentChromeWindowHandle()
	if err != nil {
		fmt.Println(err)
		t.FailNow()
	}

	fmt.Println(r.Value)
}

func TestWindowHandles(t *testing.T) {
	r, err := client.WindowHandles()
	if err != nil {
		fmt.Println(err)
		t.FailNow()
	}

	fmt.Println(r)
}

// working
//func TestQuitApplication(t *testing.T) {
//	r, err := client.QuitApplication()
//	if err != nil {
//		fmt.Println(err)
//		t.FailNow()
//	}
//
//	fmt.Println(r.ResponseError)
//}
<commit_msg>changes errors in response to DriverError struct<commit_after>package marionette_client

import (
	"fmt"
	"testing"
)

var client *Client

func init() {
	client = NewClient()
	client.Transport(&MarionetteTransport{})
}

func TestNewSession(t *testing.T) {
	err := client.Connect("", 0)
	if err != nil {
		t.Error(err)
	}

	r, err := client.NewSession("", nil)
	if err != nil {
		t.Error(err)
	}

	fmt.Println(r.Value)
	//client.Close()
}

// working
func TestGetSessionID(t *testing.T) {
	if client.SessionId != client.GetSessionID() {
		fmt.Println("SessionId differ...")
		t.FailNow()
	}

	fmt.Println("session is : ", client.SessionId)
}

func TestGetPage(t *testing.T) {
	r, err := client.Get("http://www.abola.pt/")
	if err != nil {
		fmt.Println(err)
		t.FailNow()
	}

	fmt.Println(r.Value)
}

//func TestConnectWithActiveConnection(t *testing.T) {
//	err := client.Connect("", 0)
//	if err == nil {
//		fmt.Println(err)
//	}
//
//	fmt.Println("No Error..")
//}

// working
func TestGetSessionCapabilities(t *testing.T) {
	r, err := client.GetSessionCapabilities()
	if err != nil {
		fmt.Println(err)
		t.FailNow()
	}

	fmt.Println(r.BrowserName)
}

func TestScreenshot(t *testing.T) {
	r, err := client.Screenshot()
	if err != nil {
		t.Log(err)
		t.FailNow()
	}

	println(r.MessageID)
	println(r.DriverError)
	println(r.Size)
	//this print ise a problem for travis builds, since it can surpass the 4 MB of log size.
	// don't print the base64 encoded image.
	//println(r.Value)
}

// working
func TestLog(t *testing.T) {
	r, err := client.Log("message testing", "warning")
	if err != nil {
		fmt.Println(err)
		t.FailNow()
	}

	fmt.Println(r.Value)
}

// working
func TestGetLogs(t *testing.T) {
	r, err := client.GetLogs()
	if err != nil {
		fmt.Println(err)
		t.FailNow()
	}

	fmt.Println(r.Value)
}

func TestSetContext(t *testing.T) {
	r, err := client.SetContext(CONTEXT_CHROME)
	if err != nil {
		fmt.Println(err)
		t.FailNow()
	}

	fmt.Println(r.Value)

	r, err = client.SetContext(CONTEXT_CONTENT)
	if err != nil {
		fmt.Println(err)
		t.FailNow()
	}

	fmt.Println(r.Value)
}

func TestGetContext(t *testing.T) {
	r, err := client.GetContext()
	if err != nil {
		fmt.Println(err)
		t.FailNow()
	}

	fmt.Println(r.Value)
}

func TestSetScriptTimout(t *testing.T) {
	r, err := client.SetScriptTimeout(1000)
	if err != nil {
		fmt.Println(err)
		t.FailNow()
	}

	fmt.Println(r.Value)
}

func TestSetPageTimout(t *testing.T) {
	r, err := client.SetPageTimeout(1000)
	if err != nil {
		fmt.Println(err)
		t.FailNow()
	}

	fmt.Println(r.Value)
}

func TestSetSearchTimout(t *testing.T) {
	r, err := client.SetSearchTimeout(1000)
	if err != nil {
		fmt.Println(err)
		t.FailNow()
	}

	fmt.Println(r.Value)
}

func TestExecuteScript(t *testing.T) {
	script := "function testMyGoMarionetteClient() { alert('yes'); } testMyGoMarionetteClient();"
	args := []interface{}{}
	r, err := client.ExecuteScript(script, args, 1000, false)
	if err != nil {
		fmt.Println(err)
		t.FailNow()
	}

	fmt.Println(r.Value)

	client.DismissDialog()
}

func TestExecuteScriptWithArgs(t *testing.T) {
	script := "function testMyGoMarionetteClientArgs(a, b) { alert(a + b); }; testMyGoMarionetteClientArgs(arguments[0], arguments[1]);"
	args := []interface{}{1, 3}
	r, err := client.ExecuteScript(script, args, 1000, false)
	if err != nil {
		fmt.Println(err)
		t.FailNow()
	}

	fmt.Println(r.Value)

	client.DismissDialog()
}

func TestGetTitle(t *testing.T) {
	title, err := client.GetTitle()
	if err != nil {
		fmt.Println(err)
		t.FailNow()
	}

	fmt.Println(title)

}
func TestFindElement(t *testing.T) {
	element, err := client.FindElement("id", "clubes-hp", nil)
	if err != nil {
		fmt.Println(err)
		t.FailNow()
	}

	fmt.Println(element.Id())
	fmt.Println(element.IsEnabled())
	fmt.Println(element.IsSelected())
	fmt.Println(element.IsDisplayed())
	fmt.Println(element.TagName())
	fmt.Println(element.Text())
	fmt.Println(element.Attribute("id"))
	fmt.Println(element.CssValue("text-decoration"))
	fmt.Println(element.Rect())

	collection, err := element.FindElements("css selector", "li")
	if 18 != len(collection) {
		t.FailNow()
	}
}

func TestSendKeys(t *testing.T) {
	e, err := client.FindElement("id", "topo_txtPesquisa", nil)
	if err != nil {
		fmt.Println(err)
	}

	e.SendKeys("teste")
}

func TestFindElements(t *testing.T) {
	elements, err := client.FindElements("css selector", "li", nil)
	if err != nil {
		fmt.Println(err)
		t.FailNow()
	}

	fmt.Println(len(elements))
}

func TestCurrentWindowHandle(t *testing.T) {
	r, err := client.GetCurrentWindowHandle()
	if err != nil {
		fmt.Println(err)
		t.FailNow()
	}

	fmt.Println(r.Value)
}

func TestCurrentChromeWindowHandle(t *testing.T) {
	r, err := client.GetCurrentChromeWindowHandle()
	if err != nil {
		fmt.Println(err)
		t.FailNow()
	}

	fmt.Println(r.Value)
}

func TestWindowHandles(t *testing.T) {
	r, err := client.WindowHandles()
	if err != nil {
		fmt.Println(err)
		t.FailNow()
	}

	fmt.Println(r)
}

// working
//func TestQuitApplication(t *testing.T) {
//	r, err := client.QuitApplication()
//	if err != nil {
//		fmt.Println(err)
//		t.FailNow()
//	}
//
//	fmt.Println(r.ResponseError)
//}
<|endoftext|>


<commit_before>package hawk

import (
	"testing"

	"strings"
	"time"
	"unicode/utf8"
	"fmt"
)

func TestClientHeader(t *testing.T) {
	c := &Client{
		Credential: &Credential{
			ID: "test-id",
			Key: "test-key",
			Alg: SHA256,
		},
		Option: &Option{
			TimeStamp: time.Now().Unix(),
			Nonce: "xyz123",
			Ext: "sample-ext-string",
		},
	}

	url := "https://example.com/test/hawk"
	act, err := c.Header(url, "GET")
	if err != nil {
		t.Error("got an error,", err.Error())
	}

	if !strings.Contains(act, "Authorization: Hawk") {
		t.Error("actual not contains 'Authorization: Hawk'")
	}
	if !strings.Contains(act, "id=") {
		t.Error("actual not contains 'id' attribute")
	}
	if !strings.Contains(act, "ts=") {
		t.Error("actual not contains 'ts' attribute")
	}
	if !strings.Contains(act, "nonce=") {
		t.Error("actual not contains 'nonce' attribute")
	}
	if !strings.Contains(act, "ext=") {
		t.Error("actual not contains 'ext=' attribute")
	}
}

func TestNonce(t *testing.T) {
	byteSize := 10
	act, err := Nonce(byteSize)
	if err != nil {
		t.Error("got an error," + err.Error())
	}

	if utf8.RuneCountInString(act) != byteSize * 2 {
		t.Error("expected length=10, but actual length=", utf8.RuneCountInString(act))
	}
}<commit_msg>Remove unused import<commit_after>package hawk

import (
	"testing"

	"strings"
	"time"
	"unicode/utf8"
)

func TestClientHeader(t *testing.T) {
	c := &Client{
		Credential: &Credential{
			ID: "test-id",
			Key: "test-key",
			Alg: SHA256,
		},
		Option: &Option{
			TimeStamp: time.Now().Unix(),
			Nonce: "xyz123",
			Ext: "sample-ext-string",
		},
	}

	url := "https://example.com/test/hawk"
	act, err := c.Header(url, "GET")
	if err != nil {
		t.Error("got an error,", err.Error())
	}

	if !strings.Contains(act, "Authorization: Hawk") {
		t.Error("actual not contains 'Authorization: Hawk'")
	}
	if !strings.Contains(act, "id=") {
		t.Error("actual not contains 'id' attribute")
	}
	if !strings.Contains(act, "ts=") {
		t.Error("actual not contains 'ts' attribute")
	}
	if !strings.Contains(act, "nonce=") {
		t.Error("actual not contains 'nonce' attribute")
	}
	if !strings.Contains(act, "ext=") {
		t.Error("actual not contains 'ext=' attribute")
	}
}

func TestNonce(t *testing.T) {
	byteSize := 10
	act, err := Nonce(byteSize)
	if err != nil {
		t.Error("got an error," + err.Error())
	}

	if utf8.RuneCountInString(act) != byteSize * 2 {
		t.Error("expected length=10, but actual length=", utf8.RuneCountInString(act))
	}
}<|endoftext|>


<commit_before>package main

import (
	"context"
	"fmt"

	"github.com/manifoldco/go-manifold"
	"github.com/urfave/cli"

	"github.com/manifoldco/manifold-cli/clients"
	"github.com/manifoldco/manifold-cli/config"
	"github.com/manifoldco/manifold-cli/errs"
	"github.com/manifoldco/manifold-cli/prompts"
	"github.com/manifoldco/manifold-cli/session"

	"github.com/manifoldco/manifold-cli/generated/billing/client/profile"
	bModels "github.com/manifoldco/manifold-cli/generated/billing/models"
)

func init() {
	billingCmd := cli.Command{
		Name:  "billing",
		Usage: "Manage your billing information",
		Subcommands: []cli.Command{
			{
				Name:   "add",
				Usage:  "Add a credit card",
				Action: addBillingProfile,
			},
			{
				Name:   "update",
				Usage:  "Change the credit card on file",
				Action: updateBillingProfile,
			},
		},
	}

	cmds = append(cmds, billingCmd)
}

func addBillingProfile(_ *cli.Context) error {
	ctx := context.Background()
	cfg, err := config.Load()
	if err != nil {
		return cli.NewExitError("Could not load config: "+err.Error(), -1)
	}

	userID, token, err := inputAndTokenize(ctx, cfg)
	if err != nil {
		return err
	}

	bClient, err := clients.NewBilling(cfg)
	if err != nil {
		return cli.NewExitError("Failed to create a Billing API client: "+
			err.Error(), -1)
	}

	p := profile.NewPostProfilesParamsWithContext(ctx)
	p.SetBody(&bModels.ProfileCreateRequest{
		Token:  token,
		UserID: userID,
	})

	_, err = bClient.Profile.PostProfiles(p, nil)
	if err != nil {
		return cli.NewExitError("Failed to add billing profile: "+err.Error(), -1)
	}

	fmt.Println("Your billing info has been saved.")
	return nil
}

func updateBillingProfile(_ *cli.Context) error {
	ctx := context.Background()
	cfg, err := config.Load()
	if err != nil {
		return cli.NewExitError("Could not load config: "+err.Error(), -1)
	}

	userID, token, err := inputAndTokenize(ctx, cfg)
	if err != nil {
		return err
	}

	bClient, err := clients.NewBilling(cfg)
	if err != nil {
		return cli.NewExitError("Failed to create a Billing API client: "+
			err.Error(), -1)
	}

	p := profile.NewPatchProfilesIDParamsWithContext(ctx)
	p.SetID(userID.String())
	p.SetBody(&bModels.ProfileUpdateRequest{
		Token: token,
	})

	_, err = bClient.Profile.PatchProfilesID(p, nil)
	if err != nil {
		return cli.NewExitError("Failed to update billing profile: "+err.Error(), -1)
	}

	fmt.Println("Your billing info has been saved.")
	return nil
}

func inputAndTokenize(ctx context.Context, cfg *config.Config) (*manifold.ID, *string, error) {
	s, err := session.Retrieve(ctx, cfg)
	if err != nil {
		return nil, nil, cli.NewExitError("Could not retrieve session: "+err.Error(), -1)
	}

	if !s.Authenticated() {
		return nil, nil, errs.ErrMustLogin
	}

	token, err := prompts.CreditCard()
	if err != nil {
		return nil, nil, cli.NewExitError("Failed to tokenize credit card: "+err.Error(), -1)
	}

	return &s.User().ID, &token.ID, nil
}
<commit_msg>Add team option to billing<commit_after>package main

import (
	"context"
	"fmt"

	"github.com/manifoldco/go-manifold"
	"github.com/urfave/cli"

	"github.com/manifoldco/manifold-cli/clients"
	"github.com/manifoldco/manifold-cli/config"
	"github.com/manifoldco/manifold-cli/errs"
	"github.com/manifoldco/manifold-cli/middleware"
	"github.com/manifoldco/manifold-cli/prompts"
	"github.com/manifoldco/manifold-cli/session"

	"github.com/manifoldco/manifold-cli/generated/billing/client/profile"
	bModels "github.com/manifoldco/manifold-cli/generated/billing/models"
)

func init() {
	billingCmd := cli.Command{
		Name:  "billing",
		Usage: "Manage your billing information",
		Subcommands: []cli.Command{
			{
				Name:  "add",
				Usage: "Add a credit card",
				Flags: teamFlags,
				Action: middleware.Chain(middleware.EnsureSession,
					middleware.LoadTeamPrefs, addBillingProfile),
			},
			{
				Name:  "update",
				Usage: "Change the credit card on file",
				Flags: teamFlags,
				Action: middleware.Chain(middleware.EnsureSession,
					middleware.LoadTeamPrefs, updateBillingProfile),
			},
		},
	}

	cmds = append(cmds, billingCmd)
}

func addBillingProfile(cliCtx *cli.Context) error {
	ctx := context.Background()
	cfg, err := config.Load()
	if err != nil {
		return cli.NewExitError("Could not load config: "+err.Error(), -1)
	}

	teamID, err := validateTeamID(cliCtx)
	if err != nil {
		return err
	}

	userID, token, err := inputAndTokenize(ctx, cfg)
	if err != nil {
		return err
	}

	bClient, err := clients.NewBilling(cfg)
	if err != nil {
		return cli.NewExitError("Failed to create a Billing API client: "+
			err.Error(), -1)
	}

	p := profile.NewPostProfilesParamsWithContext(ctx)

	if teamID.IsEmpty() {
		p.SetBody(&bModels.ProfileCreateRequest{
			Token:  token,
			UserID: userID,
		})
	} else {
		p.SetBody(&bModels.ProfileCreateRequest{
			Token:  token,
			TeamID: teamID,
		})
	}

	_, err = bClient.Profile.PostProfiles(p, nil)
	if err != nil {
		return cli.NewExitError("Failed to add billing profile: "+err.Error(), -1)
	}

	fmt.Println("Your billing info has been saved.")
	return nil
}

func updateBillingProfile(cliCtx *cli.Context) error {
	ctx := context.Background()
	cfg, err := config.Load()
	if err != nil {
		return cli.NewExitError("Could not load config: "+err.Error(), -1)
	}

	teamID, err := validateTeamID(cliCtx)
	if err != nil {
		return err
	}

	userID, token, err := inputAndTokenize(ctx, cfg)
	if err != nil {
		return err
	}

	bClient, err := clients.NewBilling(cfg)
	if err != nil {
		return cli.NewExitError("Failed to create a Billing API client: "+
			err.Error(), -1)
	}

	p := profile.NewPatchProfilesIDParamsWithContext(ctx)

	if teamID.IsEmpty() {
		p.SetID(userID.String())
	} else {
		p.SetID(teamID.String())
	}

	p.SetBody(&bModels.ProfileUpdateRequest{
		Token: token,
	})

	_, err = bClient.Profile.PatchProfilesID(p, nil)
	if err != nil {
		return cli.NewExitError("Failed to update billing profile: "+err.Error(), -1)
	}

	fmt.Println("Your billing info has been saved.")
	return nil
}

func inputAndTokenize(ctx context.Context, cfg *config.Config) (*manifold.ID, *string, error) {
	s, err := session.Retrieve(ctx, cfg)
	if err != nil {
		return nil, nil, cli.NewExitError("Could not retrieve session: "+err.Error(), -1)
	}

	if !s.Authenticated() {
		return nil, nil, errs.ErrMustLogin
	}

	token, err := prompts.CreditCard()
	if err != nil {
		return nil, nil, cli.NewExitError("Failed to tokenize credit card: "+err.Error(), -1)
	}

	return &s.User().ID, &token.ID, nil
}
<|endoftext|>


<commit_before>package cmd

import (
	"bufio"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"strings"

	"golang.org/x/net/context"

	docker "github.com/docker/engine-api/client"
	dtypes "github.com/docker/engine-api/types"
	"github.com/gocql/gocql"
)

type actionType int

// Docker action types
const (
	Build actionType = iota // Build is an image build
	Push                    // Push is a registry push
)

// RepoBuildData contains data about a GitHub repo necessary to do a Docker build
type RepoBuildData struct {
	DockerfilePath string
	Context        io.Reader
	Tags           []string //{name}:{tag}
}

// ImageBuilder is an object that builds and pushes images
type ImageBuilder struct {
	c  *docker.Client
	gf *GitHubFetcher
}

// NewImageBuilder returns a new ImageBuilder
func NewImageBuilder(ghtoken string) (*ImageBuilder, error) {
	ib := &ImageBuilder{}
	dc, err := docker.NewEnvClient()
	ib.gf = NewGitHubFetcher(ghtoken)
	if err != nil {
		return ib, err
	}
	ib.c = dc
	return ib, nil
}

// Returns full docker name:tag strings from the supplied repo/tags
func (ib *ImageBuilder) getFullImageNames(req *BuildRequest) []string {
	var bname string
	names := []string{}
	if req.Push.Registry.Repo != "" {
		bname = req.Push.Registry.Repo
	} else {
		bname = req.Build.GithubRepo
	}
	for _, t := range req.Build.Tags {
		names = append(names, fmt.Sprintf("%v:%v", bname, t))
	}
	return names
}

// Build builds an image accourding to the request
func (ib *ImageBuilder) Build(ctx context.Context, req *BuildRequest, id gocql.UUID) (string, error) {
	log.Printf("starting build %v", id.String())
	rl := strings.Split(req.Build.GithubRepo, "/")
	if len(rl) != 2 {
		return "", fmt.Errorf("malformed github repo: %v", req.Build.GithubRepo)
	}
	owner := rl[0]
	repo := rl[1]
	if isCancelled(ctx.Done()) {
		return "", fmt.Errorf("build was cancelled: %v", ctx.Err())
	}
	log.Printf("%v: fetching github repo: %v", id.String(), req.Build.GithubRepo)
	contents, err := ib.gf.Get(owner, repo, req.Build.Ref)
	if err != nil {
		return "", err
	}
	var dp string
	if req.Build.DockerfilePath == "" {
		dp = "Dockerfile"
	} else {
		dp = req.Build.DockerfilePath
	}
	rbi := &RepoBuildData{
		DockerfilePath: dp,
		Context:        contents,
		Tags:           ib.getFullImageNames(req),
	}
	return ib.dobuild(ctx, req, rbi)
}

func (ib *ImageBuilder) saveOutput(ctx context.Context, action actionType, events []dockerStreamEvent) error {
	if isCancelled(ctx.Done()) {
		return fmt.Errorf("build was cancelled: %v", ctx.Err())
	}
	output := []byte{}
	for _, e := range events {
		j, err := json.Marshal(&e)
		if err != nil {
			return fmt.Errorf("error marshaling dockerStreamEvent: %v", err)
		}
		j = append(j, byte('\n'))
		output = append(output, j...)
	}
	idstring := ctx.Value("id").(string)
	id, err := gocql.ParseUUID(idstring)
	if err != nil {
		return fmt.Errorf("malformed id: %v", err)
	}
	switch action {
	case Build:
		return setBuildImageBuildOutput(dbConfig.session, id, output)
	case Push:
		return setBuildPushOutput(dbConfig.session, id, output)
	default:
		return fmt.Errorf("unknown action: %v", action)
	}
}

const (
	buildSuccessEventPrefix = "Successfully built "
)

// doBuild executes the archive file GET and triggers the Docker build
func (ib *ImageBuilder) dobuild(ctx context.Context, req *BuildRequest, rbi *RepoBuildData) (string, error) {
	var imageid string
	if isCancelled(ctx.Done()) {
		return imageid, fmt.Errorf("build was cancelled: %v", ctx.Err())
	}
	opts := dtypes.ImageBuildOptions{
		Tags:        rbi.Tags,
		Remove:      true,
		ForceRemove: true,
		PullParent:  true,
		Dockerfile:  rbi.DockerfilePath,
	}
	ibr, err := ib.c.ImageBuild(ctx, rbi.Context, opts)
	if err != nil {
		return imageid, fmt.Errorf("error starting build: %v", err)
	}
	output, err := ib.monitorDockerAction(ctx, ibr.Body)
	err2 := ib.saveOutput(ctx, Build, output) // we want to save output even if error
	if err != nil {
		return imageid, err
	}
	if err2 != nil {
		return imageid, err2
	}
	// Parse final stream event to find image ID
	fe := output[len(output)-1]
	if strings.HasPrefix(fe.Stream, buildSuccessEventPrefix) {
		imageid = strings.TrimRight(fe.Stream[len(buildSuccessEventPrefix):len(fe.Stream)], "\n")
	} else {
		return imageid, fmt.Errorf("could not determine image id from final event: %v", fe.Stream)
	}
	log.Printf("built image ID %v", imageid)
	return imageid, nil
}

// Models for the JSON objects the Docker API returns
// This is a combination of all fields we may be interested in
// Each Docker API endpoint returns a different response schema :-\
type dockerStreamEvent struct {
	Stream         string                 `json:"stream"`
	Status         string                 `json:"status"`
	ProgressDetail map[string]interface{} `json:"progressDetail"`
	Progress       string                 `json:"progress"`
	ID             string                 `json:"id"`
	Aux            map[string]interface{} `json:"aux"`
	Error          string                 `json:"error"`
	ErrorDetail    dockerErrorDetail      `json:"errorDetail"`
}

type dockerErrorDetail struct {
	Code    int    `json:"code"`
	Message string `json:"message"`
}

// monitorDockerAction reads the Docker API response stream and detects any errors
func (ib *ImageBuilder) monitorDockerAction(ctx context.Context, rc io.ReadCloser) ([]dockerStreamEvent, error) {
	rdr := bufio.NewReader(rc)
	output := []dockerStreamEvent{}
	for {
		if isCancelled(ctx.Done()) {
			return output, fmt.Errorf("action was cancelled: %v", ctx.Err())
		}
		line, err := rdr.ReadBytes('\n')
		if err != nil {
			if err == io.EOF {
				return output, nil
			}
			return output, fmt.Errorf("error reading event stream: %v", err)
		}
		log.Printf("%v: %v", ctx.Value("id").(string), string(line))
		var event dockerStreamEvent
		err = json.Unmarshal(line, &event)
		if err != nil {
			return output, fmt.Errorf("error unmarshaling event: %v (event: %v)", err, string(line))
		}
		output = append(output, event)
	}
}

// CleanImage cleans up the built image after it's been pushed
func (ib *ImageBuilder) CleanImage(ctx context.Context, imageid string) error {
	if isCancelled(ctx.Done()) {
		return fmt.Errorf("clean was cancelled: %v", ctx.Err())
	}
	log.Printf("Cleaning up images for %v", ctx.Value("id").(string))
	opts := dtypes.ImageRemoveOptions{
		Force:         true,
		PruneChildren: true,
	}
	resp, err := ib.c.ImageRemove(ctx, imageid, opts)
	for _, r := range resp {
		log.Printf("ImageDelete: %v", r)
	}
	return err
}

// PushBuildToRegistry pushes the already built image and all associated tags to the
// configured remote Docker registry. Caller must ensure the image has already
// been built successfully
func (ib *ImageBuilder) PushBuildToRegistry(ctx context.Context, req *BuildRequest) error {
	if isCancelled(ctx.Done()) {
		return fmt.Errorf("push was cancelled: %v", ctx.Err())
	}
	log.Printf("doing push for %v", ctx.Value("id").(string))
	repo := req.Push.Registry.Repo
	if repo == "" {
		return fmt.Errorf("PushBuildToRegistry called but repo is empty")
	}
	rsl := strings.Split(repo, "/")
	var registry string
	switch len(rsl) {
	case 2: // Docker Hub
		registry = "https://index.docker.io/v2/"
	case 3: // private registry
		registry = rsl[0]
	default:
		return fmt.Errorf("cannot determine base registry URL from %v", repo)
	}
	var auth string
	if val, ok := dockerConfig.dockercfgContents[registry]; ok {
		j, err := json.Marshal(&val)
		if err != nil {
			return fmt.Errorf("error marshaling auth: %v", err)
		}
		auth = base64.StdEncoding.EncodeToString(j)
	} else {
		return fmt.Errorf("auth not found in dockercfg for %v", registry)
	}
	opts := dtypes.ImagePushOptions{
		All:          true,
		RegistryAuth: auth,
	}
	var output []dockerStreamEvent
	defer ib.saveOutput(ctx, Push, output) // we want to save output even if error
	for _, name := range ib.getFullImageNames(req) {
		if isCancelled(ctx.Done()) {
			return fmt.Errorf("push was cancelled: %v", ctx.Err())
		}
		ipr, err := ib.c.ImagePush(ctx, name, opts)
		if err != nil {
			return fmt.Errorf("error initiating registry push: %v", err)
		}
		o, err := ib.monitorDockerAction(ctx, ipr)
		output = append(output, o...)
		if err != nil {
			return err
		}
	}
	return nil
}

// PushBuildToS3 exports and uploads the already built image to the configured S3 bucket/key
func (ib *ImageBuilder) PushBuildToS3(ctx context.Context, req *BuildRequest) error {
	if isCancelled(ctx.Done()) {
		return fmt.Errorf("push was cancelled: %v", ctx.Err())
	}
	return fmt.Errorf("not yet implemented")
}
<commit_msg>fix push status output<commit_after>package cmd

import (
	"bufio"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"strings"

	"golang.org/x/net/context"

	docker "github.com/docker/engine-api/client"
	dtypes "github.com/docker/engine-api/types"
	"github.com/gocql/gocql"
)

type actionType int

// Docker action types
const (
	Build actionType = iota // Build is an image build
	Push                    // Push is a registry push
)

// RepoBuildData contains data about a GitHub repo necessary to do a Docker build
type RepoBuildData struct {
	DockerfilePath string
	Context        io.Reader
	Tags           []string //{name}:{tag}
}

// ImageBuilder is an object that builds and pushes images
type ImageBuilder struct {
	c  *docker.Client
	gf *GitHubFetcher
}

// NewImageBuilder returns a new ImageBuilder
func NewImageBuilder(ghtoken string) (*ImageBuilder, error) {
	ib := &ImageBuilder{}
	dc, err := docker.NewEnvClient()
	ib.gf = NewGitHubFetcher(ghtoken)
	if err != nil {
		return ib, err
	}
	ib.c = dc
	return ib, nil
}

// Returns full docker name:tag strings from the supplied repo/tags
func (ib *ImageBuilder) getFullImageNames(req *BuildRequest) []string {
	var bname string
	names := []string{}
	if req.Push.Registry.Repo != "" {
		bname = req.Push.Registry.Repo
	} else {
		bname = req.Build.GithubRepo
	}
	for _, t := range req.Build.Tags {
		names = append(names, fmt.Sprintf("%v:%v", bname, t))
	}
	return names
}

// Build builds an image accourding to the request
func (ib *ImageBuilder) Build(ctx context.Context, req *BuildRequest, id gocql.UUID) (string, error) {
	log.Printf("starting build %v", id.String())
	rl := strings.Split(req.Build.GithubRepo, "/")
	if len(rl) != 2 {
		return "", fmt.Errorf("malformed github repo: %v", req.Build.GithubRepo)
	}
	owner := rl[0]
	repo := rl[1]
	if isCancelled(ctx.Done()) {
		return "", fmt.Errorf("build was cancelled: %v", ctx.Err())
	}
	log.Printf("%v: fetching github repo: %v", id.String(), req.Build.GithubRepo)
	contents, err := ib.gf.Get(owner, repo, req.Build.Ref)
	if err != nil {
		return "", err
	}
	var dp string
	if req.Build.DockerfilePath == "" {
		dp = "Dockerfile"
	} else {
		dp = req.Build.DockerfilePath
	}
	rbi := &RepoBuildData{
		DockerfilePath: dp,
		Context:        contents,
		Tags:           ib.getFullImageNames(req),
	}
	return ib.dobuild(ctx, req, rbi)
}

func (ib *ImageBuilder) saveOutput(ctx context.Context, action actionType, events []dockerStreamEvent) error {
	if isCancelled(ctx.Done()) {
		return fmt.Errorf("build was cancelled: %v", ctx.Err())
	}
	output := []byte{}
	for _, e := range events {
		j, err := json.Marshal(&e)
		if err != nil {
			return fmt.Errorf("error marshaling dockerStreamEvent: %v", err)
		}
		j = append(j, byte('\n'))
		output = append(output, j...)
	}
	idstring := ctx.Value("id").(string)
	id, err := gocql.ParseUUID(idstring)
	if err != nil {
		return fmt.Errorf("malformed id: %v", err)
	}
	switch action {
	case Build:
		return setBuildImageBuildOutput(dbConfig.session, id, output)
	case Push:
		return setBuildPushOutput(dbConfig.session, id, output)
	default:
		return fmt.Errorf("unknown action: %v", action)
	}
}

const (
	buildSuccessEventPrefix = "Successfully built "
)

// doBuild executes the archive file GET and triggers the Docker build
func (ib *ImageBuilder) dobuild(ctx context.Context, req *BuildRequest, rbi *RepoBuildData) (string, error) {
	var imageid string
	if isCancelled(ctx.Done()) {
		return imageid, fmt.Errorf("build was cancelled: %v", ctx.Err())
	}
	opts := dtypes.ImageBuildOptions{
		Tags:        rbi.Tags,
		Remove:      true,
		ForceRemove: true,
		PullParent:  true,
		Dockerfile:  rbi.DockerfilePath,
		AuthConfigs: dockerConfig.dockercfgContents,
	}
	ibr, err := ib.c.ImageBuild(ctx, rbi.Context, opts)
	if err != nil {
		return imageid, fmt.Errorf("error starting build: %v", err)
	}
	output, err := ib.monitorDockerAction(ctx, ibr.Body)
	err2 := ib.saveOutput(ctx, Build, output) // we want to save output even if error
	if err != nil {
		return imageid, err
	}
	if err2 != nil {
		return imageid, err2
	}
	// Parse final stream event to find image ID
	fe := output[len(output)-1]
	if strings.HasPrefix(fe.Stream, buildSuccessEventPrefix) {
		imageid = strings.TrimRight(fe.Stream[len(buildSuccessEventPrefix):len(fe.Stream)], "\n")
	} else {
		return imageid, fmt.Errorf("could not determine image id from final event: %v", fe.Stream)
	}
	log.Printf("built image ID %v", imageid)
	return imageid, nil
}

// Models for the JSON objects the Docker API returns
// This is a combination of all fields we may be interested in
// Each Docker API endpoint returns a different response schema :-\
type dockerStreamEvent struct {
	Stream         string                 `json:"stream,omitempty"`
	Status         string                 `json:"status,omitempty"`
	ProgressDetail map[string]interface{} `json:"progressDetail,omitempty"`
	Progress       string                 `json:"progress,omitempty"`
	ID             string                 `json:"id,omitempty"`
	Aux            map[string]interface{} `json:"aux,omitempty"`
	Error          string                 `json:"error,omitempty"`
	ErrorDetail    dockerErrorDetail      `json:"errorDetail,omitempty"`
}

type dockerErrorDetail struct {
	Code    int    `json:"code"`
	Message string `json:"message"`
}

// monitorDockerAction reads the Docker API response stream and detects any errors
func (ib *ImageBuilder) monitorDockerAction(ctx context.Context, rc io.ReadCloser) ([]dockerStreamEvent, error) {
	rdr := bufio.NewReader(rc)
	output := []dockerStreamEvent{}
	for {
		if isCancelled(ctx.Done()) {
			return output, fmt.Errorf("action was cancelled: %v", ctx.Err())
		}
		line, err := rdr.ReadBytes('\n')
		if err != nil {
			if err == io.EOF {
				return output, nil
			}
			return output, fmt.Errorf("error reading event stream: %v", err)
		}
		log.Printf("%v: %v", ctx.Value("id").(string), string(line))
		var event dockerStreamEvent
		err = json.Unmarshal(line, &event)
		if err != nil {
			return output, fmt.Errorf("error unmarshaling event: %v (event: %v)", err, string(line))
		}
		output = append(output, event)
	}
}

// CleanImage cleans up the built image after it's been pushed
func (ib *ImageBuilder) CleanImage(ctx context.Context, imageid string) error {
	if isCancelled(ctx.Done()) {
		return fmt.Errorf("clean was cancelled: %v", ctx.Err())
	}
	log.Printf("Cleaning up images for %v", ctx.Value("id").(string))
	opts := dtypes.ImageRemoveOptions{
		Force:         true,
		PruneChildren: true,
	}
	resp, err := ib.c.ImageRemove(ctx, imageid, opts)
	for _, r := range resp {
		log.Printf("ImageDelete: %v", r)
	}
	return err
}

// PushBuildToRegistry pushes the already built image and all associated tags to the
// configured remote Docker registry. Caller must ensure the image has already
// been built successfully
func (ib *ImageBuilder) PushBuildToRegistry(ctx context.Context, req *BuildRequest) error {
	if isCancelled(ctx.Done()) {
		return fmt.Errorf("push was cancelled: %v", ctx.Err())
	}
	log.Printf("doing push for %v", ctx.Value("id").(string))
	repo := req.Push.Registry.Repo
	if repo == "" {
		return fmt.Errorf("PushBuildToRegistry called but repo is empty")
	}
	rsl := strings.Split(repo, "/")
	var registry string
	switch len(rsl) {
	case 2: // Docker Hub
		registry = "https://index.docker.io/v2/"
	case 3: // private registry
		registry = rsl[0]
	default:
		return fmt.Errorf("cannot determine base registry URL from %v", repo)
	}
	var auth string
	if val, ok := dockerConfig.dockercfgContents[registry]; ok {
		j, err := json.Marshal(&val)
		if err != nil {
			return fmt.Errorf("error marshaling auth: %v", err)
		}
		auth = base64.StdEncoding.EncodeToString(j)
	} else {
		return fmt.Errorf("auth not found in dockercfg for %v", registry)
	}
	opts := dtypes.ImagePushOptions{
		All:          true,
		RegistryAuth: auth,
	}
	var output []dockerStreamEvent
	for _, name := range ib.getFullImageNames(req) {
		if isCancelled(ctx.Done()) {
			return fmt.Errorf("push was cancelled: %v", ctx.Err())
		}
		ipr, err := ib.c.ImagePush(ctx, name, opts)
		if err != nil {
			return fmt.Errorf("error initiating registry push: %v", err)
		}
		o, err := ib.monitorDockerAction(ctx, ipr)
		output = append(output, o...)
		if err != nil {
			return err
		}
	}
	return ib.saveOutput(ctx, Push, output)
}

// PushBuildToS3 exports and uploads the already built image to the configured S3 bucket/key
func (ib *ImageBuilder) PushBuildToS3(ctx context.Context, req *BuildRequest) error {
	if isCancelled(ctx.Done()) {
		return fmt.Errorf("push was cancelled: %v", ctx.Err())
	}
	return fmt.Errorf("not yet implemented")
}
<|endoftext|>


<commit_before>/*
copyright 2019 google llc
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 cmd

import (
	"fmt"
	"github.com/spf13/cobra"
	"log"
	generators "shifter/generators"
	inputs "shifter/inputs"
)

var (
	inputType string
	input     string
	output    string
	kind      string
)

var convertCmd = &cobra.Command{
	Use:   "convert",
	Short: "Convert Openshift Resources to Kubernetes native formats",
	Long: `

   _____ __    _ ______
  / ___// /_  (_) __/ /____  _____
  \__ \/ __ \/ / /_/ __/ _ \/ ___/
 ___/ / / / / / __/ /_/  __/ /
/____/_/ /_/_/_/  \__/\___/_/

Convert OpenShift resources to kubernetes native formats

Usage: shifter convert -i ./input.yaml -o ./output_dir -k kind
Supply the input file with the -i or --input flag
Supply the output using the -o or --output flag, the directory will be created with the contents of the helm chart.`,
	Run: func(cmd *cobra.Command, args []string) {

		fmt.Println("Shifter - Convert")
		fmt.Println("Converting", inputType, input, "to", kind, output)

		switch inputType {
		case "template":
			t := inputs.Template(input)
			switch kind {
			case "helm":
				generators.Helm(output, t)
			}
		case "yaml":
			t := inputs.Yaml(input)
			switch kind {
			case "yaml":
				generators.Yaml(output, t)
			}
		case "cluster":
			log.Fatal("Openshift resources have not been implemented yet!")

		}
	},
}

func init() {
	rootCmd.AddCommand(convertCmd)
	convertCmd.Flags().StringVarP(&inputType, "type", "t", "", "The input type e.g. template, yaml or openshift")
	convertCmd.Flags().StringVarP(&input, "input", "i", "", "Path to the input file to convert, must be in Openshift format")
	convertCmd.Flags().StringVarP(&kind, "kind", "k", "helm", "Output kind options are either: yaml, helm or kpt")
	convertCmd.Flags().StringVarP(&output, "output", "o", "", "Relative path to the output directory for the results on the conversion")
	convertCmd.MarkFlagRequired("input")
	convertCmd.MarkFlagRequired("output")
}
<commit_msg>Adding cloudbuild (#6)<commit_after>/*
copyright 2019 google llc
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 cmd

import (
	"fmt"
	"github.com/spf13/cobra"
	"log"
	generators "shifter/generators"
	inputs "shifter/inputs"
)

var (
	inputType string
	input     string
	output    string
	kind      string
)

var convertCmd = &cobra.Command{
	Use:   "convert",
	Short: "Convert Openshift Resources to Kubernetes native formats",
	Long: `

   _____ __    _ ______
  / ___// /_  (_) __/ /____  _____
  \__ \/ __ \/ / /_/ __/ _ \/ ___/
 ___/ / / / / / __/ /_/  __/ /
/____/_/ /_/_/_/  \__/\___/_/

Convert OpenShift resources to kubernetes native formats

Usage: shifter convert -i ./input.yaml -o ./output_dir -k kind -t kind
Supply the input file or directory of files with the -i or --input flag
Supply the output using the -o or --output flag, the directory will be created with the contents of the helm chart.
`,
	Run: func(cmd *cobra.Command, args []string) {

		fmt.Println("Shifter - Convert")
		fmt.Println("Converting", inputType, input, "to", kind, output)

		switch inputType {
		case "template":
			t := inputs.Template(input)
			switch kind {
			case "helm":
				generators.Helm(output, t)
			}
		case "yaml":
			t := inputs.Yaml(input)
			switch kind {
			case "yaml":
				generators.Yaml(output, t)
			}
		case "cluster":
			log.Fatal("Openshift resources have not been implemented yet!")

		}
	},
}

func init() {
	rootCmd.AddCommand(convertCmd)
	convertCmd.Flags().StringVarP(&inputType, "type", "t", "yaml", "The input type e.g. template, yaml or openshift")
	convertCmd.Flags().StringVarP(&input, "input", "i", "", "Path to the input file or directory to convert, (contents must be in OpenShift format)")
	convertCmd.Flags().StringVarP(&kind, "kind", "k", "yaml", "Output kind options are either: yaml, helm or kpt")
	convertCmd.Flags().StringVarP(&output, "output", "o", "", "Relative path to the output directory for the results on the conversion")
	convertCmd.MarkFlagRequired("input")
	convertCmd.MarkFlagRequired("output")
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"os"

	"github.com/fiatjaf/jiq"
)

func main() {
	content := os.Stdin

	if os.Args[1] == "--help" {
		fmt.Print(`jiq - interactive commandline JSON processor
Usage: <json string> | jiq [options] [initial filter]

    jiq is a tool that allows you to play with jq filters interactively
    acting direcly on a JSON source of your choice, given through STDIN.
    For all the details about which filters you can use to transform your
    JSON string, see jq(1) manpage or https://stedolan.github.io/jq

    jiq supports all command line arguments jq supports, plus
     -q         will print the ending filter to STDOUT, instead of
                printing the resulting filtered JSON, the default.
     --help     prints this help message.
      `)
		os.Exit(0)
	}

	initialquery := "."
	outputquery := false
	jqargs := os.Args[1:]
	for i, arg := range os.Args[1:] {
		i = i + 1
		if arg == "-q" {
			outputquery = true
			jqargs = os.Args[1:i]
			jqargs = append(jqargs, os.Args[i+1:]...)
			break
		} else if arg[0] != '-' {
			log.Print(i, " ", arg)
			initialquery = arg
			jqargs = os.Args[1:i]
			jqargs = append(jqargs, os.Args[i+1:]...)
			break
		}
	}

	e := jiq.NewEngine(content, jqargs, initialquery)
	os.Exit(run(e, outputquery))
}

func run(e *jiq.Engine, outputquery bool) int {
	result := e.Run()
	if result.Err != nil {
		return 2
	}
	if outputquery {
		fmt.Printf("%s", result.Qs)
	} else {
		fmt.Printf("%s", result.Content)
	}
	return 0
}
<commit_msg>fix stupid os.Args length bug.<commit_after>package main

import (
	"fmt"
	"log"
	"os"

	"github.com/fiatjaf/jiq"
)

func main() {
	content := os.Stdin

	if len(os.Args) > 1 && os.Args[1] == "--help" {
		fmt.Print(`jiq - interactive commandline JSON processor
Usage: <json string> | jiq [options] [initial filter]

    jiq is a tool that allows you to play with jq filters interactively
    acting direcly on a JSON source of your choice, given through STDIN.
    For all the details about which filters you can use to transform your
    JSON string, see jq(1) manpage or https://stedolan.github.io/jq

    jiq supports all command line arguments jq supports, plus
     -q         will print the ending filter to STDOUT, instead of
                printing the resulting filtered JSON, the default.
     --help     prints this help message.
      `)
		os.Exit(0)
	}

	initialquery := "."
	outputquery := false
	jqargs := os.Args[1:]
	for i, arg := range os.Args[1:] {
		i = i + 1
		if arg == "-q" {
			outputquery = true
			jqargs = os.Args[1:i]
			jqargs = append(jqargs, os.Args[i+1:]...)
			break
		} else if arg[0] != '-' {
			log.Print(i, " ", arg)
			initialquery = arg
			jqargs = os.Args[1:i]
			jqargs = append(jqargs, os.Args[i+1:]...)
			break
		}
	}

	e := jiq.NewEngine(content, jqargs, initialquery)
	os.Exit(run(e, outputquery))
}

func run(e *jiq.Engine, outputquery bool) int {
	result := e.Run()
	if result.Err != nil {
		return 2
	}
	if outputquery {
		fmt.Printf("%s", result.Qs)
	} else {
		fmt.Printf("%s", result.Content)
	}
	return 0
}
<|endoftext|>


<commit_before>// Copyright © 2016 Kirill Danshin <k@guava.by>
//
// 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 cmd

import (
	"log"
	"os/exec"

	"github.com/spf13/cobra"
)

// releaseCmd represents the release command
var releaseCmd = &cobra.Command{
	Use:   "release",
	Short: "Adds all changes to git, commits it and pushes to origin/master",
	Run: func(cmd *cobra.Command, args []string) {
		if len(args) != 1 {
			log.Printf("args: %#+v\n", args)
			log.Println("Enter the release message")
		}
		if o, err := exec.Command("git", "add", ".").CombinedOutput(); err != nil {
			log.Printf("git add . error: %s", o)
		}
		if o, err := exec.Command("git", "commit", "-m", args[0]).CombinedOutput(); err != nil {
			log.Printf("git commit error: %s", o)
		}
		if o, err := exec.Command("git", "push", "origin", "master").CombinedOutput(); err != nil {
			log.Printf("git push origin master error: %s", o)
		}
	},
}

func init() {
	RootCmd.AddCommand(releaseCmd)
}
<commit_msg>add release status<commit_after>// Copyright © 2016 Kirill Danshin <k@guava.by>
//
// 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 cmd

import (
	"log"
	"os"
	"os/exec"

	"github.com/spf13/cobra"
)

// releaseCmd represents the release command
var releaseCmd = &cobra.Command{
	Use:   "release",
	Short: "Adds all changes to git, commits it and pushes to origin/master",
	Run: func(cmd *cobra.Command, args []string) {
		if len(args) != 1 {
			log.Printf("args: %#+v\n", args)
			log.Println("Enter the release message")
		}
		log.Println("Adding changes to git")
		if o, err := exec.Command("git", "add", ".").CombinedOutput(); err != nil {
			log.Printf("git add . error: %s", o)
			os.Exit(1)
		}
		log.Printf(`Commiting them with "%s" message`, args[0])
		if o, err := exec.Command("git", "commit", "-m", args[0]).CombinedOutput(); err != nil {
			log.Printf("git commit error: %s", o)
			os.Exit(1)
		}
		log.Println("Pushing it")
		if o, err := exec.Command("git", "push", "origin", "master").CombinedOutput(); err != nil {
			log.Printf("git push origin master error: %s", o)
			os.Exit(1)
		}
		log.Println("Done!")
	},
}

func init() {
	RootCmd.AddCommand(releaseCmd)
}
<|endoftext|>