<commit_before>// Package gaussian provides algorithms for working with Gaussian distributions.
//
// https://en.wikipedia.org/wiki/Normal_distribution
package gaussian

import (
	"math"
	"math/rand"
)

// Self represents a particular distribution from the family.
type Self struct {
	μ  float64
	σ2 float64
}

// New returns a Gaussian distribution with mean μ and variance σ2.
func New(μ, σ2 float64) *Self {
	return &Self{μ, σ2}
}

// Sample draws samples from the distribution.
func (s *Self) Sample(count uint32) []float64 {
	points := make([]float64, count)

	μ, σ := s.μ, math.Sqrt(s.σ2)

	for i := range points {
		points[i] = μ + σ*rand.NormFloat64()
	}

	return points
}

// CDF evaluates the CDF of the distribution.
func (s *Self) CDF(points []float64) []float64 {
	values := make([]float64, len(points))

	a, b := s.μ, math.Sqrt(2*s.σ2)

	for i, x := range points {
		values[i] = (1 + math.Erf((x-a)/b)) / 2
	}

	return values
}

// InvCDF evaluates the inverse CDF of the distribution.
func (s *Self) InvCDF(points []float64) []float64 {
	// The code is based on a C implementation by John Burkardt.
	// http://people.sc.fsu.edu/~jburkardt/c_src/asa241/asa241.html

	const (
		const1 = 0.180625
		const2 = 1.6
		split1 = 0.425
		split2 = 5
	)

	values := make([]float64, len(points))

	μ, σ := s.μ, math.Sqrt(s.σ2)
	inf := math.Inf(1)

	var q, r float64

	for i, p := range points {
		if p <= 0 {
			values[i] = -inf
			continue
		}
		if 1 <= p {
			values[i] = inf
			continue
		}

		q = p - 0.5

		if math.Abs(q) <= split1 {
			r = const1 - q*q
			values[i] = μ + σ*q*polynom(coefA, r)/polynom(coeffB, r)
			continue
		}

		if q < 0 {
			r = p
		} else {
			r = 1 - p
		}

		r = math.Sqrt(-math.Log(r))

		if r <= split2 {
			r -= const2
			values[i] = polynom(coefC, r) / polynom(coefD, r)
		} else {
			r -= split2
			values[i] = polynom(coefE, r) / polynom(coefF, r)
		}

		if q < 0 {
			values[i] = μ - σ*values[i]
		} else {
			values[i] = μ + σ*values[i]
		}
	}

	return values
}

func polynom(coef []float64, x float64) (value float64) {
	for i := 8 - 1; 0 <= i; i-- {
		value = value*x + coef[i]
	}

	return
}

var coefA = []float64{
	3.3871328727963666080,
	1.3314166789178437745e+2,
	1.9715909503065514427e+3,
	1.3731693765509461125e+4,
	4.5921953931549871457e+4,
	6.7265770927008700853e+4,
	3.3430575583588128105e+4,
	2.5090809287301226727e+3,
}

var coeffB = []float64{
	1.0,
	4.2313330701600911252e+1,
	6.8718700749205790830e+2,
	5.3941960214247511077e+3,
	2.1213794301586595867e+4,
	3.9307895800092710610e+4,
	2.8729085735721942674e+4,
	5.2264952788528545610e+3,
}

var coefC = []float64{
	1.42343711074968357734,
	4.63033784615654529590,
	5.76949722146069140550,
	3.64784832476320460504,
	1.27045825245236838258,
	2.41780725177450611770e-1,
	2.27238449892691845833e-2,
	7.74545014278341407640e-4,
}

var coefD = []float64{
	1.0,
	2.05319162663775882187,
	1.67638483018380384940,
	6.89767334985100004550e-1,
	1.48103976427480074590e-1,
	1.51986665636164571966e-2,
	5.47593808499534494600e-4,
	1.05075007164441684324e-9,
}

var coefE = []float64{
	6.65790464350110377720,
	5.46378491116411436990,
	1.78482653991729133580,
	2.96560571828504891230e-1,
	2.65321895265761230930e-2,
	1.24266094738807843860e-3,
	2.71155556874348757815e-5,
	2.01033439929228813265e-7,
}

var coefF = []float64{
	1.0,
	5.99832206555887937690e-1,
	1.36929880922735805310e-1,
	1.48753612908506148525e-2,
	7.86869131145613259100e-4,
	1.84631831751005468180e-5,
	1.42151175831644588870e-7,
	2.04426310338993978564e-15,
}
<commit_msg>Cosmetic changes in gaussian<commit_after>// Package gaussian provides algorithms for working with Gaussian distributions.
//
// https://en.wikipedia.org/wiki/Normal_distribution
package gaussian

import (
	"math"
	"math/rand"
)

// Self represents a particular distribution from the family.
type Self struct {
	μ  float64
	σ2 float64
}

// New returns a Gaussian distribution with mean μ and variance σ2.
func New(μ, σ2 float64) *Self {
	return &Self{μ, σ2}
}

// Sample draws samples from the distribution.
func (s *Self) Sample(count uint32) []float64 {
	points := make([]float64, count)

	μ, σ := s.μ, math.Sqrt(s.σ2)

	for i := range points {
		points[i] = μ + σ*rand.NormFloat64()
	}

	return points
}

// CDF evaluates the CDF of the distribution.
func (s *Self) CDF(points []float64) []float64 {
	values := make([]float64, len(points))

	a, b := s.μ, math.Sqrt(2*s.σ2)

	for i, x := range points {
		values[i] = (1 + math.Erf((x-a)/b)) / 2
	}

	return values
}

// InvCDF evaluates the inverse CDF of the distribution.
//
// The code is based on a C implementation by John Burkardt.
// http://people.sc.fsu.edu/~jburkardt/c_src/asa241/asa241.html
func (s *Self) InvCDF(points []float64) []float64 {

	const (
		const1 = 0.180625
		const2 = 1.6
		split1 = 0.425
		split2 = 5
	)

	values := make([]float64, len(points))

	μ, σ := s.μ, math.Sqrt(s.σ2)
	inf := math.Inf(1)

	var q, r float64

	for i, p := range points {
		if p <= 0 {
			values[i] = -inf
			continue
		}
		if 1 <= p {
			values[i] = inf
			continue
		}

		q = p - 0.5

		if math.Abs(q) <= split1 {
			r = const1 - q*q
			values[i] = μ + σ*q*poly7(coefA, r)/poly7(coeffB, r)
			continue
		}

		if q < 0 {
			r = p
		} else {
			r = 1 - p
		}

		r = math.Sqrt(-math.Log(r))

		if r <= split2 {
			r -= const2
			values[i] = poly7(coefC, r) / poly7(coefD, r)
		} else {
			r -= split2
			values[i] = poly7(coefE, r) / poly7(coefF, r)
		}

		if q < 0 {
			values[i] = μ - σ*values[i]
		} else {
			values[i] = μ + σ*values[i]
		}
	}

	return values
}

func poly7(coef []float64, x float64) (value float64) {
	for i := 8 - 1; 0 <= i; i-- {
		value = value*x + coef[i]
	}

	return
}

var coefA = []float64{
	3.3871328727963666080,
	1.3314166789178437745e+2,
	1.9715909503065514427e+3,
	1.3731693765509461125e+4,
	4.5921953931549871457e+4,
	6.7265770927008700853e+4,
	3.3430575583588128105e+4,
	2.5090809287301226727e+3,
}

var coeffB = []float64{
	1.0,
	4.2313330701600911252e+1,
	6.8718700749205790830e+2,
	5.3941960214247511077e+3,
	2.1213794301586595867e+4,
	3.9307895800092710610e+4,
	2.8729085735721942674e+4,
	5.2264952788528545610e+3,
}

var coefC = []float64{
	1.42343711074968357734,
	4.63033784615654529590,
	5.76949722146069140550,
	3.64784832476320460504,
	1.27045825245236838258,
	2.41780725177450611770e-1,
	2.27238449892691845833e-2,
	7.74545014278341407640e-4,
}

var coefD = []float64{
	1.0,
	2.05319162663775882187,
	1.67638483018380384940,
	6.89767334985100004550e-1,
	1.48103976427480074590e-1,
	1.51986665636164571966e-2,
	5.47593808499534494600e-4,
	1.05075007164441684324e-9,
}

var coefE = []float64{
	6.65790464350110377720,
	5.46378491116411436990,
	1.78482653991729133580,
	2.96560571828504891230e-1,
	2.65321895265761230930e-2,
	1.24266094738807843860e-3,
	2.71155556874348757815e-5,
	2.01033439929228813265e-7,
}

var coefF = []float64{
	1.0,
	5.99832206555887937690e-1,
	1.36929880922735805310e-1,
	1.48753612908506148525e-2,
	7.86869131145613259100e-4,
	1.84631831751005468180e-5,
	1.42151175831644588870e-7,
	2.04426310338993978564e-15,
}
<|endoftext|>


<commit_before>package meter2
<commit_msg>Remove empty file<commit_after><|endoftext|>


<commit_before>package philarios

import (
  "database/sql"
  "regexp"
  "github.com/wangjohn/quickselect"
)

type WordVector struct {
  Word string
  Score float64
}

type WordVectorCollection []WordVector struct

func (t WordVectorCollection) Len() int {
  return len(t)
}

func (t WordVectorCollection) Less(i, j int) bool {
  return synonymScore(t[i].Score) < synonymScore(t[j].Score)
}

func (t WordVectorCollection) Swap(i, j int) {
  t[i], t[j] = t[j], t[i]
}

/*
AlternativeWords returns alternative words that can be used in place of the
current word. The words that are returned will have close meanings to the word
used as an argument, but which are usually used in place of that word.

The maxWords parameter specifies the maximum number of words to return.
*/
func AlternativeWords(word string, maxWords int) ([]string, error) {
  var alternativeWords []string
  wordVectors := make(WordVectorCollection, 0)

  targetVectors, err := TargetVectors(word)
  if err != nil {
    return alternativeWords, err
  }
  wordVectors = append(wordVectors, targetVectors...)

  synonyms, err := Synonyms(word)
  if err != nil {
    return alternativeWords, err
  }

  for _, synonym := range synonyms {
    synonymVectors, err := TargetVectors(synonym)
    wordVectors = append(wordVectors, synonymVectors)
  }

  var wordsToSelect int
  if len(wordVectors) < maxWords {
    wordsToSelect = len(wordVectors)
  } else {
    wordsToSelect = maxWords
  }
  quickselect.QuickSelect(wordVectors, wordsToSelect)

  alternativeWords = make([]string, wordsToSelect)
  for i := 0; i < wordsToSelect; i++ {
    alternativeWords[i] = wordVectors[i].Word
  }

  return alternativeWords
}

/*
The synonymScore method specifies the mapping between a word's score and its
rank relative to other words. This function allows finer control over the words
that are returned.
*/
func synonymScore(score float64) (float64) {
  return score
}

func TargetVectors(word string) ([]WordVector, error) {
  var wordVectors []WordVector

  // TODO: figure out a way to get pre and post target vectors
  rows, err := db.Query(`SELECT body FROM paragraphs
                         WHERE to_tsvector(body) @@ to_tsquery(?)`, word)
  if err != nil {
    return wordVectors, err
  }
  defer rows.Close()

  for rows.Next() {
    var body string
    if err = rows.Scan(&body); err != nil {
      return wordVectors, err
    }

    newVectors := paragraphTargetVectors(body, word)
    wordVectors = append(wordVectors, newVectors...)
  }

  return wordVectors
}

func paragraphTargetVectors(paragraph, word string) ([]WordVector) {
  regexString := fmt.Printf(`[\s[[:punct:]]]*%s[\s[[:punct:]]]*`, word)
  compiledRegex := regexp.Compile(regexString)

  allIndices := compiledRegex.FindAllStringIndex(paragraph, -1)
  if allIndices != nil {
    for i := 0; i < len(allIndices); i++ {
      matchedIndexPair := allIndices[i]
      start, end := matchedIndexPair[0], matchedIndexPair[1]
      lookForWord(paragraph[:start], false)
      lookForword(paragraph[end:], true)
    }
  }
}

func lookForWord(paragraph string, atBeginning bool) string {
  // TODO: implement
}

func Synonyms(word string) ([]string, error) {
  // TODO: implement
}
<commit_msg>Implementation for lookForWord method.<commit_after>package philarios

import (
  "database/sql"
  "regexp"
  "github.com/wangjohn/quickselect"
)

type WordVector struct {
  Word string
  Score float64
}

type WordVectorCollection []WordVector struct

func (t WordVectorCollection) Len() int {
  return len(t)
}

func (t WordVectorCollection) Less(i, j int) bool {
  return synonymScore(t[i].Score) < synonymScore(t[j].Score)
}

func (t WordVectorCollection) Swap(i, j int) {
  t[i], t[j] = t[j], t[i]
}

/*
AlternativeWords returns alternative words that can be used in place of the
current word. The words that are returned will have close meanings to the word
used as an argument, but which are usually used in place of that word.

The maxWords parameter specifies the maximum number of words to return.
*/
func AlternativeWords(word string, maxWords int) ([]string, error) {
  var alternativeWords []string
  wordVectors := make(WordVectorCollection, 0)

  targetVectors, err := TargetVectors(word)
  if err != nil {
    return alternativeWords, err
  }
  wordVectors = append(wordVectors, targetVectors...)

  synonyms, err := Synonyms(word)
  if err != nil {
    return alternativeWords, err
  }

  for _, synonym := range synonyms {
    synonymVectors, err := TargetVectors(synonym)
    wordVectors = append(wordVectors, synonymVectors)
  }

  var wordsToSelect int
  if len(wordVectors) < maxWords {
    wordsToSelect = len(wordVectors)
  } else {
    wordsToSelect = maxWords
  }
  quickselect.QuickSelect(wordVectors, wordsToSelect)

  alternativeWords = make([]string, wordsToSelect)
  for i := 0; i < wordsToSelect; i++ {
    alternativeWords[i] = wordVectors[i].Word
  }

  return alternativeWords
}

/*
The synonymScore method specifies the mapping between a word's score and its
rank relative to other words. This function allows finer control over the words
that are returned.
*/
func synonymScore(score float64) (float64) {
  return score
}

func TargetVectors(word string) ([]WordVector, error) {
  var wordVectors []WordVector

  // TODO: figure out a way to get pre and post target vectors
  rows, err := db.Query(`SELECT body FROM paragraphs
                         WHERE to_tsvector(body) @@ to_tsquery(?)`, word)
  if err != nil {
    return wordVectors, err
  }
  defer rows.Close()

  for rows.Next() {
    var body string
    if err = rows.Scan(&body); err != nil {
      return wordVectors, err
    }

    newVectors := paragraphTargetVectors(body, word)
    wordVectors = append(wordVectors, newVectors...)
  }

  return wordVectors
}

func paragraphTargetVectors(paragraph, word string) ([]WordVector) {
  wordVectors := make([]WordVector, 0)

  regexString := fmt.Printf(`[\s[[:punct:]]]*%s[\s[[:punct:]]]*`, word)
  compiledRegex := regexp.Compile(regexString)

  allIndices := compiledRegex.FindAllStringIndex(paragraph, -1)
  var potentialVector string
  if allIndices != nil {
    for i := 0; i < len(allIndices); i++ {
      matchedIndexPair := allIndices[i]
      start, end := matchedIndexPair[0], matchedIndexPair[1]

      potentialVector = lookForWord(paragraph[:start], false)
      if potentialVector != "" {
        wordVectors = append(wordVectors, potentialVector)
      }

      potentialVector := lookForword(paragraph[end:], true)
      if potentialVector != "" {
        wordVectors = append(wordVectors, potentialVector)
      }
    }
  }

  return wordVectors
}

func lookForWord(paragraph string, atBeginning bool) string {
  if strings.Trim(paragraph, " ") == "" {
    return ""
  }

  var compiledRegex regexp.Regexp
  if atBeginning {
    compiledRegex = regexp.Compile(`^(\w+)[\s[[:punct:]]]?`)
  } else {
    compiledRegex = regexp.Compile(`[\s[[:punct:]]]?(\w+)$`)
  }
  return compiledRegex.FindString(paragraph)
}

func Synonyms(word string) ([]string, error) {
  // TODO: implement
}
<|endoftext|>


<commit_before>package dsdk

import (
	"context"
	_path "path"

	greq "github.com/levigross/grequests"
)

type Initiator struct {
	Path string `json:"path,omitempty" mapstructure:"path"`
	Id   string `json:"id,omitempty" mapstructure:"id"`
	Name string `json:"name,omitempty" mapstructure:"name"`
}

type Initiators struct {
	Path string
}

type InitiatorsCreateRequest struct {
	Ctxt  context.Context `json:"-"`
	Id    string          `json:"id,omitempty" mapstructure:"id"`
	Name  string          `json:"name,omitempty" mapstructure:"name"`
	Force bool            `json:"force,omitempty" mapstructure:"force"`
}

func newInitiators(path string) *Initiators {
	return &Initiators{
		Path: _path.Join(path, "initiators"),
	}
}

func (e *Initiators) Create(ro *InitiatorsCreateRequest) (*Initiator, *ApiErrorResponse, error) {
	gro := &greq.RequestOptions{JSON: ro}
	rs, apierr, err := GetConn(ro.Ctxt).Post(ro.Ctxt, e.Path, gro)
	if apierr != nil {
		return nil, apierr, err
	}
	if err != nil {
		return nil, nil, err
	}
	resp := &Initiator{}
	if err = FillStruct(rs.Data, resp); err != nil {
		return nil, nil, err
	}
	return resp, nil, nil
}

type InitiatorsListRequest struct {
	Ctxt   context.Context `json:"-"`
	Params ListParams      `json:"params,omitempty"`
}

func (e *Initiators) List(ro *InitiatorsListRequest) ([]*Initiator, *ApiErrorResponse, error) {
	gro := &greq.RequestOptions{
		JSON:   ro,
		Params: ro.Params.ToMap()}
	rs, apierr, err := GetConn(ro.Ctxt).GetList(ro.Ctxt, e.Path, gro)
	if apierr != nil {
		return nil, apierr, err
	}
	if err != nil {
		return nil, nil, err
	}
	resp := []*Initiator{}
	for _, data := range rs.Data {
		elem := &Initiator{}
		adata := data.(map[string]interface{})
		if err = FillStruct(adata, elem); err != nil {
			return nil, nil, err
		}
		resp = append(resp, elem)
	}
	return resp, nil, nil
}

type InitiatorsGetRequest struct {
	Ctxt context.Context `json:"-"`
	Id   string          `json:"-"`
}

func (e *Initiators) Get(ro *InitiatorsGetRequest) (*Initiator, *ApiErrorResponse, error) {
	gro := &greq.RequestOptions{JSON: ro}
	rs, apierr, err := GetConn(ro.Ctxt).Get(ro.Ctxt, _path.Join(e.Path, ro.Id), gro)
	if apierr != nil {
		return nil, apierr, err
	}
	if err != nil {
		return nil, nil, err
	}
	resp := &Initiator{}
	if err = FillStruct(rs.Data, resp); err != nil {
		return nil, nil, err
	}
	return resp, nil, nil
}

type InitiatorSetRequest struct {
	Ctxt context.Context `json:"-"`
	Name string          `json:"name,omitempty" mapstructure:"name"`
}

func (e *Initiator) Set(ro *InitiatorSetRequest) (*Initiator, *ApiErrorResponse, error) {
	gro := &greq.RequestOptions{JSON: ro}
	rs, apierr, err := GetConn(ro.Ctxt).Put(ro.Ctxt, e.Path, gro)
	if apierr != nil {
		return nil, apierr, err
	}
	if err != nil {
		return nil, nil, err
	}
	resp := &Initiator{}
	if err = FillStruct(rs.Data, resp); err != nil {
		return nil, nil, err
	}
	return resp, nil, nil

}

type InitiatorDeleteRequest struct {
	Ctxt context.Context `json:"-"`
	Id   string          `json:"id,omitempty" mapstructure:"id"`
}

func (e *Initiator) Delete(ro *InitiatorDeleteRequest) (*Initiator, *ApiErrorResponse, error) {
	rs, apierr, err := GetConn(ro.Ctxt).Delete(ro.Ctxt, e.Path, nil)
	if apierr != nil {
		return nil, apierr, err
	}
	if err != nil {
		return nil, nil, err
	}
	resp := &Initiator{}
	if err = FillStruct(rs.Data, resp); err != nil {
		return nil, nil, err
	}
	return resp, nil, nil
}
<commit_msg>Add missing tenant field to initiator struct<commit_after>package dsdk

import (
	"context"
	_path "path"

	greq "github.com/levigross/grequests"
)

type Initiator struct {
	Path   string `json:"path,omitempty" mapstructure:"path"`
	Id     string `json:"id,omitempty" mapstructure:"id"`
	Name   string `json:"name,omitempty" mapstructure:"name"`
	Tenant string `json:"tenant,omitempty" mapstructure:"tenant"`
}

type Initiators struct {
	Path string
}

type InitiatorsCreateRequest struct {
	Ctxt  context.Context `json:"-"`
	Id    string          `json:"id,omitempty" mapstructure:"id"`
	Name  string          `json:"name,omitempty" mapstructure:"name"`
	Force bool            `json:"force,omitempty" mapstructure:"force"`
}

func newInitiators(path string) *Initiators {
	return &Initiators{
		Path: _path.Join(path, "initiators"),
	}
}

func (e *Initiators) Create(ro *InitiatorsCreateRequest) (*Initiator, *ApiErrorResponse, error) {
	gro := &greq.RequestOptions{JSON: ro}
	rs, apierr, err := GetConn(ro.Ctxt).Post(ro.Ctxt, e.Path, gro)
	if apierr != nil {
		return nil, apierr, err
	}
	if err != nil {
		return nil, nil, err
	}
	resp := &Initiator{}
	if err = FillStruct(rs.Data, resp); err != nil {
		return nil, nil, err
	}
	return resp, nil, nil
}

type InitiatorsListRequest struct {
	Ctxt   context.Context `json:"-"`
	Params ListParams      `json:"params,omitempty"`
}

func (e *Initiators) List(ro *InitiatorsListRequest) ([]*Initiator, *ApiErrorResponse, error) {
	gro := &greq.RequestOptions{
		JSON:   ro,
		Params: ro.Params.ToMap()}
	rs, apierr, err := GetConn(ro.Ctxt).GetList(ro.Ctxt, e.Path, gro)
	if apierr != nil {
		return nil, apierr, err
	}
	if err != nil {
		return nil, nil, err
	}
	resp := []*Initiator{}
	for _, data := range rs.Data {
		elem := &Initiator{}
		adata := data.(map[string]interface{})
		if err = FillStruct(adata, elem); err != nil {
			return nil, nil, err
		}
		resp = append(resp, elem)
	}
	return resp, nil, nil
}

type InitiatorsGetRequest struct {
	Ctxt context.Context `json:"-"`
	Id   string          `json:"-"`
}

func (e *Initiators) Get(ro *InitiatorsGetRequest) (*Initiator, *ApiErrorResponse, error) {
	gro := &greq.RequestOptions{JSON: ro}
	rs, apierr, err := GetConn(ro.Ctxt).Get(ro.Ctxt, _path.Join(e.Path, ro.Id), gro)
	if apierr != nil {
		return nil, apierr, err
	}
	if err != nil {
		return nil, nil, err
	}
	resp := &Initiator{}
	if err = FillStruct(rs.Data, resp); err != nil {
		return nil, nil, err
	}
	return resp, nil, nil
}

type InitiatorSetRequest struct {
	Ctxt context.Context `json:"-"`
	Name string          `json:"name,omitempty" mapstructure:"name"`
}

func (e *Initiator) Set(ro *InitiatorSetRequest) (*Initiator, *ApiErrorResponse, error) {
	gro := &greq.RequestOptions{JSON: ro}
	rs, apierr, err := GetConn(ro.Ctxt).Put(ro.Ctxt, e.Path, gro)
	if apierr != nil {
		return nil, apierr, err
	}
	if err != nil {
		return nil, nil, err
	}
	resp := &Initiator{}
	if err = FillStruct(rs.Data, resp); err != nil {
		return nil, nil, err
	}
	return resp, nil, nil

}

type InitiatorDeleteRequest struct {
	Ctxt context.Context `json:"-"`
	Id   string          `json:"id,omitempty" mapstructure:"id"`
}

func (e *Initiator) Delete(ro *InitiatorDeleteRequest) (*Initiator, *ApiErrorResponse, error) {
	rs, apierr, err := GetConn(ro.Ctxt).Delete(ro.Ctxt, e.Path, nil)
	if apierr != nil {
		return nil, apierr, err
	}
	if err != nil {
		return nil, nil, err
	}
	resp := &Initiator{}
	if err = FillStruct(rs.Data, resp); err != nil {
		return nil, nil, err
	}
	return resp, nil, nil
}
<|endoftext|>


<commit_before>package editcmd

import (
	"bufio"
	"errors"
	"fmt"
	"github.com/skatteetaten/aoc/pkg/auroraconfig"
	"github.com/skatteetaten/aoc/pkg/cmdoptions"
	"github.com/skatteetaten/aoc/pkg/configuration"
	"github.com/skatteetaten/aoc/pkg/fileutil"
	"github.com/skatteetaten/aoc/pkg/jsonutil"
	"github.com/skatteetaten/aoc/pkg/serverapi"
	//"github.com/skatteetaten/aoc/pkg/serverapi_v2"
	"io/ioutil"
	//"net/http"
	"os"
	//"strconv"
	"strings"
)

const commentString = "# "
const editMessage = `# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
`

type EditcmdClass struct {
	configuration configuration.ConfigurationClass
}

func (editcmdClass *EditcmdClass) getAffiliation() (affiliation string) {
	if editcmdClass.configuration.GetOpenshiftConfig() != nil {
		affiliation = editcmdClass.configuration.GetOpenshiftConfig().Affiliation
	}
	return
}

func (editcmdClass *EditcmdClass) EditFile(args []string, persistentOptions *cmdoptions.CommonCommandOptions) (output string, err error) {
	err = validateEditcmd(args)
	if err != nil {
		return
	}
	if !serverapi.ValidateLogin(editcmdClass.configuration.GetOpenshiftConfig()) {
		return "", errors.New("Not logged in, please use aoc login")
	}

	var filename string = args[0]
	var content string

	content, err = auroraconfig.GetContent(filename, persistentOptions, editcmdClass.getAffiliation(), editcmdClass.configuration.GetOpenshiftConfig())
	content = jsonutil.PrettyPrintJson(content)

	var editCycleDone bool
	var modifiedContent = content
	for editCycleDone == false {
		contentBeforeEdit := modifiedContent
		modifiedContent, err = editString(modifiedContent)
		if err != nil {
			return "", err
		}
		if (stripComments(modifiedContent) == stripComments(contentBeforeEdit)) || stripComments(modifiedContent) == stripComments(content) {
			if stripComments(modifiedContent) != stripComments(content) {
				tempfile, err := createTempFile(stripComments(modifiedContent))
				if err != nil {
					return "", nil
				}
				output += "A copy of your changes har been stored to \"" + tempfile + "\"\n"
			}
			output += "Edit cancelled, no valid changes were saved."
			return output, nil
		}
		modifiedContent = stripComments(modifiedContent)

		if jsonutil.IsLegalJson(modifiedContent) {
			validationMessages, err := auroraconfig.PutContent(filename, modifiedContent, persistentOptions, editcmdClass.getAffiliation(), editcmdClass.configuration.GetOpenshiftConfig())
			if err != nil {
				if err.Error() == auroraconfig.InvalidConfigurationError {
					modifiedContent, _ = addComments(modifiedContent, validationMessages)
				} else {
					editCycleDone = true
				}
			} else {
				editCycleDone = true
			}
		} else {
			modifiedContent, _ = addComments(modifiedContent, "Illegal JSON Format")
		}
	}

	return
}

func addComments(content string, comments string) (commentedContent string, err error) {
	var commentLines []string

	const newline = "\n"
	var commentedComments string
	commentLines, _ = contentToLines(comments)
	for lineno := range commentLines {
		commentedComments += commentString + commentLines[lineno] + newline
	}
	commentedContent = commentedComments + content

	return
}

func stripComments(content string) (uncommentedContent string) {
	var contenttLines []string

	var newline = ""
	contenttLines, _ = contentToLines(content)
	for lineno := range contenttLines {
		if strings.TrimLeft(contenttLines[lineno], commentString) == contenttLines[lineno] {
			uncommentedContent += newline + contenttLines[lineno]
			newline = "\n"
		}
	}

	return
}

func contentToLines(content string) (contentLines []string, err error) {

	scanner := bufio.NewScanner(strings.NewReader(content))
	for scanner.Scan() {
		contentLines = append(contentLines, scanner.Text())
	}

	if err := scanner.Err(); err != nil {
		return nil, err
	}

	return
}

/*func (editcmdClass *EditcmdClass) getContent(filename string, persistentOptions *cmdoptions.CommonCommandOptions) (content string, err error) {
	var affiliation = editcmdClass.getAffiliation()
	var apiEndpoint string = "/affiliation/" + affiliation + "/auroraconfig"
	var responses map[string]string
	var auroraConfig serverapi_v2.AuroraConfig

	responses, err = serverapi_v2.CallApi(http.MethodGet, apiEndpoint, "", persistentOptions.ShowConfig,
		persistentOptions.ShowObjects, true, persistentOptions.Localhost,
		persistentOptions.Verbose, editcmdClass.configuration.GetOpenshiftConfig(), persistentOptions.DryRun, persistentOptions.Debug)
	if err != nil {
		for server := range responses {
			response, err := serverapi_v2.ParseResponse(responses[server])
			if err != nil {
				return "", err
			}
			if !response.Success {
				output, err := serverapi_v2.ResponsItems2MessageString(response)
				if err != nil {
					return "", err
				}
				return "", errors.New(output)

			}
		}

		return "", err
	}

	if len(responses) != 1 {
		err = errors.New("Internal error in getContent: Response from " + strconv.Itoa(len(responses)))
		return
	}

	for server := range responses {
		response, err := serverapi_v2.ParseResponse(responses[server])
		if err != nil {
			return "", err
		}
		auroraConfig, err = serverapi_v2.ResponseItems2AuroraConfig(response)

		var fileFound bool

		for filenameIndex := range auroraConfig.Files {
			if filenameIndex == filename {
				fileFound = true
				content = string(auroraConfig.Files[filenameIndex])
			}
		}
		if !fileFound {
			return "", errors.New("Illegal file/folder")
		}
	}

	return content, nil
}

func (editcmdClass *EditcmdClass) putContent(filename string, content string, persistentOptions *cmdoptions.CommonCommandOptions) (validationMessages string, err error) {
	var affiliation = editcmdClass.getAffiliation()
	var apiEndpoint = "/affiliation/" + affiliation + "/auroraconfig/" + filename
	var responses map[string]string
	responses, err = serverapi_v2.CallApi(http.MethodPut, apiEndpoint, content, persistentOptions.ShowConfig,
		persistentOptions.ShowObjects, true, persistentOptions.Localhost,
		persistentOptions.Verbose, editcmdClass.configuration.GetOpenshiftConfig(), persistentOptions.DryRun, persistentOptions.Debug)
	if err != nil {
		for server := range responses {
			response, err := serverapi_v2.ParseResponse(responses[server])
			if err != nil {
				return "", err
			}
			if !response.Success {
				validationMessages, _ := serverapi_v2.ResponsItems2MessageString(response)
				return validationMessages, errors.New(auroraconfig.InvalidConfigurationError)
			}
		}

	}
	return
}*/

func editString(content string) (modifiedContent string, err error) {

	filename, err := createTempFile(editMessage + content)

	err = fileutil.EditFile(filename)
	if err != nil {
		return
	}

	fileText, err := ioutil.ReadFile(filename)
	if err != nil {
		return
	}
	modifiedContent = string(fileText)

	err = os.Remove(filename)
	if err != nil {
		fmt.Println("WARNING: Unable to delete tempfile " + filename)
	}
	return
}

func createTempFile(content string) (filename string, err error) {
	const tmpFilePrefix = ".aoc_edit_file_"
	var tmpDir = os.TempDir()
	tmpFile, err := ioutil.TempFile(tmpDir, tmpFilePrefix)
	if err != nil {
		return "", errors.New("Unable to create temporary file: " + err.Error())
	}
	if fileutil.IsLegalFileFolder(tmpFile.Name()) != fileutil.SpecIsFile {
		err = errors.New("Internal error: Illegal temp file name: " + tmpFile.Name())
	}
	filename = tmpFile.Name()
	err = ioutil.WriteFile(tmpFile.Name(), []byte(content), 0700)
	if err != nil {
		return
	}
	return
}

func validateEditcmd(args []string) (err error) {
	if len(args) != 1 {
		err = errors.New("Usage: aoc edit [env/]file")
		return
	}

	return
}
<commit_msg>Removed old code<commit_after>package editcmd

import (
	"bufio"
	"errors"
	"fmt"
	"github.com/skatteetaten/aoc/pkg/auroraconfig"
	"github.com/skatteetaten/aoc/pkg/cmdoptions"
	"github.com/skatteetaten/aoc/pkg/configuration"
	"github.com/skatteetaten/aoc/pkg/fileutil"
	"github.com/skatteetaten/aoc/pkg/jsonutil"
	"github.com/skatteetaten/aoc/pkg/serverapi"
	//"github.com/skatteetaten/aoc/pkg/serverapi_v2"
	"io/ioutil"
	//"net/http"
	"os"
	//"strconv"
	"strings"
)

const commentString = "# "
const editMessage = `# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
`

type EditcmdClass struct {
	configuration configuration.ConfigurationClass
}

func (editcmdClass *EditcmdClass) getAffiliation() (affiliation string) {
	if editcmdClass.configuration.GetOpenshiftConfig() != nil {
		affiliation = editcmdClass.configuration.GetOpenshiftConfig().Affiliation
	}
	return
}

func (editcmdClass *EditcmdClass) EditFile(args []string, persistentOptions *cmdoptions.CommonCommandOptions) (output string, err error) {
	err = validateEditcmd(args)
	if err != nil {
		return
	}
	if !serverapi.ValidateLogin(editcmdClass.configuration.GetOpenshiftConfig()) {
		return "", errors.New("Not logged in, please use aoc login")
	}

	var filename string = args[0]
	var content string

	content, err = auroraconfig.GetContent(filename, persistentOptions, editcmdClass.getAffiliation(), editcmdClass.configuration.GetOpenshiftConfig())
	content = jsonutil.PrettyPrintJson(content)

	var editCycleDone bool
	var modifiedContent = content
	for editCycleDone == false {
		contentBeforeEdit := modifiedContent
		modifiedContent, err = editString(modifiedContent)
		if err != nil {
			return "", err
		}
		if (stripComments(modifiedContent) == stripComments(contentBeforeEdit)) || stripComments(modifiedContent) == stripComments(content) {
			if stripComments(modifiedContent) != stripComments(content) {
				tempfile, err := createTempFile(stripComments(modifiedContent))
				if err != nil {
					return "", nil
				}
				output += "A copy of your changes har been stored to \"" + tempfile + "\"\n"
			}
			output += "Edit cancelled, no valid changes were saved."
			return output, nil
		}
		modifiedContent = stripComments(modifiedContent)

		if jsonutil.IsLegalJson(modifiedContent) {
			validationMessages, err := auroraconfig.PutContent(filename, modifiedContent, persistentOptions, editcmdClass.getAffiliation(), editcmdClass.configuration.GetOpenshiftConfig())
			if err != nil {
				if err.Error() == auroraconfig.InvalidConfigurationError {
					modifiedContent, _ = addComments(modifiedContent, validationMessages)
				} else {
					editCycleDone = true
				}
			} else {
				editCycleDone = true
			}
		} else {
			modifiedContent, _ = addComments(modifiedContent, "Illegal JSON Format")
		}
	}

	return
}

func addComments(content string, comments string) (commentedContent string, err error) {
	var commentLines []string

	const newline = "\n"
	var commentedComments string
	commentLines, _ = contentToLines(comments)
	for lineno := range commentLines {
		commentedComments += commentString + commentLines[lineno] + newline
	}
	commentedContent = commentedComments + content

	return
}

func stripComments(content string) (uncommentedContent string) {
	var contenttLines []string

	var newline = ""
	contenttLines, _ = contentToLines(content)
	for lineno := range contenttLines {
		if strings.TrimLeft(contenttLines[lineno], commentString) == contenttLines[lineno] {
			uncommentedContent += newline + contenttLines[lineno]
			newline = "\n"
		}
	}

	return
}

func contentToLines(content string) (contentLines []string, err error) {

	scanner := bufio.NewScanner(strings.NewReader(content))
	for scanner.Scan() {
		contentLines = append(contentLines, scanner.Text())
	}

	if err := scanner.Err(); err != nil {
		return nil, err
	}

	return
}

func editString(content string) (modifiedContent string, err error) {

	filename, err := createTempFile(editMessage + content)

	err = fileutil.EditFile(filename)
	if err != nil {
		return
	}

	fileText, err := ioutil.ReadFile(filename)
	if err != nil {
		return
	}
	modifiedContent = string(fileText)

	err = os.Remove(filename)
	if err != nil {
		fmt.Println("WARNING: Unable to delete tempfile " + filename)
	}
	return
}

func createTempFile(content string) (filename string, err error) {
	const tmpFilePrefix = ".aoc_edit_file_"
	var tmpDir = os.TempDir()
	tmpFile, err := ioutil.TempFile(tmpDir, tmpFilePrefix)
	if err != nil {
		return "", errors.New("Unable to create temporary file: " + err.Error())
	}
	if fileutil.IsLegalFileFolder(tmpFile.Name()) != fileutil.SpecIsFile {
		err = errors.New("Internal error: Illegal temp file name: " + tmpFile.Name())
	}
	filename = tmpFile.Name()
	err = ioutil.WriteFile(tmpFile.Name(), []byte(content), 0700)
	if err != nil {
		return
	}
	return
}

func validateEditcmd(args []string) (err error) {
	if len(args) != 1 {
		err = errors.New("Usage: aoc edit [env/]file")
		return
	}

	return
}
<|endoftext|>


<commit_before>/*
Copyright 2020 The Knative 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 feature

import (
	"context"
	"fmt"
	"runtime"
	"strings"

	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"knative.dev/pkg/apis"
	"knative.dev/pkg/injection/clients/dynamicclient"

	"knative.dev/reconciler-test/pkg/state"
)

// Feature is a list of steps and feature name.
type Feature struct {
	Name  string
	Steps []Step
	State state.Store
	// Contains all the resources created as part of this Feature.
	refs []corev1.ObjectReference
}

// NewFeatureNamed creates a new feature with the provided name
func NewFeatureNamed(name string) *Feature {
	f := new(Feature)
	f.Name = name
	return f
}

// NewFeature creates a new feature with name taken from the caller name
func NewFeature() *Feature {
	f := new(Feature)

	pc, _, _, _ := runtime.Caller(1)
	caller := runtime.FuncForPC(pc)
	if caller != nil {
		splitted := strings.Split(caller.Name(), ".")
		f.Name = splitted[len(splitted)-1]
	}

	return f
}

// FeatureSet is a list of features and feature set name.
type FeatureSet struct {
	Name     string
	Features []Feature
}

// StepFn is the function signature for steps.
type StepFn func(ctx context.Context, t T)

// Step is a structure to hold the step function, step name and state, level and
// timing configuration.
type Step struct {
	Name string
	S    States
	L    Levels
	T    Timing
	Fn   StepFn
}

// TestName returns the constructed test name based on the timing, step, state,
// level, and the Name provided in the step.
func (s *Step) TestName() string {
	switch s.T {
	case Assert:
		return fmt.Sprintf("[%s/%s]%s", s.S, s.L, s.Name)
	default:
		return s.Name
	}
}

// Reference adds references to keep track of for example, for cleaning things
// after a Feature completes.
func (f *Feature) Reference(ref ...corev1.ObjectReference) {
	f.refs = append(f.refs, ref...)
}

// References returns all known resources to the Feature registered via
// `Reference`.
func (f *Feature) References() []corev1.ObjectReference {
	return f.refs
}

// DeleteResourcesFn delete all known resources to the Feature registered
// via `Reference`. Expected to be used as a StepFn.
func (f *Feature) DeleteResources(ctx context.Context, t T) {
	dc := dynamicclient.Get(ctx)
	for _, ref := range f.References() {
		gv, err := schema.ParseGroupVersion(ref.APIVersion)
		if err != nil {
			t.Errorf("Could not parse GroupVersion for %+v", ref.APIVersion)
		} else {
			resource := apis.KindToResource(gv.WithKind(ref.Kind))
			t.Logf("Deleting %s/%s of GVR: %+v", ref.Namespace, ref.Name, resource)
			if err := dc.Resource(resource).Namespace(ref.Namespace).Delete(ctx, ref.Name, *metav1.NewDeleteOptions(0)); err != nil {
				t.Logf("Warning, failed to delete %s/%s of GVR: %+v", ref.Namespace, ref.Name, resource)
			}
		}
	}
	f.refs = []corev1.ObjectReference(nil)
}

// Setup adds a step function to the feature set at the Setup timing phase.
func (f *Feature) Setup(name string, fn StepFn) {
	f.AddStep(Step{
		Name: name,
		S:    Any,
		L:    All,
		T:    Setup,
		Fn:   fn,
	})
}

// Requirement adds a step function to the feature set at the Requirement timing phase.
func (f *Feature) Requirement(name string, fn StepFn) {
	f.AddStep(Step{
		Name: name,
		S:    Any,
		L:    All,
		T:    Requirement,
		Fn:   fn,
	})
}

// Assert is a shortcut for Stable(name).Must(name, fn),
// useful for developing integration tests that doesn't require assertion levels.
func (f *Feature) Assert(name string, fn StepFn) {
	f.Stable(name).Must(name, fn)
}

// Assert adds a step function to the feature set at the Assert timing phase.
func (a *Asserter) Assert(l Levels, name string, fn StepFn) {
	a.f.AddStep(Step{
		Name: fmt.Sprintf("%s %s", a.name, name),
		S:    a.s,
		L:    l,
		T:    Assert,
		Fn:   fn,
	})
}

// Teardown adds a step function to the feature set at the Teardown timing phase.
func (f *Feature) Teardown(name string, fn StepFn) {
	f.AddStep(Step{
		Name: name,
		S:    Any,
		L:    All,
		T:    Teardown,
		Fn:   fn,
	})
}

// AddStep appends one or more steps to the Feature.
func (f *Feature) AddStep(step ...Step) {
	f.Steps = append(f.Steps, step...)
}

// Assertable is a fluent interface based on Levels for creating an Assert step.
type Assertable interface {
	Must(name string, fn StepFn) Assertable
	Should(name string, fn StepFn) Assertable
	May(name string, fn StepFn) Assertable
	MustNot(name string, fn StepFn) Assertable
	ShouldNot(name string, fn StepFn) Assertable
}

// Alpha is a fluent style method for creating an Assert step in Alpha State.
func (f *Feature) Alpha(name string) Assertable {
	return f.asserter(Alpha, name)
}

// Beta is a fluent style method for creating an Assert step in Beta State.
func (f *Feature) Beta(name string) Assertable {
	return f.asserter(Beta, name)
}

// Stable is a fluent style method for creating an Assert step in Stable State.
func (f *Feature) Stable(name string) Assertable {
	return f.asserter(Stable, name)
}

func (f *Feature) asserter(s States, name string) Assertable {
	return &Asserter{
		f:    f,
		name: name,
		s:    s,
	}
}

type Asserter struct {
	f    *Feature
	name string
	s    States
}

func (a *Asserter) Must(name string, fn StepFn) Assertable {
	a.Assert(Must, name, fn)
	return a
}

func (a *Asserter) Should(name string, fn StepFn) Assertable {
	a.Assert(Should, name, fn)
	return a
}

func (a *Asserter) May(name string, fn StepFn) Assertable {
	a.Assert(May, name, fn)
	return a
}

func (a *Asserter) MustNot(name string, fn StepFn) Assertable {
	a.Assert(MustNot, name, fn)
	return a
}

func (a *Asserter) ShouldNot(name string, fn StepFn) Assertable {
	a.Assert(ShouldNot, name, fn)
	return a
}
<commit_msg>Fix redundant name in Assert helper (#205)<commit_after>/*
Copyright 2020 The Knative 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 feature

import (
	"context"
	"fmt"
	"runtime"
	"strings"

	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"knative.dev/pkg/apis"
	"knative.dev/pkg/injection/clients/dynamicclient"

	"knative.dev/reconciler-test/pkg/state"
)

// Feature is a list of steps and feature name.
type Feature struct {
	Name  string
	Steps []Step
	State state.Store
	// Contains all the resources created as part of this Feature.
	refs []corev1.ObjectReference
}

// NewFeatureNamed creates a new feature with the provided name
func NewFeatureNamed(name string) *Feature {
	f := new(Feature)
	f.Name = name
	return f
}

// NewFeature creates a new feature with name taken from the caller name
func NewFeature() *Feature {
	f := new(Feature)

	pc, _, _, _ := runtime.Caller(1)
	caller := runtime.FuncForPC(pc)
	if caller != nil {
		splitted := strings.Split(caller.Name(), ".")
		f.Name = splitted[len(splitted)-1]
	}

	return f
}

// FeatureSet is a list of features and feature set name.
type FeatureSet struct {
	Name     string
	Features []Feature
}

// StepFn is the function signature for steps.
type StepFn func(ctx context.Context, t T)

// Step is a structure to hold the step function, step name and state, level and
// timing configuration.
type Step struct {
	Name string
	S    States
	L    Levels
	T    Timing
	Fn   StepFn
}

// TestName returns the constructed test name based on the timing, step, state,
// level, and the Name provided in the step.
func (s *Step) TestName() string {
	switch s.T {
	case Assert:
		return fmt.Sprintf("[%s/%s]%s", s.S, s.L, s.Name)
	default:
		return s.Name
	}
}

// Reference adds references to keep track of for example, for cleaning things
// after a Feature completes.
func (f *Feature) Reference(ref ...corev1.ObjectReference) {
	f.refs = append(f.refs, ref...)
}

// References returns all known resources to the Feature registered via
// `Reference`.
func (f *Feature) References() []corev1.ObjectReference {
	return f.refs
}

// DeleteResourcesFn delete all known resources to the Feature registered
// via `Reference`. Expected to be used as a StepFn.
func (f *Feature) DeleteResources(ctx context.Context, t T) {
	dc := dynamicclient.Get(ctx)
	for _, ref := range f.References() {
		gv, err := schema.ParseGroupVersion(ref.APIVersion)
		if err != nil {
			t.Errorf("Could not parse GroupVersion for %+v", ref.APIVersion)
		} else {
			resource := apis.KindToResource(gv.WithKind(ref.Kind))
			t.Logf("Deleting %s/%s of GVR: %+v", ref.Namespace, ref.Name, resource)
			if err := dc.Resource(resource).Namespace(ref.Namespace).Delete(ctx, ref.Name, *metav1.NewDeleteOptions(0)); err != nil {
				t.Logf("Warning, failed to delete %s/%s of GVR: %+v", ref.Namespace, ref.Name, resource)
			}
		}
	}
	f.refs = []corev1.ObjectReference(nil)
}

// Setup adds a step function to the feature set at the Setup timing phase.
func (f *Feature) Setup(name string, fn StepFn) {
	f.AddStep(Step{
		Name: name,
		S:    Any,
		L:    All,
		T:    Setup,
		Fn:   fn,
	})
}

// Requirement adds a step function to the feature set at the Requirement timing phase.
func (f *Feature) Requirement(name string, fn StepFn) {
	f.AddStep(Step{
		Name: name,
		S:    Any,
		L:    All,
		T:    Requirement,
		Fn:   fn,
	})
}

// Assert is a shortcut for Stable().Must(name, fn),
// useful for developing integration tests that don't require assertion levels.
func (f *Feature) Assert(name string, fn StepFn) {
	f.AddStep(Step{
		Name: name,
		S:    Stable,
		L:    Must,
		T:    Assert,
		Fn:   fn,
	})
}

// Assert adds a step function to the feature set at the Assert timing phase.
func (a *Asserter) Assert(l Levels, name string, fn StepFn) {
	a.f.AddStep(Step{
		Name: fmt.Sprintf("%s %s", a.name, name),
		S:    a.s,
		L:    l,
		T:    Assert,
		Fn:   fn,
	})
}

// Teardown adds a step function to the feature set at the Teardown timing phase.
func (f *Feature) Teardown(name string, fn StepFn) {
	f.AddStep(Step{
		Name: name,
		S:    Any,
		L:    All,
		T:    Teardown,
		Fn:   fn,
	})
}

// AddStep appends one or more steps to the Feature.
func (f *Feature) AddStep(step ...Step) {
	f.Steps = append(f.Steps, step...)
}

// Assertable is a fluent interface based on Levels for creating an Assert step.
type Assertable interface {
	Must(name string, fn StepFn) Assertable
	Should(name string, fn StepFn) Assertable
	May(name string, fn StepFn) Assertable
	MustNot(name string, fn StepFn) Assertable
	ShouldNot(name string, fn StepFn) Assertable
}

// Alpha is a fluent style method for creating an Assert step in Alpha State.
func (f *Feature) Alpha(name string) Assertable {
	return f.asserter(Alpha, name)
}

// Beta is a fluent style method for creating an Assert step in Beta State.
func (f *Feature) Beta(name string) Assertable {
	return f.asserter(Beta, name)
}

// Stable is a fluent style method for creating an Assert step in Stable State.
func (f *Feature) Stable(name string) Assertable {
	return f.asserter(Stable, name)
}

func (f *Feature) asserter(s States, name string) Assertable {
	return &Asserter{
		f:    f,
		name: name,
		s:    s,
	}
}

type Asserter struct {
	f    *Feature
	name string
	s    States
}

func (a *Asserter) Must(name string, fn StepFn) Assertable {
	a.Assert(Must, name, fn)
	return a
}

func (a *Asserter) Should(name string, fn StepFn) Assertable {
	a.Assert(Should, name, fn)
	return a
}

func (a *Asserter) May(name string, fn StepFn) Assertable {
	a.Assert(May, name, fn)
	return a
}

func (a *Asserter) MustNot(name string, fn StepFn) Assertable {
	a.Assert(MustNot, name, fn)
	return a
}

func (a *Asserter) ShouldNot(name string, fn StepFn) Assertable {
	a.Assert(ShouldNot, name, fn)
	return a
}
<|endoftext|>


<commit_before>/*
 Copyright 2010 Jeremy Wall (jeremy@marzhillstudios.com)
 Use of this source code is governed by the Artistic License 2.0.
 That License is included in the LICENSE file.
*/
package trans

import (
	. "html"
	"os"
	"log"
	"strings"
	v "container/vector"
)

type NodeType int

const (
	TEXT NodeType = iota // 0 value so the default
	TAG
)

type Node struct {
	nodeType NodeType
	nodeValue string
	nodeAttributes map[string] string
	children v.Vector
}

func lazyTokens(t *Tokenizer) <-chan Token {
	tokens := make(chan Token, 1)
	go func() {
		for {
			tt := t.Next()
			if tt == Error {
				switch t.Error() {
				case os.EOF:
					break
				default:
					log.Panicf(
						"Error tokenizing string: %s",
						t.Error())
				}
			}
			tokens <- t.Token()
		}
	}()
	return tokens
}

type Document struct {
	top Node
}

func transformAttributes(attrs []Attribute) map[string] string {
	attributes := make(map[string] string)
	for _, attr := range attrs {
		attributes[attr.Key] = attr.Val
	}
	return attributes
}

func typeFromToken(t Token) NodeType {
	if t.Type == Text {
		return TEXT
	}
	return TAG
}

func nodeFromToken(t Token) Node {
	return Node{
		nodeType: typeFromToken(t),
		nodeValue: t.Data,
		nodeAttributes: transformAttributes(t.Attr),
	}
}

func NewDoc(s string) *Document {
	t := NewTokenizer(strings.NewReader(s))
	tokens := lazyTokens(t)
	tok1 := <-tokens
	doc := Document{top: nodeFromToken(tok1)}

	queue := new(v.Vector)
	queue.Push(doc.top)
	for tok := range tokens {
		curr := queue.At(0).(Node)
		switch tok.Type {
		case SelfClosingTag, Text:
			curr.children.Push(nodeFromToken(tok))
		case StartTag:
			curr.children.Push(nodeFromToken(tok))
			queue.Push(nodeFromToken(tok))
		case EndTag:
			queue.Pop()
		}
	}
	return &doc
}

// TODO(jwall): css style addressing of elements
<commit_msg>Added fragments<commit_after>/*
 Copyright 2010 Jeremy Wall (jeremy@marzhillstudios.com)
 Use of this source code is governed by the Artistic License 2.0.
 That License is included in the LICENSE file.
*/
package trans

import (
	. "html"
	"os"
	"log"
	"strings"
	v "container/vector"
)

type NodeType int

const (
	TEXT NodeType = iota // 0 value so the default
	TAG
)

type Node struct {
	nodeType NodeType
	nodeValue string
	nodeAttributes map[string] string
	children v.Vector
}

func lazyTokens(t *Tokenizer) <-chan Token {
	tokens := make(chan Token, 1)
	go func() {
		for {
			tt := t.Next()
			if tt == Error {
				switch t.Error() {
				case os.EOF:
					break
				default:
					log.Panicf(
						"Error tokenizing string: %s",
						t.Error())
				}
			}
			tokens <- t.Token()
		}
	}()
	return tokens
}

type Document struct {
	top Node
}

func transformAttributes(attrs []Attribute) map[string] string {
	attributes := make(map[string] string)
	for _, attr := range attrs {
		attributes[attr.Key] = attr.Val
	}
	return attributes
}

func typeFromToken(t Token) NodeType {
	if t.Type == Text {
		return TEXT
	}
	return TAG
}

func nodeFromToken(t Token) Node {
	return Node{
		nodeType: typeFromToken(t),
		nodeValue: t.Data,
		nodeAttributes: transformAttributes(t.Attr),
	}
}

func NewDoc(s string) *Document {
	t := NewTokenizer(strings.NewReader(s))
	tokens := lazyTokens(t)
	tok1 := <-tokens
	doc := Document{top: nodeFromToken(tok1)}

	queue := new(v.Vector)
	queue.Push(doc.top)
	for tok := range tokens {
		curr := queue.At(0).(Node)
		switch tok.Type {
		case SelfClosingTag, Text:
			curr.children.Push(nodeFromToken(tok))
		case StartTag:
			curr.children.Push(nodeFromToken(tok))
			queue.Push(nodeFromToken(tok))
		case EndTag:
			queue.Pop()
		}
	}
	return &doc
}

// TODO(jwall): not sure I even need fragments but oh well
type Fragment struct {
	*Document
}

func NewFragment(s string) *Fragment {
	return &Fragment{NewDoc(s)}
}

// TODO(jwall): css style addressing of elements
<|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 hyper

import (
	"fmt"
	"strings"

	"github.com/golang/glog"

	"k8s.io/frakti/pkg/hyper/types"
	kubeapi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime"
)

// CreateContainer creates a new container in specified PodSandbox
func (h *Runtime) CreateContainer(podSandboxID string, config *kubeapi.ContainerConfig, sandboxConfig *kubeapi.PodSandboxConfig) (string, error) {
	containerSpec, err := buildUserContainer(config, sandboxConfig)
	if err != nil {
		glog.Errorf("Build UserContainer for container %q failed: %v", config.String(), err)
		return "", err
	}

	// TODO: support container-level log_path in upstream hyperd when creating container.
	containerID, err := h.client.CreateContainer(podSandboxID, containerSpec)
	if err != nil {
		glog.Errorf("Create container %s in pod %s failed: %v", config.Metadata.GetName(), podSandboxID, err)
		return "", err
	}

	return containerID, nil
}

// buildUserContainer builds hyperd's UserContainer based kubelet ContainerConfig.
func buildUserContainer(config *kubeapi.ContainerConfig, sandboxConfig *kubeapi.PodSandboxConfig) (*types.UserContainer, error) {
	if config.GetLinux().GetSecurityContext().GetPrivileged() {
		return nil, fmt.Errorf("Priviledged containers are not supported in hyper")
	}

	containerSpec := &types.UserContainer{
		Name:       buildContainerName(sandboxConfig, config),
		Image:      config.Image.GetImage(),
		Workdir:    config.GetWorkingDir(),
		Tty:        config.GetTty(),
		Command:    config.GetArgs(),
		Entrypoint: config.GetCommand(),
		Labels:     buildLabelsWithAnnotations(config.Labels, config.Annotations),
	}

	// TODO: support adding device in upstream hyperd when creating container.

	// TODO: support volume mounts in upstream hyperd.
	// volumes := make([]*types.UserVolumeReference, len(config.Mounts))
	// for idx, v := range config.Mounts {
	// 	volumes[idx] = &types.UserVolumeReference{
	// 		Volume:   v.GetHostPath(),
	// 		Path:     v.GetContainerPath(),
	// 		ReadOnly: v.GetReadonly(),
	// 	}
	// }
	// containerSpec.Volumes = volumes

	// make environments
	environments := make([]*types.EnvironmentVar, len(config.Envs))
	for idx, env := range config.Envs {
		environments[idx] = &types.EnvironmentVar{
			Env:   env.GetKey(),
			Value: env.GetValue(),
		}
	}
	containerSpec.Envs = environments

	return containerSpec, nil
}

// StartContainer starts the container.
func (h *Runtime) StartContainer(rawContainerID string) error {
	// Hyperd doesn't support start a standalone container yet, restart the
	// pod to workaround this.
	// TODO: replace this with real StartContainer after hyperd's refactoring.
	container, err := h.client.GetContainerInfo(rawContainerID)
	if err != nil {
		glog.Errorf("Failed to get container %q: %v", rawContainerID, err)
		return err
	}
	_, reason, err := h.client.StopPod(container.PodID)
	if err != nil {
		glog.Errorf("Failed to stop pod %q with reason (%q): %v", container.PodID, reason, err)
		return err
	}
	err = h.client.StartPod(container.PodID)
	if err != nil {
		glog.Errorf("Failed to start pod %q: %v", container.PodID, err)
		return err
	}

	return nil
}

// StopContainer stops a running container with a grace period (i.e. timeout).
func (h *Runtime) StopContainer(rawContainerID string, timeout int64) error {
	err := h.client.StopContainer(rawContainerID, timeout)
	if err != nil {
		glog.Errorf("Stop container %s failed: %v", rawContainerID, err)
		return err
	}

	return nil
}

// RemoveContainer removes the container. If the container is running, the container
// should be force removed.
func (h *Runtime) RemoveContainer(rawContainerID string) error {
	// Workaround: always suppose container are deleted successfully.
	// TODO: remove container when hyperd is ready for this.
	return nil
}

// ListContainers lists all containers by filters.
func (h *Runtime) ListContainers(filter *kubeapi.ContainerFilter) ([]*kubeapi.Container, error) {
	containerList, err := h.client.GetContainerList(false)
	if err != nil {
		glog.Errorf("Get container list failed: %v", err)
		return nil, err
	}

	containers := make([]*kubeapi.Container, 0, len(containerList))

	for _, c := range containerList {
		state := toKubeContainerState(c.Status)
		_, _, _, containerName, attempt, err := parseContainerName(strings.Replace(c.ContainerName, "/", "", -1))

		if err != nil {
			glog.Errorf("ParseContainerName for %s failed: %v", c.ContainerName, err)
			return nil, err
		}

		if filter != nil {
			if filter.Id != nil && c.ContainerID != filter.GetId() {
				continue
			}

			if filter.PodSandboxId != nil && c.PodID != filter.GetPodSandboxId() {
				continue
			}

			if filter.State != nil && state != filter.GetState() {
				continue
			}
		}

		info, err := h.client.GetContainerInfo(c.ContainerID)
		if err != nil {
			glog.Errorf("Get container info for %s failed: %v", c.ContainerID, err)
			return nil, err
		}

		annotations := getAnnotationsFromLabels(info.Container.Labels)
		kubeletLabels := getKubeletLabels(info.Container.Labels)

		if filter != nil {
			if filter.LabelSelector != nil && !inMap(filter.LabelSelector, kubeletLabels) {
				continue
			}
		}

		containerMetadata := &kubeapi.ContainerMetadata{
			Name:    &containerName,
			Attempt: &attempt,
		}

		createdAtNano := info.CreatedAt * secondToNano
		containers = append(containers, &kubeapi.Container{
			Id:           &c.ContainerID,
			PodSandboxId: &c.PodID,
			CreatedAt:    &createdAtNano,
			Metadata:     containerMetadata,
			Image:        &kubeapi.ImageSpec{Image: &info.Container.Image},
			ImageRef:     &info.Container.ImageID,
			State:        &state,
			Labels:       kubeletLabels,
			Annotations:  annotations,
		})
	}

	return containers, nil
}

// ContainerStatus returns the container status.
func (h *Runtime) ContainerStatus(containerID string) (*kubeapi.ContainerStatus, error) {
	status, err := h.client.GetContainerInfo(containerID)
	if err != nil {
		glog.Errorf("Get container info for %s failed: %v", containerID, err)
		return nil, err
	}

	podInfo, err := h.client.GetPodInfo(status.PodID)
	if err != nil {
		glog.Errorf("Get pod info for %s failed: %v", status.PodID, err)
		return nil, err
	}

	state := toKubeContainerState(status.Status.Phase)
	annotations := getAnnotationsFromLabels(status.Container.Labels)
	kubeletLabels := getKubeletLabels(status.Container.Labels)

	_, _, _, containerName, attempt, err := parseContainerName(strings.Replace(status.Container.Name, "/", "", -1))
	if err != nil {
		glog.Errorf("ParseContainerName for %s failed: %v", status.Container.Name, err)
		return nil, err
	}

	containerMetadata := &kubeapi.ContainerMetadata{
		Name:    &containerName,
		Attempt: &attempt,
	}

	createdAtNano := status.CreatedAt * secondToNano
	kubeStatus := &kubeapi.ContainerStatus{
		Id:          &status.Container.ContainerID,
		Image:       &kubeapi.ImageSpec{Image: &status.Container.Image},
		ImageRef:    &status.Container.ImageID,
		Metadata:    containerMetadata,
		State:       &state,
		Labels:      kubeletLabels,
		Annotations: annotations,
		CreatedAt:   &createdAtNano,
	}

	mounts := make([]*kubeapi.Mount, len(status.Container.VolumeMounts))
	for idx, mnt := range status.Container.VolumeMounts {
		mounts[idx] = &kubeapi.Mount{
			ContainerPath: &mnt.MountPath,
			Readonly:      &mnt.ReadOnly,
		}

		for _, v := range podInfo.Spec.Volumes {
			if v.Name == mnt.Name {
				mounts[idx].HostPath = &v.Source
			}
		}
	}
	kubeStatus.Mounts = mounts

	switch status.Status.Phase {
	case "running":
		startedAt, err := parseTimeString(status.Status.Running.StartedAt)
		if err != nil {
			glog.Errorf("Hyper: can't parse startedAt %s", status.Status.Running.StartedAt)
			return nil, err
		}
		kubeStatus.StartedAt = &startedAt
	case "failed", "succeeded":
		startedAt, err := parseTimeString(status.Status.Terminated.StartedAt)
		if err != nil {
			glog.Errorf("Hyper: can't parse startedAt %s", status.Status.Terminated.StartedAt)
			return nil, err
		}
		finishedAt, err := parseTimeString(status.Status.Terminated.FinishedAt)
		if err != nil {
			glog.Errorf("Hyper: can't parse finishedAt %s", status.Status.Terminated.FinishedAt)
			return nil, err
		}

		kubeStatus.StartedAt = &startedAt
		kubeStatus.FinishedAt = &finishedAt
		kubeStatus.Reason = &status.Status.Terminated.Reason
		kubeStatus.ExitCode = &status.Status.Terminated.ExitCode
	default:
		kubeStatus.Reason = &status.Status.Waiting.Reason
	}

	return kubeStatus, nil
}
<commit_msg>make StartContainer logs clear<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 hyper

import (
	"fmt"
	"strings"

	"github.com/golang/glog"

	"k8s.io/frakti/pkg/hyper/types"
	kubeapi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime"
)

// CreateContainer creates a new container in specified PodSandbox
func (h *Runtime) CreateContainer(podSandboxID string, config *kubeapi.ContainerConfig, sandboxConfig *kubeapi.PodSandboxConfig) (string, error) {
	containerSpec, err := buildUserContainer(config, sandboxConfig)
	if err != nil {
		glog.Errorf("Build UserContainer for container %q failed: %v", config.String(), err)
		return "", err
	}

	// TODO: support container-level log_path in upstream hyperd when creating container.
	containerID, err := h.client.CreateContainer(podSandboxID, containerSpec)
	if err != nil {
		glog.Errorf("Create container %s in pod %s failed: %v", config.Metadata.GetName(), podSandboxID, err)
		return "", err
	}

	return containerID, nil
}

// buildUserContainer builds hyperd's UserContainer based kubelet ContainerConfig.
func buildUserContainer(config *kubeapi.ContainerConfig, sandboxConfig *kubeapi.PodSandboxConfig) (*types.UserContainer, error) {
	if config.GetLinux().GetSecurityContext().GetPrivileged() {
		return nil, fmt.Errorf("Priviledged containers are not supported in hyper")
	}

	containerSpec := &types.UserContainer{
		Name:       buildContainerName(sandboxConfig, config),
		Image:      config.Image.GetImage(),
		Workdir:    config.GetWorkingDir(),
		Tty:        config.GetTty(),
		Command:    config.GetArgs(),
		Entrypoint: config.GetCommand(),
		Labels:     buildLabelsWithAnnotations(config.Labels, config.Annotations),
	}

	// TODO: support adding device in upstream hyperd when creating container.

	// TODO: support volume mounts in upstream hyperd.
	// volumes := make([]*types.UserVolumeReference, len(config.Mounts))
	// for idx, v := range config.Mounts {
	// 	volumes[idx] = &types.UserVolumeReference{
	// 		Volume:   v.GetHostPath(),
	// 		Path:     v.GetContainerPath(),
	// 		ReadOnly: v.GetReadonly(),
	// 	}
	// }
	containerSpec.Volumes = []*types.UserVolumeReference{}

	// make environments
	environments := make([]*types.EnvironmentVar, len(config.Envs))
	for idx, env := range config.Envs {
		environments[idx] = &types.EnvironmentVar{
			Env:   env.GetKey(),
			Value: env.GetValue(),
		}
	}
	containerSpec.Envs = environments

	return containerSpec, nil
}

// StartContainer starts the container.
func (h *Runtime) StartContainer(rawContainerID string) error {
	// Hyperd doesn't support start a standalone container yet, restart the
	// pod to workaround this.
	// TODO: replace this with real StartContainer after hyperd's refactoring.
	container, err := h.client.GetContainerInfo(rawContainerID)
	if err != nil {
		glog.Errorf("Failed to get container %q: %v", rawContainerID, err)
		return err
	}
	_, reason, err := h.client.StopPod(container.PodID)
	if err != nil {
		glog.Errorf("[StartContainer] Failed to stop pod %q with reason (%q): %v", container.PodID, reason, err)
		return err
	}
	err = h.client.StartPod(container.PodID)
	if err != nil {
		glog.Errorf("[StartContainer] Failed to start pod %q: %v", container.PodID, err)
		return err
	}

	return nil
}

// StopContainer stops a running container with a grace period (i.e. timeout).
func (h *Runtime) StopContainer(rawContainerID string, timeout int64) error {
	err := h.client.StopContainer(rawContainerID, timeout)
	if err != nil {
		glog.Errorf("Stop container %s failed: %v", rawContainerID, err)
		return err
	}

	return nil
}

// RemoveContainer removes the container. If the container is running, the container
// should be force removed.
func (h *Runtime) RemoveContainer(rawContainerID string) error {
	// Workaround: always suppose container are deleted successfully.
	// TODO: remove container when hyperd is ready for this.
	return nil
}

// ListContainers lists all containers by filters.
func (h *Runtime) ListContainers(filter *kubeapi.ContainerFilter) ([]*kubeapi.Container, error) {
	containerList, err := h.client.GetContainerList(false)
	if err != nil {
		glog.Errorf("Get container list failed: %v", err)
		return nil, err
	}

	containers := make([]*kubeapi.Container, 0, len(containerList))

	for _, c := range containerList {
		state := toKubeContainerState(c.Status)
		_, _, _, containerName, attempt, err := parseContainerName(strings.Replace(c.ContainerName, "/", "", -1))

		if err != nil {
			glog.Errorf("ParseContainerName for %s failed: %v", c.ContainerName, err)
			return nil, err
		}

		if filter != nil {
			if filter.Id != nil && c.ContainerID != filter.GetId() {
				continue
			}

			if filter.PodSandboxId != nil && c.PodID != filter.GetPodSandboxId() {
				continue
			}

			if filter.State != nil && state != filter.GetState() {
				continue
			}
		}

		info, err := h.client.GetContainerInfo(c.ContainerID)
		if err != nil {
			glog.Errorf("Get container info for %s failed: %v", c.ContainerID, err)
			return nil, err
		}

		annotations := getAnnotationsFromLabels(info.Container.Labels)
		kubeletLabels := getKubeletLabels(info.Container.Labels)

		if filter != nil {
			if filter.LabelSelector != nil && !inMap(filter.LabelSelector, kubeletLabels) {
				continue
			}
		}

		containerMetadata := &kubeapi.ContainerMetadata{
			Name:    &containerName,
			Attempt: &attempt,
		}

		createdAtNano := info.CreatedAt * secondToNano
		containers = append(containers, &kubeapi.Container{
			Id:           &c.ContainerID,
			PodSandboxId: &c.PodID,
			CreatedAt:    &createdAtNano,
			Metadata:     containerMetadata,
			Image:        &kubeapi.ImageSpec{Image: &info.Container.Image},
			ImageRef:     &info.Container.ImageID,
			State:        &state,
			Labels:       kubeletLabels,
			Annotations:  annotations,
		})
	}

	return containers, nil
}

// ContainerStatus returns the container status.
func (h *Runtime) ContainerStatus(containerID string) (*kubeapi.ContainerStatus, error) {
	status, err := h.client.GetContainerInfo(containerID)
	if err != nil {
		glog.Errorf("Get container info for %s failed: %v", containerID, err)
		return nil, err
	}

	podInfo, err := h.client.GetPodInfo(status.PodID)
	if err != nil {
		glog.Errorf("Get pod info for %s failed: %v", status.PodID, err)
		return nil, err
	}

	state := toKubeContainerState(status.Status.Phase)
	annotations := getAnnotationsFromLabels(status.Container.Labels)
	kubeletLabels := getKubeletLabels(status.Container.Labels)

	_, _, _, containerName, attempt, err := parseContainerName(strings.Replace(status.Container.Name, "/", "", -1))
	if err != nil {
		glog.Errorf("ParseContainerName for %s failed: %v", status.Container.Name, err)
		return nil, err
	}

	containerMetadata := &kubeapi.ContainerMetadata{
		Name:    &containerName,
		Attempt: &attempt,
	}

	createdAtNano := status.CreatedAt * secondToNano
	kubeStatus := &kubeapi.ContainerStatus{
		Id:          &status.Container.ContainerID,
		Image:       &kubeapi.ImageSpec{Image: &status.Container.Image},
		ImageRef:    &status.Container.ImageID,
		Metadata:    containerMetadata,
		State:       &state,
		Labels:      kubeletLabels,
		Annotations: annotations,
		CreatedAt:   &createdAtNano,
	}

	mounts := make([]*kubeapi.Mount, len(status.Container.VolumeMounts))
	for idx, mnt := range status.Container.VolumeMounts {
		mounts[idx] = &kubeapi.Mount{
			ContainerPath: &mnt.MountPath,
			Readonly:      &mnt.ReadOnly,
		}

		for _, v := range podInfo.Spec.Volumes {
			if v.Name == mnt.Name {
				mounts[idx].HostPath = &v.Source
			}
		}
	}
	kubeStatus.Mounts = mounts

	switch status.Status.Phase {
	case "running":
		startedAt, err := parseTimeString(status.Status.Running.StartedAt)
		if err != nil {
			glog.Errorf("Hyper: can't parse startedAt %s", status.Status.Running.StartedAt)
			return nil, err
		}
		kubeStatus.StartedAt = &startedAt
	case "failed", "succeeded":
		startedAt, err := parseTimeString(status.Status.Terminated.StartedAt)
		if err != nil {
			glog.Errorf("Hyper: can't parse startedAt %s", status.Status.Terminated.StartedAt)
			return nil, err
		}
		finishedAt, err := parseTimeString(status.Status.Terminated.FinishedAt)
		if err != nil {
			glog.Errorf("Hyper: can't parse finishedAt %s", status.Status.Terminated.FinishedAt)
			return nil, err
		}

		kubeStatus.StartedAt = &startedAt
		kubeStatus.FinishedAt = &finishedAt
		kubeStatus.Reason = &status.Status.Terminated.Reason
		kubeStatus.ExitCode = &status.Status.Terminated.ExitCode
	default:
		kubeStatus.Reason = &status.Status.Waiting.Reason
	}

	return kubeStatus, nil
}
<|endoftext|>


<commit_before>/*
Copyright 2014 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 cmd

import (
	"fmt"
	"io"

	"k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
	cmdconfig "k8s.io/kubernetes/pkg/kubectl/cmd/config"
	"k8s.io/kubernetes/pkg/kubectl/cmd/rollout"
	"k8s.io/kubernetes/pkg/kubectl/cmd/set"
	"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
	cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
	"k8s.io/kubernetes/pkg/util/flag"

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

const (
	bash_completion_func = `# call kubectl get $1,
__kubectl_override_flag_list=(kubeconfig cluster user context namespace server)
__kubectl_override_flags()
{
    local ${__kubectl_override_flag_list[*]} two_word_of of
    for w in "${words[@]}"; do
        if [ -n "${two_word_of}" ]; then
            eval "${two_word_of}=\"--${two_word_of}=\${w}\""
            two_word_of=
            continue
        fi
        for of in "${__kubectl_override_flag_list[@]}"; do
            case "${w}" in
                --${of}=*)
                    eval "${of}=\"${w}\""
                    ;;
                --${of})
                    two_word_of="${of}"
                    ;;
            esac
        done
        if [ "${w}" == "--all-namespaces" ]; then
            namespace="--all-namespaces"
        fi
    done
    for of in "${__kubectl_override_flag_list[@]}"; do
        if eval "test -n \"\$${of}\""; then
            eval "echo \${${of}}"
        fi
    done
}

__kubectl_get_namespaces()
{
    local template kubectl_out
    template="{{ range .items  }}{{ .metadata.name }} {{ end }}"
    if kubectl_out=$(kubectl get -o template --template="${template}" namespace 2>/dev/null); then
        COMPREPLY=( $( compgen -W "${kubectl_out[*]}" -- "$cur" ) )
    fi
}

__kubectl_parse_get()
{
    local template
    template="{{ range .items  }}{{ .metadata.name }} {{ end }}"
    local kubectl_out
    if kubectl_out=$(kubectl get $(__kubectl_override_flags) -o template --template="${template}" "$1" 2>/dev/null); then
        COMPREPLY=( $( compgen -W "${kubectl_out[*]}" -- "$cur" ) )
    fi
}

__kubectl_get_resource()
{
    if [[ ${#nouns[@]} -eq 0 ]]; then
        return 1
    fi
    __kubectl_parse_get "${nouns[${#nouns[@]} -1]}"
}

__kubectl_get_resource_pod()
{
    __kubectl_parse_get "pod"
}

__kubectl_get_resource_rc()
{
    __kubectl_parse_get "rc"
}

__kubectl_get_resource_node()
{
    __kubectl_parse_get "node"
}

# $1 is the name of the pod we want to get the list of containers inside
__kubectl_get_containers()
{
    local template
    template="{{ range .spec.containers  }}{{ .name }} {{ end }}"
    __debug "${FUNCNAME} nouns are ${nouns[*]}"

    local len="${#nouns[@]}"
    if [[ ${len} -ne 1 ]]; then
        return
    fi
    local last=${nouns[${len} -1]}
    local kubectl_out
    if kubectl_out=$(kubectl get $(__kubectl_override_flags) -o template --template="${template}" pods "${last}" 2>/dev/null); then
        COMPREPLY=( $( compgen -W "${kubectl_out[*]}" -- "$cur" ) )
    fi
}

# Require both a pod and a container to be specified
__kubectl_require_pod_and_container()
{
    if [[ ${#nouns[@]} -eq 0 ]]; then
        __kubectl_parse_get pods
        return 0
    fi;
    __kubectl_get_containers
    return 0
}

__custom_func() {
    case ${last_command} in
        kubectl_get | kubectl_describe | kubectl_delete | kubectl_label | kubectl_stop | kubectl_edit | kubectl_patch |\
        kubectl_annotate | kubectl_expose | kubectl_scale | kubectl_autoscale | kubectl_taint | kubectl_rollout_*)
            __kubectl_get_resource
            return
            ;;
        kubectl_logs | kubectl_attach)
            __kubectl_require_pod_and_container
            return
            ;;
        kubectl_exec | kubectl_port-forward | kubectl_top_pod)
            __kubectl_get_resource_pod
            return
            ;;
        kubectl_rolling-update)
            __kubectl_get_resource_rc
            return
            ;;
        kubectl_cordon | kubectl_uncordon | kubectl_drain | kubectl_top_node)
            __kubectl_get_resource_node
            return
            ;;
        *)
            ;;
    esac
}
`

	// If you add a resource to this list, please also take a look at pkg/kubectl/kubectl.go
	// and add a short forms entry in expandResourceShortcut() when appropriate.
	// TODO: This should be populated using the discovery information from apiserver.
	valid_resources = `Valid resource types include:

    * clusters (valid only for federation apiservers)
    * componentstatuses (aka 'cs')
    * configmaps (aka 'cm')
    * daemonsets (aka 'ds')
    * deployments (aka 'deploy')
    * endpoints (aka 'ep')
    * events (aka 'ev')
    * horizontalpodautoscalers (aka 'hpa')
    * ingresses (aka 'ing')
    * jobs
    * limitranges (aka 'limits')
    * namespaces (aka 'ns')
    * networkpolicies
    * nodes (aka 'no')
    * persistentvolumeclaims (aka 'pvc')
    * persistentvolumes (aka 'pv')
    * pods (aka 'po')
    * podsecuritypolicies (aka 'psp')
    * podtemplates
    * replicasets (aka 'rs')
    * replicationcontrollers (aka 'rc')
    * resourcequotas (aka 'quota')
    * secrets
    * serviceaccounts (aka 'sa')
    * services (aka 'svc')
    * statefulsets
    * storageclasses
    * thirdpartyresources
    `
)

// NewKubectlCommand creates the `kubectl` command and its nested children.
func NewKubectlCommand(f cmdutil.Factory, in io.Reader, out, err io.Writer) *cobra.Command {
	// Parent command to which all subcommands are added.
	cmds := &cobra.Command{
		Use:   "kubectl",
		Short: "kubectl controls the Kubernetes cluster manager",
		Long: templates.LongDesc(`
      kubectl controls the Kubernetes cluster manager.

      Find more information at https://github.com/kubernetes/kubernetes.`),
		Run: runHelp,
		BashCompletionFunction: bash_completion_func,
	}

	f.BindFlags(cmds.PersistentFlags())
	f.BindExternalFlags(cmds.PersistentFlags())

	// From this point and forward we get warnings on flags that contain "_" separators
	cmds.SetGlobalNormalizationFunc(flag.WarnWordSepNormalizeFunc)

	groups := templates.CommandGroups{
		{
			Message: "Basic Commands (Beginner):",
			Commands: []*cobra.Command{
				NewCmdCreate(f, out, err),
				NewCmdExposeService(f, out),
				NewCmdRun(f, in, out, err),
				set.NewCmdSet(f, out, err),
			},
		},
		{
			Message: "Basic Commands (Intermediate):",
			Commands: []*cobra.Command{
				NewCmdGet(f, out, err),
				NewCmdExplain(f, out, err),
				NewCmdEdit(f, out, err),
				NewCmdDelete(f, out),
			},
		},
		{
			Message: "Deploy Commands:",
			Commands: []*cobra.Command{
				rollout.NewCmdRollout(f, out, err),
				NewCmdRollingUpdate(f, out),
				NewCmdScale(f, out),
				NewCmdAutoscale(f, out),
			},
		},
		{
			Message: "Cluster Management Commands:",
			Commands: []*cobra.Command{
				NewCmdCertificate(f, out),
				NewCmdClusterInfo(f, out),
				NewCmdTop(f, out, err),
				NewCmdCordon(f, out),
				NewCmdUncordon(f, out),
				NewCmdDrain(f, out, err),
				NewCmdTaint(f, out),
			},
		},
		{
			Message: "Troubleshooting and Debugging Commands:",
			Commands: []*cobra.Command{
				NewCmdDescribe(f, out, err),
				NewCmdLogs(f, out),
				NewCmdAttach(f, in, out, err),
				NewCmdExec(f, in, out, err),
				NewCmdPortForward(f, out, err),
				NewCmdProxy(f, out),
				NewCmdCp(f, in, out, err),
			},
		},
		{
			Message: "Advanced Commands:",
			Commands: []*cobra.Command{
				NewCmdApply(f, out),
				NewCmdPatch(f, out),
				NewCmdReplace(f, out),
				NewCmdConvert(f, out),
			},
		},
		{
			Message: "Settings Commands:",
			Commands: []*cobra.Command{
				NewCmdLabel(f, out),
				NewCmdAnnotate(f, out),
				NewCmdCompletion(f, out),
			},
		},
	}
	groups.Add(cmds)

	filters := []string{
		"options",
		Deprecated("kubectl", "delete", cmds, NewCmdStop(f, out)),
	}
	templates.ActsAsRootCommand(cmds, filters, groups...)

	if cmds.Flag("namespace") != nil {
		if cmds.Flag("namespace").Annotations == nil {
			cmds.Flag("namespace").Annotations = map[string][]string{}
		}
		cmds.Flag("namespace").Annotations[cobra.BashCompCustom] = append(
			cmds.Flag("namespace").Annotations[cobra.BashCompCustom],
			"__kubectl_get_namespaces",
		)
	}

	cmds.AddCommand(cmdconfig.NewCmdConfig(clientcmd.NewDefaultPathOptions(), out, err))
	cmds.AddCommand(NewCmdVersion(f, out))
	cmds.AddCommand(NewCmdApiVersions(f, out))
	cmds.AddCommand(NewCmdOptions(out))

	return cmds
}

func runHelp(cmd *cobra.Command, args []string) {
	cmd.Help()
}

func printDeprecationWarning(command, alias string) {
	glog.Warningf("%s is DEPRECATED and will be removed in a future version. Use %s instead.", alias, command)
}

func Deprecated(baseName, to string, parent, cmd *cobra.Command) string {
	cmd.Long = fmt.Sprintf("Deprecated: This command is deprecated, all its functionalities are covered by \"%s %s\"", baseName, to)
	cmd.Short = fmt.Sprintf("Deprecated: %s", to)
	parent.AddCommand(cmd)
	return cmd.Name()
}
<commit_msg>extend cmd valid resources information<commit_after>/*
Copyright 2014 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 cmd

import (
	"fmt"
	"io"

	"k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
	cmdconfig "k8s.io/kubernetes/pkg/kubectl/cmd/config"
	"k8s.io/kubernetes/pkg/kubectl/cmd/rollout"
	"k8s.io/kubernetes/pkg/kubectl/cmd/set"
	"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
	cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
	"k8s.io/kubernetes/pkg/util/flag"

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

const (
	bash_completion_func = `# call kubectl get $1,
__kubectl_override_flag_list=(kubeconfig cluster user context namespace server)
__kubectl_override_flags()
{
    local ${__kubectl_override_flag_list[*]} two_word_of of
    for w in "${words[@]}"; do
        if [ -n "${two_word_of}" ]; then
            eval "${two_word_of}=\"--${two_word_of}=\${w}\""
            two_word_of=
            continue
        fi
        for of in "${__kubectl_override_flag_list[@]}"; do
            case "${w}" in
                --${of}=*)
                    eval "${of}=\"${w}\""
                    ;;
                --${of})
                    two_word_of="${of}"
                    ;;
            esac
        done
        if [ "${w}" == "--all-namespaces" ]; then
            namespace="--all-namespaces"
        fi
    done
    for of in "${__kubectl_override_flag_list[@]}"; do
        if eval "test -n \"\$${of}\""; then
            eval "echo \${${of}}"
        fi
    done
}

__kubectl_get_namespaces()
{
    local template kubectl_out
    template="{{ range .items  }}{{ .metadata.name }} {{ end }}"
    if kubectl_out=$(kubectl get -o template --template="${template}" namespace 2>/dev/null); then
        COMPREPLY=( $( compgen -W "${kubectl_out[*]}" -- "$cur" ) )
    fi
}

__kubectl_parse_get()
{
    local template
    template="{{ range .items  }}{{ .metadata.name }} {{ end }}"
    local kubectl_out
    if kubectl_out=$(kubectl get $(__kubectl_override_flags) -o template --template="${template}" "$1" 2>/dev/null); then
        COMPREPLY=( $( compgen -W "${kubectl_out[*]}" -- "$cur" ) )
    fi
}

__kubectl_get_resource()
{
    if [[ ${#nouns[@]} -eq 0 ]]; then
        return 1
    fi
    __kubectl_parse_get "${nouns[${#nouns[@]} -1]}"
}

__kubectl_get_resource_pod()
{
    __kubectl_parse_get "pod"
}

__kubectl_get_resource_rc()
{
    __kubectl_parse_get "rc"
}

__kubectl_get_resource_node()
{
    __kubectl_parse_get "node"
}

# $1 is the name of the pod we want to get the list of containers inside
__kubectl_get_containers()
{
    local template
    template="{{ range .spec.containers  }}{{ .name }} {{ end }}"
    __debug "${FUNCNAME} nouns are ${nouns[*]}"

    local len="${#nouns[@]}"
    if [[ ${len} -ne 1 ]]; then
        return
    fi
    local last=${nouns[${len} -1]}
    local kubectl_out
    if kubectl_out=$(kubectl get $(__kubectl_override_flags) -o template --template="${template}" pods "${last}" 2>/dev/null); then
        COMPREPLY=( $( compgen -W "${kubectl_out[*]}" -- "$cur" ) )
    fi
}

# Require both a pod and a container to be specified
__kubectl_require_pod_and_container()
{
    if [[ ${#nouns[@]} -eq 0 ]]; then
        __kubectl_parse_get pods
        return 0
    fi;
    __kubectl_get_containers
    return 0
}

__custom_func() {
    case ${last_command} in
        kubectl_get | kubectl_describe | kubectl_delete | kubectl_label | kubectl_stop | kubectl_edit | kubectl_patch |\
        kubectl_annotate | kubectl_expose | kubectl_scale | kubectl_autoscale | kubectl_taint | kubectl_rollout_*)
            __kubectl_get_resource
            return
            ;;
        kubectl_logs | kubectl_attach)
            __kubectl_require_pod_and_container
            return
            ;;
        kubectl_exec | kubectl_port-forward | kubectl_top_pod)
            __kubectl_get_resource_pod
            return
            ;;
        kubectl_rolling-update)
            __kubectl_get_resource_rc
            return
            ;;
        kubectl_cordon | kubectl_uncordon | kubectl_drain | kubectl_top_node)
            __kubectl_get_resource_node
            return
            ;;
        *)
            ;;
    esac
}
`

	// If you add a resource to this list, please also take a look at pkg/kubectl/kubectl.go
	// and add a short forms entry in expandResourceShortcut() when appropriate.
	// TODO: This should be populated using the discovery information from apiserver.
	valid_resources = `Valid resource types include:

    * clusters (valid only for federation apiservers)
    * clusterrolebindings
    * clusterroles
    * componentstatuses (aka 'cs')
    * configmaps (aka 'cm')
    * daemonsets (aka 'ds')
    * deployments (aka 'deploy')
    * endpoints (aka 'ep')
    * events (aka 'ev')
    * horizontalpodautoscalers (aka 'hpa')
    * ingresses (aka 'ing')
    * jobs
    * limitranges (aka 'limits')
    * namespaces (aka 'ns')
    * networkpolicies
    * nodes (aka 'no')
    * persistentvolumeclaims (aka 'pvc')
    * persistentvolumes (aka 'pv')
    * pods (aka 'po')
    * podsecuritypolicies (aka 'psp')
    * podtemplates
    * replicasets (aka 'rs')
    * replicationcontrollers (aka 'rc')
    * resourcequotas (aka 'quota')
    * rolebindings
    * roles
    * secrets
    * serviceaccounts (aka 'sa')
    * services (aka 'svc')
    * statefulsets
    * storageclasses
    * thirdpartyresources
    `
)

// NewKubectlCommand creates the `kubectl` command and its nested children.
func NewKubectlCommand(f cmdutil.Factory, in io.Reader, out, err io.Writer) *cobra.Command {
	// Parent command to which all subcommands are added.
	cmds := &cobra.Command{
		Use:   "kubectl",
		Short: "kubectl controls the Kubernetes cluster manager",
		Long: templates.LongDesc(`
      kubectl controls the Kubernetes cluster manager.

      Find more information at https://github.com/kubernetes/kubernetes.`),
		Run: runHelp,
		BashCompletionFunction: bash_completion_func,
	}

	f.BindFlags(cmds.PersistentFlags())
	f.BindExternalFlags(cmds.PersistentFlags())

	// From this point and forward we get warnings on flags that contain "_" separators
	cmds.SetGlobalNormalizationFunc(flag.WarnWordSepNormalizeFunc)

	groups := templates.CommandGroups{
		{
			Message: "Basic Commands (Beginner):",
			Commands: []*cobra.Command{
				NewCmdCreate(f, out, err),
				NewCmdExposeService(f, out),
				NewCmdRun(f, in, out, err),
				set.NewCmdSet(f, out, err),
			},
		},
		{
			Message: "Basic Commands (Intermediate):",
			Commands: []*cobra.Command{
				NewCmdGet(f, out, err),
				NewCmdExplain(f, out, err),
				NewCmdEdit(f, out, err),
				NewCmdDelete(f, out),
			},
		},
		{
			Message: "Deploy Commands:",
			Commands: []*cobra.Command{
				rollout.NewCmdRollout(f, out, err),
				NewCmdRollingUpdate(f, out),
				NewCmdScale(f, out),
				NewCmdAutoscale(f, out),
			},
		},
		{
			Message: "Cluster Management Commands:",
			Commands: []*cobra.Command{
				NewCmdCertificate(f, out),
				NewCmdClusterInfo(f, out),
				NewCmdTop(f, out, err),
				NewCmdCordon(f, out),
				NewCmdUncordon(f, out),
				NewCmdDrain(f, out, err),
				NewCmdTaint(f, out),
			},
		},
		{
			Message: "Troubleshooting and Debugging Commands:",
			Commands: []*cobra.Command{
				NewCmdDescribe(f, out, err),
				NewCmdLogs(f, out),
				NewCmdAttach(f, in, out, err),
				NewCmdExec(f, in, out, err),
				NewCmdPortForward(f, out, err),
				NewCmdProxy(f, out),
				NewCmdCp(f, in, out, err),
			},
		},
		{
			Message: "Advanced Commands:",
			Commands: []*cobra.Command{
				NewCmdApply(f, out),
				NewCmdPatch(f, out),
				NewCmdReplace(f, out),
				NewCmdConvert(f, out),
			},
		},
		{
			Message: "Settings Commands:",
			Commands: []*cobra.Command{
				NewCmdLabel(f, out),
				NewCmdAnnotate(f, out),
				NewCmdCompletion(f, out),
			},
		},
	}
	groups.Add(cmds)

	filters := []string{
		"options",
		Deprecated("kubectl", "delete", cmds, NewCmdStop(f, out)),
	}
	templates.ActsAsRootCommand(cmds, filters, groups...)

	if cmds.Flag("namespace") != nil {
		if cmds.Flag("namespace").Annotations == nil {
			cmds.Flag("namespace").Annotations = map[string][]string{}
		}
		cmds.Flag("namespace").Annotations[cobra.BashCompCustom] = append(
			cmds.Flag("namespace").Annotations[cobra.BashCompCustom],
			"__kubectl_get_namespaces",
		)
	}

	cmds.AddCommand(cmdconfig.NewCmdConfig(clientcmd.NewDefaultPathOptions(), out, err))
	cmds.AddCommand(NewCmdVersion(f, out))
	cmds.AddCommand(NewCmdApiVersions(f, out))
	cmds.AddCommand(NewCmdOptions(out))

	return cmds
}

func runHelp(cmd *cobra.Command, args []string) {
	cmd.Help()
}

func printDeprecationWarning(command, alias string) {
	glog.Warningf("%s is DEPRECATED and will be removed in a future version. Use %s instead.", alias, command)
}

func Deprecated(baseName, to string, parent, cmd *cobra.Command) string {
	cmd.Long = fmt.Sprintf("Deprecated: This command is deprecated, all its functionalities are covered by \"%s %s\"", baseName, to)
	cmd.Short = fmt.Sprintf("Deprecated: %s", to)
	parent.AddCommand(cmd)
	return cmd.Name()
}
<|endoftext|>