<commit_before>package main

import (
	"os"
	"fmt"
	"log"
	"time"
	"strings"
	"strconv"
	"text/template"
	"github.com/hashicorp/terraform/helper/schema"
	"google.golang.org/api/appengine/v1beta4"
	"google.golang.org/api/storage/v1"
)

func resourceAppengine() *schema.Resource {
	return &schema.Resource{
		Create: resourceAppengineCreate,
		Read:   resourceAppengineRead,
		Delete: resourceAppengineDelete,

		Schema: map[string]*schema.Schema{
			"moduleName": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},

			"version": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},

			"gstorageBucket": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},

			"gstorageKey": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},

			"scaling": &schema.Schema{
				Type:     schema.TypeList,
				Optional: true,
				ForceNew: true,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"minIdleInstances": &schema.Schema{
							Type:     schema.TypeInt,
							Optional: true,
							Default:  "1",
						},

						"maxIdleInstances": &schema.Schema{
							Type:     schema.TypeInt,
							Optional: true,
							Default: "3",
						},

						"minPendingLatency": &schema.Schema{
							Type:     schema.TypeString,
							Optional: true,
							Default: "Automatic",
						},

						"maxPendingLatency": &schema.Schema{
							Type:     schema.TypeString,
							Optional: true,
							Default: "Automatic",
						},
					},
				},
			},
			"topicName": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"servingStatus": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},
		},
	}
}

var (
	remoteBase = "https://storage.googleapis.com/"
)

func urlHandlers() ([]*appengine.UrlMap) {
	handlers := make([]*appengine.UrlMap, 0)
		handlers = append(handlers, &appengine.UrlMap{
			SecurityLevel: "SECURE_OPTIONAL",
			Login: "LOGIN_OPTIONAL",
			UrlRegex:"/",
			Script:&appengine.ScriptHandler{
				ScriptPath:"unused",
			},
		})
		handlers = append(handlers, &appengine.UrlMap{
			SecurityLevel: "SECURE_OPTIONAL",
			Login: "LOGIN_OPTIONAL",
			UrlRegex:"/.*/",
			Script:&appengine.ScriptHandler{
				ScriptPath:"unused",
			},
		})
		handlers = append(handlers, &appengine.UrlMap{
			SecurityLevel: "SECURE_OPTIONAL",
			Login: "LOGIN_OPTIONAL",
			UrlRegex:"/_ah/.*",
			Script:&appengine.ScriptHandler{
				ScriptPath:"unused",
			},
		})
		handlers = append(handlers, &appengine.UrlMap{
			SecurityLevel: "SECURE_OPTIONAL",
			Login: "LOGIN_OPTIONAL",
			UrlRegex:"/endpoint",
			Script:&appengine.ScriptHandler{
				ScriptPath:"unused",
			},
		})

		return handlers
}

// known issues with this function:
//   assumes "/" is delimiter in gstorage and forces that to be last char in key
//   only searches first page, if more then 1k files to load, will only grab first 1k
func generateFileList(d *schema.ResourceData, config *Config) (map[string]appengine.FileInfo, error) {
	listService := storage.NewObjectsService(config.clientStorage)
	bucket := d.Get("gstorageBucket").(string)
	listCall := listService.List(bucket)
	key := d.Get("gstorageKey").(string)
	lastChar := key[len(key)-1:]
	if lastChar != "/" {
		key = key + "/"
	}
	listCall = listCall.Prefix(key)
	objs, err := listCall.Do()
	if err != nil {
		return nil, err
	}

	files := make(map[string]appengine.FileInfo)
	for _, obj := range objs.Items {
		onDiskName := strings.Replace(obj.Name, key, "", 1)  // trims key from file name
		inCloudURL := remoteBase + bucket + "/" + obj.Name
		files[onDiskName] = appengine.FileInfo{SourceUrl:inCloudURL}
	}

	return files, nil
}

func renderAppengineXML(d  *schema.ResourceData, config *Config) (error) {
	type AppengineXmlData struct {
		Project			string
		SourceVersion	string
		Module			string
		TopicName		string
	}

	axd := AppengineXmlData{
		Project: config.Project,
		SourceVersion: d.Get("version").(string),
		Module: d.Get("moduleName").(string),
		TopicName: d.Get("topicName").(string),
	}

	templ, err := template.New("appengine-web.xml.template").Parse(axdTemplate)
	if err != nil {
		return err
	}

	axdRendered, err := os.Create("appengine-web.xml")
	if err != nil {
		return err
	}
	defer axdRendered.Close()
	err = templ.Execute(axdRendered, axd)
	if err != nil {
		return err
	}

	return nil
}

func pushAppengineXmlToCloud(d *schema.ResourceData, config *Config) (error) {
	key := d.Get("gstorageKey").(string)
	lastChar := key[len(key)-1:]
	if lastChar != "/" {
		key = key + "/"
	}
	key = key + "WEB-INF/appengine-web.xml"
	object := &storage.Object{Name: key}
    file, err := os.Open("appengine-web.xml")
    if err != nil {
    	fmt.Errorf("Error opening %q: %v", "appengine.xml", err)
    }
	objectService := storage.NewObjectsService(config.clientStorage)
	_, err = objectService.Insert(d.Get("gstorageBucket").(string), object).Media(file).Do()
    if err != nil {
        fmt.Errorf("Objects.Insert failed: %v", err)
    }

	return nil
}

func renderAppengineXMLToCloud(d *schema.ResourceData, config *Config) (error) {
	err := renderAppengineXML(d, config)
	if err != nil {
		return err
	}

	err = pushAppengineXmlToCloud(d, config)
	if err != nil {
		return err
	}

	return nil
}

func validateLatency(latency string) (string, error) {
	lastChar := latency[len(latency)-1:]
	if lastChar != "s" {
		return "", fmt.Errorf("latency values must be between 1 and 15 seconds in the form: 3s")
	}
	latency_i, err := strconv.Atoi(latency[:len(latency)-1])
	if err != nil {
		return "", err
	}
	if latency_i < 1 || latency_i > 15 {
		return "", fmt.Errorf("latency values must be between 1 and 15 seconds in the form: 3s")
	}

	return latency, nil
}

func resourceAppengineCreate(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)

	scaling_raw := d.Get("scaling").([]interface{})
	if len(scaling_raw) > 1 {
		return fmt.Errorf("User supplied more then one scaling setting.  This is wrong")
	}

	scale := scaling_raw[0].(map[string]interface{})
	minPendingLatency, err := validateLatency(scale["minPendingLatency"].(string))
	if err != nil {
		return err
	}

	maxPendingLatency, err := validateLatency(scale["maxPendingLatency"].(string))
	if err != nil {
		return err
	}
	automaticScaling := &appengine.AutomaticScaling{
		MinIdleInstances: int64(scale["minIdleInstances"].(int)),
		MaxIdleInstances: int64(scale["maxIdleInstances"].(int)),
		MinPendingLatency: minPendingLatency,
		MaxPendingLatency: maxPendingLatency,
	}

	err = renderAppengineXMLToCloud(d, config)
	if err != nil {
		return err
	}

	files, err := generateFileList(d, config)
	if err != nil {
		return err
	}
	deployment := &appengine.Deployment{Files:files}

	handlers := urlHandlers()

	inbound_services := make([]string, 1)
	inbound_services[0] = "INBOUND_SERVICE_WARMUP"

	//  Version object for this module
	version := &appengine.Version{
		AutomaticScaling: automaticScaling,
		Deployment:deployment,
		Handlers: handlers,
		Id: d.Get("version").(string),
		Runtime: "java7",
		//InstanceClass: "F2",  this is exploding.  not sure why
		InboundServices: inbound_services,
		Threadsafe: true,
	}

	//  create the application
	moduleVersionService := appengine.NewAppsModulesVersionsService(config.clientAppengine)
	createCall := moduleVersionService.Create(config.Project, d.Get("moduleName").(string), version)
	operation, err := createCall.Do()
	if err != nil {
		return err
	}

	err = operationWait(operation, config)
	if err != nil {
		return err
	}

	return resourceAppengineRead(d, meta)
}

func operationWait(operation *appengine.Operation, config *Config) (error) {
	//  wait for the creation to complete
	operationService := appengine.NewAppsOperationsService(config.clientAppengine)
	operationGet := operationService.Get(config.Project, strings.Replace(operation.Name, "apps/"+config.Project+"/operations/", "", 1))
	carryon := true
	for carryon {
		operation, err := operationGet.Do()
		if err != nil {
			return err
		}
		carryon = !operation.Done
		time.Sleep(10*time.Second)
	}

	//   if it failed, explode
	if operation.Error != nil {
		log.Printf("[DEBUG] status list from bad operation: %q", operation.Error.Details)
		return fmt.Errorf(operation.Error.Message)
	}

	return nil
}

func resourceAppengineRead(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)

	moduleVersionService := appengine.NewAppsModulesVersionsService(config.clientAppengine)
	getCall := moduleVersionService.Get(config.Project, d.Get("moduleName").(string), d.Get("version").(string))
	version, err := getCall.Do()
	if err != nil {
		return err
	}

	d.SetId(version.Name)
	d.Set("servingStatus", version.ServingStatus)
	return nil
}

func resourceAppengineDelete(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)

	moduleVersionService := appengine.NewAppsModulesVersionsService(config.clientAppengine)
	deleteCall := moduleVersionService.Delete(config.Project, d.Get("moduleName").(string), d.Get("version").(string))
	operation, err := deleteCall.Do()
	if err != nil {
		if strings.Contains(err.Error(), "Cannot delete the final version of a service (module)") {
			moduleService := appengine.NewAppsModulesService(config.clientAppengine)
			moduleDelete := moduleService.Delete(config.Project, d.Get("moduleName").(string))
			operation, err = moduleDelete.Do()
			if err != nil {
				return err
			}

			err = operationWait(operation, config)
			if err != nil {
				return err
			}
		} else {
			return err
		}
	} else {
		err = operationWait(operation, config)
		if err != nil {
			return err
		}
	}

	d.SetId("")
	return nil
}
<commit_msg>add env variables to appengine deploy<commit_after>package main

import (
	"os"
	"fmt"
	"log"
	"time"
	"strings"
	"strconv"
	"text/template"
	"github.com/hashicorp/terraform/helper/schema"
	"google.golang.org/api/appengine/v1beta4"
	"google.golang.org/api/storage/v1"
)

func resourceAppengine() *schema.Resource {
	return &schema.Resource{
		Create: resourceAppengineCreate,
		Read:   resourceAppengineRead,
		Delete: resourceAppengineDelete,

		Schema: map[string]*schema.Schema{
			"moduleName": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},

			"version": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},

			"gstorageBucket": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},

			"gstorageKey": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},

			"scaling": &schema.Schema{
				Type:     schema.TypeList,
				Optional: true,
				ForceNew: true,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"minIdleInstances": &schema.Schema{
							Type:     schema.TypeInt,
							Optional: true,
							Default:  "1",
						},

						"maxIdleInstances": &schema.Schema{
							Type:     schema.TypeInt,
							Optional: true,
							Default: "3",
						},

						"minPendingLatency": &schema.Schema{
							Type:     schema.TypeString,
							Optional: true,
							Default: "Automatic",
						},

						"maxPendingLatency": &schema.Schema{
							Type:     schema.TypeString,
							Optional: true,
							Default: "Automatic",
						},
					},
				},
			},
			"topicName": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"servingStatus": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},
		},
	}
}

var (
	remoteBase = "https://storage.googleapis.com/"
)

func urlHandlers() ([]*appengine.UrlMap) {
	handlers := make([]*appengine.UrlMap, 0)
		handlers = append(handlers, &appengine.UrlMap{
			SecurityLevel: "SECURE_OPTIONAL",
			Login: "LOGIN_OPTIONAL",
			UrlRegex:"/",
			Script:&appengine.ScriptHandler{
				ScriptPath:"unused",
			},
		})
		handlers = append(handlers, &appengine.UrlMap{
			SecurityLevel: "SECURE_OPTIONAL",
			Login: "LOGIN_OPTIONAL",
			UrlRegex:"/.*/",
			Script:&appengine.ScriptHandler{
				ScriptPath:"unused",
			},
		})
		handlers = append(handlers, &appengine.UrlMap{
			SecurityLevel: "SECURE_OPTIONAL",
			Login: "LOGIN_OPTIONAL",
			UrlRegex:"/_ah/.*",
			Script:&appengine.ScriptHandler{
				ScriptPath:"unused",
			},
		})
		handlers = append(handlers, &appengine.UrlMap{
			SecurityLevel: "SECURE_OPTIONAL",
			Login: "LOGIN_OPTIONAL",
			UrlRegex:"/endpoint",
			Script:&appengine.ScriptHandler{
				ScriptPath:"unused",
			},
		})

		return handlers
}

// known issues with this function:
//   assumes "/" is delimiter in gstorage and forces that to be last char in key
//   only searches first page, if more then 1k files to load, will only grab first 1k
func generateFileList(d *schema.ResourceData, config *Config) (map[string]appengine.FileInfo, error) {
	listService := storage.NewObjectsService(config.clientStorage)
	bucket := d.Get("gstorageBucket").(string)
	listCall := listService.List(bucket)
	key := d.Get("gstorageKey").(string)
	lastChar := key[len(key)-1:]
	if lastChar != "/" {
		key = key + "/"
	}
	listCall = listCall.Prefix(key)
	objs, err := listCall.Do()
	if err != nil {
		return nil, err
	}

	files := make(map[string]appengine.FileInfo)
	for _, obj := range objs.Items {
		onDiskName := strings.Replace(obj.Name, key, "", 1)  // trims key from file name
		inCloudURL := remoteBase + bucket + "/" + obj.Name
		files[onDiskName] = appengine.FileInfo{SourceUrl:inCloudURL}
	}

	return files, nil
}

func renderAppengineXML(d  *schema.ResourceData, config *Config) (error) {
	type AppengineXmlData struct {
		Project			string
		SourceVersion	string
		Module			string
		TopicName		string
	}

	axd := AppengineXmlData{
		Project: config.Project,
		SourceVersion: d.Get("version").(string),
		Module: d.Get("moduleName").(string),
		TopicName: d.Get("topicName").(string),
	}

	templ, err := template.New("appengine-web.xml.template").Parse(axdTemplate)
	if err != nil {
		return err
	}

	axdRendered, err := os.Create("appengine-web.xml")
	if err != nil {
		return err
	}
	defer axdRendered.Close()
	err = templ.Execute(axdRendered, axd)
	if err != nil {
		return err
	}

	return nil
}

func pushAppengineXmlToCloud(d *schema.ResourceData, config *Config) (error) {
	key := d.Get("gstorageKey").(string)
	lastChar := key[len(key)-1:]
	if lastChar != "/" {
		key = key + "/"
	}
	key = key + "WEB-INF/appengine-web.xml"
	object := &storage.Object{Name: key}
    file, err := os.Open("appengine-web.xml")
    if err != nil {
    	fmt.Errorf("Error opening %q: %v", "appengine.xml", err)
    }
	objectService := storage.NewObjectsService(config.clientStorage)
	_, err = objectService.Insert(d.Get("gstorageBucket").(string), object).Media(file).Do()
    if err != nil {
        fmt.Errorf("Objects.Insert failed: %v", err)
    }

	return nil
}

func renderAppengineXMLToCloud(d *schema.ResourceData, config *Config) (error) {
	err := renderAppengineXML(d, config)
	if err != nil {
		return err
	}

	err = pushAppengineXmlToCloud(d, config)
	if err != nil {
		return err
	}

	return nil
}

func validateLatency(latency string) (string, error) {
	lastChar := latency[len(latency)-1:]
	if lastChar != "s" {
		return "", fmt.Errorf("latency values must be between 1 and 15 seconds in the form: 3s")
	}
	latency_i, err := strconv.Atoi(latency[:len(latency)-1])
	if err != nil {
		return "", err
	}
	if latency_i < 1 || latency_i > 15 {
		return "", fmt.Errorf("latency values must be between 1 and 15 seconds in the form: 3s")
	}

	return latency, nil
}

func resourceAppengineCreate(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)

	scaling_raw := d.Get("scaling").([]interface{})
	if len(scaling_raw) > 1 {
		return fmt.Errorf("User supplied more then one scaling setting.  This is wrong")
	}

	scale := scaling_raw[0].(map[string]interface{})
	minPendingLatency, err := validateLatency(scale["minPendingLatency"].(string))
	if err != nil {
		return err
	}

	maxPendingLatency, err := validateLatency(scale["maxPendingLatency"].(string))
	if err != nil {
		return err
	}
	automaticScaling := &appengine.AutomaticScaling{
		MinIdleInstances: int64(scale["minIdleInstances"].(int)),
		MaxIdleInstances: int64(scale["maxIdleInstances"].(int)),
		MinPendingLatency: minPendingLatency,
		MaxPendingLatency: maxPendingLatency,
	}

	err = renderAppengineXMLToCloud(d, config)
	if err != nil {
		return err
	}

	files, err := generateFileList(d, config)
	if err != nil {
		return err
	}
	deployment := &appengine.Deployment{Files:files}

	handlers := urlHandlers()

	inbound_services := make([]string, 1)
	inbound_services[0] = "INBOUND_SERVICE_WARMUP"

	env_vars := make(map[string]string,2)
	env_vars["OUTPUTPUBSUB"] = d.Get("topicName").(string)
	env_vars["RETURNMESSAGEIDS"] = "true"

	//  Version object for this module
	version := &appengine.Version{
		AutomaticScaling: automaticScaling,
		Deployment:deployment,
		Handlers: handlers,
		Id: d.Get("version").(string),
		Runtime: "java7",
		//InstanceClass: "F2",  this is exploding.  not sure why
		InboundServices: inbound_services,
		EnvVariables: env_vars,
		Threadsafe: true,
	}

	//  create the application
	moduleVersionService := appengine.NewAppsModulesVersionsService(config.clientAppengine)
	createCall := moduleVersionService.Create(config.Project, d.Get("moduleName").(string), version)
	operation, err := createCall.Do()
	if err != nil {
		return err
	}

	err = operationWait(operation, config)
	if err != nil {
		return err
	}

	return resourceAppengineRead(d, meta)
}

func operationWait(operation *appengine.Operation, config *Config) (error) {
	//  wait for the creation to complete
	operationService := appengine.NewAppsOperationsService(config.clientAppengine)
	operationGet := operationService.Get(config.Project, strings.Replace(operation.Name, "apps/"+config.Project+"/operations/", "", 1))
	carryon := true
	for carryon {
		operation, err := operationGet.Do()
		if err != nil {
			return err
		}
		carryon = !operation.Done
		time.Sleep(10*time.Second)
	}

	//   if it failed, explode
	if operation.Error != nil {
		log.Printf("[DEBUG] status list from bad operation: %q", operation.Error.Details)
		return fmt.Errorf(operation.Error.Message)
	}

	return nil
}

func resourceAppengineRead(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)

	moduleVersionService := appengine.NewAppsModulesVersionsService(config.clientAppengine)
	getCall := moduleVersionService.Get(config.Project, d.Get("moduleName").(string), d.Get("version").(string))
	version, err := getCall.Do()
	if err != nil {
		return err
	}

	d.SetId(version.Name)
	d.Set("servingStatus", version.ServingStatus)
	return nil
}

func resourceAppengineDelete(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)

	moduleVersionService := appengine.NewAppsModulesVersionsService(config.clientAppengine)
	deleteCall := moduleVersionService.Delete(config.Project, d.Get("moduleName").(string), d.Get("version").(string))
	operation, err := deleteCall.Do()
	if err != nil {
		if strings.Contains(err.Error(), "Cannot delete the final version of a service (module)") {
			moduleService := appengine.NewAppsModulesService(config.clientAppengine)
			moduleDelete := moduleService.Delete(config.Project, d.Get("moduleName").(string))
			operation, err = moduleDelete.Do()
			if err != nil {
				return err
			}

			err = operationWait(operation, config)
			if err != nil {
				return err
			}
		} else {
			return err
		}
	} else {
		err = operationWait(operation, config)
		if err != nil {
			return err
		}
	}

	d.SetId("")
	return nil
}
<|endoftext|>


<commit_before>package web_test

import (
	"fmt"
	"time"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	// . "github.com/sclevine/agouti/matchers"

	"github.com/concourse/atc"
)

var _ = Describe("Viewing resources", func() {
	Describe("a broken resource", func() {
		var brokenResource atc.Resource

		BeforeEach(func() {
			_, _, _, err := team.CreateOrUpdatePipelineConfig(pipelineName, "0", atc.Config{
				Resources: []atc.ResourceConfig{
					{
						Name: "broken-resource",
						Type: "git",
						Source: atc.Source{
							"branch": "master",
							"uri":    "i r not reall?",
						},
						CheckEvery: "",
					},
				},
			})
			Expect(err).NotTo(HaveOccurred())

			_, err = team.UnpausePipeline(pipelineName)
			Expect(err).NotTo(HaveOccurred())

			var found bool
			brokenResource, found, err = team.Resource(pipelineName, "broken-resource")
			Expect(found).To(BeTrue())
			Expect(err).NotTo(HaveOccurred())
		})

		It("correctly displays logs", func() {
			url := atcRoute(fmt.Sprintf("/teams/%s/pipelines/%s/resources/%s", teamName, pipelineName, brokenResource.Name))

			counter := 0
			for {
				Expect(page.Navigate(url)).To(Succeed())
				if counter == 120 {
					Fail("Unable to locate resource log information.")
				}

				if visible, _ := page.Find(".resource-check-status .header i.errored").Visible(); visible {
					break
				}
				counter++
				time.Sleep(500 * time.Millisecond)
			}

			Eventually(page.Find("pre").Text).Should(ContainSubstring("failed: exit status"))
		})
	})
})
<commit_msg>fix invalid config<commit_after>package web_test

import (
	"fmt"
	"time"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	// . "github.com/sclevine/agouti/matchers"

	"github.com/concourse/atc"
)

var _ = Describe("Viewing resources", func() {
	Describe("a broken resource", func() {
		var brokenResource atc.Resource

		BeforeEach(func() {
			_, _, _, err := team.CreateOrUpdatePipelineConfig(pipelineName, "0", atc.Config{
				Resources: []atc.ResourceConfig{
					{
						Name: "broken-resource",
						Type: "git",
						Source: atc.Source{
							"branch": "master",
							"uri":    "i r not reall?",
						},
						CheckEvery: "",
					},
				},
				Jobs: atc.JobConfigs{
					{
						Name: "broken-resource-user",
						Plan: atc.PlanSequence{
							{Get: "broken-resource"},
						},
					},
				},
			})
			Expect(err).NotTo(HaveOccurred())

			_, err = team.UnpausePipeline(pipelineName)
			Expect(err).NotTo(HaveOccurred())

			var found bool
			brokenResource, found, err = team.Resource(pipelineName, "broken-resource")
			Expect(found).To(BeTrue())
			Expect(err).NotTo(HaveOccurred())
		})

		It("correctly displays logs", func() {
			url := atcRoute(fmt.Sprintf("/teams/%s/pipelines/%s/resources/%s", teamName, pipelineName, brokenResource.Name))

			counter := 0
			for {
				Expect(page.Navigate(url)).To(Succeed())
				if counter == 120 {
					Fail("Unable to locate resource log information.")
				}

				if visible, _ := page.Find(".resource-check-status .header i.errored").Visible(); visible {
					break
				}
				counter++
				time.Sleep(500 * time.Millisecond)
			}

			Eventually(page.Find("pre").Text).Should(ContainSubstring("failed: exit status"))
		})
	})
})
<|endoftext|>


<commit_before><commit_msg>more Commuting Engineer<commit_after><|endoftext|>


<commit_before>package scanner

import (
	"fmt"
)

func compare(left *FileSystem, right *FileSystem, verbose bool) bool {
	if len(left.InodeTable) != len(right.InodeTable) {
		fmt.Printf("left vs. right: %d vs %d inodes\n",
			len(left.InodeTable), len(right.InodeTable))
		return false
	}
	return true
}
<commit_msg>Add embryonic scanner.compareDirectories() function.<commit_after>package scanner

import (
	"fmt"
)

func compare(left *FileSystem, right *FileSystem, verbose bool) bool {
	if len(left.InodeTable) != len(right.InodeTable) {
		fmt.Printf("left vs. right: %d vs. %d inodes\n",
			len(left.InodeTable), len(right.InodeTable))
		return false
	}
	return compareDirectories(&left.Directory, &right.Directory, verbose)
}

func compareDirectories(left *Directory, right *Directory, verbose bool) bool {
	if left.name != right.name {
		fmt.Printf("left vs. right: %s vs. %s\n", left.name, right.name)
		return false
	}
	if len(left.FileList) != len(right.FileList) {
		fmt.Printf("left vs. right: %d vs. %d files\n",
			len(left.FileList), len(right.FileList))
		return false
	}
	if len(left.DirectoryList) != len(right.DirectoryList) {
		fmt.Printf("left vs. right: %d vs. %d subdirs\n",
			len(left.DirectoryList), len(right.DirectoryList))
		return false
	}
	return true
}
<|endoftext|>


<commit_before>// Copyright 2019 Istio 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 mesh

import (
	"flag"

	"github.com/spf13/cobra"

	binversion "istio.io/istio/operator/version"
	"istio.io/pkg/log"
	"istio.io/pkg/version"
)

const (
	setFlagHelpStr = `Override an IstioOperator value, e.g. to choose a profile
(--set profile=demo), enable or disable components (--set components.policy.enabled=true), or override Istio
settings (--set values.grafana.enabled=true). See documentation for more info:
https://istio.io/docs/reference/config/istio.operator.v1alpha1/#IstioOperatorSpec`
	// ChartsFlagHelpStr is the command line description for --charts
	ChartsFlagHelpStr = `Specify a path to a directory of charts and profiles
(e.g. ~/Downloads/istio-1.6.0/install/kubernetes/operator)
or release tar URL (e.g. https://github.com/istio/istio/releases/download/1.6.0/istio-1.6.0-linux-amd64.tar.gz).
`
	revisionFlagHelpStr         = `Target control plane revision for the command.`
	skipConfirmationFlagHelpStr = `skipConfirmation determines whether the user is prompted for confirmation.
If set to true, the user is not prompted and a Yes response is assumed in all cases.`
	filenameFlagHelpStr = `Path to file containing IstioOperator custom resource
This flag can be specified multiple times to overlay multiple files. Multiple files are overlaid in left to right order.`
	installationCompleteStr = `Installation complete`
)

type rootArgs struct {
	// Dry run performs all steps except actually applying the manifests or creating output dirs/files.
	dryRun bool
}

func addFlags(cmd *cobra.Command, rootArgs *rootArgs) {
	cmd.PersistentFlags().BoolVarP(&rootArgs.dryRun, "dry-run", "",
		false, "Console/log output only, make no changes.")
}

// GetRootCmd returns the root of the cobra command-tree.
func GetRootCmd(args []string) *cobra.Command {
	rootCmd := &cobra.Command{
		Use:          "mesh",
		Short:        "Command line Istio install utility.",
		SilenceUsage: true,
		Long: "This command uses the Istio operator code to generate templates, query configurations and perform " +
			"utility operations.",
	}
	rootCmd.SetArgs(args)
	rootCmd.PersistentFlags().AddGoFlagSet(flag.CommandLine)

	rootCmd.AddCommand(ManifestCmd(log.DefaultOptions()))
	rootCmd.AddCommand(ProfileCmd())
	rootCmd.AddCommand(OperatorCmd())
	rootCmd.AddCommand(version.CobraCommand())
	rootCmd.AddCommand(UpgradeCmd())

	version.Info.Version = binversion.OperatorVersionString

	return rootCmd
}
<commit_msg>Update path of charts and profile (#24202)<commit_after>// Copyright 2019 Istio 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 mesh

import (
	"flag"

	"github.com/spf13/cobra"

	binversion "istio.io/istio/operator/version"
	"istio.io/pkg/log"
	"istio.io/pkg/version"
)

const (
	setFlagHelpStr = `Override an IstioOperator value, e.g. to choose a profile
(--set profile=demo), enable or disable components (--set components.policy.enabled=true), or override Istio
settings (--set values.grafana.enabled=true). See documentation for more info:
https://istio.io/docs/reference/config/istio.operator.v1alpha1/#IstioOperatorSpec`
	// ChartsFlagHelpStr is the command line description for --charts
	ChartsFlagHelpStr = `Specify a path to a directory of charts and profiles
(e.g. ~/Downloads/istio-1.6.0/manifests)
or release tar URL (e.g. https://github.com/istio/istio/releases/download/1.6.0/istio-1.6.0-linux-amd64.tar.gz).
`
	revisionFlagHelpStr         = `Target control plane revision for the command.`
	skipConfirmationFlagHelpStr = `skipConfirmation determines whether the user is prompted for confirmation.
If set to true, the user is not prompted and a Yes response is assumed in all cases.`
	filenameFlagHelpStr = `Path to file containing IstioOperator custom resource
This flag can be specified multiple times to overlay multiple files. Multiple files are overlaid in left to right order.`
	installationCompleteStr = `Installation complete`
)

type rootArgs struct {
	// Dry run performs all steps except actually applying the manifests or creating output dirs/files.
	dryRun bool
}

func addFlags(cmd *cobra.Command, rootArgs *rootArgs) {
	cmd.PersistentFlags().BoolVarP(&rootArgs.dryRun, "dry-run", "",
		false, "Console/log output only, make no changes.")
}

// GetRootCmd returns the root of the cobra command-tree.
func GetRootCmd(args []string) *cobra.Command {
	rootCmd := &cobra.Command{
		Use:          "mesh",
		Short:        "Command line Istio install utility.",
		SilenceUsage: true,
		Long: "This command uses the Istio operator code to generate templates, query configurations and perform " +
			"utility operations.",
	}
	rootCmd.SetArgs(args)
	rootCmd.PersistentFlags().AddGoFlagSet(flag.CommandLine)

	rootCmd.AddCommand(ManifestCmd(log.DefaultOptions()))
	rootCmd.AddCommand(ProfileCmd())
	rootCmd.AddCommand(OperatorCmd())
	rootCmd.AddCommand(version.CobraCommand())
	rootCmd.AddCommand(UpgradeCmd())

	version.Info.Version = binversion.OperatorVersionString

	return rootCmd
}
<|endoftext|>


<commit_before>package main

import (
	"../nsq"
	"../util/notify"
	"log"
	"net"
	"time"
)

var notifyChannelChan = make(chan interface{})
var notifyTopicChan = make(chan interface{})
var lookupPeers = make([]*nsq.LookupPeer, 0)

func LookupRouter(lookupHosts []string) {
	for _, host := range lookupHosts {
		tcpAddr, err := net.ResolveTCPAddr("tcp", host)
		if err != nil {
			log.Fatal("LOOKUP: could not resolve TCP address for %s", host)
		}
		lookupPeer := nsq.NewLookupPeer(tcpAddr)
		lookupPeers = append(lookupPeers, lookupPeer)
	}

	notify.Observe("new_channel", notifyChannelChan)
	notify.Observe("new_topic", notifyTopicChan)

	for {
		select {
		case <-time.After(10 * time.Second):
			// send a heartbeat and read a response (read detects closed conns)
			for _, lookupPeer := range lookupPeers {
				log.Printf("LOOKUP: sending heartbeat to %s", lookupPeer.String())
				if !lookupPeer.IsConnected() {
					err := lookupPeer.Connect()
					if err != nil {
						log.Printf("LOOKUP: failed to connect to %s", lookupPeer.String())
						continue
					}
					lookupPeer.Version(nsq.LookupProtocolV1Magic)
				}
				err := lookupPeer.WriteCommand(lookupPeer.Ping())
				if err != nil {
					lookupPeer.Close()
					continue
				}
				_, err = lookupPeer.ReadResponse()
				if err != nil {
					lookupPeer.Close()
					continue
				}
			}
		case newChannel := <-notifyChannelChan:
			channel := newChannel.(*Channel)
			log.Printf("LOOKUP: new channel %s", channel.name)
		case newTopic := <-notifyTopicChan:
			topic := newTopic.(*Topic)
			log.Printf("LOOKUP: new topic %s", topic.name)
			for _, lookupPeer := range lookupPeers {
				if !lookupPeer.IsConnected() {
					err := lookupPeer.Connect()
					if err != nil {
						log.Printf("LOOKUP: failed to connect to %s", lookupPeer.String())
						continue
					}
					lookupPeer.Version(nsq.LookupProtocolV1Magic)
				}
				err := lookupPeer.WriteCommand(lookupPeer.Announce(topic.name, *bindAddress, *tcpPort))
				if err != nil {
					log.Printf("LOOKUP: error announcing to %s... closing", lookupPeer.String())
					lookupPeer.Close()
					continue
				}
				_, err = lookupPeer.ReadResponse()
				if err != nil {
					lookupPeer.Close()
					continue
				}
			}
		}
	}
}
<commit_msg>DRY up the outbound req/resp from nsqd -> nsqlookupd<commit_after>package main

import (
	"../nsq"
	"../util/notify"
	"log"
	"net"
	"time"
)

var notifyChannelChan = make(chan interface{})
var notifyTopicChan = make(chan interface{})
var lookupPeers = make([]*nsq.LookupPeer, 0)

func LookupRouter(lookupHosts []string) {
	for _, host := range lookupHosts {
		tcpAddr, err := net.ResolveTCPAddr("tcp", host)
		if err != nil {
			log.Fatal("LOOKUP: could not resolve TCP address for %s", host)
		}
		lookupPeer := nsq.NewLookupPeer(tcpAddr)
		lookupPeers = append(lookupPeers, lookupPeer)
	}

	notify.Observe("new_channel", notifyChannelChan)
	notify.Observe("new_topic", notifyTopicChan)

	for {
		select {
		case <-time.After(10 * time.Second):
			// send a heartbeat and read a response (read detects closed conns)
			for _, lookupPeer := range lookupPeers {
				log.Printf("LOOKUP: sending heartbeat to %s", lookupPeer.String())
				lookupCommand(lookupPeer, lookupPeer.Ping())
			}
		case newChannel := <-notifyChannelChan:
			channel := newChannel.(*Channel)
			log.Printf("LOOKUP: new channel %s", channel.name)
			// TODO: notify all nsds that a new channel exists
		case newTopic := <-notifyTopicChan:
			// notify all nsds that a new topic exists
			topic := newTopic.(*Topic)
			log.Printf("LOOKUP: new topic %s", topic.name)
			for _, lookupPeer := range lookupPeers {
				lookupCommand(lookupPeer, lookupPeer.Announce(topic.name, *bindAddress, *tcpPort))
			}
		}
	}
}

func lookupCommand(peer *nsq.LookupPeer, cmd *nsq.ProtocolCommand) ([]byte, error) {
	if !peer.IsConnected() {
		err := peer.Connect()
		if err != nil {
			log.Printf("LOOKUP: failed to connect to %s", peer.String())
			return nil, err
		}
		peer.Version(nsq.LookupProtocolV1Magic)
	}
	err := peer.WriteCommand(cmd)
	if err != nil {
		peer.Close()
		return nil, err
	}
	resp, err := peer.ReadResponse()
	if err != nil {
		peer.Close()
		return nil, err
	}
	return resp, nil
}
<|endoftext|>


<commit_before>package appstore

import (
	"errors"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"os"
	"reflect"
	"strings"
	"testing"
	"time"
)

func TestHandleError(t *testing.T) {
	var expected, actual error

	// status 0
	expected = nil
	actual = HandleError(0)
	if !reflect.DeepEqual(actual, expected) {
		t.Errorf("got %v\nwant %v", actual, expected)
	}

	// status 21000
	expected = errors.New("The App Store could not read the JSON object you provided.")
	actual = HandleError(21000)
	if !reflect.DeepEqual(actual, expected) {
		t.Errorf("got %v\nwant %v", actual, expected)
	}

	// status 21002
	expected = errors.New("The data in the receipt-data property was malformed or missing.")
	actual = HandleError(21002)
	if !reflect.DeepEqual(actual, expected) {
		t.Errorf("got %v\nwant %v", actual, expected)
	}

	// status 21003
	expected = errors.New("The receipt could not be authenticated.")
	actual = HandleError(21003)
	if !reflect.DeepEqual(actual, expected) {
		t.Errorf("got %v\nwant %v", actual, expected)
	}

	// status 21004
	expected = errors.New("The shared secret you provided does not match the shared secret on file for your account.")
	actual = HandleError(21004)
	if !reflect.DeepEqual(actual, expected) {
		t.Errorf("got %v\nwant %v", actual, expected)
	}

	// status 21005
	expected = errors.New("The receipt server is not currently available.")
	actual = HandleError(21005)
	if !reflect.DeepEqual(actual, expected) {
		t.Errorf("got %v\nwant %v", actual, expected)
	}

	// status 21007
	expected = errors.New("This receipt is from the test environment, but it was sent to the production environment for verification. Send it to the test environment instead.")
	actual = HandleError(21007)
	if !reflect.DeepEqual(actual, expected) {
		t.Errorf("got %v\nwant %v", actual, expected)
	}

	// status 21008
	expected = errors.New("This receipt is from the production environment, but it was sent to the test environment for verification. Send it to the production environment instead.")
	actual = HandleError(21008)
	if !reflect.DeepEqual(actual, expected) {
		t.Errorf("got %v\nwant %v", actual, expected)
	}

	// status 21010
	expected = errors.New("This receipt could not be authorized. Treat this the same as if a purchase was never made.")
	actual = HandleError(21010)
	if !reflect.DeepEqual(actual, expected) {
		t.Errorf("got %v\nwant %v", actual, expected)
	}

	// status 21100 - 21199
	expected = errors.New("Internal data access error.")
	actual = HandleError(21155)
	if !reflect.DeepEqual(actual, expected) {
		t.Errorf("got %v\nwant %v", actual, expected)
	}

	// status unknown
	expected = errors.New("An unknown error occurred")
	actual = HandleError(100)
	if !reflect.DeepEqual(actual, expected) {
		t.Errorf("got %v\nwant %v", actual, expected)
	}
}

func TestNew(t *testing.T) {
	expected := Client{
		ProductionURL: ProductionURL,
		SandboxURL:    SandboxURL,
		TimeOut:       time.Second * 5,
	}

	actual := New()
	if !reflect.DeepEqual(actual, expected) {
		t.Errorf("got %v\nwant %v", actual, expected)
	}
}

func TestNewWithEnvironment(t *testing.T) {
	expected := Client{
		ProductionURL: ProductionURL,
		TimeOut:       time.Second * 5,
		SandboxURL:    SandboxURL,
	}

	os.Setenv("IAP_ENVIRONMENT", "production")
	actual := New()
	os.Clearenv()

	if !reflect.DeepEqual(actual, expected) {
		t.Errorf("got %v\nwant %v", actual, expected)
	}
}

func TestNewWithConfig(t *testing.T) {
	config := Config{
		TimeOut: time.Second * 2,
	}

	expected := Client{
		ProductionURL: ProductionURL,
		SandboxURL:    SandboxURL,
		TimeOut:       time.Second * 2,
	}

	actual := NewWithConfig(config)
	if !reflect.DeepEqual(actual, expected) {
		t.Errorf("got %v\nwant %v", actual, expected)
	}
}

func TestNewWithConfigTimeout(t *testing.T) {
	config := Config{}

	expected := Client{
		ProductionURL: ProductionURL,
		SandboxURL:    SandboxURL,
		TimeOut:       time.Second * 5,
	}

	actual := NewWithConfig(config)
	if !reflect.DeepEqual(actual, expected) {
		t.Errorf("got %v\nwant %v", actual, expected)
	}
}

func TestVerifyTimeout(t *testing.T) {
	client := New()
	client.TimeOut = time.Millisecond

	req := IAPRequest{
		ReceiptData: "dummy data",
	}
	result := &IAPResponse{}
	err := client.Verify(req, result)
	if err == nil {
		t.Errorf("error should be occurred because of timeout")
	}
}

func TestVerifyBadURL(t *testing.T) {
	client := New()
	client.ProductionURL = "127.0.0.1"

	req := IAPRequest{
		ReceiptData: "dummy data",
	}
	result := &IAPResponse{}
	err := client.Verify(req, result)
	if err == nil {
		t.Errorf("error should be occurred because the server is not real")
	}
}

func TestVerifyBadPayload(t *testing.T) {
	s := httptest.NewServer(serverWithResponse(`{"status": 21002}`))
	defer s.Close()

	client := New()
	client.ProductionURL = s.URL
	expected := &IAPResponse{
		Status: 21002,
	}
	req := IAPRequest{
		ReceiptData: "dummy data",
	}
	result := &IAPResponse{}

	err := client.Verify(req, result)
	if err != nil {
		t.Errorf("got error %s", err)
	}
	if !reflect.DeepEqual(result, expected) {
		t.Errorf("got %v\nwant %v", result, expected)
	}
}

func TestVerifyBadResponse(t *testing.T) {
	s := httptest.NewServer(serverWithResponse(`qwerty!@#$%^`))
	defer s.Close()

	client := New()
	client.ProductionURL = s.URL
	req := IAPRequest{
		ReceiptData: "dummy data",
	}
	result := &IAPResponse{}

	err := client.Verify(req, result)
	if err == nil {
		t.Errorf("expected an error because Verify could not unmarshal server response")
	}
}

func TestVerifySandboxReceipt(t *testing.T) {
	s := httptest.NewServer(serverWithResponse(`{"status": 21007}`))
	defer s.Close()

	sandboxServ := httptest.NewServer(serverWithResponse(`{"status": 0}`))
	defer sandboxServ.Close()

	client := New()
	client.ProductionURL = s.URL
	client.TimeOut = time.Second * 100
	client.SandboxURL = sandboxServ.URL

	expected := &IAPResponse{
		Status: 0,
	}
	req := IAPRequest{
		ReceiptData: "dummy data",
	}
	result := &IAPResponse{}

	err := client.Verify(req, result)
	if err != nil {
		t.Errorf("got error %s", err)
	}
	if !reflect.DeepEqual(result, expected) {
		t.Errorf("got %v\nwant %v", result, expected)
	}
}

func TestVerifySandboxReceiptFailure(t *testing.T) {
	s := httptest.NewServer(serverWithResponse(`{"status": 21007}`))
	defer s.Close()

	client := New()
	client.ProductionURL = s.URL
	client.TimeOut = time.Second * 100
	client.SandboxURL = "localhost"

	req := IAPRequest{
		ReceiptData: "dummy data",
	}
	result := &IAPResponse{}

	err := client.Verify(req, result)
	if err == nil {
		t.Errorf("expected error to be not nil since the sandbox is not responding")
	}
}

func TestCannotReadBody(t *testing.T) {
	client := New()
	testResponse := http.Response{Body: ioutil.NopCloser(errReader(0))}

	if client.parseResponse(&testResponse, IAPResponse{}, http.Client{}, IAPRequest{}) == nil {
		t.Errorf("expected redirectToSandbox to fail to read the body")
	}
}

func TestCannotUnmarshalBody(t *testing.T) {
	client := New()
	testResponse := http.Response{Body: ioutil.NopCloser(strings.NewReader(`{"status": true}`))}

	if client.parseResponse(&testResponse, StatusResponse{}, http.Client{}, IAPRequest{}) == nil {
		t.Errorf("expected redirectToSandbox to fail to unmarshal the data")
	}
}

type errReader int

func (errReader) Read(p []byte) (n int, err error) {
	return 0, errors.New("test error")
}

func serverWithResponse(response string) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if "POST" == r.Method {
			w.Header().Set("Content-Type", "application/json")
			w.Write([]byte(response))
			return
		} else {
			w.Write([]byte(`unsupported request`))
		}

		w.WriteHeader(http.StatusBadRequest)
	})
}
<commit_msg>Correct tests<commit_after>package appstore

import (
	"errors"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"os"
	"reflect"
	"strings"
	"testing"
	"time"
)

func TestHandleError(t *testing.T) {
	var expected, actual error

	// status 0
	expected = nil
	actual = HandleError(0)
	if !reflect.DeepEqual(actual, expected) {
		t.Errorf("got %v\nwant %v", actual, expected)
	}

	// status 21000
	expected = errors.New("The App Store could not read the JSON object you provided.")
	actual = HandleError(21000)
	if !reflect.DeepEqual(actual, expected) {
		t.Errorf("got %v\nwant %v", actual, expected)
	}

	// status 21002
	expected = errors.New("The data in the receipt-data property was malformed or missing.")
	actual = HandleError(21002)
	if !reflect.DeepEqual(actual, expected) {
		t.Errorf("got %v\nwant %v", actual, expected)
	}

	// status 21003
	expected = errors.New("The receipt could not be authenticated.")
	actual = HandleError(21003)
	if !reflect.DeepEqual(actual, expected) {
		t.Errorf("got %v\nwant %v", actual, expected)
	}

	// status 21004
	expected = errors.New("The shared secret you provided does not match the shared secret on file for your account.")
	actual = HandleError(21004)
	if !reflect.DeepEqual(actual, expected) {
		t.Errorf("got %v\nwant %v", actual, expected)
	}

	// status 21005
	expected = errors.New("The receipt server is not currently available.")
	actual = HandleError(21005)
	if !reflect.DeepEqual(actual, expected) {
		t.Errorf("got %v\nwant %v", actual, expected)
	}

	// status 21007
	expected = errors.New("This receipt is from the test environment, but it was sent to the production environment for verification. Send it to the test environment instead.")
	actual = HandleError(21007)
	if !reflect.DeepEqual(actual, expected) {
		t.Errorf("got %v\nwant %v", actual, expected)
	}

	// status 21008
	expected = errors.New("This receipt is from the production environment, but it was sent to the test environment for verification. Send it to the production environment instead.")
	actual = HandleError(21008)
	if !reflect.DeepEqual(actual, expected) {
		t.Errorf("got %v\nwant %v", actual, expected)
	}

	// status 21010
	expected = errors.New("This receipt could not be authorized. Treat this the same as if a purchase was never made.")
	actual = HandleError(21010)
	if !reflect.DeepEqual(actual, expected) {
		t.Errorf("got %v\nwant %v", actual, expected)
	}

	// status 21100 - 21199
	expected = errors.New("Internal data access error.")
	actual = HandleError(21155)
	if !reflect.DeepEqual(actual, expected) {
		t.Errorf("got %v\nwant %v", actual, expected)
	}

	// status unknown
	expected = errors.New("An unknown error occurred")
	actual = HandleError(100)
	if !reflect.DeepEqual(actual, expected) {
		t.Errorf("got %v\nwant %v", actual, expected)
	}
}

func TestNew(t *testing.T) {
	expected := Client{
		ProductionURL: ProductionURL,
		SandboxURL:    SandboxURL,
		TimeOut:       time.Second * 5,
	}

	actual := New()
	if !reflect.DeepEqual(actual, expected) {
		t.Errorf("got %v\nwant %v", actual, expected)
	}
}

func TestNewWithEnvironment(t *testing.T) {
	expected := Client{
		ProductionURL: ProductionURL,
		TimeOut:       time.Second * 5,
		SandboxURL:    SandboxURL,
	}

	os.Setenv("IAP_ENVIRONMENT", "production")
	actual := New()
	os.Clearenv()

	if !reflect.DeepEqual(actual, expected) {
		t.Errorf("got %v\nwant %v", actual, expected)
	}
}

func TestNewWithConfig(t *testing.T) {
	config := Config{
		TimeOut: time.Second * 2,
	}

	expected := Client{
		ProductionURL: ProductionURL,
		SandboxURL:    SandboxURL,
		TimeOut:       time.Second * 2,
	}

	actual := NewWithConfig(config)
	if !reflect.DeepEqual(actual, expected) {
		t.Errorf("got %v\nwant %v", actual, expected)
	}
}

func TestNewWithConfigTimeout(t *testing.T) {
	config := Config{}

	expected := Client{
		ProductionURL: ProductionURL,
		SandboxURL:    SandboxURL,
		TimeOut:       time.Second * 5,
	}

	actual := NewWithConfig(config)
	if !reflect.DeepEqual(actual, expected) {
		t.Errorf("got %v\nwant %v", actual, expected)
	}
}

func TestVerifyTimeout(t *testing.T) {
	client := New()
	client.TimeOut = time.Millisecond

	req := IAPRequest{
		ReceiptData: "dummy data",
	}
	result := &IAPResponse{}
	err := client.Verify(req, result)
	if err == nil {
		t.Errorf("error should be occurred because of timeout")
	}
}

func TestVerifyBadURL(t *testing.T) {
	client := New()
	client.ProductionURL = "127.0.0.1"

	req := IAPRequest{
		ReceiptData: "dummy data",
	}
	result := &IAPResponse{}
	err := client.Verify(req, result)
	if err == nil {
		t.Errorf("error should be occurred because the server is not real")
	}
}

func TestVerifyBadPayload(t *testing.T) {
	s := httptest.NewServer(serverWithResponse(http.StatusBadRequest, `{"status": 21002}`))
	defer s.Close()

	client := New()
	client.ProductionURL = s.URL
	expected := &IAPResponse{
		Status: 21002,
	}
	req := IAPRequest{
		ReceiptData: "dummy data",
	}
	result := &IAPResponse{}

	err := client.Verify(req, result)
	if err != nil {
		t.Errorf("got error %s", err)
	}
	if !reflect.DeepEqual(result, expected) {
		t.Errorf("got %v\nwant %v", result, expected)
	}
}

func TestVerifyBadResponse(t *testing.T) {
	s := httptest.NewServer(serverWithResponse(http.StatusInternalServerError, `qwerty!@#$%^`))
	defer s.Close()

	client := New()
	client.ProductionURL = s.URL
	req := IAPRequest{
		ReceiptData: "dummy data",
	}
	result := &IAPResponse{}

	err := client.Verify(req, result)
	if err == nil {
		t.Errorf("expected an error because Verify could not unmarshal server response")
	}
}

func TestVerifySandboxReceipt(t *testing.T) {
	s := httptest.NewServer(serverWithResponse(http.StatusOK, `{"status": 21007}`))
	defer s.Close()

	sandboxServ := httptest.NewServer(serverWithResponse(http.StatusOK, `{"status": 0}`))
	defer sandboxServ.Close()

	client := New()
	client.ProductionURL = s.URL
	client.TimeOut = time.Second * 100
	client.SandboxURL = sandboxServ.URL

	expected := &IAPResponse{
		Status: 0,
	}
	req := IAPRequest{
		ReceiptData: "dummy data",
	}
	result := &IAPResponse{}

	err := client.Verify(req, result)
	if err != nil {
		t.Errorf("got error %s", err)
	}
	if !reflect.DeepEqual(result, expected) {
		t.Errorf("got %v\nwant %v", result, expected)
	}
}

func TestVerifySandboxReceiptFailure(t *testing.T) {
	s := httptest.NewServer(serverWithResponse(http.StatusOK, `{"status": 21007}`))
	defer s.Close()

	client := New()
	client.ProductionURL = s.URL
	client.TimeOut = time.Second * 100
	client.SandboxURL = "localhost"

	req := IAPRequest{
		ReceiptData: "dummy data",
	}
	result := &IAPResponse{}

	err := client.Verify(req, result)
	if err == nil {
		t.Errorf("expected error to be not nil since the sandbox is not responding")
	}
}

func TestCannotReadBody(t *testing.T) {
	client := New()
	testResponse := http.Response{Body: ioutil.NopCloser(errReader(0))}

	if client.parseResponse(&testResponse, IAPResponse{}, http.Client{}, IAPRequest{}) == nil {
		t.Errorf("expected redirectToSandbox to fail to read the body")
	}
}

func TestCannotUnmarshalBody(t *testing.T) {
	client := New()
	testResponse := http.Response{Body: ioutil.NopCloser(strings.NewReader(`{"status": true}`))}

	if client.parseResponse(&testResponse, StatusResponse{}, http.Client{}, IAPRequest{}) == nil {
		t.Errorf("expected redirectToSandbox to fail to unmarshal the data")
	}
}

type errReader int

func (errReader) Read(p []byte) (n int, err error) {
	return 0, errors.New("test error")
}

func serverWithResponse(statusCode int, response string) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if "POST" == r.Method {
			w.Header().Set("Content-Type", "application/json")
			w.Write([]byte(response))
			return
		} else {
			w.Write([]byte(`unsupported request`))
		}

		w.WriteHeader(statusCode)
	})
}
<|endoftext|>


<commit_before>// Copyright ©2014 The Gonum 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 distuv

import (
	"math"
	"math/cmplx"

	"golang.org/x/exp/rand"
)

// Weibull distribution. Valid range for x is [0,+∞).
type Weibull struct {
	// Shape parameter of the distribution. A value of 1 represents
	// the exponential distribution. A value of 2 represents the
	// Rayleigh distribution. Valid range is (0,+∞).
	K float64
	// Scale parameter of the distribution. Valid range is (0,+∞).
	Lambda float64
	// Source of random numbers
	Src rand.Source
}

// CDF computes the value of the cumulative density function at x.
func (w Weibull) CDF(x float64) float64 {
	if x < 0 {
		return 0
	}
	return 1 - cmplx.Abs(cmplx.Exp(w.LogCDF(x)))
}

// Entropy returns the entropy of the distribution.
func (w Weibull) Entropy() float64 {
	return eulerGamma*(1-1/w.K) + math.Log(w.Lambda/w.K) + 1
}

// ExKurtosis returns the excess kurtosis of the distribution.
func (w Weibull) ExKurtosis() float64 {
	return (-6*w.gammaIPow(1, 4) + 12*w.gammaIPow(1, 2)*math.Gamma(1+2/w.K) - 3*w.gammaIPow(2, 2) - 4*math.Gamma(1+1/w.K)*math.Gamma(1+3/w.K) + math.Gamma(1+4/w.K)) / math.Pow(math.Gamma(1+2/w.K)-w.gammaIPow(1, 2), 2)
}

// gammIPow is a shortcut for computing the gamma function to a power.
func (w Weibull) gammaIPow(i, pow float64) float64 {
	return math.Pow(math.Gamma(1+i/w.K), pow)
}

// LogCDF computes the value of the log of the cumulative density function at x.
func (w Weibull) LogCDF(x float64) complex128 {
	if x < 0 {
		return 0
	}
	return cmplx.Log(-1) + complex(-math.Pow(x/w.Lambda, w.K), 0)
}

// LogProb computes the natural logarithm of the value of the probability
// density function at x. Zero is returned if x is less than zero.
//
// Special cases occur when x == 0, and the result depends on the shape
// parameter as follows:
//  If 0 < K < 1, LogProb returns +Inf.
//  If K == 1, LogProb returns 0.
//  If K > 1, LogProb returns -Inf.
func (w Weibull) LogProb(x float64) float64 {
	if x < 0 {
		return 0
	}
	return math.Log(w.K) - math.Log(w.Lambda) + (w.K-1)*(math.Log(x)-math.Log(w.Lambda)) - math.Pow(x/w.Lambda, w.K)
}

// LogSurvival returns the log of the survival function (complementary CDF) at x.
func (w Weibull) LogSurvival(x float64) float64 {
	if x < 0 {
		return 0
	}
	return -math.Pow(x/w.Lambda, w.K)
}

// Mean returns the mean of the probability distribution.
func (w Weibull) Mean() float64 {
	return w.Lambda * math.Gamma(1+1/w.K)
}

// Median returns the median of the normal distribution.
func (w Weibull) Median() float64 {
	return w.Lambda * math.Pow(ln2, 1/w.K)
}

// Mode returns the mode of the normal distribution.
//
// The mode is NaN in the special case where the K (shape) parameter
// is less than 1.
func (w Weibull) Mode() float64 {
	if w.K > 1 {
		return w.Lambda * math.Pow((w.K-1)/w.K, 1/w.K)
	} else if w.K == 1 {
		return 0
	} else {
		return math.NaN()
	}
}

// NumParameters returns the number of parameters in the distribution.
func (Weibull) NumParameters() int {
	return 2
}

// Prob computes the value of the probability density function at x.
func (w Weibull) Prob(x float64) float64 {
	if x < 0 {
		return 0
	}
	return math.Exp(w.LogProb(x))
}

// Quantile returns the inverse of the cumulative probability distribution.
func (w Weibull) Quantile(p float64) float64 {
	if p < 0 || p > 1 {
		panic(badPercentile)
	}
	return w.Lambda * math.Pow(-math.Log(1-p), 1/w.K)
}

// Rand returns a random sample drawn from the distribution.
func (w Weibull) Rand() float64 {
	var rnd float64
	if w.Src == nil {
		rnd = rand.Float64()
	} else {
		rnd = rand.New(w.Src).Float64()
	}
	return w.Quantile(rnd)
}

// Score returns the score function with respect to the parameters of the
// distribution at the input location x. The score function is the derivative
// of the log-likelihood at x with respect to the parameters
//  (∂/∂θ) log(p(x;θ))
// If deriv is non-nil, len(deriv) must equal the number of parameters otherwise
// Score will panic, and the derivative is stored in-place into deriv. If deriv
// is nil a new slice will be allocated and returned.
//
// The order is [∂LogProb / ∂K, ∂LogProb / ∂λ].
//
// For more information, see https://en.wikipedia.org/wiki/Score_%28statistics%29.
//
// Special cases:
//  Score(0) = [NaN, NaN]
func (w Weibull) Score(deriv []float64, x float64) []float64 {
	if deriv == nil {
		deriv = make([]float64, w.NumParameters())
	}
	if len(deriv) != w.NumParameters() {
		panic(badLength)
	}
	if x > 0 {
		deriv[0] = 1/w.K + math.Log(x) - math.Log(w.Lambda) - (math.Log(x)-math.Log(w.Lambda))*math.Pow(x/w.Lambda, w.K)
		deriv[1] = (w.K * (math.Pow(x/w.Lambda, w.K) - 1)) / w.Lambda
		return deriv
	}
	if x < 0 {
		deriv[0] = 0
		deriv[1] = 0
		return deriv
	}
	deriv[0] = math.NaN()
	deriv[0] = math.NaN()
	return deriv
}

// ScoreInput returns the score function with respect to the input of the
// distribution at the input location specified by x. The score function is the
// derivative of the log-likelihood
//  (d/dx) log(p(x)) .
//
// Special cases:
//  ScoreInput(0) = NaN
func (w Weibull) ScoreInput(x float64) float64 {
	if x > 0 {
		return (-w.K*math.Pow(x/w.Lambda, w.K) + w.K - 1) / x
	}
	if x < 0 {
		return 0
	}
	return math.NaN()
}

// Skewness returns the skewness of the distribution.
func (w Weibull) Skewness() float64 {
	stdDev := w.StdDev()
	firstGamma, firstGammaSign := math.Lgamma(1 + 3/w.K)
	logFirst := firstGamma + 3*(math.Log(w.Lambda)-math.Log(stdDev))
	logSecond := math.Log(3) + math.Log(w.Mean()) + 2*math.Log(stdDev) - 3*math.Log(stdDev)
	logThird := 3 * (math.Log(w.Mean()) - math.Log(stdDev))
	return float64(firstGammaSign)*math.Exp(logFirst) - math.Exp(logSecond) - math.Exp(logThird)
}

// StdDev returns the standard deviation of the probability distribution.
func (w Weibull) StdDev() float64 {
	return math.Sqrt(w.Variance())
}

// Survival returns the survival function (complementary CDF) at x.
func (w Weibull) Survival(x float64) float64 {
	return math.Exp(w.LogSurvival(x))
}

// setParameters modifies the parameters of the distribution.
func (w *Weibull) setParameters(p []Parameter) {
	if len(p) != w.NumParameters() {
		panic("weibull: incorrect number of parameters to set")
	}
	if p[0].Name != "K" {
		panic("weibull: " + panicNameMismatch)
	}
	if p[1].Name != "λ" {
		panic("weibull: " + panicNameMismatch)
	}
	w.K = p[0].Value
	w.Lambda = p[1].Value
}

// Variance returns the variance of the probability distribution.
func (w Weibull) Variance() float64 {
	return math.Pow(w.Lambda, 2) * (math.Gamma(1+2/w.K) - w.gammaIPow(1, 2))
}

// parameters returns the parameters of the distribution.
func (w Weibull) parameters(p []Parameter) []Parameter {
	nParam := w.NumParameters()
	if p == nil {
		p = make([]Parameter, nParam)
	} else if len(p) != nParam {
		panic("weibull: improper parameter length")
	}
	p[0].Name = "K"
	p[0].Value = w.K
	p[1].Name = "λ"
	p[1].Value = w.Lambda
	return p

}
<commit_msg>stat/distuv: fix duplicated assignment<commit_after>// Copyright ©2014 The Gonum 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 distuv

import (
	"math"
	"math/cmplx"

	"golang.org/x/exp/rand"
)

// Weibull distribution. Valid range for x is [0,+∞).
type Weibull struct {
	// Shape parameter of the distribution. A value of 1 represents
	// the exponential distribution. A value of 2 represents the
	// Rayleigh distribution. Valid range is (0,+∞).
	K float64
	// Scale parameter of the distribution. Valid range is (0,+∞).
	Lambda float64
	// Source of random numbers
	Src rand.Source
}

// CDF computes the value of the cumulative density function at x.
func (w Weibull) CDF(x float64) float64 {
	if x < 0 {
		return 0
	}
	return 1 - cmplx.Abs(cmplx.Exp(w.LogCDF(x)))
}

// Entropy returns the entropy of the distribution.
func (w Weibull) Entropy() float64 {
	return eulerGamma*(1-1/w.K) + math.Log(w.Lambda/w.K) + 1
}

// ExKurtosis returns the excess kurtosis of the distribution.
func (w Weibull) ExKurtosis() float64 {
	return (-6*w.gammaIPow(1, 4) + 12*w.gammaIPow(1, 2)*math.Gamma(1+2/w.K) - 3*w.gammaIPow(2, 2) - 4*math.Gamma(1+1/w.K)*math.Gamma(1+3/w.K) + math.Gamma(1+4/w.K)) / math.Pow(math.Gamma(1+2/w.K)-w.gammaIPow(1, 2), 2)
}

// gammIPow is a shortcut for computing the gamma function to a power.
func (w Weibull) gammaIPow(i, pow float64) float64 {
	return math.Pow(math.Gamma(1+i/w.K), pow)
}

// LogCDF computes the value of the log of the cumulative density function at x.
func (w Weibull) LogCDF(x float64) complex128 {
	if x < 0 {
		return 0
	}
	return cmplx.Log(-1) + complex(-math.Pow(x/w.Lambda, w.K), 0)
}

// LogProb computes the natural logarithm of the value of the probability
// density function at x. Zero is returned if x is less than zero.
//
// Special cases occur when x == 0, and the result depends on the shape
// parameter as follows:
//  If 0 < K < 1, LogProb returns +Inf.
//  If K == 1, LogProb returns 0.
//  If K > 1, LogProb returns -Inf.
func (w Weibull) LogProb(x float64) float64 {
	if x < 0 {
		return 0
	}
	return math.Log(w.K) - math.Log(w.Lambda) + (w.K-1)*(math.Log(x)-math.Log(w.Lambda)) - math.Pow(x/w.Lambda, w.K)
}

// LogSurvival returns the log of the survival function (complementary CDF) at x.
func (w Weibull) LogSurvival(x float64) float64 {
	if x < 0 {
		return 0
	}
	return -math.Pow(x/w.Lambda, w.K)
}

// Mean returns the mean of the probability distribution.
func (w Weibull) Mean() float64 {
	return w.Lambda * math.Gamma(1+1/w.K)
}

// Median returns the median of the normal distribution.
func (w Weibull) Median() float64 {
	return w.Lambda * math.Pow(ln2, 1/w.K)
}

// Mode returns the mode of the normal distribution.
//
// The mode is NaN in the special case where the K (shape) parameter
// is less than 1.
func (w Weibull) Mode() float64 {
	if w.K > 1 {
		return w.Lambda * math.Pow((w.K-1)/w.K, 1/w.K)
	} else if w.K == 1 {
		return 0
	} else {
		return math.NaN()
	}
}

// NumParameters returns the number of parameters in the distribution.
func (Weibull) NumParameters() int {
	return 2
}

// Prob computes the value of the probability density function at x.
func (w Weibull) Prob(x float64) float64 {
	if x < 0 {
		return 0
	}
	return math.Exp(w.LogProb(x))
}

// Quantile returns the inverse of the cumulative probability distribution.
func (w Weibull) Quantile(p float64) float64 {
	if p < 0 || p > 1 {
		panic(badPercentile)
	}
	return w.Lambda * math.Pow(-math.Log(1-p), 1/w.K)
}

// Rand returns a random sample drawn from the distribution.
func (w Weibull) Rand() float64 {
	var rnd float64
	if w.Src == nil {
		rnd = rand.Float64()
	} else {
		rnd = rand.New(w.Src).Float64()
	}
	return w.Quantile(rnd)
}

// Score returns the score function with respect to the parameters of the
// distribution at the input location x. The score function is the derivative
// of the log-likelihood at x with respect to the parameters
//  (∂/∂θ) log(p(x;θ))
// If deriv is non-nil, len(deriv) must equal the number of parameters otherwise
// Score will panic, and the derivative is stored in-place into deriv. If deriv
// is nil a new slice will be allocated and returned.
//
// The order is [∂LogProb / ∂K, ∂LogProb / ∂λ].
//
// For more information, see https://en.wikipedia.org/wiki/Score_%28statistics%29.
//
// Special cases:
//  Score(0) = [NaN, NaN]
func (w Weibull) Score(deriv []float64, x float64) []float64 {
	if deriv == nil {
		deriv = make([]float64, w.NumParameters())
	}
	if len(deriv) != w.NumParameters() {
		panic(badLength)
	}
	if x > 0 {
		deriv[0] = 1/w.K + math.Log(x) - math.Log(w.Lambda) - (math.Log(x)-math.Log(w.Lambda))*math.Pow(x/w.Lambda, w.K)
		deriv[1] = (w.K * (math.Pow(x/w.Lambda, w.K) - 1)) / w.Lambda
		return deriv
	}
	if x < 0 {
		deriv[0] = 0
		deriv[1] = 0
		return deriv
	}
	deriv[0] = math.NaN()
	deriv[1] = math.NaN()
	return deriv
}

// ScoreInput returns the score function with respect to the input of the
// distribution at the input location specified by x. The score function is the
// derivative of the log-likelihood
//  (d/dx) log(p(x)) .
//
// Special cases:
//  ScoreInput(0) = NaN
func (w Weibull) ScoreInput(x float64) float64 {
	if x > 0 {
		return (-w.K*math.Pow(x/w.Lambda, w.K) + w.K - 1) / x
	}
	if x < 0 {
		return 0
	}
	return math.NaN()
}

// Skewness returns the skewness of the distribution.
func (w Weibull) Skewness() float64 {
	stdDev := w.StdDev()
	firstGamma, firstGammaSign := math.Lgamma(1 + 3/w.K)
	logFirst := firstGamma + 3*(math.Log(w.Lambda)-math.Log(stdDev))
	logSecond := math.Log(3) + math.Log(w.Mean()) + 2*math.Log(stdDev) - 3*math.Log(stdDev)
	logThird := 3 * (math.Log(w.Mean()) - math.Log(stdDev))
	return float64(firstGammaSign)*math.Exp(logFirst) - math.Exp(logSecond) - math.Exp(logThird)
}

// StdDev returns the standard deviation of the probability distribution.
func (w Weibull) StdDev() float64 {
	return math.Sqrt(w.Variance())
}

// Survival returns the survival function (complementary CDF) at x.
func (w Weibull) Survival(x float64) float64 {
	return math.Exp(w.LogSurvival(x))
}

// setParameters modifies the parameters of the distribution.
func (w *Weibull) setParameters(p []Parameter) {
	if len(p) != w.NumParameters() {
		panic("weibull: incorrect number of parameters to set")
	}
	if p[0].Name != "K" {
		panic("weibull: " + panicNameMismatch)
	}
	if p[1].Name != "λ" {
		panic("weibull: " + panicNameMismatch)
	}
	w.K = p[0].Value
	w.Lambda = p[1].Value
}

// Variance returns the variance of the probability distribution.
func (w Weibull) Variance() float64 {
	return math.Pow(w.Lambda, 2) * (math.Gamma(1+2/w.K) - w.gammaIPow(1, 2))
}

// parameters returns the parameters of the distribution.
func (w Weibull) parameters(p []Parameter) []Parameter {
	nParam := w.NumParameters()
	if p == nil {
		p = make([]Parameter, nParam)
	} else if len(p) != nParam {
		panic("weibull: improper parameter length")
	}
	p[0].Name = "K"
	p[0].Value = w.K
	p[1].Name = "λ"
	p[1].Value = w.Lambda
	return p

}
<|endoftext|>


<commit_before>package main

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

	"github.com/Sirupsen/logrus"

	"github.com/containernetworking/cni/pkg/skel"
	"github.com/containernetworking/cni/pkg/version"
	"github.com/containernetworking/plugins/pkg/ip"
	"github.com/containernetworking/plugins/pkg/ns"
	"github.com/vishvananda/netlink"

	"github.com/openvswitch/ovn-kubernetes/go-controller/pkg/kube"

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

const defaultVethMTU = 1400

func renameLink(curName, newName string) error {
	link, err := netlink.LinkByName(curName)
	if err != nil {
		return err
	}

	if err := netlink.LinkSetDown(link); err != nil {
		return err
	}
	if err := netlink.LinkSetName(link, newName); err != nil {
		return err
	}
	if err := netlink.LinkSetUp(link); err != nil {
		return err
	}

	return nil
}

func setupInterface(netns ns.NetNS, containerID, ifName, macAddress, ipAddress, gatewayIP string) (string, error) {
	var hostIfaceName string

	err := netns.Do(func(hostNS ns.NetNS) error {
		// create the veth pair in the container and move host end into host netns
		hostVeth, containerVeth, err := ip.SetupVeth(ifName, defaultVethMTU, hostNS)
		if err != nil {
			return err
		}

		contIfaceName := containerVeth.Name

		link, err := netlink.LinkByName(contIfaceName)
		if err != nil {
			return fmt.Errorf("failed to lookup %s: %v", contIfaceName, err)
		}

		hwAddr, err := net.ParseMAC(macAddress)
		if err != nil {
			return fmt.Errorf("failed to parse mac address for %s: %v", contIfaceName, err)
		}
		err = netlink.LinkSetHardwareAddr(link, hwAddr)
		if err != nil {
			return fmt.Errorf("failed to add mac address %s to %s: %v", macAddress, contIfaceName, err)
		}

		addr, err := netlink.ParseAddr(ipAddress)
		if err != nil {
			return err
		}
		err = netlink.AddrAdd(link, addr)
		if err != nil {
			return fmt.Errorf("failed to add IP addr %s to %s: %v", ipAddress, contIfaceName, err)
		}

		gw := net.ParseIP(gatewayIP)
		if gw == nil {
			return fmt.Errorf("parse ip of gateway failed")
		}
		err = ip.AddRoute(nil, gw, link)
		if err != nil {
			return err
		}

		hostIfaceName = hostVeth.Name

		return nil
	})
	if err != nil {
		return "", err
	}

	// rename the host end of veth pair
	newHostIfaceName := containerID[:15]
	if err := renameLink(hostIfaceName, newHostIfaceName); err != nil {
		return "", fmt.Errorf("failed to rename %s to %s: %v", hostIfaceName, newHostIfaceName, err)
	}

	return newHostIfaceName, nil
}

func argString2Map(args string) (map[string]string, error) {
	argsMap := make(map[string]string)

	pairs := strings.Split(args, ";")
	for _, pair := range pairs {
		kv := strings.Split(pair, "=")
		if len(kv) != 2 {
			return nil, fmt.Errorf("ARGS: invalid pair %q", pair)
		}
		keyString := kv[0]
		valueString := kv[1]
		argsMap[keyString] = valueString
	}

	return argsMap, nil
}

func cmdAdd(args *skel.CmdArgs) error {
	argsMap, err := argString2Map(args.Args)
	if err != nil {
		return err
	}

	namespace := argsMap["K8S_POD_NAMESPACE"]
	podName := argsMap["K8S_POD_NAME"]
	if namespace == "" || podName == "" {
		return fmt.Errorf("required CNI variable missing")
	}

	ovsArgs := []string{
		"--if-exists", "get", "Open_vSwitch",
		".", "external_ids:k8s-api-server",
	}
	out, err := exec.Command("ovs-vsctl", ovsArgs...).CombinedOutput()
	if err != nil {
		return fmt.Errorf("failed to get K8S_API_SERVER")
	}
	k8sAPIServer := strings.Trim(strings.TrimSpace(string(out)), "\"")
	if !strings.HasPrefix(k8sAPIServer, "http") {
		k8sAPIServer = fmt.Sprintf("http://%s", k8sAPIServer)
	}

	config, err := clientcmd.BuildConfigFromFlags(k8sAPIServer, "")
	if err != nil {
		return err
	}
	clientset, err := kubernetes.NewForConfig(config)
	if err != nil {
		return err
	}
	kubecli := &kube.Kube{KClient: clientset}

	// Get the IP address and MAC address from the API server.
	// Wait for a maximum of 3 seconds with a retry every 0.1 second.
	var annotation map[string]string
	for cnt := 0; cnt < 30; cnt++ {
		annotation, err = kubecli.GetAnnotationsOnPod(namespace, podName)
		if err != nil {
			continue
		}
		if _, ok := annotation["ovn"]; ok {
			break
		}
	}

	if annotation == nil {
		return fmt.Errorf("failed to get pod annotation")
	}

	ovnAnnotation, ok := annotation["ovn"]
	if !ok {
		return fmt.Errorf("failed to get annotation of ovn")
	}

	var ovnAnnotatedMap map[string]string
	err = json.Unmarshal([]byte(ovnAnnotation), &ovnAnnotatedMap)
	if err != nil {
		return fmt.Errorf("unmarshal ovn annotation failed")
	}

	ipAddress := ovnAnnotatedMap["ip_address"]
	macAddress := ovnAnnotatedMap["mac_address"]
	gatewayIP := ovnAnnotatedMap["gateway_ip"]

	if ipAddress == "" || macAddress == "" || gatewayIP == "" {
		return fmt.Errorf("failed in pod annotation key extract")
	}

	netns, err := ns.GetNS(args.Netns)
	if err != nil {
		return fmt.Errorf("failed to open netns %q: %v", args.Netns, err)
	}
	defer netns.Close()

	vethOutside, err := setupInterface(netns, args.ContainerID, args.IfName, macAddress, ipAddress, gatewayIP)
	if err != nil {
		return err
	}

	ifaceID := fmt.Sprintf("%s_%s", namespace, podName)

	ovsArgs = []string{
		"add-port", "br-int", vethOutside, "--", "set",
		"interface", vethOutside,
		fmt.Sprintf("external_ids:attached_mac=%s", macAddress),
		fmt.Sprintf("external_ids:iface-id=%s", ifaceID),
		fmt.Sprintf("external_ids:ip_address=%s", ipAddress),
	}
	out, err = exec.Command("ovs-vsctl", ovsArgs...).CombinedOutput()
	if err != nil {
		return fmt.Errorf("failure in plugging pod interface: %v\n  %q", err, string(out))
	}

	// TODO: conform with cni specification
	result := fmt.Sprintf("{\"ip_address\":\"%s\", \"mac_address\":\"%s\", \"gateway_ip\": \"%s\"}", ipAddress, macAddress, gatewayIP)
	_, err = os.Stdout.Write([]byte(result))

	return err
}

func cmdDel(args *skel.CmdArgs) error {
	ifaceName := args.ContainerID[:15]
	ovsArgs := []string{
		"del-port", "br-int", ifaceName,
	}
	out, err := exec.Command("ovs-vsctl", ovsArgs...).CombinedOutput()
	if err != nil && !strings.Contains(string(out), "no port named") {
		// DEL should be idempotent; don't return an error just log it
		logrus.Warningf("failed to delete OVS port %s: %v\n  %q", ifaceName, err, string(out))
	}

	return nil
}

func main() {
	skel.PluginMain(cmdAdd, cmdDel, version.All)
}
<commit_msg>go-overlay: conform to CNI spec when returning the ADD result<commit_after>package main

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

	"github.com/Sirupsen/logrus"

	"github.com/containernetworking/cni/pkg/skel"
	"github.com/containernetworking/cni/pkg/types"
	"github.com/containernetworking/cni/pkg/types/current"
	"github.com/containernetworking/cni/pkg/version"
	"github.com/containernetworking/plugins/pkg/ip"
	"github.com/containernetworking/plugins/pkg/ns"
	"github.com/vishvananda/netlink"

	"github.com/openvswitch/ovn-kubernetes/go-controller/pkg/kube"

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

const defaultVethMTU = 1400

func renameLink(curName, newName string) error {
	link, err := netlink.LinkByName(curName)
	if err != nil {
		return err
	}

	if err := netlink.LinkSetDown(link); err != nil {
		return err
	}
	if err := netlink.LinkSetName(link, newName); err != nil {
		return err
	}
	if err := netlink.LinkSetUp(link); err != nil {
		return err
	}

	return nil
}

func setupInterface(netns ns.NetNS, containerID, ifName, macAddress, ipAddress, gatewayIP string) (*current.Interface, *current.Interface, error) {
	hostIface := &current.Interface{}
	contIface := &current.Interface{}

	var oldHostVethName string
	err := netns.Do(func(hostNS ns.NetNS) error {
		// create the veth pair in the container and move host end into host netns
		hostVeth, containerVeth, err := ip.SetupVeth(ifName, defaultVethMTU, hostNS)
		if err != nil {
			return err
		}
		hostIface.Mac = hostVeth.HardwareAddr.String()
		contIface.Name = containerVeth.Name

		link, err := netlink.LinkByName(contIface.Name)
		if err != nil {
			return fmt.Errorf("failed to lookup %s: %v", contIface.Name, err)
		}

		hwAddr, err := net.ParseMAC(macAddress)
		if err != nil {
			return fmt.Errorf("failed to parse mac address for %s: %v", contIface.Name, err)
		}
		err = netlink.LinkSetHardwareAddr(link, hwAddr)
		if err != nil {
			return fmt.Errorf("failed to add mac address %s to %s: %v", macAddress, contIface.Name, err)
		}
		contIface.Mac = macAddress
		contIface.Sandbox = netns.Path()

		addr, err := netlink.ParseAddr(ipAddress)
		if err != nil {
			return err
		}
		err = netlink.AddrAdd(link, addr)
		if err != nil {
			return fmt.Errorf("failed to add IP addr %s to %s: %v", ipAddress, contIface.Name, err)
		}

		gw := net.ParseIP(gatewayIP)
		if gw == nil {
			return fmt.Errorf("parse ip of gateway failed")
		}
		err = ip.AddRoute(nil, gw, link)
		if err != nil {
			return err
		}

		oldHostVethName = hostVeth.Name

		return nil
	})
	if err != nil {
		return nil, nil, err
	}

	// rename the host end of veth pair
	hostIface.Name = containerID[:15]
	if err := renameLink(oldHostVethName, hostIface.Name); err != nil {
		return nil, nil, fmt.Errorf("failed to rename %s to %s: %v", oldHostVethName, hostIface.Name, err)
	}

	return hostIface, contIface, nil
}

func argString2Map(args string) (map[string]string, error) {
	argsMap := make(map[string]string)

	pairs := strings.Split(args, ";")
	for _, pair := range pairs {
		kv := strings.Split(pair, "=")
		if len(kv) != 2 {
			return nil, fmt.Errorf("ARGS: invalid pair %q", pair)
		}
		keyString := kv[0]
		valueString := kv[1]
		argsMap[keyString] = valueString
	}

	return argsMap, nil
}

func cmdAdd(args *skel.CmdArgs) error {
	conf := &types.NetConf{}
	if err := json.Unmarshal(args.StdinData, conf); err != nil {
		return fmt.Errorf("failed to load netconf: %v", err)
	}

	argsMap, err := argString2Map(args.Args)
	if err != nil {
		return err
	}

	namespace := argsMap["K8S_POD_NAMESPACE"]
	podName := argsMap["K8S_POD_NAME"]
	if namespace == "" || podName == "" {
		return fmt.Errorf("required CNI variable missing")
	}

	ovsArgs := []string{
		"--if-exists", "get", "Open_vSwitch",
		".", "external_ids:k8s-api-server",
	}
	out, err := exec.Command("ovs-vsctl", ovsArgs...).CombinedOutput()
	if err != nil {
		return fmt.Errorf("failed to get K8S_API_SERVER")
	}
	k8sAPIServer := strings.Trim(strings.TrimSpace(string(out)), "\"")
	if !strings.HasPrefix(k8sAPIServer, "http") {
		k8sAPIServer = fmt.Sprintf("http://%s", k8sAPIServer)
	}

	config, err := clientcmd.BuildConfigFromFlags(k8sAPIServer, "")
	if err != nil {
		return err
	}
	clientset, err := kubernetes.NewForConfig(config)
	if err != nil {
		return err
	}
	kubecli := &kube.Kube{KClient: clientset}

	// Get the IP address and MAC address from the API server.
	// Wait for a maximum of 3 seconds with a retry every 0.1 second.
	var annotation map[string]string
	for cnt := 0; cnt < 30; cnt++ {
		annotation, err = kubecli.GetAnnotationsOnPod(namespace, podName)
		if err != nil {
			continue
		}
		if _, ok := annotation["ovn"]; ok {
			break
		}
	}

	if annotation == nil {
		return fmt.Errorf("failed to get pod annotation")
	}

	ovnAnnotation, ok := annotation["ovn"]
	if !ok {
		return fmt.Errorf("failed to get annotation of ovn")
	}

	var ovnAnnotatedMap map[string]string
	err = json.Unmarshal([]byte(ovnAnnotation), &ovnAnnotatedMap)
	if err != nil {
		return fmt.Errorf("unmarshal ovn annotation failed")
	}

	ipAddress := ovnAnnotatedMap["ip_address"]
	macAddress := ovnAnnotatedMap["mac_address"]
	gatewayIP := ovnAnnotatedMap["gateway_ip"]

	if ipAddress == "" || macAddress == "" || gatewayIP == "" {
		return fmt.Errorf("failed in pod annotation key extract")
	}

	netns, err := ns.GetNS(args.Netns)
	if err != nil {
		return fmt.Errorf("failed to open netns %q: %v", args.Netns, err)
	}
	defer netns.Close()

	hostIface, contIface, err := setupInterface(netns, args.ContainerID, args.IfName, macAddress, ipAddress, gatewayIP)
	if err != nil {
		return err
	}

	ifaceID := fmt.Sprintf("%s_%s", namespace, podName)

	ovsArgs = []string{
		"add-port", "br-int", hostIface.Name, "--", "set",
		"interface", hostIface.Name,
		fmt.Sprintf("external_ids:attached_mac=%s", macAddress),
		fmt.Sprintf("external_ids:iface-id=%s", ifaceID),
		fmt.Sprintf("external_ids:ip_address=%s", ipAddress),
	}
	out, err = exec.Command("ovs-vsctl", ovsArgs...).CombinedOutput()
	if err != nil {
		return fmt.Errorf("failure in plugging pod interface: %v\n  %q", err, string(out))
	}

	// Build the result structure to pass back to the runtime
	addr, addrNet, err := net.ParseCIDR(ipAddress)
	if err != nil {
		return fmt.Errorf("failed to parse IP address %q: %v", ipAddress, err)
	}
	ipVersion := "6"
	if addr.To4() != nil {
		ipVersion = "4"
	}
	result := &current.Result{
		Interfaces: []*current.Interface{hostIface, contIface},
		IPs: []*current.IPConfig{
			{
				Version:   ipVersion,
				Interface: current.Int(1),
				Address:   net.IPNet{IP: addr, Mask: addrNet.Mask},
				Gateway:   net.ParseIP(gatewayIP),
			},
		},
	}

	return types.PrintResult(result, conf.CNIVersion)
}

func cmdDel(args *skel.CmdArgs) error {
	ifaceName := args.ContainerID[:15]
	ovsArgs := []string{
		"del-port", "br-int", ifaceName,
	}
	out, err := exec.Command("ovs-vsctl", ovsArgs...).CombinedOutput()
	if err != nil && !strings.Contains(string(out), "no port named") {
		// DEL should be idempotent; don't return an error just log it
		logrus.Warningf("failed to delete OVS port %s: %v\n  %q", ifaceName, err, string(out))
	}

	return nil
}

func main() {
	skel.PluginMain(cmdAdd, cmdDel, version.All)
}
<|endoftext|>


<commit_before>/*
Copyright IBM Corp. 2017 All Rights Reserved.

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 sw

import (
	"crypto/ecdsa"
	"crypto/elliptic"
	"crypto/rand"
	"crypto/sha256"
	"crypto/x509"
	"math/big"
	"testing"

	"github.com/hyperledger/fabric/bccsp/utils"
	"github.com/stretchr/testify/assert"
)

func TestSignECDSABadParameter(t *testing.T) {
	// Generate a key
	lowLevelKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
	assert.NoError(t, err)

	// Induce an error on the underlying ecdsa algorithm
	msg := []byte("hello world")
	oldN := lowLevelKey.Params().N
	defer func() { lowLevelKey.Params().N = oldN }()
	lowLevelKey.Params().N = big.NewInt(0)
	_, err = signECDSA(lowLevelKey, msg, nil)
	assert.Error(t, err)
	assert.Contains(t, err.Error(), "zero parameter")
}

func TestVerifyECDSA(t *testing.T) {
	t.Parallel()

	// Generate a key
	lowLevelKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
	assert.NoError(t, err)

	msg := []byte("hello world")
	sigma, err := signECDSA(lowLevelKey, msg, nil)
	assert.NoError(t, err)

	valid, err := verifyECDSA(&lowLevelKey.PublicKey, sigma, msg, nil)
	assert.NoError(t, err)
	assert.True(t, valid)

	_, err = verifyECDSA(&lowLevelKey.PublicKey, nil, msg, nil)
	assert.Error(t, err)
	assert.Contains(t, err.Error(), "Failed unmashalling signature [")

	R, S, err := utils.UnmarshalECDSASignature(sigma)
	assert.NoError(t, err)
	S.Add(utils.GetCurveHalfOrdersAt(elliptic.P256()), big.NewInt(1))
	sigmaWrongS, err := utils.MarshalECDSASignature(R, S)
	assert.NoError(t, err)
	_, err = verifyECDSA(&lowLevelKey.PublicKey, sigmaWrongS, msg, nil)
	assert.Error(t, err)
	assert.Contains(t, err.Error(), "Invalid S. Must be smaller than half the order [")
}

func TestEcdsaSignerSign(t *testing.T) {
	t.Parallel()

	signer := &ecdsaSigner{}
	verifierPrivateKey := &ecdsaPrivateKeyVerifier{}
	verifierPublicKey := &ecdsaPublicKeyKeyVerifier{}

	// Generate a key
	lowLevelKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
	assert.NoError(t, err)
	k := &ecdsaPrivateKey{lowLevelKey}
	pk, err := k.PublicKey()
	assert.NoError(t, err)

	// Sign
	msg := []byte("Hello World")
	sigma, err := signer.Sign(k, msg, nil)
	assert.NoError(t, err)
	assert.NotNil(t, sigma)

	// Verify
	valid, err := verifyECDSA(&lowLevelKey.PublicKey, sigma, msg, nil)
	assert.NoError(t, err)
	assert.True(t, valid)

	valid, err = verifierPrivateKey.Verify(k, sigma, msg, nil)
	assert.NoError(t, err)
	assert.True(t, valid)

	valid, err = verifierPublicKey.Verify(pk, sigma, msg, nil)
	assert.NoError(t, err)
	assert.True(t, valid)
}

func TestEcdsaPrivateKey(t *testing.T) {
	t.Parallel()

	lowLevelKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
	assert.NoError(t, err)
	k := &ecdsaPrivateKey{lowLevelKey}

	assert.False(t, k.Symmetric())
	assert.True(t, k.Private())

	_, err = k.Bytes()
	assert.Error(t, err)
	assert.Contains(t, err.Error(), "Not supported.")

	k.privKey = nil
	ski := k.SKI()
	assert.Nil(t, ski)

	k.privKey = lowLevelKey
	ski = k.SKI()
	raw := elliptic.Marshal(k.privKey.Curve, k.privKey.PublicKey.X, k.privKey.PublicKey.Y)
	hash := sha256.New()
	hash.Write(raw)
	ski2 := hash.Sum(nil)
	assert.Equal(t, ski2, ski, "SKI is not computed in the right way.")

	pk, err := k.PublicKey()
	assert.NoError(t, err)
	assert.NotNil(t, pk)
	ecdsaPK, ok := pk.(*ecdsaPublicKey)
	assert.True(t, ok)
	assert.Equal(t, &lowLevelKey.PublicKey, ecdsaPK.pubKey)
}

func TestEcdsaPublicKey(t *testing.T) {
	t.Parallel()

	lowLevelKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
	assert.NoError(t, err)
	k := &ecdsaPublicKey{&lowLevelKey.PublicKey}

	assert.False(t, k.Symmetric())
	assert.False(t, k.Private())

	k.pubKey = nil
	ski := k.SKI()
	assert.Nil(t, ski)

	k.pubKey = &lowLevelKey.PublicKey
	ski = k.SKI()
	raw := elliptic.Marshal(k.pubKey.Curve, k.pubKey.X, k.pubKey.Y)
	hash := sha256.New()
	hash.Write(raw)
	ski2 := hash.Sum(nil)
	assert.Equal(t, ski, ski2, "SKI is not computed in the right way.")

	pk, err := k.PublicKey()
	assert.NoError(t, err)
	assert.Equal(t, k, pk)

	bytes, err := k.Bytes()
	assert.NoError(t, err)
	bytes2, err := x509.MarshalPKIXPublicKey(k.pubKey)
	assert.NoError(t, err)
	assert.Equal(t, bytes2, bytes, "bytes are not computed in the right way.")

	invalidCurve := &elliptic.CurveParams{Name: "P-Invalid"}
	invalidCurve.BitSize = 1024
	k.pubKey = &ecdsa.PublicKey{Curve: invalidCurve, X: big.NewInt(1), Y: big.NewInt(1)}
	_, err = k.Bytes()
	assert.Error(t, err)
	assert.Contains(t, err.Error(), "Failed marshalling key [")
}
<commit_msg>Stop modifying curve held in crypto package var<commit_after>/*
Copyright IBM Corp. 2017 All Rights Reserved.

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 sw

import (
	"crypto/ecdsa"
	"crypto/elliptic"
	"crypto/rand"
	"crypto/sha256"
	"crypto/x509"
	"math/big"
	"testing"

	"github.com/hyperledger/fabric/bccsp/utils"
	"github.com/stretchr/testify/assert"
)

func TestSignECDSABadParameter(t *testing.T) {
	// Generate a key
	lowLevelKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
	assert.NoError(t, err)

	// Induce an error on the underlying ecdsa algorithm
	curve := *elliptic.P256().Params()
	curve.N = big.NewInt(0)
	lowLevelKey.Curve = &curve

	_, err = signECDSA(lowLevelKey, []byte("hello world"), nil)
	assert.Error(t, err)
	assert.Contains(t, err.Error(), "zero parameter")
}

func TestVerifyECDSA(t *testing.T) {
	t.Parallel()

	// Generate a key
	lowLevelKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
	assert.NoError(t, err)

	msg := []byte("hello world")
	sigma, err := signECDSA(lowLevelKey, msg, nil)
	assert.NoError(t, err)

	valid, err := verifyECDSA(&lowLevelKey.PublicKey, sigma, msg, nil)
	assert.NoError(t, err)
	assert.True(t, valid)

	_, err = verifyECDSA(&lowLevelKey.PublicKey, nil, msg, nil)
	assert.Error(t, err)
	assert.Contains(t, err.Error(), "Failed unmashalling signature [")

	R, S, err := utils.UnmarshalECDSASignature(sigma)
	assert.NoError(t, err)
	S.Add(utils.GetCurveHalfOrdersAt(elliptic.P256()), big.NewInt(1))
	sigmaWrongS, err := utils.MarshalECDSASignature(R, S)
	assert.NoError(t, err)
	_, err = verifyECDSA(&lowLevelKey.PublicKey, sigmaWrongS, msg, nil)
	assert.Error(t, err)
	assert.Contains(t, err.Error(), "Invalid S. Must be smaller than half the order [")
}

func TestEcdsaSignerSign(t *testing.T) {
	t.Parallel()

	signer := &ecdsaSigner{}
	verifierPrivateKey := &ecdsaPrivateKeyVerifier{}
	verifierPublicKey := &ecdsaPublicKeyKeyVerifier{}

	// Generate a key
	lowLevelKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
	assert.NoError(t, err)
	k := &ecdsaPrivateKey{lowLevelKey}
	pk, err := k.PublicKey()
	assert.NoError(t, err)

	// Sign
	msg := []byte("Hello World")
	sigma, err := signer.Sign(k, msg, nil)
	assert.NoError(t, err)
	assert.NotNil(t, sigma)

	// Verify
	valid, err := verifyECDSA(&lowLevelKey.PublicKey, sigma, msg, nil)
	assert.NoError(t, err)
	assert.True(t, valid)

	valid, err = verifierPrivateKey.Verify(k, sigma, msg, nil)
	assert.NoError(t, err)
	assert.True(t, valid)

	valid, err = verifierPublicKey.Verify(pk, sigma, msg, nil)
	assert.NoError(t, err)
	assert.True(t, valid)
}

func TestEcdsaPrivateKey(t *testing.T) {
	t.Parallel()

	lowLevelKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
	assert.NoError(t, err)
	k := &ecdsaPrivateKey{lowLevelKey}

	assert.False(t, k.Symmetric())
	assert.True(t, k.Private())

	_, err = k.Bytes()
	assert.Error(t, err)
	assert.Contains(t, err.Error(), "Not supported.")

	k.privKey = nil
	ski := k.SKI()
	assert.Nil(t, ski)

	k.privKey = lowLevelKey
	ski = k.SKI()
	raw := elliptic.Marshal(k.privKey.Curve, k.privKey.PublicKey.X, k.privKey.PublicKey.Y)
	hash := sha256.New()
	hash.Write(raw)
	ski2 := hash.Sum(nil)
	assert.Equal(t, ski2, ski, "SKI is not computed in the right way.")

	pk, err := k.PublicKey()
	assert.NoError(t, err)
	assert.NotNil(t, pk)
	ecdsaPK, ok := pk.(*ecdsaPublicKey)
	assert.True(t, ok)
	assert.Equal(t, &lowLevelKey.PublicKey, ecdsaPK.pubKey)
}

func TestEcdsaPublicKey(t *testing.T) {
	t.Parallel()

	lowLevelKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
	assert.NoError(t, err)
	k := &ecdsaPublicKey{&lowLevelKey.PublicKey}

	assert.False(t, k.Symmetric())
	assert.False(t, k.Private())

	k.pubKey = nil
	ski := k.SKI()
	assert.Nil(t, ski)

	k.pubKey = &lowLevelKey.PublicKey
	ski = k.SKI()
	raw := elliptic.Marshal(k.pubKey.Curve, k.pubKey.X, k.pubKey.Y)
	hash := sha256.New()
	hash.Write(raw)
	ski2 := hash.Sum(nil)
	assert.Equal(t, ski, ski2, "SKI is not computed in the right way.")

	pk, err := k.PublicKey()
	assert.NoError(t, err)
	assert.Equal(t, k, pk)

	bytes, err := k.Bytes()
	assert.NoError(t, err)
	bytes2, err := x509.MarshalPKIXPublicKey(k.pubKey)
	assert.NoError(t, err)
	assert.Equal(t, bytes2, bytes, "bytes are not computed in the right way.")

	invalidCurve := &elliptic.CurveParams{Name: "P-Invalid"}
	invalidCurve.BitSize = 1024
	k.pubKey = &ecdsa.PublicKey{Curve: invalidCurve, X: big.NewInt(1), Y: big.NewInt(1)}
	_, err = k.Bytes()
	assert.Error(t, err)
	assert.Contains(t, err.Error(), "Failed marshalling key [")
}
<|endoftext|>


<commit_before>package router

import (
	"sync/atomic"

	"github.com/AsynkronIT/protoactor-go/actor"
)

type roundRobinGroupRouter struct {
	GroupRouter
}

type roundRobinPoolRouter struct {
	PoolRouter
}

type roundRobinState struct {
	index   int32
	routees *actor.PIDSet
	values  []actor.PID
}

func (state *roundRobinState) SetRoutees(routees *actor.PIDSet) {
	state.routees = routees
	state.values = routees.Values()
}

func (state *roundRobinState) GetRoutees() *actor.PIDSet {
	return state.routees
}

func (state *roundRobinState) RouteMessage(message interface{}, sender *actor.PID) {
	pid := roundRobinRoutee(&state.index, state.values)
	pid.Request(message, sender)
}

func NewRoundRobinPool(size int) *actor.Props {
	return actor.FromSpawnFunc(spawner(&roundRobinPoolRouter{PoolRouter{PoolSize: size}}))
}

func NewRoundRobinGroup(routees ...*actor.PID) *actor.Props {
	return actor.FromSpawnFunc(spawner(&roundRobinGroupRouter{GroupRouter{Routees: actor.NewPIDSet(routees...)}}))
}

func (config *roundRobinPoolRouter) CreateRouterState() Interface {
	return &roundRobinState{}
}

func (config *roundRobinGroupRouter) CreateRouterState() Interface {
	return &roundRobinState{}
}

func roundRobinRoutee(index *int32, routees []actor.PID) actor.PID {
	i := int(atomic.AddInt32(index, 1))
	mod := len(routees)
	routee := routees[i%mod]
	return routee
}
<commit_msg>fix roundrobin_router when access the maximum of int32 will produce a minus index value which will cause panic<commit_after>package router

import (
	"sync/atomic"

	"github.com/AsynkronIT/protoactor-go/actor"
)

type roundRobinGroupRouter struct {
	GroupRouter
}

type roundRobinPoolRouter struct {
	PoolRouter
}

type roundRobinState struct {
	index   int32
	routees *actor.PIDSet
	values  []actor.PID
}

func (state *roundRobinState) SetRoutees(routees *actor.PIDSet) {
	state.routees = routees
	state.values = routees.Values()
}

func (state *roundRobinState) GetRoutees() *actor.PIDSet {
	return state.routees
}

func (state *roundRobinState) RouteMessage(message interface{}, sender *actor.PID) {
	pid := roundRobinRoutee(&state.index, state.values)
	pid.Request(message, sender)
}

func NewRoundRobinPool(size int) *actor.Props {
	return actor.FromSpawnFunc(spawner(&roundRobinPoolRouter{PoolRouter{PoolSize: size}}))
}

func NewRoundRobinGroup(routees ...*actor.PID) *actor.Props {
	return actor.FromSpawnFunc(spawner(&roundRobinGroupRouter{GroupRouter{Routees: actor.NewPIDSet(routees...)}}))
}

func (config *roundRobinPoolRouter) CreateRouterState() Interface {
	return &roundRobinState{}
}

func (config *roundRobinGroupRouter) CreateRouterState() Interface {
	return &roundRobinState{}
}

func roundRobinRoutee(index *int32, routees []actor.PID) actor.PID {
	i := int(atomic.AddInt32(index, 1))
	if i < 0 {
		*index = 0
		i = 0
	}
	mod := len(routees)
	routee := routees[i%mod]
	return routee
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"github.com/mozmark/OneCRL-Tools/oneCRL"
	"github.com/mozmark/OneCRL-Tools/config"
)

type revocations struct {
	byIssuerSerialNumber map[string][]string
	bySubjectPubKeyHash map[string][]string
}

func (r *revocations) LoadRecord(record oneCRL.Record) {
	// if there's no issuer name, assume we're revoking by Subject / PubKeyHash
	// otherwise it's issuer / serial
	if 0 == len(record.IssuerName) {
		if nil == r.bySubjectPubKeyHash {
			r.bySubjectPubKeyHash = make(map[string][]string)
		}
		if nil == r.bySubjectPubKeyHash[record.Subject]{
			pubKeyHashes := make([]string, 1)
			pubKeyHashes[0] = record.PubKeyHash
			r.bySubjectPubKeyHash[record.Subject] = pubKeyHashes
		} else {
			r.bySubjectPubKeyHash[record.Subject] = append(r.bySubjectPubKeyHash[record.Subject], record.PubKeyHash)
		}
	} else {
		if nil == r.byIssuerSerialNumber {
			r.byIssuerSerialNumber= make(map[string][]string)
		}
		if nil == r.byIssuerSerialNumber[record.IssuerName]{
			serials := make([]string, 1)
			serials[0] = record.SerialNumber
			r.byIssuerSerialNumber[record.IssuerName] = serials
		} else {
			r.byIssuerSerialNumber[record.IssuerName] = append(r.byIssuerSerialNumber[record.IssuerName], record.SerialNumber)
		}
	}
}

func main() {
	config.DefineFlags()
	flag.Parse()

	rev := new (revocations)

	config := config.GetConfig()

	url := config.GetRecordURL()

	err := oneCRL.LoadJSONFromURL(url, rev)
	if err != nil {
		panic(err)
	}

	for issuer, serials := range rev.byIssuerSerialNumber {
		fmt.Printf("%s\n", issuer)
		for _, serial := range serials {
			fmt.Printf(" %s\n", serial)
		}
	}
	for subject, pubKeyHashes := range rev.bySubjectPubKeyHash {
		fmt.Printf("%s\n", subject)
		for _, pubKeyHash := range pubKeyHashes {
			fmt.Printf("\t%s\n", pubKeyHash)
		}
	}
}
<commit_msg>Issue #43 - oneCRL2RevocationsTxt fails with "multiple-value config.GetRecordURL() in single-value context"<commit_after>package main

import (
	"flag"
	"fmt"
	"github.com/mozmark/OneCRL-Tools/oneCRL"
	"github.com/mozmark/OneCRL-Tools/config"
)

type revocations struct {
	byIssuerSerialNumber map[string][]string
	bySubjectPubKeyHash map[string][]string
}

func (r *revocations) LoadRecord(record oneCRL.Record) {
	// if there's no issuer name, assume we're revoking by Subject / PubKeyHash
	// otherwise it's issuer / serial
	if 0 == len(record.IssuerName) {
		if nil == r.bySubjectPubKeyHash {
			r.bySubjectPubKeyHash = make(map[string][]string)
		}
		if nil == r.bySubjectPubKeyHash[record.Subject]{
			pubKeyHashes := make([]string, 1)
			pubKeyHashes[0] = record.PubKeyHash
			r.bySubjectPubKeyHash[record.Subject] = pubKeyHashes
		} else {
			r.bySubjectPubKeyHash[record.Subject] = append(r.bySubjectPubKeyHash[record.Subject], record.PubKeyHash)
		}
	} else {
		if nil == r.byIssuerSerialNumber {
			r.byIssuerSerialNumber= make(map[string][]string)
		}
		if nil == r.byIssuerSerialNumber[record.IssuerName]{
			serials := make([]string, 1)
			serials[0] = record.SerialNumber
			r.byIssuerSerialNumber[record.IssuerName] = serials
		} else {
			r.byIssuerSerialNumber[record.IssuerName] = append(r.byIssuerSerialNumber[record.IssuerName], record.SerialNumber)
		}
	}
}

func main() {
	config.DefineFlags()
	flag.Parse()

	rev := new (revocations)

	config := config.GetConfig()

	err, url := config.GetRecordURL()
	if err != nil {
		panic(err)
	}

	err = oneCRL.LoadJSONFromURL(url, rev)
	if err != nil {
		panic(err)
	}

	for issuer, serials := range rev.byIssuerSerialNumber {
		fmt.Printf("%s\n", issuer)
		for _, serial := range serials {
			fmt.Printf(" %s\n", serial)
		}
	}
	for subject, pubKeyHashes := range rev.bySubjectPubKeyHash {
		fmt.Printf("%s\n", subject)
		for _, pubKeyHash := range pubKeyHashes {
			fmt.Printf("\t%s\n", pubKeyHash)
		}
	}
}
<|endoftext|>