<commit_before>// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package ssa

import "sort"

// cse does common-subexpression elimination on the Function.
// Values are just relinked, nothing is deleted.  A subsequent deadcode
// pass is required to actually remove duplicate expressions.
func cse(f *Func) {
	// Two values are equivalent if they satisfy the following definition:
	// equivalent(v, w):
	//   v.op == w.op
	//   v.type == w.type
	//   v.aux == w.aux
	//   v.auxint == w.auxint
	//   len(v.args) == len(w.args)
	//   v.block == w.block if v.op == OpPhi
	//   equivalent(v.args[i], w.args[i]) for i in 0..len(v.args)-1

	// The algorithm searches for a partition of f's values into
	// equivalence classes using the above definition.
	// It starts with a coarse partition and iteratively refines it
	// until it reaches a fixed point.

	// Make initial partition based on opcode, type-name, aux, auxint, nargs, phi-block, and the ops of v's first args
	type key struct {
		op     Op
		typ    string
		aux    interface{}
		auxint int64
		nargs  int
		block  ID // block id for phi vars, -1 otherwise
		arg0op Op // v.Args[0].Op if len(v.Args) > 0, OpInvalid otherwise
		arg1op Op // v.Args[1].Op if len(v.Args) > 1, OpInvalid otherwise
	}
	m := map[key]eqclass{}
	for _, b := range f.Blocks {
		for _, v := range b.Values {
			bid := ID(-1)
			if v.Op == OpPhi {
				bid = b.ID
			}
			arg0op := OpInvalid
			if len(v.Args) > 0 {
				arg0op = v.Args[0].Op
			}
			arg1op := OpInvalid
			if len(v.Args) > 1 {
				arg1op = v.Args[1].Op
			}
			k := key{v.Op, v.Type.String(), v.Aux, v.AuxInt, len(v.Args), bid, arg0op, arg1op}
			m[k] = append(m[k], v)
		}
	}

	// A partition is a set of disjoint eqclasses.
	var partition []eqclass
	for _, v := range m {
		partition = append(partition, v)
	}
	// TODO: Sort partition here for perfect reproducibility?
	// Sort by what? Partition size?
	// (Could that improve efficiency by discovering splits earlier?)

	// map from value id back to eqclass id
	valueEqClass := make([]int, f.NumValues())
	for i, e := range partition {
		for _, v := range e {
			valueEqClass[v.ID] = i
		}
	}

	// Find an equivalence class where some members of the class have
	// non-equivalent arguments.  Split the equivalence class appropriately.
	// Repeat until we can't find any more splits.
	for {
		changed := false

		// partition can grow in the loop. By not using a range loop here,
		// we process new additions as they arrive, avoiding O(n^2) behavior.
		for i := 0; i < len(partition); i++ {
			e := partition[i]
			v := e[0]
			// all values in this equiv class that are not equivalent to v get moved
			// into another equiv class q.
			var q eqclass
		eqloop:
			for j := 1; j < len(e); {
				w := e[j]
				for i := 0; i < len(v.Args); i++ {
					if valueEqClass[v.Args[i].ID] != valueEqClass[w.Args[i].ID] || !v.Type.Equal(w.Type) {
						// w is not equivalent to v.
						// remove w from e
						e, e[j] = e[:len(e)-1], e[len(e)-1]
						// add w to q
						q = append(q, w)
						valueEqClass[w.ID] = len(partition)
						changed = true
						continue eqloop
					}
				}
				// v and w are equivalent.  Keep w in e.
				j++
			}
			partition[i] = e
			if q != nil {
				partition = append(partition, q)
			}
		}

		if !changed {
			break
		}
	}

	// Compute dominator tree
	idom := dominators(f)

	// Compute substitutions we would like to do.  We substitute v for w
	// if v and w are in the same equivalence class and v dominates w.
	rewrite := make([]*Value, f.NumValues())
	for _, e := range partition {
		sort.Sort(e) // ensure deterministic ordering
		for len(e) > 1 {
			// Find a maximal dominant element in e
			v := e[0]
			for _, w := range e[1:] {
				if dom(w.Block, v.Block, idom) {
					v = w
				}
			}

			// Replace all elements of e which v dominates
			for i := 0; i < len(e); {
				w := e[i]
				if w == v {
					e, e[i] = e[:len(e)-1], e[len(e)-1]
				} else if dom(v.Block, w.Block, idom) {
					rewrite[w.ID] = v
					e, e[i] = e[:len(e)-1], e[len(e)-1]
				} else {
					i++
				}
			}
			// TODO(khr): if value is a control value, do we need to keep it block-local?
		}
	}

	// Apply substitutions
	for _, b := range f.Blocks {
		for _, v := range b.Values {
			for i, w := range v.Args {
				if x := rewrite[w.ID]; x != nil {
					v.SetArg(i, x)
				}
			}
		}
	}
}

// returns true if b dominates c.
// TODO(khr): faster
func dom(b, c *Block, idom []*Block) bool {
	// Walk up from c in the dominator tree looking for b.
	for c != nil {
		if c == b {
			return true
		}
		c = idom[c.ID]
	}
	// Reached the entry block, never saw b.
	return false
}

// An eqclass approximates an equivalence class.  During the
// algorithm it may represent the union of several of the
// final equivalence classes.
type eqclass []*Value

// Sort an equivalence class by value ID.
func (e eqclass) Len() int           { return len(e) }
func (e eqclass) Swap(i, j int)      { e[i], e[j] = e[j], e[i] }
func (e eqclass) Less(i, j int) bool { return e[i].ID < e[j].ID }
<commit_msg>[dev.ssa] cmd/compile: don't alloc new CSE classes<commit_after>// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package ssa

import "sort"

// cse does common-subexpression elimination on the Function.
// Values are just relinked, nothing is deleted.  A subsequent deadcode
// pass is required to actually remove duplicate expressions.
func cse(f *Func) {
	// Two values are equivalent if they satisfy the following definition:
	// equivalent(v, w):
	//   v.op == w.op
	//   v.type == w.type
	//   v.aux == w.aux
	//   v.auxint == w.auxint
	//   len(v.args) == len(w.args)
	//   v.block == w.block if v.op == OpPhi
	//   equivalent(v.args[i], w.args[i]) for i in 0..len(v.args)-1

	// The algorithm searches for a partition of f's values into
	// equivalence classes using the above definition.
	// It starts with a coarse partition and iteratively refines it
	// until it reaches a fixed point.

	// Make initial partition based on opcode, type-name, aux, auxint, nargs, phi-block, and the ops of v's first args
	type key struct {
		op     Op
		typ    string
		aux    interface{}
		auxint int64
		nargs  int
		block  ID // block id for phi vars, -1 otherwise
		arg0op Op // v.Args[0].Op if len(v.Args) > 0, OpInvalid otherwise
		arg1op Op // v.Args[1].Op if len(v.Args) > 1, OpInvalid otherwise
	}
	m := map[key]eqclass{}
	for _, b := range f.Blocks {
		for _, v := range b.Values {
			bid := ID(-1)
			if v.Op == OpPhi {
				bid = b.ID
			}
			arg0op := OpInvalid
			if len(v.Args) > 0 {
				arg0op = v.Args[0].Op
			}
			arg1op := OpInvalid
			if len(v.Args) > 1 {
				arg1op = v.Args[1].Op
			}
			k := key{v.Op, v.Type.String(), v.Aux, v.AuxInt, len(v.Args), bid, arg0op, arg1op}
			m[k] = append(m[k], v)
		}
	}

	// A partition is a set of disjoint eqclasses.
	var partition []eqclass
	for _, v := range m {
		partition = append(partition, v)
	}
	// TODO: Sort partition here for perfect reproducibility?
	// Sort by what? Partition size?
	// (Could that improve efficiency by discovering splits earlier?)

	// map from value id back to eqclass id
	valueEqClass := make([]int, f.NumValues())
	for i, e := range partition {
		for _, v := range e {
			valueEqClass[v.ID] = i
		}
	}

	// Find an equivalence class where some members of the class have
	// non-equivalent arguments.  Split the equivalence class appropriately.
	// Repeat until we can't find any more splits.
	for {
		changed := false

		// partition can grow in the loop. By not using a range loop here,
		// we process new additions as they arrive, avoiding O(n^2) behavior.
		for i := 0; i < len(partition); i++ {
			e := partition[i]
			v := e[0]
			// all values in this equiv class that are not equivalent to v get moved
			// into another equiv class.
			// To avoid allocating while building that equivalence class,
			// move the values equivalent to v to the beginning of e,
			// other values to the end of e, and track where the split is.
			allvals := e
			split := len(e)
		eqloop:
			for j := 1; j < len(e); {
				w := e[j]
				for i := 0; i < len(v.Args); i++ {
					if valueEqClass[v.Args[i].ID] != valueEqClass[w.Args[i].ID] || !v.Type.Equal(w.Type) {
						// w is not equivalent to v.
						// move it to the end, shrink e, and move the split.
						e[j], e[len(e)-1] = e[len(e)-1], e[j]
						e = e[:len(e)-1]
						split--
						valueEqClass[w.ID] = len(partition)
						changed = true
						continue eqloop
					}
				}
				// v and w are equivalent.  Keep w in e.
				j++
			}
			partition[i] = e
			if split < len(allvals) {
				partition = append(partition, allvals[split:])
			}
		}

		if !changed {
			break
		}
	}

	// Compute dominator tree
	idom := dominators(f)

	// Compute substitutions we would like to do.  We substitute v for w
	// if v and w are in the same equivalence class and v dominates w.
	rewrite := make([]*Value, f.NumValues())
	for _, e := range partition {
		sort.Sort(e) // ensure deterministic ordering
		for len(e) > 1 {
			// Find a maximal dominant element in e
			v := e[0]
			for _, w := range e[1:] {
				if dom(w.Block, v.Block, idom) {
					v = w
				}
			}

			// Replace all elements of e which v dominates
			for i := 0; i < len(e); {
				w := e[i]
				if w == v {
					e, e[i] = e[:len(e)-1], e[len(e)-1]
				} else if dom(v.Block, w.Block, idom) {
					rewrite[w.ID] = v
					e, e[i] = e[:len(e)-1], e[len(e)-1]
				} else {
					i++
				}
			}
			// TODO(khr): if value is a control value, do we need to keep it block-local?
		}
	}

	// Apply substitutions
	for _, b := range f.Blocks {
		for _, v := range b.Values {
			for i, w := range v.Args {
				if x := rewrite[w.ID]; x != nil {
					v.SetArg(i, x)
				}
			}
		}
	}
}

// returns true if b dominates c.
// TODO(khr): faster
func dom(b, c *Block, idom []*Block) bool {
	// Walk up from c in the dominator tree looking for b.
	for c != nil {
		if c == b {
			return true
		}
		c = idom[c.ID]
	}
	// Reached the entry block, never saw b.
	return false
}

// An eqclass approximates an equivalence class.  During the
// algorithm it may represent the union of several of the
// final equivalence classes.
type eqclass []*Value

// Sort an equivalence class by value ID.
func (e eqclass) Len() int           { return len(e) }
func (e eqclass) Swap(i, j int)      { e[i], e[j] = e[j], e[i] }
func (e eqclass) Less(i, j int) bool { return e[i].ID < e[j].ID }
<|endoftext|>


<commit_before>// Copyright (C) 2015 Thomas de Zeeuw.
//
// Licensed onder the MIT license that can be found in the LICENSE file.

package logger

import (
	"fmt"
	"testing"
	"time"
)

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

	tests := []struct {
		input    int
		width    int
		expected string
	}{
		{1999, 4, "1999"}, // In case of time travel.
		{2009, 4, "2009"},
		{2010, 4, "2010"},
		{2015, 4, "2015"},
		{2016, 4, "2016"},
		{2017, 4, "2017"},
		{2018, 4, "2018"},
		{2019, 4, "2019"},
		{2020, 4, "2020"},
		{5000, 4, "5000"}, // At this point, all bets are off.
		{1, 2, "01"},
		{5, 2, "05"},
		{8, 2, "08"},
		{10, 2, "10"},
		{11, 2, "11"},
		{12, 2, "12"},
		{21, 2, "21"},
		{25, 2, "25"},
		{31, 2, "31"},
	}

	for _, test := range tests {
		var buf []byte
		itoa(&buf, test.input, test.width)

		if got := string(buf); got != test.expected {
			t.Errorf("Expected itoa(%v, %d, %d) to return %q, but got %q",
				&buf, test.input, test.width, test.expected, got)
		}
	}
}

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

	var now = time.Now()
	var tStr = now.Format("2006-01-02 15:04:05")

	var msgTests = []struct {
		msg      Msg
		expected string
	}{
		{Msg{Fatal, "Message", Tags{}, now},
			tStr + " [Fatal] : Message\n"},
		{Msg{Error, "Message", Tags{"tag1"}, now},
			tStr + " [Error] tag1: Message\n"},
		{Msg{Info, "Message", Tags{"tag1", "tag2"}, now},
			tStr + " [Info] tag1, tag2: Message\n"},
		{Msg{Debug, "Message", Tags{"tag1", "tag2", "tag3"}, now},
			tStr + " [Debug] tag1, tag2, tag3: Message\n"},
	}

	for _, test := range msgTests {
		got, gotBytes := test.msg.String(), test.msg.Bytes()

		if got != string(gotBytes) {
			t.Errorf("Msg.Bytes() and String() don't return the same value, got %q"+
				" and %q, want %q", got, string(gotBytes), test.expected)
		} else if got != test.expected {
			t.Errorf("Expected Msg.String() to return %q, got %q",
				test.expected, got)
		}
	}
}

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

	tests := []struct {
		lvl      LogLevel
		expected string
	}{
		{Debug, "Debug"},
		{Thumb, "Thumb"},
		{Info, "Info"},
		{Warn, "Warn"},
		{Error, "Error"},
		{Fatal, "Fatal"},
	}

	for _, test := range tests {
		got := test.lvl.String()
		if got != test.expected {
			t.Fatalf("Expected Loglevel %d to return %s, but got %s", int(test.lvl),
				test.expected, got)
		}
	}
}

func TestNewLogLevel(t *testing.T) {
	for i := 1; i < 10; i++ {
		expected := fmt.Sprintf("myLogLevel%d", i)
		myLogLevel := NewLogLevel(expected)

		if got := myLogLevel.String(); got != expected {
			t.Fatalf("Expected Loglevel %d to return %s, but got %s", int(myLogLevel),
				expected, got)
		}
	}
}
<commit_msg>Test create the maximum amout of log levels<commit_after>// Copyright (C) 2015 Thomas de Zeeuw.
//
// Licensed onder the MIT license that can be found in the LICENSE file.

package logger

import (
	"fmt"
	"testing"
	"time"
)

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

	tests := []struct {
		input    int
		width    int
		expected string
	}{
		{1999, 4, "1999"}, // In case of time travel.
		{2009, 4, "2009"},
		{2010, 4, "2010"},
		{2015, 4, "2015"},
		{2016, 4, "2016"},
		{2017, 4, "2017"},
		{2018, 4, "2018"},
		{2019, 4, "2019"},
		{2020, 4, "2020"},
		{5000, 4, "5000"}, // At this point, all bets are off.
		{1, 2, "01"},
		{5, 2, "05"},
		{8, 2, "08"},
		{10, 2, "10"},
		{11, 2, "11"},
		{12, 2, "12"},
		{21, 2, "21"},
		{25, 2, "25"},
		{31, 2, "31"},
	}

	for _, test := range tests {
		var buf []byte
		itoa(&buf, test.input, test.width)

		if got := string(buf); got != test.expected {
			t.Errorf("Expected itoa(%v, %d, %d) to return %q, but got %q",
				&buf, test.input, test.width, test.expected, got)
		}
	}
}

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

	var now = time.Now()
	var tStr = now.Format("2006-01-02 15:04:05")

	var msgTests = []struct {
		msg      Msg
		expected string
	}{
		{Msg{Fatal, "Message", Tags{}, now},
			tStr + " [Fatal] : Message\n"},
		{Msg{Error, "Message", Tags{"tag1"}, now},
			tStr + " [Error] tag1: Message\n"},
		{Msg{Info, "Message", Tags{"tag1", "tag2"}, now},
			tStr + " [Info] tag1, tag2: Message\n"},
		{Msg{Debug, "Message", Tags{"tag1", "tag2", "tag3"}, now},
			tStr + " [Debug] tag1, tag2, tag3: Message\n"},
	}

	for _, test := range msgTests {
		got, gotBytes := test.msg.String(), test.msg.Bytes()

		if got != string(gotBytes) {
			t.Errorf("Msg.Bytes() and String() don't return the same value, got %q"+
				" and %q, want %q", got, string(gotBytes), test.expected)
		} else if got != test.expected {
			t.Errorf("Expected Msg.String() to return %q, got %q",
				test.expected, got)
		}
	}
}

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

	tests := []struct {
		lvl      LogLevel
		expected string
	}{
		{Debug, "Debug"},
		{Thumb, "Thumb"},
		{Info, "Info"},
		{Warn, "Warn"},
		{Error, "Error"},
		{Fatal, "Fatal"},
	}

	for _, test := range tests {
		got := test.lvl.String()
		if got != test.expected {
			t.Fatalf("Expected Loglevel %d to return %s, but got %s", int(test.lvl),
				test.expected, got)
		}
	}
}

func TestNewLogLevel(t *testing.T) {
	for i := 1; i <= 248; i++ {
		expected := fmt.Sprintf("myLogLevel%d", i)
		myLogLevel := NewLogLevel(expected)

		if got := myLogLevel.String(); got != expected {
			t.Fatalf("Expected Loglevel %d to return %s, but got %s", int(myLogLevel),
				expected, got)
		}
	}
}
<|endoftext|>


<commit_before>package mustache

import (
    "bytes"
    "container/vector"
    "fmt"
    "io"
    "io/ioutil"
    "os"
    "path"
    "reflect"
    "strings"
)

type textElement struct {
    text []byte
}

type varElement struct {
    name string
}

type sectionElement struct {
    name      string
    inverted  bool
    startline int
    elems     *vector.Vector
}

type Template struct {
    data    string
    otag    string
    ctag    string
    p       int
    curline int
    dir     string
    elems   *vector.Vector
}

type parseError struct {
    line    int
    message string
}

func (p parseError) String() string { return fmt.Sprintf("line %d: %s", p.line, p.message) }

func (tmpl *Template) readString(s string) (string, os.Error) {
    i := tmpl.p
    newlines := 0
    for true {
        //are we at the end of the string?
        if i+len(s) > len(tmpl.data) {
            return tmpl.data[tmpl.p:], os.EOF
        }

        if tmpl.data[i] == '\n' {
            newlines++
        }

        if tmpl.data[i] != s[0] {
            i++
            continue
        }

        match := true
        for j := 1; j < len(s); j++ {
            if s[j] != tmpl.data[i+j] {
                match = false
                break
            }
        }

        if match {
            e := i + len(s)
            text := tmpl.data[tmpl.p:e]
            tmpl.p = e

            tmpl.curline += newlines
            return text, nil
        } else {
            i++
        }
    }

    //should never be here
    return "", nil
}

func (tmpl *Template) parsePartial(name string) (*Template, os.Error) {
    filenames := []string{
        path.Join(tmpl.dir, name),
        path.Join(tmpl.dir, name+".mustache"),
        path.Join(tmpl.dir, name+".stache"),
        name,
        name + ".mustache",
        name + ".stache",
    }
    var filename string
    for _, name := range filenames {
        f, err := os.Open(name, os.O_RDONLY, 0666)
        f.Close()
        if err == nil {
            filename = name
            break
        }
    }
    if filename == "" {
        return nil, os.NewError(fmt.Sprintf("Could not find partial %q", name))
    }

    partial, err := ParseFile(filename)

    if err != nil {
        return nil, err
    }

    return partial, nil
}

func (tmpl *Template) parseSection(section *sectionElement) os.Error {
    for {
        text, err := tmpl.readString(tmpl.otag)

        if err == os.EOF {
            return parseError{section.startline, "Section " + section.name + " has no closing tag"}
        }

        // put text into an item
        text = text[0 : len(text)-len(tmpl.otag)]
        section.elems.Push(&textElement{[]byte(text)})

        text, err = tmpl.readString(tmpl.ctag)
        if err == os.EOF {
            //put the remaining text in a block
            return parseError{tmpl.curline, "unmatched open tag"}
        }

        //trim the close tag off the text
        tag := strings.TrimSpace(text[0 : len(text)-len(tmpl.ctag)])
        if len(tag) == 0 {
            return parseError{tmpl.curline, "empty tag"}
        }
        switch tag[0] {
        case '!':
            //ignore comment
            break
        case '#', '^':
            name := strings.TrimSpace(tag[1:])

            //ignore the newline when a section starts
            if len(tmpl.data) > tmpl.p && tmpl.data[tmpl.p] == '\n' {
                tmpl.p += 1
            } else if len(tmpl.data) > tmpl.p+1 && tmpl.data[tmpl.p] == '\r' && tmpl.data[tmpl.p+1] == '\n' {
                tmpl.p += 2
            }

            se := sectionElement{name, tag[0] == '^', tmpl.curline, new(vector.Vector)}
            err := tmpl.parseSection(&se)
            if err != nil {
                return err
            }
            section.elems.Push(&se)
        case '/':
            name := strings.TrimSpace(tag[1:])
            if name != section.name {
                return parseError{tmpl.curline, "interleaved closing tag: " + name}
            } else {
                return nil
            }
        case '>':
            name := strings.TrimSpace(tag[1:])
            partial, err := tmpl.parsePartial(name)
            if err != nil {
                return err
            }
            section.elems.Push(partial)
        case '=':
            if tag[len(tag)-1] != '=' {
                return parseError{tmpl.curline, "Invalid meta tag"}
            }
            tag = strings.TrimSpace(tag[1 : len(tag)-1])
            newtags := strings.Split(tag, " ", 2)
            if len(newtags) == 2 {
                tmpl.otag = newtags[0]
                tmpl.ctag = newtags[1]
            }
        default:
            section.elems.Push(&varElement{tag})
        }
    }

    return nil
}

func (tmpl *Template) parse() os.Error {
    for {
        text, err := tmpl.readString(tmpl.otag)

        if err == os.EOF {
            //put the remaining text in a block
            tmpl.elems.Push(&textElement{[]byte(text)})
            return nil
        }

        // put text into an item
        text = text[0 : len(text)-len(tmpl.otag)]
        tmpl.elems.Push(&textElement{[]byte(text)})

        text, err = tmpl.readString(tmpl.ctag)
        if err == os.EOF {
            //put the remaining text in a block
            return parseError{tmpl.curline, "unmatched open tag"}
        }

        //trim the close tag off the text
        tag := strings.TrimSpace(text[0 : len(text)-len(tmpl.ctag)])
        if len(tag) == 0 {
            return parseError{tmpl.curline, "empty tag"}
        }
        switch tag[0] {
        case '!':
            //ignore comment
            break
        case '#', '^':
            name := strings.TrimSpace(tag[1:])

            if len(tmpl.data) > tmpl.p && tmpl.data[tmpl.p] == '\n' {
                tmpl.p += 1
            } else if len(tmpl.data) > tmpl.p+1 && tmpl.data[tmpl.p] == '\r' && tmpl.data[tmpl.p+1] == '\n' {
                tmpl.p += 2
            }

            se := sectionElement{name, tag[0] == '^', tmpl.curline, new(vector.Vector)}
            err := tmpl.parseSection(&se)
            if err != nil {
                return err
            }
            tmpl.elems.Push(&se)
        case '/':
            return parseError{tmpl.curline, "unmatched close tag"}
        case '>':
            name := strings.TrimSpace(tag[1:])
            partial, err := tmpl.parsePartial(name)
            if err != nil {
                return err
            }
            tmpl.elems.Push(partial)
        case '=':
            if tag[len(tag)-1] != '=' {
                return parseError{tmpl.curline, "Invalid meta tag"}
            }
            tag = strings.TrimSpace(tag[1 : len(tag)-1])
            newtags := strings.Split(tag, " ", 2)
            if len(newtags) == 2 {
                tmpl.otag = newtags[0]
                tmpl.ctag = newtags[1]
            }
        default:
            tmpl.elems.Push(&varElement{tag})
        }
    }

    return nil
}

// See if name is a method of the value at some level of indirection.
// The return values are the result of the call (which may be nil if
// there's trouble) and whether a method of the right name exists with
// any signature.
func callMethod(data reflect.Value, name string) (result reflect.Value, found bool) {
    found = false
    // Method set depends on pointerness, and the value may be arbitrarily
    // indirect.  Simplest approach is to walk down the pointer chain and
    // see if we can find the method at each step.
    // Most steps will see NumMethod() == 0.
    for {
        typ := data.Type()
        if nMethod := data.Type().NumMethod(); nMethod > 0 {
            for i := 0; i < nMethod; i++ {
                method := typ.Method(i)
                if method.Name == name {

                    found = true // we found the name regardless
                    // does receiver type match? (pointerness might be off)
                    if typ == method.Type.In(0) {
                        return call(data, method), found
                    }
                }
            }
        }
        if nd, ok := data.(*reflect.PtrValue); ok {
            data = nd.Elem()
        } else {
            break
        }
    }
    return
}

// Invoke the method. If its signature is wrong, return nil.
func call(v reflect.Value, method reflect.Method) reflect.Value {
    funcType := method.Type
    // Method must take no arguments, meaning as a func it has one argument (the receiver)
    if funcType.NumIn() != 1 {
        return nil
    }
    // Method must return a single value.
    if funcType.NumOut() == 0 {
        return nil
    }
    // Result will be the zeroth element of the returned slice.
    return method.Func.Call([]reflect.Value{v})[0]
}

// Evaluate interfaces and pointers looking for a value that can look up the name, via a
// struct field, method, or map key, and return the result of the lookup.
func lookup(contextChain *vector.Vector, name string) reflect.Value {
Outer:
    for i := contextChain.Len() - 1; i >= 0; i-- {
        v := contextChain.At(i).(reflect.Value)
        for v != nil {
            typ := v.Type()
            if n := v.Type().NumMethod(); n > 0 {
                for i := 0; i < n; i++ {
                    m := typ.Method(i)
                    mtyp := m.Type
                    // We must check receiver type because of a bug in the reflection type tables:
                    // it should not be possible to find a method with the wrong receiver type but
                    // this can happen due to value/pointer receiver mismatch.
                    if m.Name == name && mtyp.NumIn() == 1 && mtyp.In(0) == typ {
                        return v.Method(i).Call(nil)[0]
                    }
                }
            }
            switch av := v.(type) {
            case *reflect.PtrValue:
                v = av.Elem()
            case *reflect.InterfaceValue:
                v = av.Elem()
            case *reflect.StructValue:
                ret := av.FieldByName(name)
                if ret != nil {
                    return ret
                } else {
                    continue Outer
                }
            case *reflect.MapValue:
                ret := av.Elem(reflect.NewValue(name))
                if ret != nil {
                    return ret
                } else {
                    continue Outer
                }
            default:
                continue Outer
            }
        }
    }
    return nil
}

func isNil(v reflect.Value) bool {
    if v == nil || v.Interface() == nil {
        return true
    }

    valueInd := indirect(v)
    switch val := valueInd.(type) {
    case *reflect.BoolValue:
        return !val.Get()
    }

    return false
}

func indirect(v reflect.Value) reflect.Value {
loop:
    for v != nil {
        switch av := v.(type) {
        case *reflect.PtrValue:
            v = av.Elem()
        case *reflect.InterfaceValue:
            v = av.Elem()
        default:
            break loop
        }
    }
    return v
}

func renderSection(section *sectionElement, contextChain *vector.Vector, buf io.Writer) {
    value := lookup(contextChain, section.name)
    var context = contextChain.At(contextChain.Len() - 1).(reflect.Value)
    var contexts = new(vector.Vector)
    // if the value is nil, check if it's an inverted section
    isNil := isNil(value)
    if isNil && !section.inverted || !isNil && section.inverted {
        return
    } else {
        valueInd := indirect(value)
        switch val := valueInd.(type) {
        case *reflect.SliceValue:
            for i := 0; i < val.Len(); i++ {
                contexts.Push(val.Elem(i))
            }
        case *reflect.ArrayValue:
            for i := 0; i < val.Len(); i++ {
                contexts.Push(val.Elem(i))
            }
        case *reflect.MapValue, *reflect.StructValue:
            contexts.Push(value)
        default:
            contexts.Push(context)
        }
    }

    //by default we execute the section
    for j := 0; j < contexts.Len(); j++ {
        ctx := contexts.At(j).(reflect.Value)
        contextChain.Push(ctx)
        for i := 0; i < section.elems.Len(); i++ {
            renderElement(section.elems.At(i), contextChain, buf)
        }
        contextChain.Pop()
    }
}

func renderElement(element interface{}, contextChain *vector.Vector, buf io.Writer) {
    switch elem := element.(type) {
    case *textElement:
        buf.Write(elem.text)
    case *varElement:
        val := lookup(contextChain, elem.name)
        if val != nil {
            fmt.Fprint(buf, val.Interface())
        }
    case *sectionElement:
        renderSection(elem, contextChain, buf)
    case *Template:
        elem.renderTemplate(contextChain, buf)
    }
}

func (tmpl *Template) renderTemplate(contextChain *vector.Vector, buf io.Writer) {
    for i := 0; i < tmpl.elems.Len(); i++ {
        renderElement(tmpl.elems.At(i), contextChain, buf)
    }
}

func (tmpl *Template) Render(context ...interface{}) string {
    var buf bytes.Buffer
    var contextChain vector.Vector
    for _, c := range context {
        val := reflect.NewValue(c)
        contextChain.Push(val)
    }
    tmpl.renderTemplate(&contextChain, &buf)
    return buf.String()
}

func ParseString(data string) (*Template, os.Error) {
    cwd := os.Getenv("CWD")
    tmpl := Template{data, "{{", "}}", 0, 1, cwd, new(vector.Vector)}
    err := tmpl.parse()

    if err != nil {
        return nil, err
    }

    return &tmpl, err
}

func ParseFile(filename string) (*Template, os.Error) {
    data, err := ioutil.ReadFile(filename)
    if err != nil {
        return nil, err
    }

    dirname, _ := path.Split(filename)

    tmpl := Template{string(data), "{{", "}}", 0, 1, dirname, new(vector.Vector)}
    err = tmpl.parse()

    if err != nil {
        return nil, err
    }

    return &tmpl, nil
}

func Render(data string, context ...interface{}) string {
    tmpl, err := ParseString(data)

    if err != nil {
        return err.String()
    }

    return tmpl.Render(context...)
}

func RenderFile(filename string, context ...interface{}) string {
    tmpl, err := ParseFile(filename)

    if err != nil {
        return err.String()
    }

    return tmpl.Render(context...)
}
<commit_msg>Remove workaround for relection table bug since it's been fixed<commit_after>package mustache

import (
    "bytes"
    "container/vector"
    "fmt"
    "io"
    "io/ioutil"
    "os"
    "path"
    "reflect"
    "strings"
)

type textElement struct {
    text []byte
}

type varElement struct {
    name string
}

type sectionElement struct {
    name      string
    inverted  bool
    startline int
    elems     *vector.Vector
}

type Template struct {
    data    string
    otag    string
    ctag    string
    p       int
    curline int
    dir     string
    elems   *vector.Vector
}

type parseError struct {
    line    int
    message string
}

func (p parseError) String() string { return fmt.Sprintf("line %d: %s", p.line, p.message) }

func (tmpl *Template) readString(s string) (string, os.Error) {
    i := tmpl.p
    newlines := 0
    for true {
        //are we at the end of the string?
        if i+len(s) > len(tmpl.data) {
            return tmpl.data[tmpl.p:], os.EOF
        }

        if tmpl.data[i] == '\n' {
            newlines++
        }

        if tmpl.data[i] != s[0] {
            i++
            continue
        }

        match := true
        for j := 1; j < len(s); j++ {
            if s[j] != tmpl.data[i+j] {
                match = false
                break
            }
        }

        if match {
            e := i + len(s)
            text := tmpl.data[tmpl.p:e]
            tmpl.p = e

            tmpl.curline += newlines
            return text, nil
        } else {
            i++
        }
    }

    //should never be here
    return "", nil
}

func (tmpl *Template) parsePartial(name string) (*Template, os.Error) {
    filenames := []string{
        path.Join(tmpl.dir, name),
        path.Join(tmpl.dir, name+".mustache"),
        path.Join(tmpl.dir, name+".stache"),
        name,
        name + ".mustache",
        name + ".stache",
    }
    var filename string
    for _, name := range filenames {
        f, err := os.Open(name, os.O_RDONLY, 0666)
        f.Close()
        if err == nil {
            filename = name
            break
        }
    }
    if filename == "" {
        return nil, os.NewError(fmt.Sprintf("Could not find partial %q", name))
    }

    partial, err := ParseFile(filename)

    if err != nil {
        return nil, err
    }

    return partial, nil
}

func (tmpl *Template) parseSection(section *sectionElement) os.Error {
    for {
        text, err := tmpl.readString(tmpl.otag)

        if err == os.EOF {
            return parseError{section.startline, "Section " + section.name + " has no closing tag"}
        }

        // put text into an item
        text = text[0 : len(text)-len(tmpl.otag)]
        section.elems.Push(&textElement{[]byte(text)})

        text, err = tmpl.readString(tmpl.ctag)
        if err == os.EOF {
            //put the remaining text in a block
            return parseError{tmpl.curline, "unmatched open tag"}
        }

        //trim the close tag off the text
        tag := strings.TrimSpace(text[0 : len(text)-len(tmpl.ctag)])
        if len(tag) == 0 {
            return parseError{tmpl.curline, "empty tag"}
        }
        switch tag[0] {
        case '!':
            //ignore comment
            break
        case '#', '^':
            name := strings.TrimSpace(tag[1:])

            //ignore the newline when a section starts
            if len(tmpl.data) > tmpl.p && tmpl.data[tmpl.p] == '\n' {
                tmpl.p += 1
            } else if len(tmpl.data) > tmpl.p+1 && tmpl.data[tmpl.p] == '\r' && tmpl.data[tmpl.p+1] == '\n' {
                tmpl.p += 2
            }

            se := sectionElement{name, tag[0] == '^', tmpl.curline, new(vector.Vector)}
            err := tmpl.parseSection(&se)
            if err != nil {
                return err
            }
            section.elems.Push(&se)
        case '/':
            name := strings.TrimSpace(tag[1:])
            if name != section.name {
                return parseError{tmpl.curline, "interleaved closing tag: " + name}
            } else {
                return nil
            }
        case '>':
            name := strings.TrimSpace(tag[1:])
            partial, err := tmpl.parsePartial(name)
            if err != nil {
                return err
            }
            section.elems.Push(partial)
        case '=':
            if tag[len(tag)-1] != '=' {
                return parseError{tmpl.curline, "Invalid meta tag"}
            }
            tag = strings.TrimSpace(tag[1 : len(tag)-1])
            newtags := strings.Split(tag, " ", 2)
            if len(newtags) == 2 {
                tmpl.otag = newtags[0]
                tmpl.ctag = newtags[1]
            }
        default:
            section.elems.Push(&varElement{tag})
        }
    }

    return nil
}

func (tmpl *Template) parse() os.Error {
    for {
        text, err := tmpl.readString(tmpl.otag)

        if err == os.EOF {
            //put the remaining text in a block
            tmpl.elems.Push(&textElement{[]byte(text)})
            return nil
        }

        // put text into an item
        text = text[0 : len(text)-len(tmpl.otag)]
        tmpl.elems.Push(&textElement{[]byte(text)})

        text, err = tmpl.readString(tmpl.ctag)
        if err == os.EOF {
            //put the remaining text in a block
            return parseError{tmpl.curline, "unmatched open tag"}
        }

        //trim the close tag off the text
        tag := strings.TrimSpace(text[0 : len(text)-len(tmpl.ctag)])
        if len(tag) == 0 {
            return parseError{tmpl.curline, "empty tag"}
        }
        switch tag[0] {
        case '!':
            //ignore comment
            break
        case '#', '^':
            name := strings.TrimSpace(tag[1:])

            if len(tmpl.data) > tmpl.p && tmpl.data[tmpl.p] == '\n' {
                tmpl.p += 1
            } else if len(tmpl.data) > tmpl.p+1 && tmpl.data[tmpl.p] == '\r' && tmpl.data[tmpl.p+1] == '\n' {
                tmpl.p += 2
            }

            se := sectionElement{name, tag[0] == '^', tmpl.curline, new(vector.Vector)}
            err := tmpl.parseSection(&se)
            if err != nil {
                return err
            }
            tmpl.elems.Push(&se)
        case '/':
            return parseError{tmpl.curline, "unmatched close tag"}
        case '>':
            name := strings.TrimSpace(tag[1:])
            partial, err := tmpl.parsePartial(name)
            if err != nil {
                return err
            }
            tmpl.elems.Push(partial)
        case '=':
            if tag[len(tag)-1] != '=' {
                return parseError{tmpl.curline, "Invalid meta tag"}
            }
            tag = strings.TrimSpace(tag[1 : len(tag)-1])
            newtags := strings.Split(tag, " ", 2)
            if len(newtags) == 2 {
                tmpl.otag = newtags[0]
                tmpl.ctag = newtags[1]
            }
        default:
            tmpl.elems.Push(&varElement{tag})
        }
    }

    return nil
}

// See if name is a method of the value at some level of indirection.
// The return values are the result of the call (which may be nil if
// there's trouble) and whether a method of the right name exists with
// any signature.
func callMethod(data reflect.Value, name string) (result reflect.Value, found bool) {
    found = false
    // Method set depends on pointerness, and the value may be arbitrarily
    // indirect.  Simplest approach is to walk down the pointer chain and
    // see if we can find the method at each step.
    // Most steps will see NumMethod() == 0.
    for {
        typ := data.Type()
        if nMethod := data.Type().NumMethod(); nMethod > 0 {
            for i := 0; i < nMethod; i++ {
                method := typ.Method(i)
                if method.Name == name {

                    found = true // we found the name regardless
                    // does receiver type match? (pointerness might be off)
                    if typ == method.Type.In(0) {
                        return call(data, method), found
                    }
                }
            }
        }
        if nd, ok := data.(*reflect.PtrValue); ok {
            data = nd.Elem()
        } else {
            break
        }
    }
    return
}

// Invoke the method. If its signature is wrong, return nil.
func call(v reflect.Value, method reflect.Method) reflect.Value {
    funcType := method.Type
    // Method must take no arguments, meaning as a func it has one argument (the receiver)
    if funcType.NumIn() != 1 {
        return nil
    }
    // Method must return a single value.
    if funcType.NumOut() == 0 {
        return nil
    }
    // Result will be the zeroth element of the returned slice.
    return method.Func.Call([]reflect.Value{v})[0]
}

// Evaluate interfaces and pointers looking for a value that can look up the name, via a
// struct field, method, or map key, and return the result of the lookup.
func lookup(contextChain *vector.Vector, name string) reflect.Value {
Outer:
    for i := contextChain.Len() - 1; i >= 0; i-- {
        v := contextChain.At(i).(reflect.Value)
        for v != nil {
            typ := v.Type()
            if n := v.Type().NumMethod(); n > 0 {
                for i := 0; i < n; i++ {
                    m := typ.Method(i)
                    mtyp := m.Type
                    if m.Name == name && mtyp.NumIn() == 1 {
                        return v.Method(i).Call(nil)[0]
                    }
                }
            }
            switch av := v.(type) {
            case *reflect.PtrValue:
                v = av.Elem()
            case *reflect.InterfaceValue:
                v = av.Elem()
            case *reflect.StructValue:
                ret := av.FieldByName(name)
                if ret != nil {
                    return ret
                } else {
                    continue Outer
                }
            case *reflect.MapValue:
                ret := av.Elem(reflect.NewValue(name))
                if ret != nil {
                    return ret
                } else {
                    continue Outer
                }
            default:
                continue Outer
            }
        }
    }
    return nil
}

func isNil(v reflect.Value) bool {
    if v == nil || v.Interface() == nil {
        return true
    }

    valueInd := indirect(v)
    switch val := valueInd.(type) {
    case *reflect.BoolValue:
        return !val.Get()
    }

    return false
}

func indirect(v reflect.Value) reflect.Value {
loop:
    for v != nil {
        switch av := v.(type) {
        case *reflect.PtrValue:
            v = av.Elem()
        case *reflect.InterfaceValue:
            v = av.Elem()
        default:
            break loop
        }
    }
    return v
}

func renderSection(section *sectionElement, contextChain *vector.Vector, buf io.Writer) {
    value := lookup(contextChain, section.name)
    var context = contextChain.At(contextChain.Len() - 1).(reflect.Value)
    var contexts = new(vector.Vector)
    // if the value is nil, check if it's an inverted section
    isNil := isNil(value)
    if isNil && !section.inverted || !isNil && section.inverted {
        return
    } else {
        valueInd := indirect(value)
        switch val := valueInd.(type) {
        case *reflect.SliceValue:
            for i := 0; i < val.Len(); i++ {
                contexts.Push(val.Elem(i))
            }
        case *reflect.ArrayValue:
            for i := 0; i < val.Len(); i++ {
                contexts.Push(val.Elem(i))
            }
        case *reflect.MapValue, *reflect.StructValue:
            contexts.Push(value)
        default:
            contexts.Push(context)
        }
    }

    //by default we execute the section
    for j := 0; j < contexts.Len(); j++ {
        ctx := contexts.At(j).(reflect.Value)
        contextChain.Push(ctx)
        for i := 0; i < section.elems.Len(); i++ {
            renderElement(section.elems.At(i), contextChain, buf)
        }
        contextChain.Pop()
    }
}

func renderElement(element interface{}, contextChain *vector.Vector, buf io.Writer) {
    switch elem := element.(type) {
    case *textElement:
        buf.Write(elem.text)
    case *varElement:
        val := lookup(contextChain, elem.name)
        if val != nil {
            fmt.Fprint(buf, val.Interface())
        }
    case *sectionElement:
        renderSection(elem, contextChain, buf)
    case *Template:
        elem.renderTemplate(contextChain, buf)
    }
}

func (tmpl *Template) renderTemplate(contextChain *vector.Vector, buf io.Writer) {
    for i := 0; i < tmpl.elems.Len(); i++ {
        renderElement(tmpl.elems.At(i), contextChain, buf)
    }
}

func (tmpl *Template) Render(context ...interface{}) string {
    var buf bytes.Buffer
    var contextChain vector.Vector
    for _, c := range context {
        val := reflect.NewValue(c)
        contextChain.Push(val)
    }
    tmpl.renderTemplate(&contextChain, &buf)
    return buf.String()
}

func ParseString(data string) (*Template, os.Error) {
    cwd := os.Getenv("CWD")
    tmpl := Template{data, "{{", "}}", 0, 1, cwd, new(vector.Vector)}
    err := tmpl.parse()

    if err != nil {
        return nil, err
    }

    return &tmpl, err
}

func ParseFile(filename string) (*Template, os.Error) {
    data, err := ioutil.ReadFile(filename)
    if err != nil {
        return nil, err
    }

    dirname, _ := path.Split(filename)

    tmpl := Template{string(data), "{{", "}}", 0, 1, dirname, new(vector.Vector)}
    err = tmpl.parse()

    if err != nil {
        return nil, err
    }

    return &tmpl, nil
}

func Render(data string, context ...interface{}) string {
    tmpl, err := ParseString(data)

    if err != nil {
        return err.String()
    }

    return tmpl.Render(context...)
}

func RenderFile(filename string, context ...interface{}) string {
    tmpl, err := ParseFile(filename)

    if err != nil {
        return err.String()
    }

    return tmpl.Render(context...)
}
<|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 validation

import (
	"k8s.io/apimachinery/pkg/api/validation/path"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	unversionedvalidation "k8s.io/apimachinery/pkg/apis/meta/v1/validation"
	"k8s.io/apimachinery/pkg/util/validation/field"
	"k8s.io/kubernetes/pkg/apis/core/validation"
	"k8s.io/kubernetes/pkg/apis/rbac"
)

// Minimal validation of names for roles and bindings. Identical to the validation for Openshift. See:
// * https://github.com/kubernetes/kubernetes/blob/60db50/pkg/api/validation/name.go
// * https://github.com/openshift/origin/blob/388478/pkg/api/helpers.go
func minimalNameRequirements(name string, prefix bool) []string {
	return path.IsValidPathSegmentName(name)
}

func ValidateRole(role *rbac.Role) field.ErrorList {
	allErrs := field.ErrorList{}
	allErrs = append(allErrs, validation.ValidateObjectMeta(&role.ObjectMeta, true, minimalNameRequirements, field.NewPath("metadata"))...)

	for i, rule := range role.Rules {
		if err := validatePolicyRule(rule, true, field.NewPath("rules").Index(i)); err != nil {
			allErrs = append(allErrs, err...)
		}
	}
	if len(allErrs) != 0 {
		return allErrs
	}
	return nil
}

func ValidateRoleUpdate(role *rbac.Role, oldRole *rbac.Role) field.ErrorList {
	allErrs := ValidateRole(role)
	allErrs = append(allErrs, validation.ValidateObjectMetaUpdate(&role.ObjectMeta, &oldRole.ObjectMeta, field.NewPath("metadata"))...)

	return allErrs
}

func ValidateClusterRole(role *rbac.ClusterRole) field.ErrorList {
	allErrs := field.ErrorList{}
	allErrs = append(allErrs, validation.ValidateObjectMeta(&role.ObjectMeta, false, minimalNameRequirements, field.NewPath("metadata"))...)

	for i, rule := range role.Rules {
		if err := validatePolicyRule(rule, false, field.NewPath("rules").Index(i)); err != nil {
			allErrs = append(allErrs, err...)
		}
	}

	if role.AggregationRule != nil {
		if len(role.AggregationRule.ClusterRoleSelectors) == 0 {
			allErrs = append(allErrs, field.Required(field.NewPath("aggregationRule", "clusterRoleSelectors"), "at least one clusterRoleSelector required if aggregationRule is non-nil"))
		}
		for i, selector := range role.AggregationRule.ClusterRoleSelectors {
			fieldPath := field.NewPath("aggregationRule", "clusterRoleSelectors").Index(i)
			allErrs = append(allErrs, unversionedvalidation.ValidateLabelSelector(&selector, fieldPath)...)

			selector, err := metav1.LabelSelectorAsSelector(&selector)
			if err != nil {
				allErrs = append(allErrs, field.Invalid(fieldPath, selector, "invalid label selector."))
			}
		}
	}

	if len(allErrs) != 0 {
		return allErrs
	}
	return nil
}

func ValidateClusterRoleUpdate(role *rbac.ClusterRole, oldRole *rbac.ClusterRole) field.ErrorList {
	allErrs := ValidateClusterRole(role)
	allErrs = append(allErrs, validation.ValidateObjectMetaUpdate(&role.ObjectMeta, &oldRole.ObjectMeta, field.NewPath("metadata"))...)

	return allErrs
}

func validatePolicyRule(rule rbac.PolicyRule, isNamespaced bool, fldPath *field.Path) field.ErrorList {
	allErrs := field.ErrorList{}
	if len(rule.Verbs) == 0 {
		allErrs = append(allErrs, field.Required(fldPath.Child("verbs"), "verbs must contain at least one value"))
	}

	if len(rule.NonResourceURLs) > 0 {
		if isNamespaced {
			allErrs = append(allErrs, field.Invalid(fldPath.Child("nonResourceURLs"), rule.NonResourceURLs, "namespaced rules cannot apply to non-resource URLs"))
		}
		if len(rule.APIGroups) > 0 || len(rule.Resources) > 0 || len(rule.ResourceNames) > 0 {
			allErrs = append(allErrs, field.Invalid(fldPath.Child("nonResourceURLs"), rule.NonResourceURLs, "rules cannot apply to both regular resources and non-resource URLs"))
		}
		return allErrs
	}

	if len(rule.APIGroups) == 0 {
		allErrs = append(allErrs, field.Required(fldPath.Child("apiGroups"), "resource rules must supply at least one api group"))
	}
	if len(rule.Resources) == 0 {
		allErrs = append(allErrs, field.Required(fldPath.Child("resources"), "resource rules must supply at least one resource"))
	}
	return allErrs
}

func ValidateRoleBinding(roleBinding *rbac.RoleBinding) field.ErrorList {
	allErrs := field.ErrorList{}
	allErrs = append(allErrs, validation.ValidateObjectMeta(&roleBinding.ObjectMeta, true, minimalNameRequirements, field.NewPath("metadata"))...)

	// TODO allow multiple API groups.  For now, restrict to one, but I can envision other experimental roles in other groups taking
	// advantage of the binding infrastructure
	if roleBinding.RoleRef.APIGroup != rbac.GroupName {
		allErrs = append(allErrs, field.NotSupported(field.NewPath("roleRef", "apiGroup"), roleBinding.RoleRef.APIGroup, []string{rbac.GroupName}))
	}

	switch roleBinding.RoleRef.Kind {
	case "Role", "ClusterRole":
	default:
		allErrs = append(allErrs, field.NotSupported(field.NewPath("roleRef", "kind"), roleBinding.RoleRef.Kind, []string{"Role", "ClusterRole"}))

	}

	if len(roleBinding.RoleRef.Name) == 0 {
		allErrs = append(allErrs, field.Required(field.NewPath("roleRef", "name"), ""))
	} else {
		for _, msg := range minimalNameRequirements(roleBinding.RoleRef.Name, false) {
			allErrs = append(allErrs, field.Invalid(field.NewPath("roleRef", "name"), roleBinding.RoleRef.Name, msg))
		}
	}

	subjectsPath := field.NewPath("subjects")
	for i, subject := range roleBinding.Subjects {
		allErrs = append(allErrs, validateRoleBindingSubject(subject, true, subjectsPath.Index(i))...)
	}

	return allErrs
}

func ValidateRoleBindingUpdate(roleBinding *rbac.RoleBinding, oldRoleBinding *rbac.RoleBinding) field.ErrorList {
	allErrs := ValidateRoleBinding(roleBinding)
	allErrs = append(allErrs, validation.ValidateObjectMetaUpdate(&roleBinding.ObjectMeta, &oldRoleBinding.ObjectMeta, field.NewPath("metadata"))...)

	if oldRoleBinding.RoleRef != roleBinding.RoleRef {
		allErrs = append(allErrs, field.Invalid(field.NewPath("roleRef"), roleBinding.RoleRef, "cannot change roleRef"))
	}

	return allErrs
}

func ValidateClusterRoleBinding(roleBinding *rbac.ClusterRoleBinding) field.ErrorList {
	allErrs := field.ErrorList{}
	allErrs = append(allErrs, validation.ValidateObjectMeta(&roleBinding.ObjectMeta, false, minimalNameRequirements, field.NewPath("metadata"))...)

	// TODO allow multiple API groups.  For now, restrict to one, but I can envision other experimental roles in other groups taking
	// advantage of the binding infrastructure
	if roleBinding.RoleRef.APIGroup != rbac.GroupName {
		allErrs = append(allErrs, field.NotSupported(field.NewPath("roleRef", "apiGroup"), roleBinding.RoleRef.APIGroup, []string{rbac.GroupName}))
	}

	switch roleBinding.RoleRef.Kind {
	case "ClusterRole":
	default:
		allErrs = append(allErrs, field.NotSupported(field.NewPath("roleRef", "kind"), roleBinding.RoleRef.Kind, []string{"ClusterRole"}))

	}

	if len(roleBinding.RoleRef.Name) == 0 {
		allErrs = append(allErrs, field.Required(field.NewPath("roleRef", "name"), ""))
	} else {
		for _, msg := range minimalNameRequirements(roleBinding.RoleRef.Name, false) {
			allErrs = append(allErrs, field.Invalid(field.NewPath("roleRef", "name"), roleBinding.RoleRef.Name, msg))
		}
	}

	subjectsPath := field.NewPath("subjects")
	for i, subject := range roleBinding.Subjects {
		allErrs = append(allErrs, validateRoleBindingSubject(subject, false, subjectsPath.Index(i))...)
	}

	return allErrs
}

func ValidateClusterRoleBindingUpdate(roleBinding *rbac.ClusterRoleBinding, oldRoleBinding *rbac.ClusterRoleBinding) field.ErrorList {
	allErrs := ValidateClusterRoleBinding(roleBinding)
	allErrs = append(allErrs, validation.ValidateObjectMetaUpdate(&roleBinding.ObjectMeta, &oldRoleBinding.ObjectMeta, field.NewPath("metadata"))...)

	if oldRoleBinding.RoleRef != roleBinding.RoleRef {
		allErrs = append(allErrs, field.Invalid(field.NewPath("roleRef"), roleBinding.RoleRef, "cannot change roleRef"))
	}

	return allErrs
}

func validateRoleBindingSubject(subject rbac.Subject, isNamespaced bool, fldPath *field.Path) field.ErrorList {
	allErrs := field.ErrorList{}

	if len(subject.Name) == 0 {
		allErrs = append(allErrs, field.Required(fldPath.Child("name"), ""))
	}

	switch subject.Kind {
	case rbac.ServiceAccountKind:
		if len(subject.Name) > 0 {
			for _, msg := range validation.ValidateServiceAccountName(subject.Name, false) {
				allErrs = append(allErrs, field.Invalid(fldPath.Child("name"), subject.Name, msg))
			}
		}
		if len(subject.APIGroup) > 0 {
			allErrs = append(allErrs, field.NotSupported(fldPath.Child("apiGroup"), subject.APIGroup, []string{""}))
		}
		if !isNamespaced && len(subject.Namespace) == 0 {
			allErrs = append(allErrs, field.Required(fldPath.Child("namespace"), ""))
		}

	case rbac.UserKind:
		// TODO(ericchiang): What other restrictions on user name are there?
		if len(subject.Name) == 0 {
			allErrs = append(allErrs, field.Invalid(fldPath.Child("name"), subject.Name, "user name cannot be empty"))
		}
		if subject.APIGroup != rbac.GroupName {
			allErrs = append(allErrs, field.NotSupported(fldPath.Child("apiGroup"), subject.APIGroup, []string{rbac.GroupName}))
		}

	case rbac.GroupKind:
		// TODO(ericchiang): What other restrictions on group name are there?
		if len(subject.Name) == 0 {
			allErrs = append(allErrs, field.Invalid(fldPath.Child("name"), subject.Name, "group name cannot be empty"))
		}
		if subject.APIGroup != rbac.GroupName {
			allErrs = append(allErrs, field.NotSupported(fldPath.Child("apiGroup"), subject.APIGroup, []string{rbac.GroupName}))
		}

	default:
		allErrs = append(allErrs, field.NotSupported(fldPath.Child("kind"), subject.Kind, []string{rbac.ServiceAccountKind, rbac.UserKind, rbac.GroupKind}))
	}

	return allErrs
}
<commit_msg>Export RBAC validation functions<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 validation

import (
	"k8s.io/apimachinery/pkg/api/validation/path"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	unversionedvalidation "k8s.io/apimachinery/pkg/apis/meta/v1/validation"
	"k8s.io/apimachinery/pkg/util/validation/field"
	"k8s.io/kubernetes/pkg/apis/core/validation"
	"k8s.io/kubernetes/pkg/apis/rbac"
)

// ValidateRBACName is exported to allow types outside of the RBAC API group to reuse this validation logic
// Minimal validation of names for roles and bindings. Identical to the validation for Openshift. See:
// * https://github.com/kubernetes/kubernetes/blob/60db50/pkg/api/validation/name.go
// * https://github.com/openshift/origin/blob/388478/pkg/api/helpers.go
func ValidateRBACName(name string, prefix bool) []string {
	return path.IsValidPathSegmentName(name)
}

func ValidateRole(role *rbac.Role) field.ErrorList {
	allErrs := field.ErrorList{}
	allErrs = append(allErrs, validation.ValidateObjectMeta(&role.ObjectMeta, true, ValidateRBACName, field.NewPath("metadata"))...)

	for i, rule := range role.Rules {
		if err := ValidatePolicyRule(rule, true, field.NewPath("rules").Index(i)); err != nil {
			allErrs = append(allErrs, err...)
		}
	}
	if len(allErrs) != 0 {
		return allErrs
	}
	return nil
}

func ValidateRoleUpdate(role *rbac.Role, oldRole *rbac.Role) field.ErrorList {
	allErrs := ValidateRole(role)
	allErrs = append(allErrs, validation.ValidateObjectMetaUpdate(&role.ObjectMeta, &oldRole.ObjectMeta, field.NewPath("metadata"))...)

	return allErrs
}

func ValidateClusterRole(role *rbac.ClusterRole) field.ErrorList {
	allErrs := field.ErrorList{}
	allErrs = append(allErrs, validation.ValidateObjectMeta(&role.ObjectMeta, false, ValidateRBACName, field.NewPath("metadata"))...)

	for i, rule := range role.Rules {
		if err := ValidatePolicyRule(rule, false, field.NewPath("rules").Index(i)); err != nil {
			allErrs = append(allErrs, err...)
		}
	}

	if role.AggregationRule != nil {
		if len(role.AggregationRule.ClusterRoleSelectors) == 0 {
			allErrs = append(allErrs, field.Required(field.NewPath("aggregationRule", "clusterRoleSelectors"), "at least one clusterRoleSelector required if aggregationRule is non-nil"))
		}
		for i, selector := range role.AggregationRule.ClusterRoleSelectors {
			fieldPath := field.NewPath("aggregationRule", "clusterRoleSelectors").Index(i)
			allErrs = append(allErrs, unversionedvalidation.ValidateLabelSelector(&selector, fieldPath)...)

			selector, err := metav1.LabelSelectorAsSelector(&selector)
			if err != nil {
				allErrs = append(allErrs, field.Invalid(fieldPath, selector, "invalid label selector."))
			}
		}
	}

	if len(allErrs) != 0 {
		return allErrs
	}
	return nil
}

func ValidateClusterRoleUpdate(role *rbac.ClusterRole, oldRole *rbac.ClusterRole) field.ErrorList {
	allErrs := ValidateClusterRole(role)
	allErrs = append(allErrs, validation.ValidateObjectMetaUpdate(&role.ObjectMeta, &oldRole.ObjectMeta, field.NewPath("metadata"))...)

	return allErrs
}

// ValidatePolicyRule is exported to allow types outside of the RBAC API group to embed a rbac.PolicyRule and reuse this validation logic
func ValidatePolicyRule(rule rbac.PolicyRule, isNamespaced bool, fldPath *field.Path) field.ErrorList {
	allErrs := field.ErrorList{}
	if len(rule.Verbs) == 0 {
		allErrs = append(allErrs, field.Required(fldPath.Child("verbs"), "verbs must contain at least one value"))
	}

	if len(rule.NonResourceURLs) > 0 {
		if isNamespaced {
			allErrs = append(allErrs, field.Invalid(fldPath.Child("nonResourceURLs"), rule.NonResourceURLs, "namespaced rules cannot apply to non-resource URLs"))
		}
		if len(rule.APIGroups) > 0 || len(rule.Resources) > 0 || len(rule.ResourceNames) > 0 {
			allErrs = append(allErrs, field.Invalid(fldPath.Child("nonResourceURLs"), rule.NonResourceURLs, "rules cannot apply to both regular resources and non-resource URLs"))
		}
		return allErrs
	}

	if len(rule.APIGroups) == 0 {
		allErrs = append(allErrs, field.Required(fldPath.Child("apiGroups"), "resource rules must supply at least one api group"))
	}
	if len(rule.Resources) == 0 {
		allErrs = append(allErrs, field.Required(fldPath.Child("resources"), "resource rules must supply at least one resource"))
	}
	return allErrs
}

func ValidateRoleBinding(roleBinding *rbac.RoleBinding) field.ErrorList {
	allErrs := field.ErrorList{}
	allErrs = append(allErrs, validation.ValidateObjectMeta(&roleBinding.ObjectMeta, true, ValidateRBACName, field.NewPath("metadata"))...)

	// TODO allow multiple API groups.  For now, restrict to one, but I can envision other experimental roles in other groups taking
	// advantage of the binding infrastructure
	if roleBinding.RoleRef.APIGroup != rbac.GroupName {
		allErrs = append(allErrs, field.NotSupported(field.NewPath("roleRef", "apiGroup"), roleBinding.RoleRef.APIGroup, []string{rbac.GroupName}))
	}

	switch roleBinding.RoleRef.Kind {
	case "Role", "ClusterRole":
	default:
		allErrs = append(allErrs, field.NotSupported(field.NewPath("roleRef", "kind"), roleBinding.RoleRef.Kind, []string{"Role", "ClusterRole"}))

	}

	if len(roleBinding.RoleRef.Name) == 0 {
		allErrs = append(allErrs, field.Required(field.NewPath("roleRef", "name"), ""))
	} else {
		for _, msg := range ValidateRBACName(roleBinding.RoleRef.Name, false) {
			allErrs = append(allErrs, field.Invalid(field.NewPath("roleRef", "name"), roleBinding.RoleRef.Name, msg))
		}
	}

	subjectsPath := field.NewPath("subjects")
	for i, subject := range roleBinding.Subjects {
		allErrs = append(allErrs, ValidateRoleBindingSubject(subject, true, subjectsPath.Index(i))...)
	}

	return allErrs
}

func ValidateRoleBindingUpdate(roleBinding *rbac.RoleBinding, oldRoleBinding *rbac.RoleBinding) field.ErrorList {
	allErrs := ValidateRoleBinding(roleBinding)
	allErrs = append(allErrs, validation.ValidateObjectMetaUpdate(&roleBinding.ObjectMeta, &oldRoleBinding.ObjectMeta, field.NewPath("metadata"))...)

	if oldRoleBinding.RoleRef != roleBinding.RoleRef {
		allErrs = append(allErrs, field.Invalid(field.NewPath("roleRef"), roleBinding.RoleRef, "cannot change roleRef"))
	}

	return allErrs
}

func ValidateClusterRoleBinding(roleBinding *rbac.ClusterRoleBinding) field.ErrorList {
	allErrs := field.ErrorList{}
	allErrs = append(allErrs, validation.ValidateObjectMeta(&roleBinding.ObjectMeta, false, ValidateRBACName, field.NewPath("metadata"))...)

	// TODO allow multiple API groups.  For now, restrict to one, but I can envision other experimental roles in other groups taking
	// advantage of the binding infrastructure
	if roleBinding.RoleRef.APIGroup != rbac.GroupName {
		allErrs = append(allErrs, field.NotSupported(field.NewPath("roleRef", "apiGroup"), roleBinding.RoleRef.APIGroup, []string{rbac.GroupName}))
	}

	switch roleBinding.RoleRef.Kind {
	case "ClusterRole":
	default:
		allErrs = append(allErrs, field.NotSupported(field.NewPath("roleRef", "kind"), roleBinding.RoleRef.Kind, []string{"ClusterRole"}))

	}

	if len(roleBinding.RoleRef.Name) == 0 {
		allErrs = append(allErrs, field.Required(field.NewPath("roleRef", "name"), ""))
	} else {
		for _, msg := range ValidateRBACName(roleBinding.RoleRef.Name, false) {
			allErrs = append(allErrs, field.Invalid(field.NewPath("roleRef", "name"), roleBinding.RoleRef.Name, msg))
		}
	}

	subjectsPath := field.NewPath("subjects")
	for i, subject := range roleBinding.Subjects {
		allErrs = append(allErrs, ValidateRoleBindingSubject(subject, false, subjectsPath.Index(i))...)
	}

	return allErrs
}

func ValidateClusterRoleBindingUpdate(roleBinding *rbac.ClusterRoleBinding, oldRoleBinding *rbac.ClusterRoleBinding) field.ErrorList {
	allErrs := ValidateClusterRoleBinding(roleBinding)
	allErrs = append(allErrs, validation.ValidateObjectMetaUpdate(&roleBinding.ObjectMeta, &oldRoleBinding.ObjectMeta, field.NewPath("metadata"))...)

	if oldRoleBinding.RoleRef != roleBinding.RoleRef {
		allErrs = append(allErrs, field.Invalid(field.NewPath("roleRef"), roleBinding.RoleRef, "cannot change roleRef"))
	}

	return allErrs
}

// ValidateRoleBindingSubject is exported to allow types outside of the RBAC API group to embed a rbac.Subject and reuse this validation logic
func ValidateRoleBindingSubject(subject rbac.Subject, isNamespaced bool, fldPath *field.Path) field.ErrorList {
	allErrs := field.ErrorList{}

	if len(subject.Name) == 0 {
		allErrs = append(allErrs, field.Required(fldPath.Child("name"), ""))
	}

	switch subject.Kind {
	case rbac.ServiceAccountKind:
		if len(subject.Name) > 0 {
			for _, msg := range validation.ValidateServiceAccountName(subject.Name, false) {
				allErrs = append(allErrs, field.Invalid(fldPath.Child("name"), subject.Name, msg))
			}
		}
		if len(subject.APIGroup) > 0 {
			allErrs = append(allErrs, field.NotSupported(fldPath.Child("apiGroup"), subject.APIGroup, []string{""}))
		}
		if !isNamespaced && len(subject.Namespace) == 0 {
			allErrs = append(allErrs, field.Required(fldPath.Child("namespace"), ""))
		}

	case rbac.UserKind:
		// TODO(ericchiang): What other restrictions on user name are there?
		if len(subject.Name) == 0 {
			allErrs = append(allErrs, field.Invalid(fldPath.Child("name"), subject.Name, "user name cannot be empty"))
		}
		if subject.APIGroup != rbac.GroupName {
			allErrs = append(allErrs, field.NotSupported(fldPath.Child("apiGroup"), subject.APIGroup, []string{rbac.GroupName}))
		}

	case rbac.GroupKind:
		// TODO(ericchiang): What other restrictions on group name are there?
		if len(subject.Name) == 0 {
			allErrs = append(allErrs, field.Invalid(fldPath.Child("name"), subject.Name, "group name cannot be empty"))
		}
		if subject.APIGroup != rbac.GroupName {
			allErrs = append(allErrs, field.NotSupported(fldPath.Child("apiGroup"), subject.APIGroup, []string{rbac.GroupName}))
		}

	default:
		allErrs = append(allErrs, field.NotSupported(fldPath.Child("kind"), subject.Kind, []string{rbac.ServiceAccountKind, rbac.UserKind, rbac.GroupKind}))
	}

	return allErrs
}
<|endoftext|>


<commit_before>/*
Copyright 2014 Google Inc. All rights reserved.

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

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

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

package resourcequota

import (
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/rest"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/fields"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
)

// Registry is an interface implemented by things that know how to store ResourceQuota objects.
type Registry interface {
	// ListResourceQuotas obtains a list of pods having labels which match selector.
	ListResourceQuotas(ctx api.Context, selector labels.Selector) (*api.ResourceQuotaList, error)
	// Watch for new/changed/deleted pods
	WatchResourceQuotas(ctx api.Context, label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error)
	// Get a specific pod
	GetResourceQuota(ctx api.Context, podID string) (*api.ResourceQuota, error)
	// Create a pod based on a specification.
	CreateResourceQuota(ctx api.Context, pod *api.ResourceQuota) error
	// Update an existing pod
	UpdateResourceQuota(ctx api.Context, pod *api.ResourceQuota) error
	// Delete an existing pod
	DeleteResourceQuota(ctx api.Context, podID string) error
}

// storage puts strong typing around storage calls
type storage struct {
	rest.StandardStorage
}

// NewRegistry returns a new Registry interface for the given Storage. Any mismatched
// types will panic.
func NewRegistry(s rest.StandardStorage) Registry {
	return &storage{s}
}

func (s *storage) ListResourceQuotas(ctx api.Context, label labels.Selector) (*api.ResourceQuotaList, error) {
	obj, err := s.List(ctx, label, fields.Everything())
	if err != nil {
		return nil, err
	}
	return obj.(*api.ResourceQuotaList), nil
}

func (s *storage) WatchResourceQuotas(ctx api.Context, label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error) {
	return s.Watch(ctx, label, field, resourceVersion)
}

func (s *storage) GetResourceQuota(ctx api.Context, podID string) (*api.ResourceQuota, error) {
	obj, err := s.Get(ctx, podID)
	if err != nil {
		return nil, err
	}
	return obj.(*api.ResourceQuota), nil
}

func (s *storage) CreateResourceQuota(ctx api.Context, pod *api.ResourceQuota) error {
	_, err := s.Create(ctx, pod)
	return err
}

func (s *storage) UpdateResourceQuota(ctx api.Context, pod *api.ResourceQuota) error {
	_, _, err := s.Update(ctx, pod)
	return err
}

func (s *storage) DeleteResourceQuota(ctx api.Context, podID string) error {
	_, err := s.Delete(ctx, podID, nil)
	return err
}
<commit_msg>changed arg names from 'pod' to 'resourceQuota'<commit_after>/*
Copyright 2014 Google Inc. All rights reserved.

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

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

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

package resourcequota

import (
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/rest"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/fields"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
)

// Registry is an interface implemented by things that know how to store ResourceQuota objects.
type Registry interface {
	// ListResourceQuotas obtains a list of resourceQuotas having labels which match selector.
	ListResourceQuotas(ctx api.Context, selector labels.Selector) (*api.ResourceQuotaList, error)
	// Watch for new/changed/deleted resourceQuotas
	WatchResourceQuotas(ctx api.Context, label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error)
	// Get a specific resourceQuota
	GetResourceQuota(ctx api.Context, resourceQuotaID string) (*api.ResourceQuota, error)
	// Create a resourceQuota based on a specification.
	CreateResourceQuota(ctx api.Context, resourceQuota *api.ResourceQuota) error
	// Update an existing resourceQuota
	UpdateResourceQuota(ctx api.Context, resourceQuota *api.ResourceQuota) error
	// Delete an existing resourceQuota
	DeleteResourceQuota(ctx api.Context, resourceQuotaID string) error
}

// storage puts strong typing around storage calls
type storage struct {
	rest.StandardStorage
}

// NewRegistry returns a new Registry interface for the given Storage. Any mismatched
// types will panic.
func NewRegistry(s rest.StandardStorage) Registry {
	return &storage{s}
}

func (s *storage) ListResourceQuotas(ctx api.Context, label labels.Selector) (*api.ResourceQuotaList, error) {
	obj, err := s.List(ctx, label, fields.Everything())
	if err != nil {
		return nil, err
	}
	return obj.(*api.ResourceQuotaList), nil
}

func (s *storage) WatchResourceQuotas(ctx api.Context, label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error) {
	return s.Watch(ctx, label, field, resourceVersion)
}

func (s *storage) GetResourceQuota(ctx api.Context, resourceQuotaID string) (*api.ResourceQuota, error) {
	obj, err := s.Get(ctx, resourceQuotaID)
	if err != nil {
		return nil, err
	}
	return obj.(*api.ResourceQuota), nil
}

func (s *storage) CreateResourceQuota(ctx api.Context, resourceQuota *api.ResourceQuota) error {
	_, err := s.Create(ctx, resourceQuota)
	return err
}

func (s *storage) UpdateResourceQuota(ctx api.Context, resourceQuota *api.ResourceQuota) error {
	_, _, err := s.Update(ctx, resourceQuota)
	return err
}

func (s *storage) DeleteResourceQuota(ctx api.Context, resourceQuotaID string) error {
	_, err := s.Delete(ctx, resourceQuotaID, nil)
	return err
}
<|endoftext|>


<commit_before>package sysregistries

import (
	"strings"

	"github.com/BurntSushi/toml"
	"github.com/containers/image/types"
	"io/ioutil"
	"path/filepath"
)

// systemRegistriesConfPath is the path to the system-wide registry configuration file
// and is used to add/subtract potential registries for obtaining images.
// You can override this at build time with
// -ldflags '-X github.com/containers/image/sysregistries.systemRegistriesConfPath=$your_path'
var systemRegistriesConfPath = builtinRegistriesConfPath

// builtinRegistriesConfPath is the path to registry configuration file
// DO NOT change this, instead see systemRegistriesConfPath above.
const builtinRegistriesConfPath = "/etc/containers/registries.conf"

type registries struct {
	Registries []string `toml:"registries"`
}

type tomlConfig struct {
	Registries struct {
		Search   registries `toml:"search"`
		Insecure registries `toml:"insecure"`
		Block    registries `toml:"block"`
	} `toml:"registries"`
}

// normalizeRegistries removes trailing slashes from registries, which is a
// common pitfall when configuring registries (e.g., "docker.io/library/).
func normalizeRegistries(regs *registries) {
	for i := range regs.Registries {
		regs.Registries[i] = strings.TrimRight(regs.Registries[i], "/")
	}
}

// Reads the global registry file from the filesystem. Returns
// a byte array
func readRegistryConf(sys *types.SystemContext) ([]byte, error) {
	dirPath := systemRegistriesConfPath
	if sys != nil {
		if sys.SystemRegistriesConfPath != "" {
			dirPath = sys.SystemRegistriesConfPath
		} else if sys.RootForImplicitAbsolutePaths != "" {
			dirPath = filepath.Join(sys.RootForImplicitAbsolutePaths, systemRegistriesConfPath)
		}
	}
	configBytes, err := ioutil.ReadFile(dirPath)
	return configBytes, err
}

// For mocking in unittests
var readConf = readRegistryConf

// Loads the registry configuration file from the filesystem and
// then unmarshals it.  Returns the unmarshalled object.
func loadRegistryConf(sys *types.SystemContext) (*tomlConfig, error) {
	config := &tomlConfig{}

	configBytes, err := readConf(sys)
	if err != nil {
		return nil, err
	}

	err = toml.Unmarshal(configBytes, &config)
	normalizeRegistries(&config.Registries.Search)
	normalizeRegistries(&config.Registries.Insecure)
	normalizeRegistries(&config.Registries.Block)
	return config, err
}

// GetRegistries returns an array of strings that contain the names
// of the registries as defined in the system-wide
// registries file.  it returns an empty array if none are
// defined
func GetRegistries(sys *types.SystemContext) ([]string, error) {
	config, err := loadRegistryConf(sys)
	if err != nil {
		return nil, err
	}
	return config.Registries.Search.Registries, nil
}

// GetInsecureRegistries returns an array of strings that contain the names
// of the insecure registries as defined in the system-wide
// registries file.  it returns an empty array if none are
// defined
func GetInsecureRegistries(sys *types.SystemContext) ([]string, error) {
	config, err := loadRegistryConf(sys)
	if err != nil {
		return nil, err
	}
	return config.Registries.Insecure.Registries, nil
}
<commit_msg>Add functions to return Registries paths<commit_after>package sysregistries

import (
	"strings"

	"github.com/BurntSushi/toml"
	"github.com/containers/image/types"
	"io/ioutil"
	"path/filepath"
)

// systemRegistriesConfPath is the path to the system-wide registry configuration file
// and is used to add/subtract potential registries for obtaining images.
// You can override this at build time with
// -ldflags '-X github.com/containers/image/sysregistries.systemRegistriesConfPath=$your_path'
var systemRegistriesConfPath = builtinRegistriesConfPath

// builtinRegistriesConfPath is the path to registry configuration file
// DO NOT change this, instead see systemRegistriesConfPath above.
const builtinRegistriesConfPath = "/etc/containers/registries.conf"

type registries struct {
	Registries []string `toml:"registries"`
}

type tomlConfig struct {
	Registries struct {
		Search   registries `toml:"search"`
		Insecure registries `toml:"insecure"`
		Block    registries `toml:"block"`
	} `toml:"registries"`
}

// normalizeRegistries removes trailing slashes from registries, which is a
// common pitfall when configuring registries (e.g., "docker.io/library/).
func normalizeRegistries(regs *registries) {
	for i := range regs.Registries {
		regs.Registries[i] = strings.TrimRight(regs.Registries[i], "/")
	}
}

// Reads the global registry file from the filesystem. Returns
// a byte array
func readRegistryConf(sys *types.SystemContext) ([]byte, error) {
	return ioutil.ReadFile(RegistriesConfPath(sys))
}

// For mocking in unittests
var readConf = readRegistryConf

// Loads the registry configuration file from the filesystem and
// then unmarshals it.  Returns the unmarshalled object.
func loadRegistryConf(sys *types.SystemContext) (*tomlConfig, error) {
	config := &tomlConfig{}

	configBytes, err := readConf(sys)
	if err != nil {
		return nil, err
	}

	err = toml.Unmarshal(configBytes, &config)
	normalizeRegistries(&config.Registries.Search)
	normalizeRegistries(&config.Registries.Insecure)
	normalizeRegistries(&config.Registries.Block)
	return config, err
}

// GetRegistries returns an array of strings that contain the names
// of the registries as defined in the system-wide
// registries file.  it returns an empty array if none are
// defined
func GetRegistries(sys *types.SystemContext) ([]string, error) {
	config, err := loadRegistryConf(sys)
	if err != nil {
		return nil, err
	}
	return config.Registries.Search.Registries, nil
}

// GetInsecureRegistries returns an array of strings that contain the names
// of the insecure registries as defined in the system-wide
// registries file.  it returns an empty array if none are
// defined
func GetInsecureRegistries(sys *types.SystemContext) ([]string, error) {
	config, err := loadRegistryConf(sys)
	if err != nil {
		return nil, err
	}
	return config.Registries.Insecure.Registries, nil
}

// RegistriesConfPath is the path to the system-wide registry configuration file
func RegistriesConfPath(ctx *types.SystemContext) string {
	path := systemRegistriesConfPath
	if ctx != nil {
		if ctx.SystemRegistriesConfPath != "" {
			path = ctx.SystemRegistriesConfPath
		} else if ctx.RootForImplicitAbsolutePaths != "" {
			path = filepath.Join(ctx.RootForImplicitAbsolutePaths, systemRegistriesConfPath)
		}
	}
	return path
}
<|endoftext|>


<commit_before>/*
Copyright 2016 Skippbox, Ltd All rights reserved.

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

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

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

package openshift

import (
	deployapi "github.com/openshift/origin/pkg/deploy/api"
	"github.com/skippbox/kompose/pkg/kobject"
	"github.com/skippbox/kompose/pkg/transformer/kubernetes"

	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/api/unversioned"
	"k8s.io/kubernetes/pkg/runtime"
)

type OpenShift struct {
}

// initDeploymentConfig initialize OpenShifts DeploymentConfig object
func initDeploymentConfig(name string, service kobject.ServiceConfig, replicas int) *deployapi.DeploymentConfig {
	dc := &deployapi.DeploymentConfig{
		TypeMeta: unversioned.TypeMeta{
			Kind:       "DeploymentConfig",
			APIVersion: "v1",
		},
		ObjectMeta: api.ObjectMeta{
			Name:   name,
			Labels: map[string]string{"service": name},
		},
		Spec: deployapi.DeploymentConfigSpec{
			Replicas: int32(replicas),
			Selector: map[string]string{"service": name},
			//UniqueLabelKey: p.Name,
			Template: &api.PodTemplateSpec{
				ObjectMeta: api.ObjectMeta{
					Labels: map[string]string{"service": name},
				},
				Spec: api.PodSpec{
					Containers: []api.Container{
						{
							Name:  name,
							Image: service.Image,
						},
					},
				},
			},
		},
	}
	return dc
}

func (k *OpenShift) Transform(komposeObject kobject.KomposeObject, opt kobject.ConvertOptions) []runtime.Object {
	// this will hold all the converted data
	var allobjects []runtime.Object

	for name, service := range komposeObject.ServiceConfigs {
		objects := kubernetes.CreateKubernetesObjects(name, service, opt)

		if opt.CreateDeploymentConfig {
			objects = append(objects, initDeploymentConfig(name, service, opt.Replicas)) // OpenShift DeploymentConfigs
		}

		// If ports not provided in configuration we will not make service
		if kubernetes.PortsExist(name, service) {
			svc := kubernetes.CreateService(name, service, objects)
			objects = append(objects, svc)
		}
		allobjects = append(allobjects, objects...)
	}

	return allobjects
}
<commit_msg>follow-up: update for openshift<commit_after>/*
Copyright 2016 Skippbox, Ltd All rights reserved.

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

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

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

package openshift

import (
	deployapi "github.com/openshift/origin/pkg/deploy/api"
	"github.com/skippbox/kompose/pkg/kobject"
	"github.com/skippbox/kompose/pkg/transformer/kubernetes"

	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/api/unversioned"
	"k8s.io/kubernetes/pkg/runtime"
)

type OpenShift struct {
}

// initDeploymentConfig initialize OpenShifts DeploymentConfig object
func initDeploymentConfig(name string, service kobject.ServiceConfig, replicas int) *deployapi.DeploymentConfig {
	dc := &deployapi.DeploymentConfig{
		TypeMeta: unversioned.TypeMeta{
			Kind:       "DeploymentConfig",
			APIVersion: "v1",
		},
		ObjectMeta: api.ObjectMeta{
			Name:   name,
			Labels: map[string]string{"service": name},
		},
		Spec: deployapi.DeploymentConfigSpec{
			Replicas: int32(replicas),
			Selector: map[string]string{"service": name},
			//UniqueLabelKey: p.Name,
			Template: &api.PodTemplateSpec{
				ObjectMeta: api.ObjectMeta{
					Labels: map[string]string{"service": name},
				},
				Spec: api.PodSpec{
					Containers: []api.Container{
						{
							Name:  name,
							Image: service.Image,
						},
					},
				},
			},
		},
	}
	return dc
}

func (k *OpenShift) Transform(komposeObject kobject.KomposeObject, opt kobject.ConvertOptions) []runtime.Object {
	// this will hold all the converted data
	var allobjects []runtime.Object

	for name, service := range komposeObject.ServiceConfigs {
		objects := kubernetes.CreateKubernetesObjects(name, service, opt)

		if opt.CreateDeploymentConfig {
			objects = append(objects, initDeploymentConfig(name, service, opt.Replicas)) // OpenShift DeploymentConfigs
		}

		// If ports not provided in configuration we will not make service
		if kubernetes.PortsExist(name, service) {
			svc := kubernetes.CreateService(name, service, objects)
			objects = append(objects, svc)
		}

		kubernetes.UpdateKubernetesObjects(name, service, objects)

		allobjects = append(allobjects, objects...)
	}

	return allobjects
}
<|endoftext|>


<commit_before>package ledis

import (
	"github.com/siddontang/ledisdb/config"
	"os"
	"testing"
)

func testTxRollback(t *testing.T, db *DB) {
	var err error
	key1 := []byte("tx_key1")
	key2 := []byte("tx_key2")
	field2 := []byte("tx_field2")

	err = db.Set(key1, []byte("value"))
	if err != nil {
		t.Fatal(err)
	}

	_, err = db.HSet(key2, field2, []byte("value"))
	if err != nil {
		t.Fatal(err)
	}

	var tx *Tx
	tx, err = db.Begin()
	if err != nil {
		t.Fatal(err)
	}

	defer tx.Rollback()

	err = tx.Set(key1, []byte("1"))

	if err != nil {
		t.Fatal(err)
	}

	_, err = tx.HSet(key2, field2, []byte("2"))

	if err != nil {
		t.Fatal(err)
	}

	_, err = tx.HSet([]byte("no_key"), field2, []byte("2"))

	if err != nil {
		t.Fatal(err)
	}

	if v, err := tx.Get(key1); err != nil {
		t.Fatal(err)
	} else if string(v) != "1" {
		t.Fatal(string(v))
	}

	if v, err := tx.HGet(key2, field2); err != nil {
		t.Fatal(err)
	} else if string(v) != "2" {
		t.Fatal(string(v))
	}

	err = tx.Rollback()
	if err != nil {
		t.Fatal(err)
	}

	if v, err := db.Get(key1); err != nil {
		t.Fatal(err)
	} else if string(v) != "value" {
		t.Fatal(string(v))
	}

	if v, err := db.HGet(key2, field2); err != nil {
		t.Fatal(err)
	} else if string(v) != "value" {
		t.Fatal(string(v))
	}
}

func testTxCommit(t *testing.T, db *DB) {
	var err error
	key1 := []byte("tx_key1")
	key2 := []byte("tx_key2")
	field2 := []byte("tx_field2")

	err = db.Set(key1, []byte("value"))
	if err != nil {
		t.Fatal(err)
	}

	_, err = db.HSet(key2, field2, []byte("value"))
	if err != nil {
		t.Fatal(err)
	}

	var tx *Tx
	tx, err = db.Begin()
	if err != nil {
		t.Fatal(err)
	}

	defer tx.Rollback()

	err = tx.Set(key1, []byte("1"))

	if err != nil {
		t.Fatal(err)
	}

	_, err = tx.HSet(key2, field2, []byte("2"))

	if err != nil {
		t.Fatal(err)
	}

	if v, err := tx.Get(key1); err != nil {
		t.Fatal(err)
	} else if string(v) != "1" {
		t.Fatal(string(v))
	}

	if v, err := tx.HGet(key2, field2); err != nil {
		t.Fatal(err)
	} else if string(v) != "2" {
		t.Fatal(string(v))
	}

	err = tx.Commit()
	if err != nil {
		t.Fatal(err)
	}

	if v, err := db.Get(key1); err != nil {
		t.Fatal(err)
	} else if string(v) != "1" {
		t.Fatal(string(v))
	}

	if v, err := db.HGet(key2, field2); err != nil {
		t.Fatal(err)
	} else if string(v) != "2" {
		t.Fatal(string(v))
	}
}

func testTxSelect(t *testing.T, db *DB) {
	tx, err := db.Begin()
	if err != nil {
		t.Fatal(err)
	}

	defer tx.Rollback()

	tx.Set([]byte("tx_select_1"), []byte("a"))

	tx.Select(1)

	tx.Set([]byte("tx_select_2"), []byte("b"))

	if err = tx.Commit(); err != nil {
		t.Fatal(err)
	}

	if v, err := db.Get([]byte("tx_select_1")); err != nil {
		t.Fatal(err)
	} else if string(v) != "a" {
		t.Fatal(string(v))
	}

	if v, err := db.Get([]byte("tx_select_2")); err != nil {
		t.Fatal(err)
	} else if v != nil {
		t.Fatal("must nil")
	}

	db, _ = db.l.Select(1)

	if v, err := db.Get([]byte("tx_select_2")); err != nil {
		t.Fatal(err)
	} else if string(v) != "b" {
		t.Fatal(string(v))
	}

	if v, err := db.Get([]byte("tx_select_1")); err != nil {
		t.Fatal(err)
	} else if v != nil {
		t.Fatal("must nil")
	}
}

func testTx(t *testing.T, name string) {
	cfg := config.NewConfigDefault()
	cfg.DataDir = "/tmp/ledis_test_tx"

	cfg.DBName = name
	cfg.LMDB.MapSize = 10 * 1024 * 1024
	//cfg.UseReplication = true

	os.RemoveAll(cfg.DataDir)

	l, err := Open(cfg)
	if err != nil {
		t.Fatal(err)
	}

	defer l.Close()

	db, _ := l.Select(0)

	testTxRollback(t, db)
	testTxCommit(t, db)
	testTxSelect(t, db)
}

//only lmdb, boltdb support Transaction
func TestTx(t *testing.T) {
	testTx(t, "lmdb")
	testTx(t, "boltdb")
}
<commit_msg>fix lmdb test error on windows<commit_after>package ledis

import (
	"github.com/siddontang/ledisdb/config"
	"os"
	"strings"
	"testing"
)

func testTxRollback(t *testing.T, db *DB) {
	var err error
	key1 := []byte("tx_key1")
	key2 := []byte("tx_key2")
	field2 := []byte("tx_field2")

	err = db.Set(key1, []byte("value"))
	if err != nil {
		t.Fatal(err)
	}

	_, err = db.HSet(key2, field2, []byte("value"))
	if err != nil {
		t.Fatal(err)
	}

	var tx *Tx
	tx, err = db.Begin()
	if err != nil {
		t.Fatal(err)
	}

	defer tx.Rollback()

	err = tx.Set(key1, []byte("1"))

	if err != nil {
		t.Fatal(err)
	}

	_, err = tx.HSet(key2, field2, []byte("2"))

	if err != nil {
		t.Fatal(err)
	}

	_, err = tx.HSet([]byte("no_key"), field2, []byte("2"))

	if err != nil {
		t.Fatal(err)
	}

	if v, err := tx.Get(key1); err != nil {
		t.Fatal(err)
	} else if string(v) != "1" {
		t.Fatal(string(v))
	}

	if v, err := tx.HGet(key2, field2); err != nil {
		t.Fatal(err)
	} else if string(v) != "2" {
		t.Fatal(string(v))
	}

	err = tx.Rollback()
	if err != nil {
		t.Fatal(err)
	}

	if v, err := db.Get(key1); err != nil {
		t.Fatal(err)
	} else if string(v) != "value" {
		t.Fatal(string(v))
	}

	if v, err := db.HGet(key2, field2); err != nil {
		t.Fatal(err)
	} else if string(v) != "value" {
		t.Fatal(string(v))
	}
}

func testTxCommit(t *testing.T, db *DB) {
	var err error
	key1 := []byte("tx_key1")
	key2 := []byte("tx_key2")
	field2 := []byte("tx_field2")

	err = db.Set(key1, []byte("value"))
	if err != nil {
		t.Fatal(err)
	}

	_, err = db.HSet(key2, field2, []byte("value"))
	if err != nil {
		t.Fatal(err)
	}

	var tx *Tx
	tx, err = db.Begin()
	if err != nil {
		t.Fatal(err)
	}

	defer tx.Rollback()

	err = tx.Set(key1, []byte("1"))

	if err != nil {
		t.Fatal(err)
	}

	_, err = tx.HSet(key2, field2, []byte("2"))

	if err != nil {
		t.Fatal(err)
	}

	if v, err := tx.Get(key1); err != nil {
		t.Fatal(err)
	} else if string(v) != "1" {
		t.Fatal(string(v))
	}

	if v, err := tx.HGet(key2, field2); err != nil {
		t.Fatal(err)
	} else if string(v) != "2" {
		t.Fatal(string(v))
	}

	err = tx.Commit()
	if err != nil {
		t.Fatal(err)
	}

	if v, err := db.Get(key1); err != nil {
		t.Fatal(err)
	} else if string(v) != "1" {
		t.Fatal(string(v))
	}

	if v, err := db.HGet(key2, field2); err != nil {
		t.Fatal(err)
	} else if string(v) != "2" {
		t.Fatal(string(v))
	}
}

func testTxSelect(t *testing.T, db *DB) {
	tx, err := db.Begin()
	if err != nil {
		t.Fatal(err)
	}

	defer tx.Rollback()

	tx.Set([]byte("tx_select_1"), []byte("a"))

	tx.Select(1)

	tx.Set([]byte("tx_select_2"), []byte("b"))

	if err = tx.Commit(); err != nil {
		t.Fatal(err)
	}

	if v, err := db.Get([]byte("tx_select_1")); err != nil {
		t.Fatal(err)
	} else if string(v) != "a" {
		t.Fatal(string(v))
	}

	if v, err := db.Get([]byte("tx_select_2")); err != nil {
		t.Fatal(err)
	} else if v != nil {
		t.Fatal("must nil")
	}

	db, _ = db.l.Select(1)

	if v, err := db.Get([]byte("tx_select_2")); err != nil {
		t.Fatal(err)
	} else if string(v) != "b" {
		t.Fatal(string(v))
	}

	if v, err := db.Get([]byte("tx_select_1")); err != nil {
		t.Fatal(err)
	} else if v != nil {
		t.Fatal("must nil")
	}
}

func testTx(t *testing.T, name string) {
	cfg := config.NewConfigDefault()
	cfg.DataDir = "/tmp/ledis_test_tx"

	cfg.DBName = name
	cfg.LMDB.MapSize = 10 * 1024 * 1024
	//cfg.UseReplication = true

	os.RemoveAll(cfg.DataDir)

	l, err := Open(cfg)
	if err != nil {
		if strings.Contains(err.Error(), "not registered") {
			return
		}
		t.Fatal(err)
	}

	defer l.Close()

	db, _ := l.Select(0)

	testTxRollback(t, db)
	testTxCommit(t, db)
	testTxSelect(t, db)
}

//only lmdb, boltdb support Transaction
func TestTx(t *testing.T) {
	testTx(t, "lmdb")
	testTx(t, "boltdb")
}
<|endoftext|>