<commit_before>package build

import "github.com/juhovuori/builder/project"

// Build describes a single build
type Build interface {
	ID() string
	ExecutorType() string
	ProjectID() string
	Script() string
	Completed() bool
	Error() error
}

type defaultBuild struct {
	id           string
	projectID    string
	script       string
	executorType string
	completed    bool
	err          error
}

func (b *defaultBuild) ID() string {
	return b.id
}

func (b *defaultBuild) ExecutorType() string {
	return b.executorType
}

func (b *defaultBuild) ProjectID() string {
	return b.projectID
}

func (b *defaultBuild) Script() string {
	return b.script
}

func (b *defaultBuild) Completed() bool {
	return b.completed
}

func (b *defaultBuild) Error() error {
	return b.err
}

// New creates a new build
func New(project project.Project) (Build, error) {
	if project == nil {
		return nil, ErrNilProject
	}
	e := "nop"
	if project.Script() != "" {
		e = "fork"
	}
	b := defaultBuild{
		id:           "",
		projectID:    project.ID(),
		script:       project.Script(),
		executorType: e,
		completed:    false,
		err:          nil,
	}
	return &b, nil

}
<commit_msg>Make build JSON serializable<commit_after>package build

import "github.com/juhovuori/builder/project"

// Build describes a single build
type Build interface {
	ID() string
	ExecutorType() string
	ProjectID() string
	Script() string
	Completed() bool
	Error() error
}

type defaultBuild struct {
	BID           string `json:"id"`
	BProjectID    string `json:"project-id"`
	BScript       string `json:"script"`
	BExecutorType string `json:"executor-type"`
	BCompleted    bool   `json:"completed"`
	BErr          error  `json:"error"`
}

func (b *defaultBuild) ID() string {
	return b.BID
}

func (b *defaultBuild) ExecutorType() string {
	return b.BExecutorType
}

func (b *defaultBuild) ProjectID() string {
	return b.BProjectID
}

func (b *defaultBuild) Script() string {
	return b.BScript
}

func (b *defaultBuild) Completed() bool {
	return b.BCompleted
}

func (b *defaultBuild) Error() error {
	return b.BErr
}

// New creates a new build
func New(project project.Project) (Build, error) {
	if project == nil {
		return nil, ErrNilProject
	}
	e := "nop"
	if project.Script() != "" {
		e = "fork"
	}
	b := defaultBuild{
		BID:           "",
		BProjectID:    project.ID(),
		BScript:       project.Script(),
		BExecutorType: e,
		BCompleted:    false,
		BErr:          nil,
	}
	return &b, nil

}
<|endoftext|>


<commit_before>package cli

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"os"
	"strings"

	"github.com/micro/cli/v2"
	"github.com/micro/go-micro/v2/client"
	cbytes "github.com/micro/go-micro/v2/codec/bytes"
	"github.com/micro/go-micro/v2/config/cmd"
	cliutil "github.com/micro/micro/v2/cli/util"
	clic "github.com/micro/micro/v2/internal/command/cli"
)

type exec func(*cli.Context, []string) ([]byte, error)

func Print(e exec) func(*cli.Context) error {
	return func(c *cli.Context) error {
		rsp, err := e(c, c.Args().Slice())
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
		if len(rsp) > 0 {
			fmt.Printf("%s\n", string(rsp))
		}
		return nil
	}
}

func list(c *cli.Context, args []string) ([]byte, error) {
	// no args
	if len(args) == 0 {
		return clic.ListServices(c)
	}

	// check first arg
	switch args[0] {
	case "services":
		return clic.ListServices(c)
	case "nodes":
		return clic.NetworkNodes(c)
	case "routes":
		return clic.NetworkRoutes(c)
	}

	return nil, errors.New("unknown command")
}

func networkConnect(c *cli.Context, args []string) ([]byte, error) {
	return clic.NetworkConnect(c, args)
}

func networkConnections(c *cli.Context, args []string) ([]byte, error) {
	return clic.NetworkConnections(c)
}

func networkGraph(c *cli.Context, args []string) ([]byte, error) {
	return clic.NetworkGraph(c)
}

func networkServices(c *cli.Context, args []string) ([]byte, error) {
	return clic.NetworkServices(c)
}

func netNodes(c *cli.Context, args []string) ([]byte, error) {
	return clic.NetworkNodes(c)
}

func netRoutes(c *cli.Context, args []string) ([]byte, error) {
	return clic.NetworkRoutes(c)
}

func netDNSAdvertise(c *cli.Context, args []string) ([]byte, error) {
	return clic.NetworkDNSAdvertise(c)
}

func netDNSRemove(c *cli.Context, args []string) ([]byte, error) {
	return clic.NetworkDNSRemove(c)
}

func netDNSResolve(c *cli.Context, args []string) ([]byte, error) {
	return clic.NetworkDNSResolve(c)
}

func listServices(c *cli.Context, args []string) ([]byte, error) {
	return clic.ListServices(c)
}

func registerService(c *cli.Context, args []string) ([]byte, error) {
	return clic.RegisterService(c, args)
}

func deregisterService(c *cli.Context, args []string) ([]byte, error) {
	return clic.DeregisterService(c, args)
}

func getService(c *cli.Context, args []string) ([]byte, error) {
	return clic.GetService(c, args)
}

func callService(c *cli.Context, args []string) ([]byte, error) {
	return clic.CallService(c, args)
}

func getEnv(c *cli.Context, args []string) ([]byte, error) {
	env := cliutil.GetEnv()
	return []byte(env.Name), nil
}

func setEnv(c *cli.Context, args []string) ([]byte, error) {
	cliutil.SetEnv(args[0])
	return nil, nil
}

func listEnvs(c *cli.Context, args []string) ([]byte, error) {
	envs := cliutil.GetEnvs()
	lines := []string{}
	for _, env := range envs {
		lines = append(lines, fmt.Sprintf("%v - %v", env.Name, env.ProxyAddress))
	}
	return []byte(strings.Join(lines, "\n")), nil
}

func addEnv(c *cli.Context, args []string) ([]byte, error) {
	cliutil.AddEnv(cliutil.Env{
		Name:         args[0],
		ProxyAddress: args[1],
	})
	return nil, nil
}

// netCall calls services through the network
func netCall(c *cli.Context, args []string) ([]byte, error) {
	os.Setenv("MICRO_PROXY", "go.micro.network")
	return clic.CallService(c, args)
}

// TODO: stream via HTTP
func streamService(c *cli.Context, args []string) ([]byte, error) {
	if len(args) < 2 {
		return nil, errors.New("require service and endpoint")
	}
	service := args[0]
	endpoint := args[1]
	var request map[string]interface{}

	// ignore error
	json.Unmarshal([]byte(strings.Join(args[2:], " ")), &request)

	req := (*cmd.DefaultOptions().Client).NewRequest(service, endpoint, request, client.WithContentType("application/json"))
	stream, err := (*cmd.DefaultOptions().Client).Stream(context.Background(), req)
	if err != nil {
		return nil, fmt.Errorf("error calling %s.%s: %v", service, endpoint, err)
	}

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

	output := c.String("output")

	for {
		if output == "raw" {
			rsp := cbytes.Frame{}
			if err := stream.Recv(&rsp); err != nil {
				return nil, fmt.Errorf("error receiving from %s.%s: %v", service, endpoint, err)
			}
			fmt.Print(string(rsp.Data))
		} else {
			var response map[string]interface{}
			if err := stream.Recv(&response); err != nil {
				return nil, fmt.Errorf("error receiving from %s.%s: %v", service, endpoint, err)
			}
			b, _ := json.MarshalIndent(response, "", "\t")
			fmt.Print(string(b))
		}
	}
}

func publish(c *cli.Context, args []string) ([]byte, error) {
	if err := clic.Publish(c, args); err != nil {
		return nil, err
	}
	return []byte(`ok`), nil
}

func queryHealth(c *cli.Context, args []string) ([]byte, error) {
	return clic.QueryHealth(c, args)
}

func queryStats(c *cli.Context, args []string) ([]byte, error) {
	return clic.QueryStats(c, args)
}
<commit_msg>Better micro env listing (#823)<commit_after>package cli

import (
	"bytes"
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"os"
	"strings"
	"text/tabwriter"

	"github.com/micro/cli/v2"
	"github.com/micro/go-micro/v2/client"
	cbytes "github.com/micro/go-micro/v2/codec/bytes"
	"github.com/micro/go-micro/v2/config/cmd"
	cliutil "github.com/micro/micro/v2/cli/util"
	clic "github.com/micro/micro/v2/internal/command/cli"
)

type exec func(*cli.Context, []string) ([]byte, error)

func Print(e exec) func(*cli.Context) error {
	return func(c *cli.Context) error {
		rsp, err := e(c, c.Args().Slice())
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
		if len(rsp) > 0 {
			fmt.Printf("%s\n", string(rsp))
		}
		return nil
	}
}

func list(c *cli.Context, args []string) ([]byte, error) {
	// no args
	if len(args) == 0 {
		return clic.ListServices(c)
	}

	// check first arg
	switch args[0] {
	case "services":
		return clic.ListServices(c)
	case "nodes":
		return clic.NetworkNodes(c)
	case "routes":
		return clic.NetworkRoutes(c)
	}

	return nil, errors.New("unknown command")
}

func networkConnect(c *cli.Context, args []string) ([]byte, error) {
	return clic.NetworkConnect(c, args)
}

func networkConnections(c *cli.Context, args []string) ([]byte, error) {
	return clic.NetworkConnections(c)
}

func networkGraph(c *cli.Context, args []string) ([]byte, error) {
	return clic.NetworkGraph(c)
}

func networkServices(c *cli.Context, args []string) ([]byte, error) {
	return clic.NetworkServices(c)
}

func netNodes(c *cli.Context, args []string) ([]byte, error) {
	return clic.NetworkNodes(c)
}

func netRoutes(c *cli.Context, args []string) ([]byte, error) {
	return clic.NetworkRoutes(c)
}

func netDNSAdvertise(c *cli.Context, args []string) ([]byte, error) {
	return clic.NetworkDNSAdvertise(c)
}

func netDNSRemove(c *cli.Context, args []string) ([]byte, error) {
	return clic.NetworkDNSRemove(c)
}

func netDNSResolve(c *cli.Context, args []string) ([]byte, error) {
	return clic.NetworkDNSResolve(c)
}

func listServices(c *cli.Context, args []string) ([]byte, error) {
	return clic.ListServices(c)
}

func registerService(c *cli.Context, args []string) ([]byte, error) {
	return clic.RegisterService(c, args)
}

func deregisterService(c *cli.Context, args []string) ([]byte, error) {
	return clic.DeregisterService(c, args)
}

func getService(c *cli.Context, args []string) ([]byte, error) {
	return clic.GetService(c, args)
}

func callService(c *cli.Context, args []string) ([]byte, error) {
	return clic.CallService(c, args)
}

func getEnv(c *cli.Context, args []string) ([]byte, error) {
	env := cliutil.GetEnv()
	return []byte(env.Name), nil
}

func setEnv(c *cli.Context, args []string) ([]byte, error) {
	cliutil.SetEnv(args[0])
	return nil, nil
}

func listEnvs(c *cli.Context, args []string) ([]byte, error) {
	envs := cliutil.GetEnvs()
	current := cliutil.GetEnv()

	byt := bytes.NewBuffer([]byte{})

	w := tabwriter.NewWriter(byt, 0, 0, 1, ' ', 0)
	for i, env := range envs {
		if i > 0 {
			fmt.Fprintf(w, "\n")
		}
		prefix := " "
		if env.Name == current.Name {
			prefix = "*"
		}
		fmt.Fprintf(w, "%v %v \t %v", prefix, env.Name, env.ProxyAddress)
	}
	w.Flush()
	return byt.Bytes(), nil
}

func addEnv(c *cli.Context, args []string) ([]byte, error) {
	cliutil.AddEnv(cliutil.Env{
		Name:         args[0],
		ProxyAddress: args[1],
	})
	return nil, nil
}

// netCall calls services through the network
func netCall(c *cli.Context, args []string) ([]byte, error) {
	os.Setenv("MICRO_PROXY", "go.micro.network")
	return clic.CallService(c, args)
}

// TODO: stream via HTTP
func streamService(c *cli.Context, args []string) ([]byte, error) {
	if len(args) < 2 {
		return nil, errors.New("require service and endpoint")
	}
	service := args[0]
	endpoint := args[1]
	var request map[string]interface{}

	// ignore error
	json.Unmarshal([]byte(strings.Join(args[2:], " ")), &request)

	req := (*cmd.DefaultOptions().Client).NewRequest(service, endpoint, request, client.WithContentType("application/json"))
	stream, err := (*cmd.DefaultOptions().Client).Stream(context.Background(), req)
	if err != nil {
		return nil, fmt.Errorf("error calling %s.%s: %v", service, endpoint, err)
	}

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

	output := c.String("output")

	for {
		if output == "raw" {
			rsp := cbytes.Frame{}
			if err := stream.Recv(&rsp); err != nil {
				return nil, fmt.Errorf("error receiving from %s.%s: %v", service, endpoint, err)
			}
			fmt.Print(string(rsp.Data))
		} else {
			var response map[string]interface{}
			if err := stream.Recv(&response); err != nil {
				return nil, fmt.Errorf("error receiving from %s.%s: %v", service, endpoint, err)
			}
			b, _ := json.MarshalIndent(response, "", "\t")
			fmt.Print(string(b))
		}
	}
}

func publish(c *cli.Context, args []string) ([]byte, error) {
	if err := clic.Publish(c, args); err != nil {
		return nil, err
	}
	return []byte(`ok`), nil
}

func queryHealth(c *cli.Context, args []string) ([]byte, error) {
	return clic.QueryHealth(c, args)
}

func queryStats(c *cli.Context, args []string) ([]byte, error) {
	return clic.QueryStats(c, args)
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"regexp"
	"strings"
	"testing"
)

func testcmd(cmd string) (string, error) {
	fmt.Println("(T) " + cmd)
	switch {
	case cmd == "sudo ls -a1F /mnt/sda1/var/lib/docker/vfs/dir":
		return currenttest.vs.ls(), nil
	case cmd == "docker ps -aq --no-trunc":
		return "", nil
	case strings.HasPrefix(cmd, "docker inspect -f '{{ .Name }},{{ range $key, $value := .Volumes }}{{ $key }},{{ $value }}##~#{{ end }}' "):
		return "", nil
	case strings.HasPrefix(cmd, "sudo rm /mnt/sda1/var/lib/docker/vfs/dir/"):
		deleted := cmd[len("sudo rm /mnt/sda1/var/lib/docker/vfs/dir/"):]
		deletions = append(deletions, deleted)
		return "", nil
	case strings.HasPrefix(cmd, "sudo readlink /mnt/sda1/var/lib/docker/vfs/dir/"):
		if strings.Contains(cmd, ",nonexistent") {
			return "", errors.New("non-existent linked folder")
		}
		r := regexp.MustCompile(`.*\$([^#]+)###.*`)
		ss := r.FindStringSubmatch(cmd)
		if len(ss) == 2 {
			folder := ss[1]
			folder = folder + strings.Repeat("1", 64-len(folder))
			return folder, nil
		}
		return "", nil
	case strings.HasPrefix(cmd, "sudo ls /mnt/sda1/var/lib/docker/vfs/dir/"):
		if cmd == "sudo ls /mnt/sda1/var/lib/docker/vfs/dir/" {
			return "", errors.New("non-ls linked folder")
		}
		return "", nil
	default:
		currentT.Fatalf("test '%s': unknown command!\n", cmd)
		return fmt.Sprintf("test '%s'", cmd), errors.New("unknown command")
	}
}

type volspecs []string
type Test struct {
	title string
	vs    volspecs
	res   []int
}

func (vs volspecs) ls() string {
	if len(vs) == 0 {
		return ""
	}
	res := ""
	for i, spec := range vs {
		if strings.HasSuffix(spec, "/") {
			spec = spec[:len(spec)-1]
			res = res + spec + strings.Repeat(fmt.Sprintf("%d", i), 64-len(spec)) + "/\n"
		}
		if strings.HasSuffix(spec, "@") {
			mp := "." + strings.Replace(spec, ";", "###", -1)
			mp = strings.Replace(mp, "/", ",#,", -1)
			res = res + mp + "\n"
		}
	}
	return res
}

var deletions = []string{}
var tests = []Test{
	Test{"empty vfs", []string{}, []int{0, 0, 0, 0, 0}},
	Test{"two volumes", []string{"fa/", "fb/"}, []int{0, 0, 2, 2, 0}},
	Test{"Invalid (ill-formed) markers must be deleted", []string{"cainv/path/a@"}, []int{0, 0, 0, 0, -1}},
	Test{"Invalid (no readlink) markers must be deleted", []string{"ca;/path/nonexistenta@", "cb;/path/nonexistentb@"}, []int{0, 0, 0, 0, -2}},
	Test{"Invalid (no ls) markers must be deleted", []string{"ca;/path/nolsa@", "cb;/path/nolsb@"}, []int{0, 0, 0, 0, -2}},
	Test{"Invalid (no vdir) markers must be deleted", []string{"ca$novdira;/path/nolsa@", "cb$novdirb;/path/nolsb@"}, []int{0, 0, 0, 0, -2}},
	Test{"two valid markers", []string{"ca$fa;/path/vola@", "cb$fb;/path/volb@"}, []int{0, 0, 0, 0, 2}},
}
var currenttest Test
var currentT *testing.T

// TestContainers test different vfs scenarios
func TestContainers(t *testing.T) {
	cmd = testcmd
	currentT = t
	for i, test := range tests {
		currenttest = test
		deletions = []string{}
		fmt.Println("------ vvv " + test.title + " vvv ------")
		main()
		tc := Containers()
		toc := OrphanedContainers()
		tv := Volumes()
		tov := OrphanedVolumes()
		tm := Markers()
		if len(tc) != test.res[0] {
			t.Errorf("Test %d: '%s' expected '%d' containers, got '%d'", i+1, test.title, test.res[0], len(tc))
		}
		if len(toc) != test.res[1] {
			t.Errorf("Test %d: '%s' expected '%d' orphaned containers, got '%d'", i+1, test.title, test.res[1], len(toc))
		}
		if len(tv) != test.res[2] {
			t.Errorf("Test %d: '%s' expected '%d' volumes, got '%d'", i+1, test.title, test.res[2], len(tv))
		}
		if len(tov) != test.res[3] {
			t.Errorf("Test %d: '%s' expected '%d' orphaned volumes, got '%d'", i+1, test.title, test.res[3], len(tov))
		}
		if nbmarkers(tm) != test.res[4] {
			t.Errorf("Test %d: '%s' expected '%d' markers, got '%d'", i+1, test.title, test.res[4], nbmarkers(tm))
		}
		fmt.Println("------ ^^^ " + test.title + " ^^^ ------")
		fmt.Println("----------")
	}
}

func nbmarkers(tm markers) int {
	res := len(tm)
	for _, d := range deletions {
		if strings.HasPrefix(d, ".") {
			res = res - 1
		}
	}
	return res
}
<commit_msg>gcl_test.go: test marker.String()<commit_after>package main

import (
	"errors"
	"fmt"
	"regexp"
	"strings"
	"testing"
)

func testcmd(cmd string) (string, error) {
	fmt.Println("(T) " + cmd)
	switch {
	case cmd == "sudo ls -a1F /mnt/sda1/var/lib/docker/vfs/dir":
		return currenttest.vs.ls(), nil
	case cmd == "docker ps -aq --no-trunc":
		return "", nil
	case strings.HasPrefix(cmd, "docker inspect -f '{{ .Name }},{{ range $key, $value := .Volumes }}{{ $key }},{{ $value }}##~#{{ end }}' "):
		return "", nil
	case strings.HasPrefix(cmd, "sudo rm /mnt/sda1/var/lib/docker/vfs/dir/"):
		deleted := cmd[len("sudo rm /mnt/sda1/var/lib/docker/vfs/dir/"):]
		deletions = append(deletions, deleted)
		return "", nil
	case strings.HasPrefix(cmd, "sudo readlink /mnt/sda1/var/lib/docker/vfs/dir/"):
		if strings.Contains(cmd, ",nonexistent") {
			return "", errors.New("non-existent linked folder")
		}
		r := regexp.MustCompile(`.*\$([^#]+)###.*`)
		ss := r.FindStringSubmatch(cmd)
		if len(ss) == 2 {
			folder := ss[1]
			folder = folder + strings.Repeat("1", 64-len(folder))
			return folder, nil
		}
		return "", nil
	case strings.HasPrefix(cmd, "sudo ls /mnt/sda1/var/lib/docker/vfs/dir/"):
		if cmd == "sudo ls /mnt/sda1/var/lib/docker/vfs/dir/" {
			return "", errors.New("non-ls linked folder")
		}
		return "", nil
	default:
		currentT.Fatalf("test '%s': unknown command!\n", cmd)
		return fmt.Sprintf("test '%s'", cmd), errors.New("unknown command")
	}
}

type volspecs []string
type Test struct {
	title string
	vs    volspecs
	res   []int
}

func (vs volspecs) ls() string {
	if len(vs) == 0 {
		return ""
	}
	res := ""
	for i, spec := range vs {
		if strings.HasSuffix(spec, "/") {
			spec = spec[:len(spec)-1]
			res = res + spec + strings.Repeat(fmt.Sprintf("%d", i), 64-len(spec)) + "/\n"
		}
		if strings.HasSuffix(spec, "@") {
			mp := "." + strings.Replace(spec, ";", "###", -1)
			mp = strings.Replace(mp, "/", ",#,", -1)
			res = res + mp + "\n"
		}
	}
	return res
}

var deletions = []string{}
var tests = []Test{
	Test{"empty vfs", []string{}, []int{0, 0, 0, 0, 0}},
	Test{"two volumes", []string{"fa/", "fb/"}, []int{0, 0, 2, 2, 0}},
	Test{"Invalid (ill-formed) markers must be deleted", []string{"cainv/path/a@"}, []int{0, 0, 0, 0, -1}},
	Test{"Invalid (no readlink) markers must be deleted", []string{"ca;/path/nonexistenta@", "cb;/path/nonexistentb@"}, []int{0, 0, 0, 0, -2}},
	Test{"Invalid (no ls) markers must be deleted", []string{"ca;/path/nolsa@", "cb;/path/nolsb@"}, []int{0, 0, 0, 0, -2}},
	Test{"Invalid (no vdir) markers must be deleted", []string{"ca$novdira;/path/nolsa@", "cb$novdirb;/path/nolsb@"}, []int{0, 0, 0, 0, -2}},
	Test{"two valid markers", []string{"ca$fa;/path/vola@", "cb$fb;/path/volb@"}, []int{0, 0, 0, 0, 2}},
}
var currenttest Test
var currentT *testing.T

// TestContainers test different vfs scenarios
func TestContainers(t *testing.T) {
	cmd = testcmd
	currentT = t
	for i, test := range tests {
		currenttest = test
		deletions = []string{}
		fmt.Println("------ vvv " + test.title + " vvv ------")
		main()
		tc := Containers()
		toc := OrphanedContainers()
		tv := Volumes()
		tov := OrphanedVolumes()
		tm := Markers()
		if len(tc) != test.res[0] {
			t.Errorf("Test %d: '%s' expected '%d' containers, got '%d'", i+1, test.title, test.res[0], len(tc))
		}
		if len(toc) != test.res[1] {
			t.Errorf("Test %d: '%s' expected '%d' orphaned containers, got '%d'", i+1, test.title, test.res[1], len(toc))
		}
		if len(tv) != test.res[2] {
			t.Errorf("Test %d: '%s' expected '%d' volumes, got '%d'", i+1, test.title, test.res[2], len(tv))
		}
		if len(tov) != test.res[3] {
			t.Errorf("Test %d: '%s' expected '%d' orphaned volumes, got '%d'", i+1, test.title, test.res[3], len(tov))
		}
		if nbmarkers(tm) != test.res[4] {
			t.Errorf("Test %d: '%s' expected '%d' markers, got '%d'", i+1, test.title, test.res[4], nbmarkers(tm))
		}
		if i == 6 && tm[0].String() != "marker 'fa11111'<ca$fa->/path/vola>" {
			t.Errorf("Test %d: '%s' expected marker '%s', got '%s'", i+1, test.title, "marker 'fa11111'<ca$fa->/path/vola>", tm[0].String())
		}
		fmt.Println("------ ^^^ " + test.title + " ^^^ ------")
		fmt.Println("----------")
	}
}

func nbmarkers(tm markers) int {
	res := len(tm)
	for _, d := range deletions {
		if strings.HasPrefix(d, ".") {
			res = res - 1
		}
	}
	return res
}
<|endoftext|>


<commit_before>// +build db

package postgres_test

import (
	"reflect"
	"testing"
	"time"

	"github.com/psimika/secure-web-app/petfind"
)

func TestCreateUser(t *testing.T) {
	s := setup(t)
	defer teardown(t, s)

	githubID := int64(5)
	u := &petfind.User{Name: "Jane Doe", GithubID: githubID}
	if err := s.CreateUser(u); err != nil {
		t.Fatalf("CreateUser failed: %v", err)
	}

	user, err := s.GetUserByGithubID(githubID)
	if err != nil {
		t.Fatalf("GetUserByGithubID failed: %v", err)
	}

	// Ignore time field.
	user.Created = time.Time{}

	want := &petfind.User{ID: 1, Name: "Jane Doe", GithubID: githubID}
	if got := user; !reflect.DeepEqual(got, want) {
		t.Fatalf("GetUserByGithubID \nhave: %#v\nwant: %#v", got, want)
	}
}

func TestGetUserByGithubID_notFound(t *testing.T) {
	s := setup(t)
	defer teardown(t, s)

	_, err := s.GetUserByGithubID(0)
	if err != petfind.ErrNotFound {
		t.Fatalf("GetUserByGithubID for unknown githubID returned %v, expected: %q", err, petfind.ErrNotFound)
	}
}

func TestPutGithubUser(t *testing.T) {
	s := setup(t)
	defer teardown(t, s)

	// We Put the GitHub user for the first time. The user does not exist so we
	// expect Put to create the user.
	githubID := int64(5)
	got, err := s.PutGithubUser(githubID, "janedoe", "Jane Doe", "jane@doe.com")
	if err != nil {
		t.Fatal("PutGithubUser for non existent user returned err:", err)
	}

	// Save created time to check it was the same when we Put for a second time
	// below.
	created := got.Created
	// Ignore time values.
	got.Created = time.Time{}
	got.Updated = time.Time{}

	want := &petfind.User{
		ID:       1, // A newly created user should get ID 1 from Postgres.
		GithubID: githubID,
		Login:    "janedoe",
		Name:     "Jane Doe",
		Email:    "jane@doe.com",
	}
	if !reflect.DeepEqual(got, want) {
		t.Fatalf("PutGithubUser first run \nhave: %#v\nwant: %#v", got, want)
	}

	// Attempt to Put again the github User. The GitHub user should have been
	// already been created from the previous run and we now expect the values
	// to be updated.
	got, err = s.PutGithubUser(githubID, "jane", "Jane", "jane@doe.com")
	if err != nil {
		t.Fatal("PutGithubUser for existing user returned err:", err)
	}

	// Ignore updated.
	got.Updated = time.Time{}

	want = &petfind.User{
		ID:       1, // ID stays the same as we are doing an update.
		GithubID: githubID,
		Login:    "jane",
		Name:     "Jane",
		Email:    "jane@doe.com",
		Created:  created,
	}
	// This time we expect the values to be updated but the created time should
	// be the same as the first run.
	if !reflect.DeepEqual(got, want) {
		t.Fatalf("PutGithubUser second run \nhave: %#v\nwant: %#v", got, want)
	}
}
<commit_msg>Add test for Put GitHub user with empty name<commit_after>// +build db

package postgres_test

import (
	"reflect"
	"testing"
	"time"

	"github.com/psimika/secure-web-app/petfind"
)

func TestCreateUser(t *testing.T) {
	s := setup(t)
	defer teardown(t, s)

	githubID := int64(5)
	u := &petfind.User{Name: "Jane Doe", GithubID: githubID}
	if err := s.CreateUser(u); err != nil {
		t.Fatalf("CreateUser failed: %v", err)
	}

	user, err := s.GetUserByGithubID(githubID)
	if err != nil {
		t.Fatalf("GetUserByGithubID failed: %v", err)
	}

	// Ignore time field.
	user.Created = time.Time{}

	want := &petfind.User{ID: 1, Name: "Jane Doe", GithubID: githubID}
	if got := user; !reflect.DeepEqual(got, want) {
		t.Fatalf("GetUserByGithubID \nhave: %#v\nwant: %#v", got, want)
	}
}

func TestGetUserByGithubID_notFound(t *testing.T) {
	s := setup(t)
	defer teardown(t, s)

	_, err := s.GetUserByGithubID(0)
	if err != petfind.ErrNotFound {
		t.Fatalf("GetUserByGithubID for unknown githubID returned %v, expected: %q", err, petfind.ErrNotFound)
	}
}

func TestPutGithubUser(t *testing.T) {
	s := setup(t)
	defer teardown(t, s)

	// We Put the GitHub user for the first time. The user does not exist so we
	// expect Put to create the user.
	githubID := int64(5)
	got, err := s.PutGithubUser(githubID, "janedoe", "Jane Doe", "jane@doe.com")
	if err != nil {
		t.Fatal("PutGithubUser for non existent user returned err:", err)
	}

	// Save created time to check it was the same when we Put for a second time
	// below.
	created := got.Created
	// Ignore time values.
	got.Created = time.Time{}
	got.Updated = time.Time{}

	want := &petfind.User{
		ID:       1, // A newly created user should get ID 1 from Postgres.
		GithubID: githubID,
		Login:    "janedoe",
		Name:     "Jane Doe",
		Email:    "jane@doe.com",
	}
	if !reflect.DeepEqual(got, want) {
		t.Fatalf("PutGithubUser first run \nhave: %#v\nwant: %#v", got, want)
	}

	// Attempt to Put again the github User. The GitHub user should have been
	// already been created from the previous run and we now expect the values
	// to be updated.
	got, err = s.PutGithubUser(githubID, "jane", "Jane", "jane@doe.com")
	if err != nil {
		t.Fatal("PutGithubUser for existing user returned err:", err)
	}

	// Ignore updated.
	got.Updated = time.Time{}

	want = &petfind.User{
		ID:       1, // ID stays the same as we are doing an update.
		GithubID: githubID,
		Login:    "jane",
		Name:     "Jane",
		Email:    "jane@doe.com",
		Created:  created,
	}
	// This time we expect the values to be updated but the created time should
	// be the same as the first run.
	if !reflect.DeepEqual(got, want) {
		t.Fatalf("PutGithubUser second run \nhave: %#v\nwant: %#v", got, want)
	}
}

// When a github user doesn't have their name filled in their profile, we
// use login instead.
func TestPutGithubUser_emptyName(t *testing.T) {
	s := setup(t)
	defer teardown(t, s)

	githubID := int64(5)
	u, err := s.PutGithubUser(githubID, "janedoe", "", "")
	if err != nil {
		t.Fatal("PutGithubUser with empty name returned err:", err)
	}

	// Check that login was used as a Name.
	if got, want := u.Name, "janedoe"; got != want {
		t.Errorf("PutGithubUser with empty name -> user.Name=%q, expected %q", got, want)
	}
}
<|endoftext|>


<commit_before>/*
Package proj provides an interface to the Cartographic Projections Library PROJ.4.

See: http://trac.osgeo.org/proj/

Example usage:

    merc, err := proj.NewProj("+proj=merc +ellps=clrk66 +lat_ts=33")
    defer merc.Close() // if omitted, this will be called on garbage collection
    if err != nil {
        log.Fatal(err)
    }

    ll, err := proj.NewProj("+proj=latlong +ellps=clrk66")
    defer ll.Close()
    if err != nil {
        log.Fatal(err)
    }

    x, y, err := proj.Transform2(ll, merc, 1, 1, proj.DegToRad(-16), proj.DegToRad(20.25))
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("%.2f %.2f", x, y)  // should print: -1495284.21 1920596.79
*/
package proj

/*
#cgo LDFLAGS: -lproj
#include "proj.h"
*/
import "C"

import (
	"errors"
	"math"
	"runtime"
	"unsafe"
)

type Proj struct {
	pj     _Ctype_projPJ
	opened bool
}

func NewProj(definition string) (*Proj, error) {
	cs := C.CString(definition)
	defer C.free(unsafe.Pointer(cs))
	proj := Proj{opened: false}
	proj.pj = C.pj_init_plus(cs)

	var err error = nil
	s := C.GoString(C.get_err())
	if s == "" {
		proj.opened = true
	} else {
		err = errors.New(s)
	}

	runtime.SetFinalizer(&proj, (*Proj).Close)

	return &proj, err
}

func (p *Proj) Close() {
	if p.opened {
		C.pj_free(p.pj)
		p.opened = false
	}
}

func transform(srcpj, dstpj *Proj, point_count int64, point_offset int, x, y, z float64, has_z bool) (float64, float64, float64, error) {
	if !(srcpj.opened && dstpj.opened) {
		return 0.0, 0.0, 0.0, errors.New("projection is closed")
	}

	var triple *C.triple
	if has_z {
		triple = C.transform(srcpj.pj, dstpj.pj, C.long(point_count), C.int(point_offset), C.double(x), C.double(y), C.double(z), C.int(0))
	} else {
		triple = C.transform(srcpj.pj, dstpj.pj, C.long(point_count), C.int(point_offset), C.double(x), C.double(y), C.double(0), C.int(0))
	}

	if triple == nil {
		return 0.0, 0.0, 0.0, errors.New("transform malloc failed")
	}
	defer C.free(unsafe.Pointer(triple))

	if e := C.GoString(triple.err); e != "" {
		return 0.0, 0.0, 0.0, errors.New(e)
	}

	return float64(triple.x), float64(triple.y), float64(triple.z), nil
}

func Transform2(srcpj, dstpj *Proj, point_count int64, point_offset int, x, y float64) (float64, float64, error) {
	xx, yy, _, err := transform(srcpj, dstpj, point_count, point_offset, x, y, 0, false)
	return xx, yy, err
}

func Transform3(srcpj, dstpj *Proj, point_count int64, point_offset int, x, y, z float64) (float64, float64, float64, error) {
	return transform(srcpj, dstpj, point_count, point_offset, x, y, z, true)
}

func DegToRad(deg float64) float64 {
	return deg / 180.0 * math.Pi
}

func RadToDeg(rad float64) float64 {
	return rad / math.Pi * 180.0
}
<commit_msg>Thread safety for C code.<commit_after>/*
Package proj provides an interface to the Cartographic Projections Library PROJ.4.

See: http://trac.osgeo.org/proj/

Example usage:

    merc, err := proj.NewProj("+proj=merc +ellps=clrk66 +lat_ts=33")
    defer merc.Close() // if omitted, this will be called on garbage collection
    if err != nil {
        log.Fatal(err)
    }

    ll, err := proj.NewProj("+proj=latlong +ellps=clrk66")
    defer ll.Close()
    if err != nil {
        log.Fatal(err)
    }

    x, y, err := proj.Transform2(ll, merc, 1, 1, proj.DegToRad(-16), proj.DegToRad(20.25))
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("%.2f %.2f", x, y)  // should print: -1495284.21 1920596.79
*/
package proj

/*
#cgo LDFLAGS: -lproj
#include "proj.h"
*/
import "C"

import (
	"errors"
	"math"
	"runtime"
	"unsafe"
)

type Proj struct {
	pj     _Ctype_projPJ
	opened bool
}

func NewProj(definition string) (*Proj, error) {
	runtime.LockOSThread()

	cs := C.CString(definition)
	defer C.free(unsafe.Pointer(cs))
	proj := Proj{opened: false}
	proj.pj = C.pj_init_plus(cs)

	var err error = nil
	s := C.GoString(C.get_err())
	if s == "" {
		proj.opened = true
	} else {
		err = errors.New(s)
	}

	runtime.UnlockOSThread()

	runtime.SetFinalizer(&proj, (*Proj).Close)

	return &proj, err
}

func (p *Proj) Close() {
	if p.opened {
		C.pj_free(p.pj)
		p.opened = false
	}
}

func transform(srcpj, dstpj *Proj, point_count int64, point_offset int, x, y, z float64, has_z bool) (float64, float64, float64, error) {
	if !(srcpj.opened && dstpj.opened) {
		return 0.0, 0.0, 0.0, errors.New("projection is closed")
	}

	var triple *C.triple
	if has_z {
		triple = C.transform(srcpj.pj, dstpj.pj, C.long(point_count), C.int(point_offset), C.double(x), C.double(y), C.double(z), C.int(0))
	} else {
		triple = C.transform(srcpj.pj, dstpj.pj, C.long(point_count), C.int(point_offset), C.double(x), C.double(y), C.double(0), C.int(0))
	}

	if triple == nil {
		return 0.0, 0.0, 0.0, errors.New("transform malloc failed")
	}
	defer C.free(unsafe.Pointer(triple))

	if e := C.GoString(triple.err); e != "" {
		return 0.0, 0.0, 0.0, errors.New(e)
	}

	return float64(triple.x), float64(triple.y), float64(triple.z), nil
}

func Transform2(srcpj, dstpj *Proj, point_count int64, point_offset int, x, y float64) (float64, float64, error) {
	xx, yy, _, err := transform(srcpj, dstpj, point_count, point_offset, x, y, 0, false)
	return xx, yy, err
}

func Transform3(srcpj, dstpj *Proj, point_count int64, point_offset int, x, y, z float64) (float64, float64, float64, error) {
	return transform(srcpj, dstpj, point_count, point_offset, x, y, z, true)
}

func DegToRad(deg float64) float64 {
	return deg / 180.0 * math.Pi
}

func RadToDeg(rad float64) float64 {
	return rad / math.Pi * 180.0
}
<|endoftext|>


<commit_before>package contractor

import (
	"errors"

	"github.com/NebulousLabs/Sia/build"
	"github.com/NebulousLabs/Sia/crypto"
	"github.com/NebulousLabs/Sia/modules"
	"github.com/NebulousLabs/Sia/modules/renter/proto"
	"github.com/NebulousLabs/Sia/types"
)

// the contractor will cap host's MaxCollateral setting to this value
var maxUploadCollateral = types.SiacoinPrecision.Mul64(1e3).Div(modules.BlockBytesPerMonthTerabyte) // 1k SC / TB / Month

// An Editor modifies a Contract by communicating with a host. It uses the
// contract revision protocol to send modification requests to the host.
// Editors are the means by which the renter uploads data to hosts.
type Editor interface {
	// Upload revises the underlying contract to store the new data. It
	// returns the Merkle root of the data.
	Upload(data []byte) (root crypto.Hash, err error)

	// Delete removes a sector from the underlying contract.
	Delete(crypto.Hash) error

	// Modify overwrites a sector with new data. Because the Editor does not
	// have access to the original sector data, the new Merkle root must be
	// supplied by the caller.
	Modify(oldRoot, newRoot crypto.Hash, offset uint64, newData []byte) error

	// Address returns the address of the host.
	Address() modules.NetAddress

	// ContractID returns the FileContractID of the contract.
	ContractID() types.FileContractID

	// EndHeight returns the height at which the contract ends.
	EndHeight() types.BlockHeight

	// Close terminates the connection to the host.
	Close() error
}

// A hostEditor modifies a Contract by calling the revise RPC on a host. It
// implements the Editor interface. hostEditors are NOT thread-safe; calls to
// Upload must happen in serial.
type hostEditor struct {
	editor     *proto.Editor
	contract   modules.RenterContract
	contractor *Contractor
}

// Address returns the NetAddress of the host.
func (he *hostEditor) Address() modules.NetAddress { return he.contract.NetAddress }

// ContractID returns the ID of the contract being revised.
func (he *hostEditor) ContractID() types.FileContractID { return he.contract.ID }

// EndHeight returns the height at which the host is no longer obligated to
// store the file.
func (he *hostEditor) EndHeight() types.BlockHeight { return he.contract.EndHeight() }

// Close cleanly terminates the revision loop with the host and closes the
// connection.
func (he *hostEditor) Close() error {
	// release revising lock
	he.contractor.mu.Lock()
	delete(he.contractor.revising, he.contract.ID)
	he.contractor.mu.Unlock()
	return he.editor.Close()
}

// Upload negotiates a revision that adds a sector to a file contract.
func (he *hostEditor) Upload(data []byte) (crypto.Hash, error) {
	oldUploadSpending := he.editor.UploadSpending
	oldStorageSpending := he.editor.StorageSpending
	contract, sectorRoot, err := he.editor.Upload(data)
	if err != nil {
		return crypto.Hash{}, err
	}
	uploadDelta := he.editor.UploadSpending.Sub(oldUploadSpending)
	storageDelta := he.editor.StorageSpending.Sub(oldStorageSpending)

	he.contractor.mu.Lock()
	he.contractor.financialMetrics.UploadSpending = he.contractor.financialMetrics.UploadSpending.Add(uploadDelta)
	he.contractor.financialMetrics.StorageSpending = he.contractor.financialMetrics.StorageSpending.Add(storageDelta)
	he.contractor.contracts[contract.ID] = contract
	he.contractor.saveSync()
	he.contractor.mu.Unlock()
	he.contract = contract

	return sectorRoot, nil
}

// Delete negotiates a revision that removes a sector from a file contract.
func (he *hostEditor) Delete(root crypto.Hash) error {
	contract, err := he.editor.Delete(root)
	if err != nil {
		return err
	}

	he.contractor.mu.Lock()
	he.contractor.contracts[contract.ID] = contract
	he.contractor.saveSync()
	he.contractor.mu.Unlock()
	he.contract = contract

	return nil
}

// Modify negotiates a revision that edits a sector in a file contract.
func (he *hostEditor) Modify(oldRoot, newRoot crypto.Hash, offset uint64, newData []byte) error {
	oldUploadSpending := he.editor.UploadSpending
	contract, err := he.editor.Modify(oldRoot, newRoot, offset, newData)
	if err != nil {
		return err
	}
	uploadDelta := he.editor.UploadSpending.Sub(oldUploadSpending)

	he.contractor.mu.Lock()
	he.contractor.financialMetrics.UploadSpending = he.contractor.financialMetrics.UploadSpending.Add(uploadDelta)
	he.contractor.contracts[contract.ID] = contract
	he.contractor.saveSync()
	he.contractor.mu.Unlock()
	he.contract = contract

	return nil
}

// Editor initiates the contract revision process with a host, and returns
// an Editor.
func (c *Contractor) Editor(contract modules.RenterContract) (Editor, error) {
	c.mu.RLock()
	height := c.blockHeight
	c.mu.RUnlock()
	if height > contract.EndHeight() {
		return nil, errors.New("contract has already ended")
	}
	host, ok := c.hdb.Host(contract.NetAddress)
	if !ok {
		return nil, errors.New("no record of that host")
	}
	if host.StoragePrice.Cmp(maxStoragePrice) > 0 {
		return nil, errTooExpensive
	}
	// cap host.Collateral on new hosts
	if build.VersionCmp(host.Version, "0.6.0") > 0 {
		if host.Collateral.Cmp(maxUploadCollateral) > 0 {
			host.Collateral = maxUploadCollateral
		}
	}

	// acquire revising lock
	c.mu.Lock()
	alreadyRevising := c.revising[contract.ID]
	if alreadyRevising {
		c.mu.Unlock()
		return nil, errors.New("already revising that contract")
	}
	c.revising[contract.ID] = true
	c.mu.Unlock()
	releaseLock := func() {
		c.mu.Lock()
		delete(c.revising, contract.ID)
		c.mu.Unlock()
	}

	// create editor
	e, err := proto.NewEditor(host, contract, height)
	if proto.IsRevisionMismatch(err) {
		// try again with the cached revision
		c.mu.RLock()
		cached, ok := c.cachedRevisions[contract.ID]
		c.mu.RUnlock()
		if !ok {
			// nothing we can do; return original error
			c.log.Printf("wanted to recover contract %v with host %v, but no revision was cached", contract.ID, contract.NetAddress)
			releaseLock()
			return nil, err
		}
		c.log.Printf("host %v has different revision for %v; retrying with cached revision", contract.NetAddress, contract.ID)
		contract.LastRevision = cached.revision
		contract.MerkleRoots = cached.merkleRoots
		e, err = proto.NewEditor(host, contract, height)
	}
	if err != nil {
		releaseLock()
		return nil, err
	}
	// supply a SaveFn that saves the revision to the contractor's persist
	// (the existing revision will be overwritten when SaveFn is called)
	e.SaveFn = c.saveRevision(contract.ID)

	return &hostEditor{
		editor:     e,
		contract:   contract,
		contractor: c,
	}, nil
}
<commit_msg>change locking scheme in contractor.Editor<commit_after>package contractor

import (
	"errors"

	"github.com/NebulousLabs/Sia/build"
	"github.com/NebulousLabs/Sia/crypto"
	"github.com/NebulousLabs/Sia/modules"
	"github.com/NebulousLabs/Sia/modules/renter/proto"
	"github.com/NebulousLabs/Sia/types"
)

// the contractor will cap host's MaxCollateral setting to this value
var maxUploadCollateral = types.SiacoinPrecision.Mul64(1e3).Div(modules.BlockBytesPerMonthTerabyte) // 1k SC / TB / Month

// An Editor modifies a Contract by communicating with a host. It uses the
// contract revision protocol to send modification requests to the host.
// Editors are the means by which the renter uploads data to hosts.
type Editor interface {
	// Upload revises the underlying contract to store the new data. It
	// returns the Merkle root of the data.
	Upload(data []byte) (root crypto.Hash, err error)

	// Delete removes a sector from the underlying contract.
	Delete(crypto.Hash) error

	// Modify overwrites a sector with new data. Because the Editor does not
	// have access to the original sector data, the new Merkle root must be
	// supplied by the caller.
	Modify(oldRoot, newRoot crypto.Hash, offset uint64, newData []byte) error

	// Address returns the address of the host.
	Address() modules.NetAddress

	// ContractID returns the FileContractID of the contract.
	ContractID() types.FileContractID

	// EndHeight returns the height at which the contract ends.
	EndHeight() types.BlockHeight

	// Close terminates the connection to the host.
	Close() error
}

// A hostEditor modifies a Contract by calling the revise RPC on a host. It
// implements the Editor interface. hostEditors are NOT thread-safe; calls to
// Upload must happen in serial.
type hostEditor struct {
	editor     *proto.Editor
	contract   modules.RenterContract
	contractor *Contractor
}

// Address returns the NetAddress of the host.
func (he *hostEditor) Address() modules.NetAddress { return he.contract.NetAddress }

// ContractID returns the ID of the contract being revised.
func (he *hostEditor) ContractID() types.FileContractID { return he.contract.ID }

// EndHeight returns the height at which the host is no longer obligated to
// store the file.
func (he *hostEditor) EndHeight() types.BlockHeight { return he.contract.EndHeight() }

// Close cleanly terminates the revision loop with the host and closes the
// connection.
func (he *hostEditor) Close() error {
	// release revising lock
	he.contractor.mu.Lock()
	delete(he.contractor.revising, he.contract.ID)
	he.contractor.mu.Unlock()
	return he.editor.Close()
}

// Upload negotiates a revision that adds a sector to a file contract.
func (he *hostEditor) Upload(data []byte) (crypto.Hash, error) {
	oldUploadSpending := he.editor.UploadSpending
	oldStorageSpending := he.editor.StorageSpending
	contract, sectorRoot, err := he.editor.Upload(data)
	if err != nil {
		return crypto.Hash{}, err
	}
	uploadDelta := he.editor.UploadSpending.Sub(oldUploadSpending)
	storageDelta := he.editor.StorageSpending.Sub(oldStorageSpending)

	he.contractor.mu.Lock()
	he.contractor.financialMetrics.UploadSpending = he.contractor.financialMetrics.UploadSpending.Add(uploadDelta)
	he.contractor.financialMetrics.StorageSpending = he.contractor.financialMetrics.StorageSpending.Add(storageDelta)
	he.contractor.contracts[contract.ID] = contract
	he.contractor.saveSync()
	he.contractor.mu.Unlock()
	he.contract = contract

	return sectorRoot, nil
}

// Delete negotiates a revision that removes a sector from a file contract.
func (he *hostEditor) Delete(root crypto.Hash) error {
	contract, err := he.editor.Delete(root)
	if err != nil {
		return err
	}

	he.contractor.mu.Lock()
	he.contractor.contracts[contract.ID] = contract
	he.contractor.saveSync()
	he.contractor.mu.Unlock()
	he.contract = contract

	return nil
}

// Modify negotiates a revision that edits a sector in a file contract.
func (he *hostEditor) Modify(oldRoot, newRoot crypto.Hash, offset uint64, newData []byte) error {
	oldUploadSpending := he.editor.UploadSpending
	contract, err := he.editor.Modify(oldRoot, newRoot, offset, newData)
	if err != nil {
		return err
	}
	uploadDelta := he.editor.UploadSpending.Sub(oldUploadSpending)

	he.contractor.mu.Lock()
	he.contractor.financialMetrics.UploadSpending = he.contractor.financialMetrics.UploadSpending.Add(uploadDelta)
	he.contractor.contracts[contract.ID] = contract
	he.contractor.saveSync()
	he.contractor.mu.Unlock()
	he.contract = contract

	return nil
}

// Editor initiates the contract revision process with a host, and returns
// an Editor.
func (c *Contractor) Editor(contract modules.RenterContract) (_ Editor, err error) {
	c.mu.RLock()
	height := c.blockHeight
	c.mu.RUnlock()
	if height > contract.EndHeight() {
		return nil, errors.New("contract has already ended")
	}
	host, ok := c.hdb.Host(contract.NetAddress)
	if !ok {
		return nil, errors.New("no record of that host")
	}
	if host.StoragePrice.Cmp(maxStoragePrice) > 0 {
		return nil, errTooExpensive
	}
	// cap host.Collateral on new hosts
	if build.VersionCmp(host.Version, "0.6.0") > 0 {
		if host.Collateral.Cmp(maxUploadCollateral) > 0 {
			host.Collateral = maxUploadCollateral
		}
	}

	// acquire revising lock
	c.mu.Lock()
	alreadyRevising := c.revising[contract.ID]
	if alreadyRevising {
		c.mu.Unlock()
		return nil, errors.New("already revising that contract")
	}
	c.revising[contract.ID] = true
	c.mu.Unlock()

	// release lock early if function returns an error
	defer func() {
		if err != nil {
			c.mu.Lock()
			delete(c.revising, contract.ID)
			c.mu.Unlock()
		}
	}()

	// create editor
	e, err := proto.NewEditor(host, contract, height)
	if proto.IsRevisionMismatch(err) {
		// try again with the cached revision
		c.mu.RLock()
		cached, ok := c.cachedRevisions[contract.ID]
		c.mu.RUnlock()
		if !ok {
			// nothing we can do; return original error
			c.log.Printf("wanted to recover contract %v with host %v, but no revision was cached", contract.ID, contract.NetAddress)
			return nil, err
		}
		c.log.Printf("host %v has different revision for %v; retrying with cached revision", contract.NetAddress, contract.ID)
		contract.LastRevision = cached.revision
		contract.MerkleRoots = cached.merkleRoots
		e, err = proto.NewEditor(host, contract, height)
	}
	if err != nil {
		return nil, err
	}
	// supply a SaveFn that saves the revision to the contractor's persist
	// (the existing revision will be overwritten when SaveFn is called)
	e.SaveFn = c.saveRevision(contract.ID)

	return &hostEditor{
		editor:     e,
		contract:   contract,
		contractor: c,
	}, nil
}
<|endoftext|>


<commit_before>package hypertrack

type GeoJSON struct {
	Type        GeoJSONType  `json:"type"`
	Coordinates []Coordinate `json:"coordinates"`
}

type GeoJSONType string

const (
	GeoJSONTypePoint = AvailabilityStatus("Point")
)

type Coordinate []float64
<commit_msg>GeoJSON coordinate is float type<commit_after>package hypertrack

type GeoJSON struct {
	Type        GeoJSONType  `json:"type"`
	Coordinates []Coordinate `json:"coordinates"`
}

type GeoJSONType float64

const (
	GeoJSONTypePoint = AvailabilityStatus("Point")
)

type Coordinate []float64
<|endoftext|>


<commit_before>/*
Copyright 2018 The Kubernetes Authors.

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

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

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

package cephfs

import (
	"fmt"
	"os"

	"github.com/golang/glog"
	"golang.org/x/net/context"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"

	"github.com/container-storage-interface/spec/lib/go/csi/v0"
	"github.com/kubernetes-csi/drivers/pkg/csi-common"
)

type controllerServer struct {
	*csicommon.DefaultControllerServer
}

const (
	oneGB = 1073741824
)

func (cs *controllerServer) validateCreateVolumeRequest(req *csi.CreateVolumeRequest) error {
	if err := cs.Driver.ValidateControllerServiceRequest(csi.ControllerServiceCapability_RPC_CREATE_DELETE_VOLUME); err != nil {
		return fmt.Errorf("Invalid CreateVolumeRequest: %v", err)
	}

	if req.GetName() == "" {
		return status.Error(codes.InvalidArgument, "Volume Name cannot be empty")
	}

	if req.GetVolumeCapabilities() == nil {
		return status.Error(codes.InvalidArgument, "Volume Capabilities cannot be empty")
	}

	return nil
}

func (cs *controllerServer) validateDeleteVolumeRequest(req *csi.DeleteVolumeRequest) error {
	if err := cs.Driver.ValidateControllerServiceRequest(csi.ControllerServiceCapability_RPC_CREATE_DELETE_VOLUME); err != nil {
		return fmt.Errorf("Invalid DeleteVolumeRequest: %v", err)
	}

	return nil
}

func (cs *controllerServer) CreateVolume(ctx context.Context, req *csi.CreateVolumeRequest) (*csi.CreateVolumeResponse, error) {
	if err := cs.validateCreateVolumeRequest(req); err != nil {
		glog.Errorf("CreateVolumeRequest validation failed: %v", err)
		return nil, err
	}

	// Configuration

	volOptions, err := newVolumeOptions(req.GetParameters())
	if err != nil {
		glog.Errorf("validation of volume options failed: %v", err)
		return nil, status.Error(codes.InvalidArgument, err.Error())
	}

	volId := newVolumeIdentifier(volOptions, req)

	// Create a volume in case the user didn't provide one

	if volOptions.ProvisionVolume {
		// Admin access is required

		cr, err := getAdminCredentials(req.GetControllerCreateSecrets())
		if err != nil {
			return nil, status.Error(codes.InvalidArgument, err.Error())
		}

		if err = storeCephAdminCredentials(cr); err != nil {
			glog.Errorf("failed to store admin credentials for '%s': %v", cr.id, err)
			return nil, status.Error(codes.Internal, err.Error())
		}

		if err = createVolume(volOptions, cr, volId.uuid, req.GetCapacityRange().GetRequiredBytes()); err != nil {
			glog.Errorf("failed to create volume %s: %v", volId.name, err)
			return nil, status.Error(codes.Internal, err.Error())
		}

		glog.V(4).Infof("cephfs: volume %s successfuly created", volId.id)
	} else {
		glog.V(4).Infof("cephfs: volume %s is provisioned statically", volId.id)
	}

	if err = volCache.insert(&volumeCacheEntry{Identifier: *volId, VolOptions: *volOptions}); err != nil {
		glog.Warningf("failed to store a volume cache entry: %v", err)
	}

	return &csi.CreateVolumeResponse{
		Volume: &csi.Volume{
			Id:            volId.id,
			CapacityBytes: req.GetCapacityRange().GetRequiredBytes(),
			Attributes:    req.GetParameters(),
		},
	}, nil
}

func (cs *controllerServer) DeleteVolume(ctx context.Context, req *csi.DeleteVolumeRequest) (*csi.DeleteVolumeResponse, error) {
	if err := cs.validateDeleteVolumeRequest(req); err != nil {
		glog.Errorf("DeleteVolumeRequest validation failed: %v", err)
		return nil, err
	}

	var (
		cr      *credentials
		err     error
		volId   = req.GetVolumeId()
		volUuid = uuidFromVolumeId(volId)
	)

	// Load volume info from cache

	ent, found := volCache.get(volUuid)
	if !found {
		msg := fmt.Sprintf("failed to retrieve cache entry for volume %s", volId)
		glog.Error(msg)
		return nil, status.Error(codes.Internal, msg)
	}

	// Set the correct user for mounting

	if ent.VolOptions.ProvisionVolume {
		// Admin access is required

		cr, err = getAdminCredentials(req.GetControllerDeleteSecrets())
		if err != nil {
			return nil, status.Error(codes.InvalidArgument, err.Error())
		}
	} else {
		cr, err = getUserCredentials(req.GetControllerDeleteSecrets())
		if err != nil {
			return nil, status.Error(codes.InvalidArgument, err.Error())
		}
	}

	// Delete the volume contents

	if err := purgeVolume(volId, cr, &ent.VolOptions); err != nil {
		glog.Error(err)
		return nil, status.Error(codes.Internal, err.Error())
	}

	// Clean up remaining files

	if ent.VolOptions.ProvisionVolume {
		// The user is no longer needed
		if err := deleteCephUser(volUuid); err != nil {
			glog.Warningf("failed to delete ceph user '%s': %v", cr.id, err)
		}

		userId := getCephUserName(volUuid)
		os.Remove(getCephKeyringPath(userId))
		os.Remove(getCephSecretPath(userId))
	} else {
		os.Remove(getCephKeyringPath(cr.id))
		os.Remove(getCephSecretPath(cr.id))
	}

	if err := volCache.erase(volUuid); err != nil {
		return nil, status.Error(codes.Internal, err.Error())
	}

	glog.V(4).Infof("cephfs: volume %s successfuly deleted", volId)

	return &csi.DeleteVolumeResponse{}, nil
}

func (cs *controllerServer) ValidateVolumeCapabilities(
	ctx context.Context,
	req *csi.ValidateVolumeCapabilitiesRequest) (*csi.ValidateVolumeCapabilitiesResponse, error) {
	return &csi.ValidateVolumeCapabilitiesResponse{Supported: true}, nil
}
<commit_msg>cephfs: CreateVolume() needs ceph config<commit_after>/*
Copyright 2018 The Kubernetes Authors.

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

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

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

package cephfs

import (
	"fmt"
	"os"

	"github.com/golang/glog"
	"golang.org/x/net/context"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"

	"github.com/container-storage-interface/spec/lib/go/csi/v0"
	"github.com/kubernetes-csi/drivers/pkg/csi-common"
)

type controllerServer struct {
	*csicommon.DefaultControllerServer
}

const (
	oneGB = 1073741824
)

func (cs *controllerServer) validateCreateVolumeRequest(req *csi.CreateVolumeRequest) error {
	if err := cs.Driver.ValidateControllerServiceRequest(csi.ControllerServiceCapability_RPC_CREATE_DELETE_VOLUME); err != nil {
		return fmt.Errorf("Invalid CreateVolumeRequest: %v", err)
	}

	if req.GetName() == "" {
		return status.Error(codes.InvalidArgument, "Volume Name cannot be empty")
	}

	if req.GetVolumeCapabilities() == nil {
		return status.Error(codes.InvalidArgument, "Volume Capabilities cannot be empty")
	}

	return nil
}

func (cs *controllerServer) validateDeleteVolumeRequest(req *csi.DeleteVolumeRequest) error {
	if err := cs.Driver.ValidateControllerServiceRequest(csi.ControllerServiceCapability_RPC_CREATE_DELETE_VOLUME); err != nil {
		return fmt.Errorf("Invalid DeleteVolumeRequest: %v", err)
	}

	return nil
}

func (cs *controllerServer) CreateVolume(ctx context.Context, req *csi.CreateVolumeRequest) (*csi.CreateVolumeResponse, error) {
	if err := cs.validateCreateVolumeRequest(req); err != nil {
		glog.Errorf("CreateVolumeRequest validation failed: %v", err)
		return nil, err
	}

	// Configuration

	volOptions, err := newVolumeOptions(req.GetParameters())
	if err != nil {
		glog.Errorf("validation of volume options failed: %v", err)
		return nil, status.Error(codes.InvalidArgument, err.Error())
	}

	volId := newVolumeIdentifier(volOptions, req)

	conf := cephConfigData{Monitors: volOptions.Monitors, VolumeUuid: volId.uuid}
	if err = conf.writeToFile(); err != nil {
		glog.Errorf("failed to write ceph config file to %s: %v", getCephConfPath(volId.uuid), err)
		return nil, status.Error(codes.Internal, err.Error())
	}

	// Create a volume in case the user didn't provide one

	if volOptions.ProvisionVolume {
		// Admin access is required

		cr, err := getAdminCredentials(req.GetControllerCreateSecrets())
		if err != nil {
			return nil, status.Error(codes.InvalidArgument, err.Error())
		}

		if err = storeCephAdminCredentials(volId.uuid, cr); err != nil {
			glog.Errorf("failed to store admin credentials for '%s': %v", cr.id, err)
			return nil, status.Error(codes.Internal, err.Error())
		}

		if err = createVolume(volOptions, cr, volId.uuid, req.GetCapacityRange().GetRequiredBytes()); err != nil {
			glog.Errorf("failed to create volume %s: %v", volId.name, err)
			return nil, status.Error(codes.Internal, err.Error())
		}

		glog.V(4).Infof("cephfs: volume %s successfuly created", volId.id)
	} else {
		glog.V(4).Infof("cephfs: volume %s is provisioned statically", volId.id)
	}

	if err = volCache.insert(&volumeCacheEntry{Identifier: *volId, VolOptions: *volOptions}); err != nil {
		glog.Warningf("failed to store a volume cache entry: %v", err)
	}

	return &csi.CreateVolumeResponse{
		Volume: &csi.Volume{
			Id:            volId.id,
			CapacityBytes: req.GetCapacityRange().GetRequiredBytes(),
			Attributes:    req.GetParameters(),
		},
	}, nil
}

func (cs *controllerServer) DeleteVolume(ctx context.Context, req *csi.DeleteVolumeRequest) (*csi.DeleteVolumeResponse, error) {
	if err := cs.validateDeleteVolumeRequest(req); err != nil {
		glog.Errorf("DeleteVolumeRequest validation failed: %v", err)
		return nil, err
	}

	var (
		cr      *credentials
		err     error
		volId   = req.GetVolumeId()
		volUuid = uuidFromVolumeId(volId)
	)

	// Load volume info from cache

	ent, found := volCache.get(volUuid)
	if !found {
		msg := fmt.Sprintf("failed to retrieve cache entry for volume %s", volId)
		glog.Error(msg)
		return nil, status.Error(codes.Internal, msg)
	}

	// Set the correct user for mounting

	if ent.VolOptions.ProvisionVolume {
		// Admin access is required

		cr, err = getAdminCredentials(req.GetControllerDeleteSecrets())
		if err != nil {
			return nil, status.Error(codes.InvalidArgument, err.Error())
		}
	} else {
		cr, err = getUserCredentials(req.GetControllerDeleteSecrets())
		if err != nil {
			return nil, status.Error(codes.InvalidArgument, err.Error())
		}
	}

	// Delete the volume contents

	if err := purgeVolume(volId, cr, &ent.VolOptions); err != nil {
		glog.Error(err)
		return nil, status.Error(codes.Internal, err.Error())
	}

	// Clean up remaining files

	if ent.VolOptions.ProvisionVolume {
		// The user is no longer needed
		if err := deleteCephUser(cr, volUuid); err != nil {
			glog.Warningf("failed to delete ceph user '%s': %v", cr.id, err)
		}

		userId := getCephUserName(volUuid)
		os.Remove(getCephKeyringPath(volUuid, userId))
		os.Remove(getCephSecretPath(volUuid, userId))
	} else {
		os.Remove(getCephKeyringPath(volUuid, cr.id))
		os.Remove(getCephSecretPath(volUuid, cr.id))
	}

	if err := volCache.erase(volUuid); err != nil {
		return nil, status.Error(codes.Internal, err.Error())
	}

	glog.V(4).Infof("cephfs: volume %s successfuly deleted", volId)

	return &csi.DeleteVolumeResponse{}, nil
}

func (cs *controllerServer) ValidateVolumeCapabilities(
	ctx context.Context,
	req *csi.ValidateVolumeCapabilitiesRequest) (*csi.ValidateVolumeCapabilitiesResponse, error) {
	return &csi.ValidateVolumeCapabilitiesResponse{Supported: true}, nil
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"net/http"
	_ "net/http/pprof"
	"os"
	"os/signal"
	"runtime"
	"runtime/trace"
	"strconv"
	"syscall"
	"time"

	extensions "github.com/grafana/grafana/pkg/extensions"
	"github.com/grafana/grafana/pkg/log"
	"github.com/grafana/grafana/pkg/metrics"
	_ "github.com/grafana/grafana/pkg/services/alerting/conditions"
	_ "github.com/grafana/grafana/pkg/services/alerting/notifiers"
	"github.com/grafana/grafana/pkg/setting"
	_ "github.com/grafana/grafana/pkg/tsdb/cloudwatch"
	_ "github.com/grafana/grafana/pkg/tsdb/elasticsearch"
	_ "github.com/grafana/grafana/pkg/tsdb/graphite"
	_ "github.com/grafana/grafana/pkg/tsdb/influxdb"
	_ "github.com/grafana/grafana/pkg/tsdb/mysql"
	_ "github.com/grafana/grafana/pkg/tsdb/opentsdb"
	_ "github.com/grafana/grafana/pkg/tsdb/postgres"
	_ "github.com/grafana/grafana/pkg/tsdb/prometheus"
	_ "github.com/grafana/grafana/pkg/tsdb/stackdriver"
	_ "github.com/grafana/grafana/pkg/tsdb/testdata"
)

var version = "5.0.0"
var commit = "NA"
var buildBranch = "master"
var buildstamp string

var configFile = flag.String("config", "", "path to config file")
var homePath = flag.String("homepath", "", "path to grafana install/home path, defaults to working directory")
var pidFile = flag.String("pidfile", "", "path to pid file")

func main() {
	v := flag.Bool("v", false, "prints current version and exits")
	profile := flag.Bool("profile", false, "Turn on pprof profiling")
	profilePort := flag.Int("profile-port", 6060, "Define custom port for profiling")
	flag.Parse()
	if *v {
		fmt.Printf("Version %s (commit: %s, branch: %s)\n", version, commit, buildBranch)
		os.Exit(0)
	}

	if *profile {
		runtime.SetBlockProfileRate(1)
		go func() {
			http.ListenAndServe(fmt.Sprintf("localhost:%d", *profilePort), nil)
		}()

		f, err := os.Create("trace.out")
		if err != nil {
			panic(err)
		}
		defer f.Close()

		err = trace.Start(f)
		if err != nil {
			panic(err)
		}
		defer trace.Stop()
	}

	buildstampInt64, _ := strconv.ParseInt(buildstamp, 10, 64)
	if buildstampInt64 == 0 {
		buildstampInt64 = time.Now().Unix()
	}

	setting.BuildVersion = version
	setting.BuildCommit = commit
	setting.BuildStamp = buildstampInt64
	setting.BuildBranch = buildBranch
	setting.IsEnterprise = extensions.IsEnterprise

	metrics.SetBuildInformation(version, commit, buildBranch)

	server := NewGrafanaServer()

	go listenToSystemSignals(server)

	err := server.Run()

	code := server.Exit(err)
	trace.Stop()
	log.Close()

	os.Exit(code)
}

func listenToSystemSignals(server *GrafanaServerImpl) {
	signalChan := make(chan os.Signal, 1)
	sighupChan := make(chan os.Signal, 1)

	signal.Notify(sighupChan, syscall.SIGHUP)
	signal.Notify(signalChan, os.Interrupt, syscall.SIGTERM)

	for {
		select {
		case <-sighupChan:
			log.Reload()
		case sig := <-signalChan:
			server.Shutdown(fmt.Sprintf("System signal: %s", sig))
		}
	}
}
<commit_msg>pkg/cmd/grafana-server/main.go: Fix error value not checked<commit_after>package main

import (
	"flag"
	"fmt"
	"net/http"
	_ "net/http/pprof"
	"os"
	"os/signal"
	"runtime"
	"runtime/trace"
	"strconv"
	"syscall"
	"time"

	extensions "github.com/grafana/grafana/pkg/extensions"
	"github.com/grafana/grafana/pkg/log"
	"github.com/grafana/grafana/pkg/metrics"
	_ "github.com/grafana/grafana/pkg/services/alerting/conditions"
	_ "github.com/grafana/grafana/pkg/services/alerting/notifiers"
	"github.com/grafana/grafana/pkg/setting"
	_ "github.com/grafana/grafana/pkg/tsdb/cloudwatch"
	_ "github.com/grafana/grafana/pkg/tsdb/elasticsearch"
	_ "github.com/grafana/grafana/pkg/tsdb/graphite"
	_ "github.com/grafana/grafana/pkg/tsdb/influxdb"
	_ "github.com/grafana/grafana/pkg/tsdb/mysql"
	_ "github.com/grafana/grafana/pkg/tsdb/opentsdb"
	_ "github.com/grafana/grafana/pkg/tsdb/postgres"
	_ "github.com/grafana/grafana/pkg/tsdb/prometheus"
	_ "github.com/grafana/grafana/pkg/tsdb/stackdriver"
	_ "github.com/grafana/grafana/pkg/tsdb/testdata"
)

var version = "5.0.0"
var commit = "NA"
var buildBranch = "master"
var buildstamp string

var configFile = flag.String("config", "", "path to config file")
var homePath = flag.String("homepath", "", "path to grafana install/home path, defaults to working directory")
var pidFile = flag.String("pidfile", "", "path to pid file")

func main() {
	v := flag.Bool("v", false, "prints current version and exits")
	profile := flag.Bool("profile", false, "Turn on pprof profiling")
	profilePort := flag.Int("profile-port", 6060, "Define custom port for profiling")
	flag.Parse()
	if *v {
		fmt.Printf("Version %s (commit: %s, branch: %s)\n", version, commit, buildBranch)
		os.Exit(0)
	}

	if *profile {
		runtime.SetBlockProfileRate(1)
		go func() {
			err := http.ListenAndServe(fmt.Sprintf("localhost:%d", *profilePort), nil)
			if err != nil {
				panic(err)
			}
		}()

		f, err := os.Create("trace.out")
		if err != nil {
			panic(err)
		}
		defer f.Close()

		err = trace.Start(f)
		if err != nil {
			panic(err)
		}
		defer trace.Stop()
	}

	buildstampInt64, _ := strconv.ParseInt(buildstamp, 10, 64)
	if buildstampInt64 == 0 {
		buildstampInt64 = time.Now().Unix()
	}

	setting.BuildVersion = version
	setting.BuildCommit = commit
	setting.BuildStamp = buildstampInt64
	setting.BuildBranch = buildBranch
	setting.IsEnterprise = extensions.IsEnterprise

	metrics.SetBuildInformation(version, commit, buildBranch)

	server := NewGrafanaServer()

	go listenToSystemSignals(server)

	err := server.Run()

	code := server.Exit(err)
	trace.Stop()
	log.Close()

	os.Exit(code)
}

func listenToSystemSignals(server *GrafanaServerImpl) {
	signalChan := make(chan os.Signal, 1)
	sighupChan := make(chan os.Signal, 1)

	signal.Notify(sighupChan, syscall.SIGHUP)
	signal.Notify(signalChan, os.Interrupt, syscall.SIGTERM)

	for {
		select {
		case <-sighupChan:
			log.Reload()
		case sig := <-signalChan:
			server.Shutdown(fmt.Sprintf("System signal: %s", sig))
		}
	}
}
<|endoftext|>


<commit_before>package configconversion

import (
	configv1 "github.com/openshift/api/config/v1"
	kubecontrolplanev1 "github.com/openshift/api/kubecontrolplane/v1"
	legacyconfigv1 "github.com/openshift/api/legacyconfig/v1"
	openshiftcontrolplanev1 "github.com/openshift/api/openshiftcontrolplane/v1"
	osinv1 "github.com/openshift/api/osin/v1"
)

func ToHTTPServingInfo(in *legacyconfigv1.HTTPServingInfo) (out configv1.HTTPServingInfo, err error) {
	err = Convert_legacyconfigv1_HTTPServingInfo_to_configv1_HTTPServingInfo(in, &out, nil)
	if err != nil {
		return configv1.HTTPServingInfo{}, err
	}
	return out, nil
}

func ToKubeClientConfig(in *legacyconfigv1.MasterClients) (out configv1.KubeClientConfig, err error) {
	err = Convert_legacyconfigv1_MasterClients_to_configv1_KubeClientConfig(in, &out, nil)
	if err != nil {
		return configv1.KubeClientConfig{}, err
	}
	return out, nil
}

func ToAuditConfig(in *legacyconfigv1.AuditConfig) (out configv1.AuditConfig, err error) {
	err = Convert_legacyconfigv1_AuditConfig_to_configv1_AuditConfig(in, &out, nil)
	if err != nil {
		return configv1.AuditConfig{}, err
	}
	return out, nil
}

func ToEtcdConnectionInfo(in *legacyconfigv1.EtcdConnectionInfo) (out configv1.EtcdConnectionInfo, err error) {
	err = Convert_legacyconfigv1_EtcdConnectionInfo_to_configv1_EtcdConnectionInfo(in, &out, nil)
	if err != nil {
		return configv1.EtcdConnectionInfo{}, err
	}
	return out, nil
}

func ToAdmissionPluginConfig(in *legacyconfigv1.AdmissionPluginConfig) (*configv1.AdmissionPluginConfig, error) {
	out := &configv1.AdmissionPluginConfig{}
	if err := Convert_legacyconfigv1_AdmissionPluginConfig_to_configv1_AdmissionPluginConfig(in, out, nil); err != nil {
		return nil, err
	}
	return out, nil
}

func ToAdmissionPluginConfigMap(in map[string]*legacyconfigv1.AdmissionPluginConfig) (out map[string]configv1.AdmissionPluginConfig, err error) {
	if in == nil {
		return nil, nil
	}

	out = map[string]configv1.AdmissionPluginConfig{}
	for k, v := range in {
		outV, err := ToAdmissionPluginConfig(v)
		if err != nil {
			return nil, err
		}
		out[k] = *outV

	}

	return out, nil
}

func ToMasterAuthConfig(in *legacyconfigv1.MasterAuthConfig) (out kubecontrolplanev1.MasterAuthConfig, err error) {
	err = Convert_legacyconfigv1_MasterAuthConfig_to_kubecontrolplanev1_MasterAuthConfig(in, &out, nil)
	if err != nil {
		return kubecontrolplanev1.MasterAuthConfig{}, err
	}
	return out, nil
}

func ToAggregatorConfig(in *legacyconfigv1.AggregatorConfig) (out kubecontrolplanev1.AggregatorConfig, err error) {
	err = Convert_legacyconfigv1_AggregatorConfig_to_kubecontrolplanev1_AggregatorConfig(in, &out, nil)
	if err != nil {
		return kubecontrolplanev1.AggregatorConfig{}, err
	}
	return out, nil
}

func ToKubeletConnectionInfo(in *legacyconfigv1.KubeletConnectionInfo) (out kubecontrolplanev1.KubeletConnectionInfo, err error) {
	err = Convert_legacyconfigv1_KubeletConnectionInfo_to_kubecontrolplanev1_KubeletConnectionInfo(in, &out, nil)
	if err != nil {
		return kubecontrolplanev1.KubeletConnectionInfo{}, err
	}
	return out, nil
}

func ToUserAgentMatchingConfig(in *legacyconfigv1.UserAgentMatchingConfig) (out kubecontrolplanev1.UserAgentMatchingConfig, err error) {
	err = Convert_legacyconfigv1_UserAgentMatchingConfig_to_kubecontrolplanev1_UserAgentMatchingConfig(in, &out, nil)
	if err != nil {
		return kubecontrolplanev1.UserAgentMatchingConfig{}, err
	}
	return out, nil
}

func ToOAuthConfig(in *legacyconfigv1.OAuthConfig) (*osinv1.OAuthConfig, error) {
	if in == nil {
		return nil, nil
	}
	out := &osinv1.OAuthConfig{}
	if err := Convert_legacyconfigv1_OAuthConfig_to_osinv1_OAuthConfig(in, out, nil); err != nil {
		return nil, err
	}
	return out, nil
}

func ToJenkinsPipelineConfig(in *legacyconfigv1.JenkinsPipelineConfig) (out openshiftcontrolplanev1.JenkinsPipelineConfig, err error) {
	err = Convert_legacyconfigv1_JenkinsPipelineConfig_to_kubecontrolplanev1_JenkinsPipelineConfig(in, &out, nil)
	if err != nil {
		return openshiftcontrolplanev1.JenkinsPipelineConfig{}, err
	}
	return out, nil
}

func ToAllowedRegistries(in *legacyconfigv1.AllowedRegistries) (openshiftcontrolplanev1.AllowedRegistries, error) {
	if in == nil {
		return openshiftcontrolplanev1.AllowedRegistries{}, nil
	}

	out := openshiftcontrolplanev1.AllowedRegistries{}
	for i := range *in {
		currOut := openshiftcontrolplanev1.RegistryLocation{}
		err := Convert_legacyconfigv1_RegistryLocation_to_kubecontrolplanev1_RegistryLocation(&(*in)[i], &currOut, nil)
		if err != nil {
			return nil, err
		}
		out = append(out, currOut)
	}
	return out, nil
}
<commit_msg>Filter kubernetes admission plugins<commit_after>package configconversion

import (
	configv1 "github.com/openshift/api/config/v1"
	kubecontrolplanev1 "github.com/openshift/api/kubecontrolplane/v1"
	legacyconfigv1 "github.com/openshift/api/legacyconfig/v1"
	openshiftcontrolplanev1 "github.com/openshift/api/openshiftcontrolplane/v1"
	osinv1 "github.com/openshift/api/osin/v1"
	"github.com/openshift/origin/pkg/apiserver/admission"
)

func ToHTTPServingInfo(in *legacyconfigv1.HTTPServingInfo) (out configv1.HTTPServingInfo, err error) {
	err = Convert_legacyconfigv1_HTTPServingInfo_to_configv1_HTTPServingInfo(in, &out, nil)
	if err != nil {
		return configv1.HTTPServingInfo{}, err
	}
	return out, nil
}

func ToKubeClientConfig(in *legacyconfigv1.MasterClients) (out configv1.KubeClientConfig, err error) {
	err = Convert_legacyconfigv1_MasterClients_to_configv1_KubeClientConfig(in, &out, nil)
	if err != nil {
		return configv1.KubeClientConfig{}, err
	}
	return out, nil
}

func ToAuditConfig(in *legacyconfigv1.AuditConfig) (out configv1.AuditConfig, err error) {
	err = Convert_legacyconfigv1_AuditConfig_to_configv1_AuditConfig(in, &out, nil)
	if err != nil {
		return configv1.AuditConfig{}, err
	}
	return out, nil
}

func ToEtcdConnectionInfo(in *legacyconfigv1.EtcdConnectionInfo) (out configv1.EtcdConnectionInfo, err error) {
	err = Convert_legacyconfigv1_EtcdConnectionInfo_to_configv1_EtcdConnectionInfo(in, &out, nil)
	if err != nil {
		return configv1.EtcdConnectionInfo{}, err
	}
	return out, nil
}

func ToAdmissionPluginConfig(in *legacyconfigv1.AdmissionPluginConfig) (*configv1.AdmissionPluginConfig, error) {
	out := &configv1.AdmissionPluginConfig{}
	if err := Convert_legacyconfigv1_AdmissionPluginConfig_to_configv1_AdmissionPluginConfig(in, out, nil); err != nil {
		return nil, err
	}
	return out, nil
}

func ToAdmissionPluginConfigMap(in map[string]*legacyconfigv1.AdmissionPluginConfig) (out map[string]configv1.AdmissionPluginConfig, err error) {
	if in == nil {
		return nil, nil
	}

	out = map[string]configv1.AdmissionPluginConfig{}
	for k, v := range in {
		if !isKnownKubeAdmissionPlugin(k) {
			continue
		}
		outV, err := ToAdmissionPluginConfig(v)
		if err != nil {
			return nil, err
		}
		out[k] = *outV

	}

	return out, nil
}

func isKnownKubeAdmissionPlugin(pluginName string) bool {
	for _, plugin := range admission.KubeAdmissionPlugins {
		if pluginName == plugin {
			return true
		}
	}

	return false
}

func ToMasterAuthConfig(in *legacyconfigv1.MasterAuthConfig) (out kubecontrolplanev1.MasterAuthConfig, err error) {
	err = Convert_legacyconfigv1_MasterAuthConfig_to_kubecontrolplanev1_MasterAuthConfig(in, &out, nil)
	if err != nil {
		return kubecontrolplanev1.MasterAuthConfig{}, err
	}
	return out, nil
}

func ToAggregatorConfig(in *legacyconfigv1.AggregatorConfig) (out kubecontrolplanev1.AggregatorConfig, err error) {
	err = Convert_legacyconfigv1_AggregatorConfig_to_kubecontrolplanev1_AggregatorConfig(in, &out, nil)
	if err != nil {
		return kubecontrolplanev1.AggregatorConfig{}, err
	}
	return out, nil
}

func ToKubeletConnectionInfo(in *legacyconfigv1.KubeletConnectionInfo) (out kubecontrolplanev1.KubeletConnectionInfo, err error) {
	err = Convert_legacyconfigv1_KubeletConnectionInfo_to_kubecontrolplanev1_KubeletConnectionInfo(in, &out, nil)
	if err != nil {
		return kubecontrolplanev1.KubeletConnectionInfo{}, err
	}
	return out, nil
}

func ToUserAgentMatchingConfig(in *legacyconfigv1.UserAgentMatchingConfig) (out kubecontrolplanev1.UserAgentMatchingConfig, err error) {
	err = Convert_legacyconfigv1_UserAgentMatchingConfig_to_kubecontrolplanev1_UserAgentMatchingConfig(in, &out, nil)
	if err != nil {
		return kubecontrolplanev1.UserAgentMatchingConfig{}, err
	}
	return out, nil
}

func ToOAuthConfig(in *legacyconfigv1.OAuthConfig) (*osinv1.OAuthConfig, error) {
	if in == nil {
		return nil, nil
	}
	out := &osinv1.OAuthConfig{}
	if err := Convert_legacyconfigv1_OAuthConfig_to_osinv1_OAuthConfig(in, out, nil); err != nil {
		return nil, err
	}
	return out, nil
}

func ToJenkinsPipelineConfig(in *legacyconfigv1.JenkinsPipelineConfig) (out openshiftcontrolplanev1.JenkinsPipelineConfig, err error) {
	err = Convert_legacyconfigv1_JenkinsPipelineConfig_to_kubecontrolplanev1_JenkinsPipelineConfig(in, &out, nil)
	if err != nil {
		return openshiftcontrolplanev1.JenkinsPipelineConfig{}, err
	}
	return out, nil
}

func ToAllowedRegistries(in *legacyconfigv1.AllowedRegistries) (openshiftcontrolplanev1.AllowedRegistries, error) {
	if in == nil {
		return openshiftcontrolplanev1.AllowedRegistries{}, nil
	}

	out := openshiftcontrolplanev1.AllowedRegistries{}
	for i := range *in {
		currOut := openshiftcontrolplanev1.RegistryLocation{}
		err := Convert_legacyconfigv1_RegistryLocation_to_kubecontrolplanev1_RegistryLocation(&(*in)[i], &currOut, nil)
		if err != nil {
			return nil, err
		}
		out = append(out, currOut)
	}
	return out, nil
}
<|endoftext|>


<commit_before>/*
Copyright 2016 The Kubernetes Authors.

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

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

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

package taint

import (
	"encoding/json"
	"fmt"
	"strings"

	"github.com/golang/glog"
	"github.com/spf13/cobra"

	"k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/meta"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/types"
	"k8s.io/apimachinery/pkg/util/strategicpatch"
	"k8s.io/apimachinery/pkg/util/validation"
	"k8s.io/cli-runtime/pkg/genericclioptions"
	"k8s.io/cli-runtime/pkg/genericclioptions/printers"
	"k8s.io/cli-runtime/pkg/genericclioptions/resource"
	cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
	"k8s.io/kubernetes/pkg/kubectl/scheme"
	"k8s.io/kubernetes/pkg/kubectl/util/i18n"
	"k8s.io/kubernetes/pkg/kubectl/util/templates"
)

// TaintOptions have the data required to perform the taint operation
type TaintOptions struct {
	PrintFlags *genericclioptions.PrintFlags
	ToPrinter  func(string) (printers.ResourcePrinter, error)

	resources      []string
	taintsToAdd    []v1.Taint
	taintsToRemove []v1.Taint
	builder        *resource.Builder
	selector       string
	overwrite      bool
	all            bool

	ClientForMapping func(*meta.RESTMapping) (resource.RESTClient, error)

	genericclioptions.IOStreams
}

var (
	taintLong = templates.LongDesc(i18n.T(`
		Update the taints on one or more nodes.

		* A taint consists of a key, value, and effect. As an argument here, it is expressed as key=value:effect.
		* The key must begin with a letter or number, and may contain letters, numbers, hyphens, dots, and underscores, up to %[1]d characters.
		* Optionally, the key can begin with a DNS subdomain prefix and a single '/', like example.com/my-app
		* The value must begin with a letter or number, and may contain letters, numbers, hyphens, dots, and underscores, up to %[2]d characters.
		* The effect must be NoSchedule, PreferNoSchedule or NoExecute.
		* Currently taint can only apply to node.`))

	taintExample = templates.Examples(i18n.T(`
		# Update node 'foo' with a taint with key 'dedicated' and value 'special-user' and effect 'NoSchedule'.
		# If a taint with that key and effect already exists, its value is replaced as specified.
		kubectl taint nodes foo dedicated=special-user:NoSchedule

		# Remove from node 'foo' the taint with key 'dedicated' and effect 'NoSchedule' if one exists.
		kubectl taint nodes foo dedicated:NoSchedule-

		# Remove from node 'foo' all the taints with key 'dedicated'
		kubectl taint nodes foo dedicated-

		# Add a taint with key 'dedicated' on nodes having label mylabel=X
		kubectl taint node -l myLabel=X  dedicated=foo:PreferNoSchedule`))
)

func NewCmdTaint(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command {
	options := &TaintOptions{
		PrintFlags: genericclioptions.NewPrintFlags("tainted").WithTypeSetter(scheme.Scheme),
		IOStreams:  streams,
	}

	validArgs := []string{"node"}

	cmd := &cobra.Command{
		Use:                   "taint NODE NAME KEY_1=VAL_1:TAINT_EFFECT_1 ... KEY_N=VAL_N:TAINT_EFFECT_N",
		DisableFlagsInUseLine: true,
		Short:                 i18n.T("Update the taints on one or more nodes"),
		Long:                  fmt.Sprintf(taintLong, validation.DNS1123SubdomainMaxLength, validation.LabelValueMaxLength),
		Example:               taintExample,
		Run: func(cmd *cobra.Command, args []string) {
			if err := options.Complete(f, cmd, args); err != nil {
				cmdutil.CheckErr(err)
			}
			if err := options.Validate(); err != nil {
				cmdutil.CheckErr(cmdutil.UsageErrorf(cmd, err.Error()))
			}
			if err := options.RunTaint(); err != nil {
				cmdutil.CheckErr(err)
			}
		},
		ValidArgs: validArgs,
	}

	options.PrintFlags.AddFlags(cmd)

	cmdutil.AddValidateFlags(cmd)
	cmd.Flags().StringVarP(&options.selector, "selector", "l", options.selector, "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)")
	cmd.Flags().BoolVar(&options.overwrite, "overwrite", options.overwrite, "If true, allow taints to be overwritten, otherwise reject taint updates that overwrite existing taints.")
	cmd.Flags().BoolVar(&options.all, "all", options.all, "Select all nodes in the cluster")
	return cmd
}

// Complete adapts from the command line args and factory to the data required.
func (o *TaintOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) (err error) {
	namespace, _, err := f.ToRawKubeConfigLoader().Namespace()
	if err != nil {
		return err
	}

	// retrieves resource and taint args from args
	// also checks args to verify that all resources are specified before taints
	taintArgs := []string{}
	metTaintArg := false
	for _, s := range args {
		isTaint := strings.Contains(s, "=") || strings.HasSuffix(s, "-")
		switch {
		case !metTaintArg && isTaint:
			metTaintArg = true
			fallthrough
		case metTaintArg && isTaint:
			taintArgs = append(taintArgs, s)
		case !metTaintArg && !isTaint:
			o.resources = append(o.resources, s)
		case metTaintArg && !isTaint:
			return fmt.Errorf("all resources must be specified before taint changes: %s", s)
		}
	}

	o.ToPrinter = func(operation string) (printers.ResourcePrinter, error) {
		o.PrintFlags.NamePrintFlags.Operation = operation
		return o.PrintFlags.ToPrinter()
	}

	if len(o.resources) < 1 {
		return fmt.Errorf("one or more resources must be specified as <resource> <name>")
	}
	if len(taintArgs) < 1 {
		return fmt.Errorf("at least one taint update is required")
	}

	if o.taintsToAdd, o.taintsToRemove, err = parseTaints(taintArgs); err != nil {
		return cmdutil.UsageErrorf(cmd, err.Error())
	}
	o.builder = f.NewBuilder().
		WithScheme(scheme.Scheme, scheme.Scheme.PrioritizedVersionsAllGroups()...).
		ContinueOnError().
		NamespaceParam(namespace).DefaultNamespace()
	if o.selector != "" {
		o.builder = o.builder.LabelSelectorParam(o.selector).ResourceTypes("node")
	}
	if o.all {
		o.builder = o.builder.SelectAllParam(o.all).ResourceTypes("node").Flatten().Latest()
	}
	if !o.all && o.selector == "" && len(o.resources) >= 2 {
		o.builder = o.builder.ResourceNames("node", o.resources[1:]...)
	}
	o.builder = o.builder.LabelSelectorParam(o.selector).
		Flatten().
		Latest()

	o.ClientForMapping = f.ClientForMapping
	return nil
}

// validateFlags checks for the validation of flags for kubectl taints.
func (o TaintOptions) validateFlags() error {
	// Cannot have a non-empty selector and all flag set. They are mutually exclusive.
	if o.all && o.selector != "" {
		return fmt.Errorf("setting 'all' parameter with a non empty selector is prohibited.")
	}
	// If both selector and all are not set.
	if !o.all && o.selector == "" {
		if len(o.resources) < 2 {
			return fmt.Errorf("at least one resource name must be specified since 'all' parameter is not set")
		} else {
			return nil
		}
	}
	return nil
}

// Validate checks to the TaintOptions to see if there is sufficient information run the command.
func (o TaintOptions) Validate() error {
	resourceType := strings.ToLower(o.resources[0])
	validResources, isValidResource := []string{"node", "nodes"}, false
	for _, validResource := range validResources {
		if resourceType == validResource {
			isValidResource = true
			break
		}
	}
	if !isValidResource {
		return fmt.Errorf("invalid resource type %s, only %q are supported", o.resources[0], validResources)
	}

	// check the format of taint args and checks removed taints aren't in the new taints list
	var conflictTaints []string
	for _, taintAdd := range o.taintsToAdd {
		for _, taintRemove := range o.taintsToRemove {
			if taintAdd.Key != taintRemove.Key {
				continue
			}
			if len(taintRemove.Effect) == 0 || taintAdd.Effect == taintRemove.Effect {
				conflictTaint := fmt.Sprintf("{\"%s\":\"%s\"}", taintRemove.Key, taintRemove.Effect)
				conflictTaints = append(conflictTaints, conflictTaint)
			}
		}
	}
	if len(conflictTaints) > 0 {
		return fmt.Errorf("can not both modify and remove the following taint(s) in the same command: %s", strings.Join(conflictTaints, ", "))
	}
	return o.validateFlags()
}

// RunTaint does the work
func (o TaintOptions) RunTaint() error {
	r := o.builder.Do()
	if err := r.Err(); err != nil {
		return err
	}

	return r.Visit(func(info *resource.Info, err error) error {
		if err != nil {
			return err
		}

		obj := info.Object
		name, namespace := info.Name, info.Namespace
		oldData, err := json.Marshal(obj)
		if err != nil {
			return err
		}
		operation, err := o.updateTaints(obj)
		if err != nil {
			return err
		}
		newData, err := json.Marshal(obj)
		if err != nil {
			return err
		}
		patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldData, newData, obj)
		createdPatch := err == nil
		if err != nil {
			glog.V(2).Infof("couldn't compute patch: %v", err)
		}

		mapping := info.ResourceMapping()
		client, err := o.ClientForMapping(mapping)
		if err != nil {
			return err
		}
		helper := resource.NewHelper(client, mapping)

		var outputObj runtime.Object
		if createdPatch {
			outputObj, err = helper.Patch(namespace, name, types.StrategicMergePatchType, patchBytes, nil)
		} else {
			outputObj, err = helper.Replace(namespace, name, false, obj)
		}
		if err != nil {
			return err
		}

		printer, err := o.ToPrinter(operation)
		if err != nil {
			return err
		}
		return printer.PrintObj(outputObj, o.Out)
	})
}

// updateTaints applies a taint option(o) to a node in cluster after computing the net effect of operation(i.e. does it result in an overwrite?), it reports back the end result in a way that user can easily interpret.
func (o TaintOptions) updateTaints(obj runtime.Object) (string, error) {
	node, ok := obj.(*v1.Node)
	if !ok {
		return "", fmt.Errorf("unexpected type %T, expected Node", obj)
	}
	if !o.overwrite {
		if exists := checkIfTaintsAlreadyExists(node.Spec.Taints, o.taintsToAdd); len(exists) != 0 {
			return "", fmt.Errorf("Node %s already has %v taint(s) with same effect(s) and --overwrite is false", node.Name, exists)
		}
	}
	operation, newTaints, err := reorganizeTaints(node, o.overwrite, o.taintsToAdd, o.taintsToRemove)
	if err != nil {
		return "", err
	}
	node.Spec.Taints = newTaints
	return operation, nil
}
<commit_msg>code cleanup for kubectl taint<commit_after>/*
Copyright 2016 The Kubernetes Authors.

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

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

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

package taint

import (
	"encoding/json"
	"fmt"
	"strings"

	"github.com/golang/glog"
	"github.com/spf13/cobra"

	"k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/meta"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/types"
	"k8s.io/apimachinery/pkg/util/strategicpatch"
	"k8s.io/apimachinery/pkg/util/validation"
	"k8s.io/cli-runtime/pkg/genericclioptions"
	"k8s.io/cli-runtime/pkg/genericclioptions/printers"
	"k8s.io/cli-runtime/pkg/genericclioptions/resource"
	cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
	"k8s.io/kubernetes/pkg/kubectl/scheme"
	"k8s.io/kubernetes/pkg/kubectl/util/i18n"
	"k8s.io/kubernetes/pkg/kubectl/util/templates"
)

// TaintOptions have the data required to perform the taint operation
type TaintOptions struct {
	PrintFlags *genericclioptions.PrintFlags
	ToPrinter  func(string) (printers.ResourcePrinter, error)

	resources      []string
	taintsToAdd    []v1.Taint
	taintsToRemove []v1.Taint
	builder        *resource.Builder
	selector       string
	overwrite      bool
	all            bool

	ClientForMapping func(*meta.RESTMapping) (resource.RESTClient, error)

	genericclioptions.IOStreams
}

var (
	taintLong = templates.LongDesc(i18n.T(`
		Update the taints on one or more nodes.

		* A taint consists of a key, value, and effect. As an argument here, it is expressed as key=value:effect.
		* The key must begin with a letter or number, and may contain letters, numbers, hyphens, dots, and underscores, up to %[1]d characters.
		* Optionally, the key can begin with a DNS subdomain prefix and a single '/', like example.com/my-app
		* The value must begin with a letter or number, and may contain letters, numbers, hyphens, dots, and underscores, up to %[2]d characters.
		* The effect must be NoSchedule, PreferNoSchedule or NoExecute.
		* Currently taint can only apply to node.`))

	taintExample = templates.Examples(i18n.T(`
		# Update node 'foo' with a taint with key 'dedicated' and value 'special-user' and effect 'NoSchedule'.
		# If a taint with that key and effect already exists, its value is replaced as specified.
		kubectl taint nodes foo dedicated=special-user:NoSchedule

		# Remove from node 'foo' the taint with key 'dedicated' and effect 'NoSchedule' if one exists.
		kubectl taint nodes foo dedicated:NoSchedule-

		# Remove from node 'foo' all the taints with key 'dedicated'
		kubectl taint nodes foo dedicated-

		# Add a taint with key 'dedicated' on nodes having label mylabel=X
		kubectl taint node -l myLabel=X  dedicated=foo:PreferNoSchedule`))
)

func NewCmdTaint(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command {
	options := &TaintOptions{
		PrintFlags: genericclioptions.NewPrintFlags("tainted").WithTypeSetter(scheme.Scheme),
		IOStreams:  streams,
	}

	validArgs := []string{"node"}

	cmd := &cobra.Command{
		Use:                   "taint NODE NAME KEY_1=VAL_1:TAINT_EFFECT_1 ... KEY_N=VAL_N:TAINT_EFFECT_N",
		DisableFlagsInUseLine: true,
		Short:                 i18n.T("Update the taints on one or more nodes"),
		Long:                  fmt.Sprintf(taintLong, validation.DNS1123SubdomainMaxLength, validation.LabelValueMaxLength),
		Example:               taintExample,
		Run: func(cmd *cobra.Command, args []string) {
			cmdutil.CheckErr(options.Complete(f, cmd, args))
			cmdutil.CheckErr(options.Validate())
			cmdutil.CheckErr(options.RunTaint())
		},
		ValidArgs: validArgs,
	}

	options.PrintFlags.AddFlags(cmd)

	cmdutil.AddValidateFlags(cmd)
	cmd.Flags().StringVarP(&options.selector, "selector", "l", options.selector, "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)")
	cmd.Flags().BoolVar(&options.overwrite, "overwrite", options.overwrite, "If true, allow taints to be overwritten, otherwise reject taint updates that overwrite existing taints.")
	cmd.Flags().BoolVar(&options.all, "all", options.all, "Select all nodes in the cluster")
	return cmd
}

// Complete adapts from the command line args and factory to the data required.
func (o *TaintOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) (err error) {
	namespace, _, err := f.ToRawKubeConfigLoader().Namespace()
	if err != nil {
		return err
	}

	// retrieves resource and taint args from args
	// also checks args to verify that all resources are specified before taints
	taintArgs := []string{}
	metTaintArg := false
	for _, s := range args {
		isTaint := strings.Contains(s, "=") || strings.HasSuffix(s, "-")
		switch {
		case !metTaintArg && isTaint:
			metTaintArg = true
			fallthrough
		case metTaintArg && isTaint:
			taintArgs = append(taintArgs, s)
		case !metTaintArg && !isTaint:
			o.resources = append(o.resources, s)
		case metTaintArg && !isTaint:
			return fmt.Errorf("all resources must be specified before taint changes: %s", s)
		}
	}

	o.ToPrinter = func(operation string) (printers.ResourcePrinter, error) {
		o.PrintFlags.NamePrintFlags.Operation = operation
		return o.PrintFlags.ToPrinter()
	}

	if len(o.resources) < 1 {
		return fmt.Errorf("one or more resources must be specified as <resource> <name>")
	}
	if len(taintArgs) < 1 {
		return fmt.Errorf("at least one taint update is required")
	}

	if o.taintsToAdd, o.taintsToRemove, err = parseTaints(taintArgs); err != nil {
		return cmdutil.UsageErrorf(cmd, err.Error())
	}
	o.builder = f.NewBuilder().
		WithScheme(scheme.Scheme, scheme.Scheme.PrioritizedVersionsAllGroups()...).
		ContinueOnError().
		NamespaceParam(namespace).DefaultNamespace()
	if o.selector != "" {
		o.builder = o.builder.LabelSelectorParam(o.selector).ResourceTypes("node")
	}
	if o.all {
		o.builder = o.builder.SelectAllParam(o.all).ResourceTypes("node").Flatten().Latest()
	}
	if !o.all && o.selector == "" && len(o.resources) >= 2 {
		o.builder = o.builder.ResourceNames("node", o.resources[1:]...)
	}
	o.builder = o.builder.LabelSelectorParam(o.selector).
		Flatten().
		Latest()

	o.ClientForMapping = f.ClientForMapping
	return nil
}

// validateFlags checks for the validation of flags for kubectl taints.
func (o TaintOptions) validateFlags() error {
	// Cannot have a non-empty selector and all flag set. They are mutually exclusive.
	if o.all && o.selector != "" {
		return fmt.Errorf("setting 'all' parameter with a non empty selector is prohibited.")
	}
	// If both selector and all are not set.
	if !o.all && o.selector == "" {
		if len(o.resources) < 2 {
			return fmt.Errorf("at least one resource name must be specified since 'all' parameter is not set")
		} else {
			return nil
		}
	}
	return nil
}

// Validate checks to the TaintOptions to see if there is sufficient information run the command.
func (o TaintOptions) Validate() error {
	resourceType := strings.ToLower(o.resources[0])
	validResources, isValidResource := []string{"node", "nodes"}, false
	for _, validResource := range validResources {
		if resourceType == validResource {
			isValidResource = true
			break
		}
	}
	if !isValidResource {
		return fmt.Errorf("invalid resource type %s, only %q are supported", o.resources[0], validResources)
	}

	// check the format of taint args and checks removed taints aren't in the new taints list
	var conflictTaints []string
	for _, taintAdd := range o.taintsToAdd {
		for _, taintRemove := range o.taintsToRemove {
			if taintAdd.Key != taintRemove.Key {
				continue
			}
			if len(taintRemove.Effect) == 0 || taintAdd.Effect == taintRemove.Effect {
				conflictTaint := fmt.Sprintf("{\"%s\":\"%s\"}", taintRemove.Key, taintRemove.Effect)
				conflictTaints = append(conflictTaints, conflictTaint)
			}
		}
	}
	if len(conflictTaints) > 0 {
		return fmt.Errorf("can not both modify and remove the following taint(s) in the same command: %s", strings.Join(conflictTaints, ", "))
	}
	return o.validateFlags()
}

// RunTaint does the work
func (o TaintOptions) RunTaint() error {
	r := o.builder.Do()
	if err := r.Err(); err != nil {
		return err
	}

	return r.Visit(func(info *resource.Info, err error) error {
		if err != nil {
			return err
		}

		obj := info.Object
		name, namespace := info.Name, info.Namespace
		oldData, err := json.Marshal(obj)
		if err != nil {
			return err
		}
		operation, err := o.updateTaints(obj)
		if err != nil {
			return err
		}
		newData, err := json.Marshal(obj)
		if err != nil {
			return err
		}
		patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldData, newData, obj)
		createdPatch := err == nil
		if err != nil {
			glog.V(2).Infof("couldn't compute patch: %v", err)
		}

		mapping := info.ResourceMapping()
		client, err := o.ClientForMapping(mapping)
		if err != nil {
			return err
		}
		helper := resource.NewHelper(client, mapping)

		var outputObj runtime.Object
		if createdPatch {
			outputObj, err = helper.Patch(namespace, name, types.StrategicMergePatchType, patchBytes, nil)
		} else {
			outputObj, err = helper.Replace(namespace, name, false, obj)
		}
		if err != nil {
			return err
		}

		printer, err := o.ToPrinter(operation)
		if err != nil {
			return err
		}
		return printer.PrintObj(outputObj, o.Out)
	})
}

// updateTaints applies a taint option(o) to a node in cluster after computing the net effect of operation(i.e. does it result in an overwrite?), it reports back the end result in a way that user can easily interpret.
func (o TaintOptions) updateTaints(obj runtime.Object) (string, error) {
	node, ok := obj.(*v1.Node)
	if !ok {
		return "", fmt.Errorf("unexpected type %T, expected Node", obj)
	}
	if !o.overwrite {
		if exists := checkIfTaintsAlreadyExists(node.Spec.Taints, o.taintsToAdd); len(exists) != 0 {
			return "", fmt.Errorf("Node %s already has %v taint(s) with same effect(s) and --overwrite is false", node.Name, exists)
		}
	}
	operation, newTaints, err := reorganizeTaints(node, o.overwrite, o.taintsToAdd, o.taintsToRemove)
	if err != nil {
		return "", err
	}
	node.Spec.Taints = newTaints
	return operation, nil
}
<|endoftext|>


<commit_before>package geos

/*
#include "geos.h"
*/
import "C"

import (
	"runtime"
	"unsafe"
)

// Reads the WKT serialization and produces geometries
type WKTDecoder struct {
	r *C.GEOSWKTReader
}

// Creates a new WKT decoder, can be nil if initialization in the C API fails
func NewWKTDecoder() *WKTDecoder {
	r := C.GEOSWKTReader_create_r(handle)
	if r == nil {
		return nil
	}
	d := &WKTDecoder{r}
	runtime.SetFinalizer(d, (*WKTDecoder).destroy)
	return d
}

// Decode decodes the WKT string and returns a geometry
func (d *WKTDecoder) Decode(wkt string) (*Geometry, error) {
	cstr := C.CString(wkt)
	defer C.free(unsafe.Pointer(cstr))
	g := C.GEOSWKTReader_read_r(handle, d.r, cstr)
	if g == nil {
		return nil, Error()
	}
	// XXX: geomFromPtr
	return &Geometry{g}, nil
}

func (d *WKTDecoder) destroy() {
	// XXX: mutex
	C.GEOSWKTReader_destroy_r(handle, d.r)
	d.r = nil
}

type WKTEncoder struct {
	w *C.GEOSWKTWriter
}

func NewWKTEncoder() *WKTEncoder {
	w := C.GEOSWKTWriter_create_r(handle)
	if w == nil {
		return nil
	}
	e := &WKTEncoder{w}
	runtime.SetFinalizer(e, (*WKTEncoder).destroy)
	return e
}

// Encode returns a string that is the geometry encoded as WKT
func (e *WKTEncoder) Encode(g *Geometry) (string, error) {
	// XXX: free?
	cstr := C.GEOSWKTWriter_write_r(handle, e.w, g.g)
	if cstr == nil {
		return "", Error()
	}
	return C.GoString(cstr), nil
}

func (e *WKTEncoder) destroy() {
	// XXX: mutex
	C.GEOSWKTWriter_destroy_r(handle, e.w)
	e.w = nil
}
<commit_msg>WKT use geomFromPtr ctor<commit_after>package geos

/*
#include "geos.h"
*/
import "C"

import (
	"runtime"
	"unsafe"
)

// Reads the WKT serialization and produces geometries
type WKTDecoder struct {
	r *C.GEOSWKTReader
}

// Creates a new WKT decoder, can be nil if initialization in the C API fails
func NewWKTDecoder() *WKTDecoder {
	r := C.GEOSWKTReader_create_r(handle)
	if r == nil {
		return nil
	}
	d := &WKTDecoder{r}
	runtime.SetFinalizer(d, (*WKTDecoder).destroy)
	return d
}

// Decode decodes the WKT string and returns a geometry
func (d *WKTDecoder) Decode(wkt string) (*Geometry, error) {
	cstr := C.CString(wkt)
	defer C.free(unsafe.Pointer(cstr))
	g := C.GEOSWKTReader_read_r(handle, d.r, cstr)
	if g == nil {
		return nil, Error()
	}
	return geomFromPtr(g), nil
}

func (d *WKTDecoder) destroy() {
	// XXX: mutex
	C.GEOSWKTReader_destroy_r(handle, d.r)
	d.r = nil
}

type WKTEncoder struct {
	w *C.GEOSWKTWriter
}

func NewWKTEncoder() *WKTEncoder {
	w := C.GEOSWKTWriter_create_r(handle)
	if w == nil {
		return nil
	}
	e := &WKTEncoder{w}
	runtime.SetFinalizer(e, (*WKTEncoder).destroy)
	return e
}

// Encode returns a string that is the geometry encoded as WKT
func (e *WKTEncoder) Encode(g *Geometry) (string, error) {
	// XXX: free?
	cstr := C.GEOSWKTWriter_write_r(handle, e.w, g.g)
	if cstr == nil {
		return "", Error()
	}
	return C.GoString(cstr), nil
}

func (e *WKTEncoder) destroy() {
	// XXX: mutex
	C.GEOSWKTWriter_destroy_r(handle, e.w)
	e.w = nil
}
<|endoftext|>