<commit_before>package client

/*
 Copyleft 2016 Alexander I.Grafov <grafov@gmail.com>

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.

 ॐ तारे तुत्तारे तुरे स्व
*/

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"net/url"
	"strings"
	"time"

	"github.com/grafov/autograf/grafana"
)

// BoardProperties keeps metadata of a dashboard.
type BoardProperties struct {
	IsStarred  bool      `json:"isStarred,omitempty"`
	IsHome     bool      `json:"isHome,omitempty"`
	IsSnapshot bool      `json:"isSnapshot,omitempty"`
	Type       string    `json:"type,omitempty"`
	CanSave    bool      `json:"canSave"`
	CanEdit    bool      `json:"canEdit"`
	CanStar    bool      `json:"canStar"`
	Slug       string    `json:"slug"`
	Expires    time.Time `json:"expires"`
	Created    time.Time `json:"created"`
	Updated    time.Time `json:"updated"`
	UpdatedBy  string    `json:"updatedBy"`
	CreatedBy  string    `json:"createdBy"`
	Version    int       `json:"version"`
}

// GetDashboard loads a dashboard from Grafana instance along with metadata for a dashboard.
func (r *Instance) GetDashboard(slug string) (grafana.Board, BoardProperties, error) {
	var (
		raw    []byte
		result struct {
			Meta  BoardProperties `json:"meta"`
			Board grafana.Board   `json:"dashboard"`
		}
		code int
		err  error
	)
	slug, _ = setPrefix(slug)
	if raw, code, err = r.get(fmt.Sprintf("api/dashboards/%s", slug), nil); err != nil {
		return grafana.Board{}, BoardProperties{}, err
	}
	if code != 200 {
		return grafana.Board{}, BoardProperties{}, fmt.Errorf("HTTP error %d: returns %s", code, raw)
	}
	dec := json.NewDecoder(bytes.NewReader(raw))
	dec.UseNumber()
	if err := dec.Decode(&result); err != nil {
		return grafana.Board{}, BoardProperties{}, fmt.Errorf("unmarshal board with meta: %s\n%s", err, raw)
	}
	return result.Board, result.Meta, err
}

// GetRawDashboard loads a dashboard JSON from Grafana instance along with metadata for a dashboard.
// Contrary to GetDashboard() it not unpack loaded JSON to grafana.Board structure. Instead it
// returns it as byte slice. It guarantee that data of dashboard returned untouched by conversion
// with grafana.Board so no matter how properly fields from a current version of Grafana mapped to
// our grafana.Board fields. It useful for backuping purposes when you want a dashboard exactly with
// same data as it exported by Grafana.
func (r *Instance) GetRawDashboard(slug string) ([]byte, BoardProperties, error) {
	var (
		raw    []byte
		result struct {
			Meta  BoardProperties `json:"meta"`
			Board json.RawMessage `json:"dashboard"`
		}
		code int
		err  error
	)
	slug, _ = setPrefix(slug)
	if raw, code, err = r.get(fmt.Sprintf("api/dashboards/%s", slug), nil); err != nil {
		return nil, BoardProperties{}, err
	}
	if code != 200 {
		return nil, BoardProperties{}, fmt.Errorf("HTTP error %d: returns %s", code, raw)
	}
	dec := json.NewDecoder(bytes.NewReader(raw))
	dec.UseNumber()
	if err := dec.Decode(&result); err != nil {
		return nil, BoardProperties{}, fmt.Errorf("unmarshal board with meta: %s\n%s", err, raw)
	}
	return []byte(result.Board), result.Meta, err
}

// FoundBoard keeps result of search with metadata of a dashboard.
type FoundBoard struct {
	ID        uint     `json:"id"`
	Title     string   `json:"title"`
	URI       string   `json:"uri"`
	Type      string   `json:"type"`
	Tags      []string `json:"tags"`
	IsStarred bool     `json:"isStarred"`
}

// SearchDashboards search dashboards by substring of their title. It allows restrict the result set with
// only starred dashboards and only for tags (logical OR applied to multiple tags).
func (r *Instance) SearchDashboards(query string, starred bool, tags ...string) ([]FoundBoard, error) {
	var (
		raw    []byte
		boards []FoundBoard
		code   int
		err    error
	)
	u := url.URL{}
	q := u.Query()
	if query != "" {
		q.Set("query", query)
	}
	if starred {
		q.Set("starred", "true")
	}
	for _, tag := range tags {
		q.Add("tag", tag)
	}
	if raw, code, err = r.get("api/search", q); err != nil {
		return nil, err
	}
	if code != 200 {
		return nil, fmt.Errorf("HTTP error %d: returns %s", code, raw)
	}
	err = json.Unmarshal(raw, &boards)
	return boards, err
}

// SetDashboard updates existing dashboard or creates a new one.
// Set dasboard ID to nil to create a new dashboard.
// Set overwrite to true if you want to overwrite existing dashboard with
// newer version or with same dashboard title.
func (r *Instance) SetDashboard(board grafana.Board, overwrite bool) error {
	var (
		isBoardFromDB bool
		newBoard      struct {
			Dashboard grafana.Board `json:"dashboard"`
			Overwrite bool          `json:"overwrite"`
		}
		raw  []byte
		resp StatusMessage
		code int
		err  error
	)
	if board.Slug, isBoardFromDB = cleanPrefix(board.Slug); !isBoardFromDB {
		return errors.New("only database dashboard (with 'db/' prefix in a slug) can be set")
	}
	newBoard.Dashboard = board
	newBoard.Overwrite = overwrite
	if !overwrite {
		newBoard.Dashboard.ID = 0
	}
	if raw, err = json.Marshal(newBoard); err != nil {
		return err
	}
	if raw, code, err = r.post("api/dashboards/db", nil, raw); err != nil {
		return err
	}
	if err = json.Unmarshal(raw, &resp); err != nil {
		return err
	}
	switch code {
	case 401:
		return fmt.Errorf("%d %s", code, *resp.Message)
	case 412:
		return fmt.Errorf("%d %s", code, *resp.Message)
	}
	return nil
}

// DeleteDashboard deletes dashboard that selected by slug string.
func (r *Instance) DeleteDashboard(slug string) (StatusMessage, error) {
	var (
		isBoardFromDB bool
		raw           []byte
		reply         StatusMessage
		err           error
	)
	if slug, isBoardFromDB = setPrefix(slug); !isBoardFromDB {
		return StatusMessage{}, errors.New("only database dashboards (with 'db/' prefix in a slug) can be removed")
	}
	if raw, err = r.delete(fmt.Sprintf("api/dashboards/db/%s", slug)); err != nil {
		return StatusMessage{}, err
	}
	err = json.Unmarshal(raw, &reply)
	return reply, err
}

// implicitely use dashboards from Grafana DB not from a file system
func setPrefix(slug string) (string, bool) {
	if strings.HasPrefix(slug, "db") {
		return slug, true
	}
	if strings.HasPrefix(slug, "file") {
		return slug, false
	}
	return fmt.Sprintf("db/%s", slug), true
}

// assume we use database dashboard by default
func cleanPrefix(slug string) (string, bool) {
	if strings.HasPrefix(slug, "db") {
		return slug[3:], true
	}
	if strings.HasPrefix(slug, "file") {
		return slug[3:], false
	}
	return fmt.Sprintf("%s", slug), true
}
<commit_msg>Add docs about file and db dashboards.<commit_after>package client

/*
 Copyleft 2016 Alexander I.Grafov <grafov@gmail.com>

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.

 ॐ तारे तुत्तारे तुरे स्व
*/

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"net/url"
	"strings"
	"time"

	"github.com/grafov/autograf/grafana"
)

// BoardProperties keeps metadata of a dashboard.
type BoardProperties struct {
	IsStarred  bool      `json:"isStarred,omitempty"`
	IsHome     bool      `json:"isHome,omitempty"`
	IsSnapshot bool      `json:"isSnapshot,omitempty"`
	Type       string    `json:"type,omitempty"`
	CanSave    bool      `json:"canSave"`
	CanEdit    bool      `json:"canEdit"`
	CanStar    bool      `json:"canStar"`
	Slug       string    `json:"slug"`
	Expires    time.Time `json:"expires"`
	Created    time.Time `json:"created"`
	Updated    time.Time `json:"updated"`
	UpdatedBy  string    `json:"updatedBy"`
	CreatedBy  string    `json:"createdBy"`
	Version    int       `json:"version"`
}

// GetDashboard loads a dashboard from Grafana instance along with metadata for a dashboard.
// For dashboards from a filesystem set "file/" prefix for slug. By default dashboards from
// a database assumed. Database dashboards may have "db/" prefix or may have not, it will
// be appended automatically.
func (r *Instance) GetDashboard(slug string) (grafana.Board, BoardProperties, error) {
	var (
		raw    []byte
		result struct {
			Meta  BoardProperties `json:"meta"`
			Board grafana.Board   `json:"dashboard"`
		}
		code int
		err  error
	)
	slug, _ = setPrefix(slug)
	if raw, code, err = r.get(fmt.Sprintf("api/dashboards/%s", slug), nil); err != nil {
		return grafana.Board{}, BoardProperties{}, err
	}
	if code != 200 {
		return grafana.Board{}, BoardProperties{}, fmt.Errorf("HTTP error %d: returns %s", code, raw)
	}
	dec := json.NewDecoder(bytes.NewReader(raw))
	dec.UseNumber()
	if err := dec.Decode(&result); err != nil {
		return grafana.Board{}, BoardProperties{}, fmt.Errorf("unmarshal board with meta: %s\n%s", err, raw)
	}
	return result.Board, result.Meta, err
}

// GetRawDashboard loads a dashboard JSON from Grafana instance along with metadata for a dashboard.
// Contrary to GetDashboard() it not unpack loaded JSON to grafana.Board structure. Instead it
// returns it as byte slice. It guarantee that data of dashboard returned untouched by conversion
// with grafana.Board so no matter how properly fields from a current version of Grafana mapped to
// our grafana.Board fields. It useful for backuping purposes when you want a dashboard exactly with
// same data as it exported by Grafana.
//
// For dashboards from a filesystem set "file/" prefix for slug. By default dashboards from
// a database assumed. Database dashboards may have "db/" prefix or may have not, it will
// be appended automatically.
func (r *Instance) GetRawDashboard(slug string) ([]byte, BoardProperties, error) {
	var (
		raw    []byte
		result struct {
			Meta  BoardProperties `json:"meta"`
			Board json.RawMessage `json:"dashboard"`
		}
		code int
		err  error
	)
	slug, _ = setPrefix(slug)
	if raw, code, err = r.get(fmt.Sprintf("api/dashboards/%s", slug), nil); err != nil {
		return nil, BoardProperties{}, err
	}
	if code != 200 {
		return nil, BoardProperties{}, fmt.Errorf("HTTP error %d: returns %s", code, raw)
	}
	dec := json.NewDecoder(bytes.NewReader(raw))
	dec.UseNumber()
	if err := dec.Decode(&result); err != nil {
		return nil, BoardProperties{}, fmt.Errorf("unmarshal board with meta: %s\n%s", err, raw)
	}
	return []byte(result.Board), result.Meta, err
}

// FoundBoard keeps result of search with metadata of a dashboard.
type FoundBoard struct {
	ID        uint     `json:"id"`
	Title     string   `json:"title"`
	URI       string   `json:"uri"`
	Type      string   `json:"type"`
	Tags      []string `json:"tags"`
	IsStarred bool     `json:"isStarred"`
}

// SearchDashboards search dashboards by substring of their title. It allows restrict the result set with
// only starred dashboards and only for tags (logical OR applied to multiple tags).
func (r *Instance) SearchDashboards(query string, starred bool, tags ...string) ([]FoundBoard, error) {
	var (
		raw    []byte
		boards []FoundBoard
		code   int
		err    error
	)
	u := url.URL{}
	q := u.Query()
	if query != "" {
		q.Set("query", query)
	}
	if starred {
		q.Set("starred", "true")
	}
	for _, tag := range tags {
		q.Add("tag", tag)
	}
	if raw, code, err = r.get("api/search", q); err != nil {
		return nil, err
	}
	if code != 200 {
		return nil, fmt.Errorf("HTTP error %d: returns %s", code, raw)
	}
	err = json.Unmarshal(raw, &boards)
	return boards, err
}

// SetDashboard updates existing dashboard or creates a new one.
// Set dasboard ID to nil to create a new dashboard.
// Set overwrite to true if you want to overwrite existing dashboard with
// newer version or with same dashboard title.
// Grafana only can create or update a dashboard in a database. File dashboards
// may be only loaded with HTTP API but not created or updated.
func (r *Instance) SetDashboard(board grafana.Board, overwrite bool) error {
	var (
		isBoardFromDB bool
		newBoard      struct {
			Dashboard grafana.Board `json:"dashboard"`
			Overwrite bool          `json:"overwrite"`
		}
		raw  []byte
		resp StatusMessage
		code int
		err  error
	)
	if board.Slug, isBoardFromDB = cleanPrefix(board.Slug); !isBoardFromDB {
		return errors.New("only database dashboard (with 'db/' prefix in a slug) can be set")
	}
	newBoard.Dashboard = board
	newBoard.Overwrite = overwrite
	if !overwrite {
		newBoard.Dashboard.ID = 0
	}
	if raw, err = json.Marshal(newBoard); err != nil {
		return err
	}
	if raw, code, err = r.post("api/dashboards/db", nil, raw); err != nil {
		return err
	}
	if err = json.Unmarshal(raw, &resp); err != nil {
		return err
	}
	switch code {
	case 401:
		return fmt.Errorf("%d %s", code, *resp.Message)
	case 412:
		return fmt.Errorf("%d %s", code, *resp.Message)
	}
	return nil
}

// DeleteDashboard deletes dashboard that selected by slug string.
// Grafana only can delete a dashboard in a database. File dashboards
// may be only loaded with HTTP API but not deteled.
func (r *Instance) DeleteDashboard(slug string) (StatusMessage, error) {
	var (
		isBoardFromDB bool
		raw           []byte
		reply         StatusMessage
		err           error
	)
	if slug, isBoardFromDB = setPrefix(slug); !isBoardFromDB {
		return StatusMessage{}, errors.New("only database dashboards (with 'db/' prefix in a slug) can be removed")
	}
	if raw, err = r.delete(fmt.Sprintf("api/dashboards/db/%s", slug)); err != nil {
		return StatusMessage{}, err
	}
	err = json.Unmarshal(raw, &reply)
	return reply, err
}

// implicitely use dashboards from Grafana DB not from a file system
func setPrefix(slug string) (string, bool) {
	if strings.HasPrefix(slug, "db") {
		return slug, true
	}
	if strings.HasPrefix(slug, "file") {
		return slug, false
	}
	return fmt.Sprintf("db/%s", slug), true
}

// assume we use database dashboard by default
func cleanPrefix(slug string) (string, bool) {
	if strings.HasPrefix(slug, "db") {
		return slug[3:], true
	}
	if strings.HasPrefix(slug, "file") {
		return slug[3:], false
	}
	return fmt.Sprintf("%s", slug), true
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"os"

	docker "github.com/bywan/go-dockercommand"
)

const (
	dockerEndpoint = "unix:///docker.sock"
)

type LanguageParser struct {
	Image string
}

func (p *LanguageParser) Parse() error {

	log.Printf("Lauching language parser %s\n", p.Image)

	client, err := docker.NewDocker(dockerEndpoint)
	if err != nil {
		return err
	}
	bazookaHome := os.Getenv("BZK_HOME")
	container, err := client.Run(&docker.RunOptions{
		Image: p.Image,
		VolumeBinds: []string{
			fmt.Sprintf("%s/source/:/bazooka", bazookaHome),
			fmt.Sprintf("%s/work/:/bazooka-output", bazookaHome),
			fmt.Sprintf("%s/meta/:/meta", bazookaHome),
		},
	})
	if err != nil {
		return err
	}

	details, err := container.Inspect()
	if err != nil {
		return err
	}
	if details.State.ExitCode != 0 {
		return fmt.Errorf("Error during execution of Language Parser container %s/parser\n Check Docker container logs, id is %s\n", p.Image, container.ID())
	}

	return container.Remove(&docker.RemoveOptions{
		Force:         true,
		RemoveVolumes: true,
	})
}
<commit_msg>Retrieve parserlang logs<commit_after>package main

import (
	"fmt"
	"log"
	"os"

	docker "github.com/bywan/go-dockercommand"
)

const (
	dockerEndpoint = "unix:///docker.sock"
)

type LanguageParser struct {
	Image string
}

func (p *LanguageParser) Parse() error {

	log.Printf("Lauching language parser %s\n", p.Image)

	client, err := docker.NewDocker(dockerEndpoint)
	if err != nil {
		return err
	}
	bazookaHome := os.Getenv("BZK_HOME")
	container, err := client.Run(&docker.RunOptions{
		Image: p.Image,
		VolumeBinds: []string{
			fmt.Sprintf("%s/source/:/bazooka", bazookaHome),
			fmt.Sprintf("%s/work/:/bazooka-output", bazookaHome),
			fmt.Sprintf("%s/meta/:/meta", bazookaHome),
		},
		Detach: true,
	})
	if err != nil {
		return err
	}

	container.Logs(p.Image)

	exitCode, err := container.Wait()
	if err != nil {
		return err
	}
	if exitCode != 0 {
		return fmt.Errorf("Error during execution of Language Parser container %s/parser\n Check Docker container logs, id is %s\n", p.Image, container.ID())
	}

	return container.Remove(&docker.RemoveOptions{
		Force:         true,
		RemoveVolumes: true,
	})
}
<|endoftext|>


<commit_before>package db

import (
	"database/sql"
	"math/rand"
	"time"

	sq "github.com/Masterminds/squirrel"
	"github.com/lib/pq"
)

var componentsQuery = psql.Select("c.id, c.name, c.interval, c.last_ran, c.paused").
	From("components c")

//counterfeiter:generate . Component
type Component interface {
	ID() int
	Name() string
	Interval() time.Duration
	LastRan() time.Time
	Paused() bool

	Reload() (bool, error)
	IntervalElapsed() bool
	UpdateLastRan() error
}

type component struct {
	id       int
	name     string
	interval time.Duration
	lastRan  time.Time
	paused   bool

	conn Conn
}

func (c *component) ID() int                 { return c.id }
func (c *component) Name() string            { return c.name }
func (c *component) Interval() time.Duration { return c.interval }
func (c *component) LastRan() time.Time      { return c.lastRan }
func (c *component) Paused() bool            { return c.paused }

func (c *component) Reload() (bool, error) {
	row := componentsQuery.Where(sq.Eq{"c.id": c.id}).
		RunWith(c.conn).
		QueryRow()

	err := scanComponent(c, row)
	if err != nil {
		if err == sql.ErrNoRows {
			return false, nil
		}
		return false, err
	}

	return true, nil
}

// IntervalElapsed adds a random tiny drift [-1, 1] seconds to interval, when
// there are multiple ATCs, each ATC uses a slightly different interval, so
// that shorter interval gets more chance to run. This mechanism helps distribute
// component to across ATCs more evenly.
func (c *component) IntervalElapsed() bool {
	interval := c.interval
	drift := time.Duration(rand.Int())%(2*time.Second) - time.Second
	if interval+drift > 0 {
		interval += drift
	}
	return time.Now().After(c.lastRan.Add(interval))
}

func (c *component) UpdateLastRan() error {
	_, err := psql.Update("components").
		Set("last_ran", sq.Expr("now()")).
		Where(sq.Eq{
			"id": c.id,
		}).
		RunWith(c.conn).
		Exec()
	if err != nil {
		return err
	}

	return nil
}

func scanComponent(c *component, row scannable) error {
	var (
		lastRan  pq.NullTime
		interval string
	)

	err := row.Scan(
		&c.id,
		&c.name,
		&interval,
		&lastRan,
		&c.paused,
	)
	if err != nil {
		return err
	}

	c.lastRan = lastRan.Time

	c.interval, err = time.ParseDuration(interval)
	if err != nil {
		return err
	}

	return nil
}
<commit_msg>address review comment<commit_after>package db

import (
	"database/sql"
	"math/rand"
	"time"

	sq "github.com/Masterminds/squirrel"
	"github.com/lib/pq"
)

var componentsQuery = psql.Select("c.id, c.name, c.interval, c.last_ran, c.paused").
	From("components c")

//counterfeiter:generate . Component
type Component interface {
	ID() int
	Name() string
	Interval() time.Duration
	LastRan() time.Time
	Paused() bool

	Reload() (bool, error)
	IntervalElapsed() bool
	UpdateLastRan() error
}

type component struct {
	id       int
	name     string
	interval time.Duration
	lastRan  time.Time
	paused   bool
	rander   *rand.Rand

	conn Conn
}

func (c *component) ID() int                 { return c.id }
func (c *component) Name() string            { return c.name }
func (c *component) Interval() time.Duration { return c.interval }
func (c *component) LastRan() time.Time      { return c.lastRan }
func (c *component) Paused() bool            { return c.paused }

func (c *component) Reload() (bool, error) {
	row := componentsQuery.Where(sq.Eq{"c.id": c.id}).
		RunWith(c.conn).
		QueryRow()

	err := scanComponent(c, row)
	if err != nil {
		if err == sql.ErrNoRows {
			return false, nil
		}
		return false, err
	}

	if c.rander == nil {
		c.rander = rand.New(rand.NewSource(time.Now().Unix()))
	}

	return true, nil
}

// IntervalElapsed adds a random tiny drift [-1, 1] seconds to interval, when
// there are multiple ATCs, each ATC uses a slightly different interval, so
// that shorter interval gets more chance to run. This mechanism helps distribute
// component to across ATCs more evenly.
func (c *component) IntervalElapsed() bool {
	interval := c.interval
	drift := time.Duration(c.rander.Int())%(2*time.Second) - time.Second
	if interval+drift > 0 {
		interval += drift
	}
	return time.Now().After(c.lastRan.Add(interval))
}

func (c *component) UpdateLastRan() error {
	_, err := psql.Update("components").
		Set("last_ran", sq.Expr("now()")).
		Where(sq.Eq{
			"id": c.id,
		}).
		RunWith(c.conn).
		Exec()
	if err != nil {
		return err
	}

	return nil
}

func scanComponent(c *component, row scannable) error {
	var (
		lastRan  pq.NullTime
		interval string
	)

	err := row.Scan(
		&c.id,
		&c.name,
		&interval,
		&lastRan,
		&c.paused,
	)
	if err != nil {
		return err
	}

	c.lastRan = lastRan.Time

	c.interval, err = time.ParseDuration(interval)
	if err != nil {
		return err
	}

	return nil
}
<|endoftext|>


<commit_before><commit_msg>Formatting.<commit_after><|endoftext|>


<commit_before>// Package resolver implements utilities for resolving paths within ipfs.
package resolver

import (
	"context"
	"errors"
	"fmt"
	"time"

	dag "github.com/ipfs/go-ipfs/merkledag"
	path "github.com/ipfs/go-ipfs/path"

	cid "gx/ipfs/QmYVNvtQkeZ6AKSwDrjQTs432QtL6umrrK41EBq3cu7iSP/go-cid"
	ipld "gx/ipfs/QmZtNq8dArGfnpCZfx2pUNY7UcjGhVp5qqwQ4hH6mpTMRQ/go-ipld-format"
	logging "gx/ipfs/QmcVVHfdyv15GVPk7NrxdWjh2hLVccXnoD8j2tyQShiXJb/go-log"
)

var log = logging.Logger("pathresolv")

// ErrNoComponents is used when Paths after a protocol
// do not contain at least one component
var ErrNoComponents = errors.New(
	"path must contain at least one component")

// ErrNoLink is returned when a link is not found in a path
type ErrNoLink struct {
	Name string
	Node *cid.Cid
}

// Error implements the Error interface for ErrNoLink with a useful
// human readable message.
func (e ErrNoLink) Error() string {
	return fmt.Sprintf("no link named %q under %s", e.Name, e.Node.String())
}

// ResolveOnce resolves path through a single node
type ResolveOnce func(ctx context.Context, ds ipld.NodeGetter, nd ipld.Node, names []string) (*ipld.Link, []string, error)

// Resolver provides path resolution to IPFS
// It has a pointer to a DAGService, which is uses to resolve nodes.
// TODO: now that this is more modular, try to unify this code with the
//       the resolvers in namesys
type Resolver struct {
	DAG ipld.NodeGetter

	ResolveOnce ResolveOnce
}

// NewBasicResolver constructs a new basic resolver.
func NewBasicResolver(ds ipld.DAGService) *Resolver {
	return &Resolver{
		DAG:         ds,
		ResolveOnce: ResolveSingle,
	}
}

// ResolveToLastNode walks the given path and returns the ipld.Node
// referenced by the last element in it.
func (r *Resolver) ResolveToLastNode(ctx context.Context, fpath path.Path) (ipld.Node, []string, error) {
	c, p, err := path.SplitAbsPath(fpath)
	if err != nil {
		return nil, nil, err
	}

	nd, err := r.DAG.Get(ctx, c)
	if err != nil {
		return nil, nil, err
	}

	for len(p) > 0 {
		lnk, rest, err := r.ResolveOnce(ctx, r.DAG, nd, p)
		if lnk == nil {
			break
		}

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

		next, err := lnk.GetNode(ctx, r.DAG)
		if err != nil {
			return nil, nil, err
		}
		nd = next
		p = rest
	}

	if len(p) == 0 {
		return nd, nil, nil
	}

	// Confirm the path exists within the object
	val, rest, err := nd.Resolve(p)
	if err != nil {
		return nil, nil, err
	}

	if len(rest) > 0 {
		return nil, nil, errors.New("path failed to resolve fully")
	}
	switch val.(type) {
	case *ipld.Link:
		return nil, nil, errors.New("inconsistent ResolveOnce / nd.Resolve")
	default:
		return nd, p, nil
	}
}

// ResolvePath fetches the node for given path. It returns the last item
// returned by ResolvePathComponents.
func (r *Resolver) ResolvePath(ctx context.Context, fpath path.Path) (ipld.Node, error) {
	// validate path
	if err := fpath.IsValid(); err != nil {
		return nil, err
	}

	nodes, err := r.ResolvePathComponents(ctx, fpath)
	if err != nil || nodes == nil {
		return nil, err
	}
	return nodes[len(nodes)-1], err
}

// ResolveSingle simply resolves one hop of a path through a graph with no
// extra context (does not opaquely resolve through sharded nodes)
func ResolveSingle(ctx context.Context, ds ipld.NodeGetter, nd ipld.Node, names []string) (*ipld.Link, []string, error) {
	return nd.ResolveLink(names)
}

// ResolvePathComponents fetches the nodes for each segment of the given path.
// It uses the first path component as a hash (key) of the first node, then
// resolves all other components walking the links, with ResolveLinks.
func (r *Resolver) ResolvePathComponents(ctx context.Context, fpath path.Path) ([]ipld.Node, error) {
	evt := log.EventBegin(ctx, "resolvePathComponents", logging.LoggableMap{"fpath": fpath})
	defer evt.Done()

	h, parts, err := path.SplitAbsPath(fpath)
	if err != nil {
		evt.Append(logging.LoggableMap{"error": err.Error()})
		return nil, err
	}

	log.Debug("resolve dag get")
	nd, err := r.DAG.Get(ctx, h)
	if err != nil {
		evt.Append(logging.LoggableMap{"error": err.Error()})
		return nil, err
	}

	return r.ResolveLinks(ctx, nd, parts)
}

// ResolveLinks iteratively resolves names by walking the link hierarchy.
// Every node is fetched from the DAGService, resolving the next name.
// Returns the list of nodes forming the path, starting with ndd. This list is
// guaranteed never to be empty.
//
// ResolveLinks(nd, []string{"foo", "bar", "baz"})
// would retrieve "baz" in ("bar" in ("foo" in nd.Links).Links).Links
func (r *Resolver) ResolveLinks(ctx context.Context, ndd ipld.Node, names []string) ([]ipld.Node, error) {

	evt := log.EventBegin(ctx, "resolveLinks", logging.LoggableMap{"names": names})
	defer evt.Done()
	result := make([]ipld.Node, 0, len(names)+1)
	result = append(result, ndd)
	nd := ndd // dup arg workaround

	// for each of the path components
	for len(names) > 0 {
		var cancel context.CancelFunc
		ctx, cancel = context.WithTimeout(ctx, time.Minute)
		defer cancel()

		lnk, rest, err := r.ResolveOnce(ctx, r.DAG, nd, names)
		if err == dag.ErrLinkNotFound {
			evt.Append(logging.LoggableMap{"error": err.Error()})
			return result, ErrNoLink{Name: names[0], Node: nd.Cid()}
		} else if err != nil {
			evt.Append(logging.LoggableMap{"error": err.Error()})
			return result, err
		}

		nextnode, err := lnk.GetNode(ctx, r.DAG)
		if err != nil {
			evt.Append(logging.LoggableMap{"error": err.Error()})
			return result, err
		}

		nd = nextnode
		result = append(result, nextnode)
		names = rest
	}
	return result, nil
}
<commit_msg>path: add a comment on dropping error in ResolveToLastNode<commit_after>// Package resolver implements utilities for resolving paths within ipfs.
package resolver

import (
	"context"
	"errors"
	"fmt"
	"time"

	dag "github.com/ipfs/go-ipfs/merkledag"
	path "github.com/ipfs/go-ipfs/path"

	cid "gx/ipfs/QmYVNvtQkeZ6AKSwDrjQTs432QtL6umrrK41EBq3cu7iSP/go-cid"
	ipld "gx/ipfs/QmZtNq8dArGfnpCZfx2pUNY7UcjGhVp5qqwQ4hH6mpTMRQ/go-ipld-format"
	logging "gx/ipfs/QmcVVHfdyv15GVPk7NrxdWjh2hLVccXnoD8j2tyQShiXJb/go-log"
)

var log = logging.Logger("pathresolv")

// ErrNoComponents is used when Paths after a protocol
// do not contain at least one component
var ErrNoComponents = errors.New(
	"path must contain at least one component")

// ErrNoLink is returned when a link is not found in a path
type ErrNoLink struct {
	Name string
	Node *cid.Cid
}

// Error implements the Error interface for ErrNoLink with a useful
// human readable message.
func (e ErrNoLink) Error() string {
	return fmt.Sprintf("no link named %q under %s", e.Name, e.Node.String())
}

// ResolveOnce resolves path through a single node
type ResolveOnce func(ctx context.Context, ds ipld.NodeGetter, nd ipld.Node, names []string) (*ipld.Link, []string, error)

// Resolver provides path resolution to IPFS
// It has a pointer to a DAGService, which is uses to resolve nodes.
// TODO: now that this is more modular, try to unify this code with the
//       the resolvers in namesys
type Resolver struct {
	DAG ipld.NodeGetter

	ResolveOnce ResolveOnce
}

// NewBasicResolver constructs a new basic resolver.
func NewBasicResolver(ds ipld.DAGService) *Resolver {
	return &Resolver{
		DAG:         ds,
		ResolveOnce: ResolveSingle,
	}
}

// ResolveToLastNode walks the given path and returns the ipld.Node
// referenced by the last element in it.
func (r *Resolver) ResolveToLastNode(ctx context.Context, fpath path.Path) (ipld.Node, []string, error) {
	c, p, err := path.SplitAbsPath(fpath)
	if err != nil {
		return nil, nil, err
	}

	nd, err := r.DAG.Get(ctx, c)
	if err != nil {
		return nil, nil, err
	}

	for len(p) > 0 {
		lnk, rest, err := r.ResolveOnce(ctx, r.DAG, nd, p)

		// Note: have to drop the error here as `ResolveOnce` doesn't handle 'leaf'
		// paths (so e.g. for `echo '{"foo":123}' | ipfs dag put` we wouldn't be
		// able to resolve `zdpu[...]/foo`)
		if lnk == nil {
			break
		}

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

		next, err := lnk.GetNode(ctx, r.DAG)
		if err != nil {
			return nil, nil, err
		}
		nd = next
		p = rest
	}

	if len(p) == 0 {
		return nd, nil, nil
	}

	// Confirm the path exists within the object
	val, rest, err := nd.Resolve(p)
	if err != nil {
		return nil, nil, err
	}

	if len(rest) > 0 {
		return nil, nil, errors.New("path failed to resolve fully")
	}
	switch val.(type) {
	case *ipld.Link:
		return nil, nil, errors.New("inconsistent ResolveOnce / nd.Resolve")
	default:
		return nd, p, nil
	}
}

// ResolvePath fetches the node for given path. It returns the last item
// returned by ResolvePathComponents.
func (r *Resolver) ResolvePath(ctx context.Context, fpath path.Path) (ipld.Node, error) {
	// validate path
	if err := fpath.IsValid(); err != nil {
		return nil, err
	}

	nodes, err := r.ResolvePathComponents(ctx, fpath)
	if err != nil || nodes == nil {
		return nil, err
	}
	return nodes[len(nodes)-1], err
}

// ResolveSingle simply resolves one hop of a path through a graph with no
// extra context (does not opaquely resolve through sharded nodes)
func ResolveSingle(ctx context.Context, ds ipld.NodeGetter, nd ipld.Node, names []string) (*ipld.Link, []string, error) {
	return nd.ResolveLink(names)
}

// ResolvePathComponents fetches the nodes for each segment of the given path.
// It uses the first path component as a hash (key) of the first node, then
// resolves all other components walking the links, with ResolveLinks.
func (r *Resolver) ResolvePathComponents(ctx context.Context, fpath path.Path) ([]ipld.Node, error) {
	evt := log.EventBegin(ctx, "resolvePathComponents", logging.LoggableMap{"fpath": fpath})
	defer evt.Done()

	h, parts, err := path.SplitAbsPath(fpath)
	if err != nil {
		evt.Append(logging.LoggableMap{"error": err.Error()})
		return nil, err
	}

	log.Debug("resolve dag get")
	nd, err := r.DAG.Get(ctx, h)
	if err != nil {
		evt.Append(logging.LoggableMap{"error": err.Error()})
		return nil, err
	}

	return r.ResolveLinks(ctx, nd, parts)
}

// ResolveLinks iteratively resolves names by walking the link hierarchy.
// Every node is fetched from the DAGService, resolving the next name.
// Returns the list of nodes forming the path, starting with ndd. This list is
// guaranteed never to be empty.
//
// ResolveLinks(nd, []string{"foo", "bar", "baz"})
// would retrieve "baz" in ("bar" in ("foo" in nd.Links).Links).Links
func (r *Resolver) ResolveLinks(ctx context.Context, ndd ipld.Node, names []string) ([]ipld.Node, error) {

	evt := log.EventBegin(ctx, "resolveLinks", logging.LoggableMap{"names": names})
	defer evt.Done()
	result := make([]ipld.Node, 0, len(names)+1)
	result = append(result, ndd)
	nd := ndd // dup arg workaround

	// for each of the path components
	for len(names) > 0 {
		var cancel context.CancelFunc
		ctx, cancel = context.WithTimeout(ctx, time.Minute)
		defer cancel()

		lnk, rest, err := r.ResolveOnce(ctx, r.DAG, nd, names)
		if err == dag.ErrLinkNotFound {
			evt.Append(logging.LoggableMap{"error": err.Error()})
			return result, ErrNoLink{Name: names[0], Node: nd.Cid()}
		} else if err != nil {
			evt.Append(logging.LoggableMap{"error": err.Error()})
			return result, err
		}

		nextnode, err := lnk.GetNode(ctx, r.DAG)
		if err != nil {
			evt.Append(logging.LoggableMap{"error": err.Error()})
			return result, err
		}

		nd = nextnode
		result = append(result, nextnode)
		names = rest
	}
	return result, nil
}
<|endoftext|>


<commit_before>// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0

package filters

import (
	"bytes"
	"fmt"
	"os"
	"os/exec"
	"strings"

	"sigs.k8s.io/kustomize/kyaml/kio"
	"sigs.k8s.io/kustomize/kyaml/kio/kioutil"

	"sigs.k8s.io/kustomize/kyaml/yaml"
)

// ContainerFilter filters Resources using a container image.
// The container must start a process that reads the list of
// input Resources from stdin, reads the Configuration from the env
// API_CONFIG, and writes the filtered Resources to stdout.
// If there is a error or validation failure, the process must exit
// non-zero.
// The full set of environment variables from the parent process
// are passed to the container.
type ContainerFilter struct {
	mountPath string

	// Image is the container image to use to create a container.
	Image string `yaml:"image,omitempty"`

	// Network is the container network to use.
	Network string `yaml:"network,omitempty"`

	// LocalVolume is the volume the container uses.
	LocalVolume string `yaml:"localVolume,omitempty"`

	// Config is the API configuration for the container and passed through the
	// API_CONFIG env var to the container.
	// Typically a Kubernetes style Resource Config.
	Config *yaml.RNode `yaml:"config,omitempty"`

	// args may be specified by tests to override how a container is spawned
	args []string

	checkInput func(string)
}

func (c *ContainerFilter) SetMountPath(path string) {
	c.mountPath = path
}

// GrepFilter implements kio.GrepFilter
func (c *ContainerFilter) Filter(input []*yaml.RNode) ([]*yaml.RNode, error) {
	// get the command to filter the Resources
	cmd, err := c.getCommand()
	if err != nil {
		return nil, err
	}

	in := &bytes.Buffer{}
	out := &bytes.Buffer{}

	// write the input
	err = kio.ByteWriter{
		WrappingApiVersion: kio.ResourceListApiVersion,
		WrappingKind:       kio.ResourceListKind,
		Writer:             in, KeepReaderAnnotations: true, FunctionConfig: c.Config}.Write(input)
	if err != nil {
		return nil, err
	}

	// capture the command stdout for the return value
	r := &kio.ByteReader{Reader: out}

	// do the filtering
	if c.checkInput != nil {
		c.checkInput(in.String())
	}
	cmd.Stdin = in
	cmd.Stdout = out
	if err := cmd.Run(); err != nil {
		return nil, err
	}

	return r.Read()
}

// getArgs returns the command + args to run to spawn the container
func (c *ContainerFilter) getArgs() []string {
	// run the container using docker.  this is simpler than using the docker
	// libraries, and ensures things like auth work the same as if the container
	// was run from the cli.

	network := "none"
	if c.Network != "" {
		network = c.Network
	}

	args := []string{"docker", "run",
		"--rm",                                              // delete the container afterward
		"-i", "-a", "STDIN", "-a", "STDOUT", "-a", "STDERR", // attach stdin, stdout, stderr

		// added security options
		"--network", network,
		"--user", "nobody", // run as nobody
		// don't make fs readonly because things like heredoc rely on writing tmp files
		"--security-opt=no-new-privileges", // don't allow the user to escalate privileges
	}
	// mount the directory containing the function as read-only
	if c.mountPath != "" {
		args = append(args, "-v", fmt.Sprintf("%s:/local/:ro", c.mountPath))
	}

	if c.LocalVolume != "" {
		args = append(args, "--mount", fmt.Sprintf("'type=volume,src=%s,dst=/local/'", c.LocalVolume))
	}

	// export the local environment vars to the container
	for _, pair := range os.Environ() {
		args = append(args, "-e", strings.Split(pair, "=")[0])
	}
	return append(args, c.Image)

}

// getCommand returns a command which will apply the GrepFilter using the container image
func (c *ContainerFilter) getCommand() (*exec.Cmd, error) {
	// encode the filter command API configuration
	cfg := &bytes.Buffer{}
	if err := func() error {
		e := yaml.NewEncoder(cfg)
		defer e.Close()
		// make it fit on a single line
		c.Config.YNode().Style = yaml.FlowStyle
		return e.Encode(c.Config.YNode())
	}(); err != nil {
		return nil, err
	}

	if len(c.args) == 0 {
		c.args = c.getArgs()
	}

	cmd := exec.Command(c.args[0], c.args[1:]...)
	cmd.Stderr = os.Stderr
	cmd.Env = os.Environ()

	// set stderr for err messaging
	return cmd, nil
}

// IsReconcilerFilter filters Resources based on whether or not they are Reconciler Resource.
// Resources with an apiVersion starting with '*.gcr.io', 'gcr.io' or 'docker.io' are considered
// Reconciler Resources.
type IsReconcilerFilter struct {
	// ExcludeReconcilers if set to true, then Reconcilers will be excluded -- e.g.
	// Resources with a reconcile container through the apiVersion (gcr.io prefix) or
	// through the annotations
	ExcludeReconcilers bool `yaml:"excludeReconcilers,omitempty"`

	// IncludeNonReconcilers if set to true, the NonReconciler will be included.
	IncludeNonReconcilers bool `yaml:"includeNonReconcilers,omitempty"`
}

// Filter implements kio.Filter
func (c *IsReconcilerFilter) Filter(inputs []*yaml.RNode) ([]*yaml.RNode, error) {
	var out []*yaml.RNode
	for i := range inputs {
		img, _ := GetContainerName(inputs[i])
		isContainerResource := img != ""
		if isContainerResource && !c.ExcludeReconcilers {
			out = append(out, inputs[i])
		}
		if !isContainerResource && c.IncludeNonReconcilers {
			out = append(out, inputs[i])
		}
	}
	return out, nil
}

// GetContainerName returns the container image for an API if one exists
func GetContainerName(n *yaml.RNode) (string, string) {
	meta, _ := n.GetMeta()

	// path to the function, this will be mounted into the container
	path := meta.Annotations[kioutil.PathAnnotation]

	container := meta.Annotations["config.kubernetes.io/container"]
	if container != "" {
		return container, path
	}

	image, err := n.Pipe(yaml.Lookup("metadata", "configFn", "container", "image"))
	if err != nil || yaml.IsMissingOrNull(image) {
		return "", path
	}
	return image.YNode().Value, path
}
<commit_msg>Make LocalVolume read only<commit_after>// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0

package filters

import (
	"bytes"
	"fmt"
	"os"
	"os/exec"
	"strings"

	"sigs.k8s.io/kustomize/kyaml/kio"
	"sigs.k8s.io/kustomize/kyaml/kio/kioutil"

	"sigs.k8s.io/kustomize/kyaml/yaml"
)

// ContainerFilter filters Resources using a container image.
// The container must start a process that reads the list of
// input Resources from stdin, reads the Configuration from the env
// API_CONFIG, and writes the filtered Resources to stdout.
// If there is a error or validation failure, the process must exit
// non-zero.
// The full set of environment variables from the parent process
// are passed to the container.
type ContainerFilter struct {
	mountPath string

	// Image is the container image to use to create a container.
	Image string `yaml:"image,omitempty"`

	// Network is the container network to use.
	Network string `yaml:"network,omitempty"`

	// LocalVolume is the volume the container uses.
	LocalVolume string `yaml:"localVolume,omitempty"`

	// Config is the API configuration for the container and passed through the
	// API_CONFIG env var to the container.
	// Typically a Kubernetes style Resource Config.
	Config *yaml.RNode `yaml:"config,omitempty"`

	// args may be specified by tests to override how a container is spawned
	args []string

	checkInput func(string)
}

func (c *ContainerFilter) SetMountPath(path string) {
	c.mountPath = path
}

// GrepFilter implements kio.GrepFilter
func (c *ContainerFilter) Filter(input []*yaml.RNode) ([]*yaml.RNode, error) {
	// get the command to filter the Resources
	cmd, err := c.getCommand()
	if err != nil {
		return nil, err
	}

	in := &bytes.Buffer{}
	out := &bytes.Buffer{}

	// write the input
	err = kio.ByteWriter{
		WrappingApiVersion: kio.ResourceListApiVersion,
		WrappingKind:       kio.ResourceListKind,
		Writer:             in, KeepReaderAnnotations: true, FunctionConfig: c.Config}.Write(input)
	if err != nil {
		return nil, err
	}

	// capture the command stdout for the return value
	r := &kio.ByteReader{Reader: out}

	// do the filtering
	if c.checkInput != nil {
		c.checkInput(in.String())
	}
	cmd.Stdin = in
	cmd.Stdout = out
	if err := cmd.Run(); err != nil {
		return nil, err
	}

	return r.Read()
}

// getArgs returns the command + args to run to spawn the container
func (c *ContainerFilter) getArgs() []string {
	// run the container using docker.  this is simpler than using the docker
	// libraries, and ensures things like auth work the same as if the container
	// was run from the cli.

	network := "none"
	if c.Network != "" {
		network = c.Network
	}

	args := []string{"docker", "run",
		"--rm",                                              // delete the container afterward
		"-i", "-a", "STDIN", "-a", "STDOUT", "-a", "STDERR", // attach stdin, stdout, stderr

		// added security options
		"--network", network,
		"--user", "nobody", // run as nobody
		// don't make fs readonly because things like heredoc rely on writing tmp files
		"--security-opt=no-new-privileges", // don't allow the user to escalate privileges
	}
	// mount the directory containing the function as read-only
	if c.mountPath != "" {
		args = append(args, "-v", fmt.Sprintf("%s:/local/:ro", c.mountPath))
	}

	if c.LocalVolume != "" {
		args = append(args, "--mount", fmt.Sprintf("'type=volume,src=%s,dst=/local/:ro'", c.LocalVolume))
	}

	// export the local environment vars to the container
	for _, pair := range os.Environ() {
		args = append(args, "-e", strings.Split(pair, "=")[0])
	}
	return append(args, c.Image)

}

// getCommand returns a command which will apply the GrepFilter using the container image
func (c *ContainerFilter) getCommand() (*exec.Cmd, error) {
	// encode the filter command API configuration
	cfg := &bytes.Buffer{}
	if err := func() error {
		e := yaml.NewEncoder(cfg)
		defer e.Close()
		// make it fit on a single line
		c.Config.YNode().Style = yaml.FlowStyle
		return e.Encode(c.Config.YNode())
	}(); err != nil {
		return nil, err
	}

	if len(c.args) == 0 {
		c.args = c.getArgs()
	}

	cmd := exec.Command(c.args[0], c.args[1:]...)
	cmd.Stderr = os.Stderr
	cmd.Env = os.Environ()

	// set stderr for err messaging
	return cmd, nil
}

// IsReconcilerFilter filters Resources based on whether or not they are Reconciler Resource.
// Resources with an apiVersion starting with '*.gcr.io', 'gcr.io' or 'docker.io' are considered
// Reconciler Resources.
type IsReconcilerFilter struct {
	// ExcludeReconcilers if set to true, then Reconcilers will be excluded -- e.g.
	// Resources with a reconcile container through the apiVersion (gcr.io prefix) or
	// through the annotations
	ExcludeReconcilers bool `yaml:"excludeReconcilers,omitempty"`

	// IncludeNonReconcilers if set to true, the NonReconciler will be included.
	IncludeNonReconcilers bool `yaml:"includeNonReconcilers,omitempty"`
}

// Filter implements kio.Filter
func (c *IsReconcilerFilter) Filter(inputs []*yaml.RNode) ([]*yaml.RNode, error) {
	var out []*yaml.RNode
	for i := range inputs {
		img, _ := GetContainerName(inputs[i])
		isContainerResource := img != ""
		if isContainerResource && !c.ExcludeReconcilers {
			out = append(out, inputs[i])
		}
		if !isContainerResource && c.IncludeNonReconcilers {
			out = append(out, inputs[i])
		}
	}
	return out, nil
}

// GetContainerName returns the container image for an API if one exists
func GetContainerName(n *yaml.RNode) (string, string) {
	meta, _ := n.GetMeta()

	// path to the function, this will be mounted into the container
	path := meta.Annotations[kioutil.PathAnnotation]

	container := meta.Annotations["config.kubernetes.io/container"]
	if container != "" {
		return container, path
	}

	image, err := n.Pipe(yaml.Lookup("metadata", "configFn", "container", "image"))
	if err != nil || yaml.IsMissingOrNull(image) {
		return "", path
	}
	return image.YNode().Value, path
}
<|endoftext|>


<commit_before>package autorest

import (
	"fmt"
)

const (
	major        = "7"
	minor        = "3"
	patch        = "1"
	tag          = ""
	semVerFormat = "%s.%s.%s%s"
)

var version string

// Version returns the semantic version (see http://semver.org).
func Version() string {
	if version == "" {
		version = fmt.Sprintf(semVerFormat, major, minor, patch, tag)
	}
	return version
}
<commit_msg>Fixing a personal nit in the Version() function.<commit_after>package autorest

import (
	"bytes"
	"fmt"
	"strings"
)

const (
	major = 7
	minor = 3
	patch = 1
	tag   = ""
)

var version string

// Version returns the semantic version (see http://semver.org).
func Version() string {
	if version == "" {
		verBuilder := bytes.NewBufferString(fmt.Sprintf("%d.%d.%d", major, minor, patch))
		if tag != "" && tag != "-" {
			updated := strings.TrimPrefix(tag, "-")
			verBuilder.WriteRune('-')
			verBuilder.WriteString(updated)
		}
		version = verBuilder.String()
	}
	return version
}
<|endoftext|>


<commit_before>/*
Copyright 2020 Gravitational, Inc.

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 scp

import (
	"os"
	"syscall"
	"time"
)

// Source: os/stat_darwin.go
func atime(fi os.FileInfo) time.Time {
	return timespecToTime(fi.Sys().(*syscall.Stat_t).Atimespec)
}

func timespecToTime(ts syscall.Timespec) time.Time {
	return time.Unix(int64(ts.Sec), int64(ts.Nsec))
}
<commit_msg>Suppress linter warning about unnecessary type conversion on darwin. (#5302)<commit_after>/*
Copyright 2020 Gravitational, Inc.

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 scp

import (
	"os"
	"syscall"
	"time"
)

// Source: os/stat_darwin.go
func atime(fi os.FileInfo) time.Time {
	return timespecToTime(fi.Sys().(*syscall.Stat_t).Atimespec)
}

func timespecToTime(ts syscall.Timespec) time.Time {
	return time.Unix(int64(ts.Sec), int64(ts.Nsec)) //nolint:unconvert
}
<|endoftext|>


<commit_before>package listmap

import (
	"bytes"
	"fmt"
	"math/rand"
	"sync"
	"testing"
	"time"
)

const N = 1 << 11

func assertOrder(l *Listmap) bool {
	prev := []byte{}
	for c := l.NewCursor(); c != nil; c = c.Next() {
		if bytes.Compare(c.Key(), prev) < 0 {
			return false
		}
	}

	return true
}

func assertZeroMissingKeys(l *Listmap) bool {
	i := 0
	for c := l.NewCursor(); c != nil; c = c.Next() {
		expectedKey := []byte(fmt.Sprintf("%020d", i))
		if bytes.Compare(c.Key(), expectedKey) != 0 {
			return false
		}

		i++
	}

	return true
}

func checkError(err error, t *testing.T) {
	if err != nil {
		t.Error(err)
	}
}

func Test1(t *testing.T) {
	t.Parallel()
	l := NewListmap("test.1")

	checkError(l.Set([]byte("1"), []byte("bar")), t)
	checkError(l.Set([]byte("2"), []byte("foobar")), t)
	checkError(l.Set([]byte("3"), []byte("barbaz")), t)
	checkError(l.Set([]byte("4"), []byte("b")), t)
	checkError(l.Set([]byte("45"), []byte("foo")), t)

	if !assertOrder(l) {
		t.Error("keys were not in order")
	}

	l.Destroy()
}

func Test2(t *testing.T) {
	t.Parallel()
	l := NewListmap("test.2")

	checkError(l.Set([]byte("a"), []byte("AAAAA")), t)
	checkError(l.Set([]byte("c"), []byte("CCCCC")), t)
	checkError(l.Set([]byte("b"), []byte("BBBBB")), t)

	if !assertOrder(l) {
		t.Error("keys were not in order")
	}

	l.Destroy()
}

func Test3(t *testing.T) {
	t.Parallel()
	l := NewListmap("test.3")

	checkError(l.Set([]byte("1"), []byte("AAAAA")), t)
	checkError(l.Set([]byte("3"), []byte("CCCCC")), t)
	checkError(l.Set([]byte("2"), []byte("BBBBB")), t)
	checkError(l.Set([]byte("0"), []byte("00000")), t)

	if !assertOrder(l) {
		t.Error("keys were not in order")
	}

	l.Destroy()
}

func TestRemove(t *testing.T) {
	t.Parallel()
	l := NewListmap("test.remove")

	checkError(l.Set([]byte("foo"), []byte("bar")), t)
	val, err := l.Get([]byte("foo"))
	if err != nil {
		t.Error(err)
	}

	if bytes.Compare(val, []byte("bar")) != 0 {
		t.Errorf("expected value to be %v, got %v", []byte("bar"), val)
	}

	l.Remove([]byte("foo"))

	val, err = l.Get([]byte("foo"))
	if err != ErrKeyNotFound {
		t.Errorf("expected error `%v', got %v", ErrKeyNotFound, err)
	}

	if bytes.Compare(val, nil) != 0 {
		t.Errorf("expected value to be %v, got %v", nil, val)
	}

	checkError(l.Set([]byte("foo"), []byte("baz")), t)
	val, err = l.Get([]byte("foo"))
	if err != nil {
		t.Error(err)
	}

	if bytes.Compare(val, []byte("baz")) != 0 {
		t.Errorf("expected value to be %v, got %v", []byte("baz"), val)
	}

	l.Destroy()
}

func TestSequentialShort(t *testing.T) {
	l := NewListmap("test.sequential_short")

	start := time.Now()
	for i := 0; i < N; i++ {
		l.Set([]byte(fmt.Sprintf("%09d", i)), []byte(fmt.Sprint(i)))
	}
	t.Log("Time to insert", N, "sequential integers:", time.Now().Sub(start))

	if !assertOrder(l) {
		t.Error("keys were not in order")
	}

	l.Close()
}

func TestSequentialLong(t *testing.T) {
	t.Parallel()
	l := NewListmap("test.sequential_long")

	start := time.Now()
	for i := 0; i < N*8; i++ {
		checkError(l.Set([]byte(fmt.Sprintf("%09d", i)), []byte(fmt.Sprint(i))), t)
	}
	t.Log("Time to insert", N*8, "sequential integers:", time.Now().Sub(start))

	if !assertOrder(l) {
		t.Error("keys were not in order")
	}

	l.Destroy()
}

func TestRead(t *testing.T) {
	l := OpenListmap("test.sequential_short")
	if l == nil {
		t.Error("Couldn't open list")
	}

	if val, err := l.Get([]byte("000000005")); err != nil || bytes.Compare(val, []byte("5")) != 0 {
		if err != nil {
			t.Error(err)
		} else {
			t.Errorf("expected value %v, got %v", []byte("5"), val)
		}
	}

	if val, err := l.Get([]byte("000000013")); err != nil || bytes.Compare(val, []byte("13")) != 0 {
		if err != nil {
			t.Error(err)
		} else {
			t.Errorf("expected value %v, got %v", []byte("13"), val)
		}
	}

	if val, err := l.Get([]byte("5")); err == nil {
		t.Errorf("expected error `%v', got %v with value `%v'", ErrKeyNotFound,
			nil, val)
	}

	if !assertOrder(l) {
		t.Error("keys were not in order")
	}

	l.Destroy()
}

func TestRandomShort(t *testing.T) {
	t.Parallel()
	l := NewListmap("test.random_short")

	start := time.Now()
	for i := 0; i < N; i++ {
		checkError(l.Set([]byte(fmt.Sprint(rand.Int())), []byte(fmt.Sprint(i))), t)
	}
	t.Log("Time to insert", N, "random integers:", time.Now().Sub(start))

	if !assertOrder(l) {
		t.Error("keys were not in order")
	}

	l.Destroy()
}

func TestRandomLong(t *testing.T) {
	t.Parallel()
	l := NewListmap("test.random_long")

	start := time.Now()
	for i := 0; i < N*8; i++ {
		checkError(l.Set([]byte(fmt.Sprint(rand.Int())), []byte(fmt.Sprint(i))), t)
	}
	t.Log("Time to insert", N*8, "random integers:", time.Now().Sub(start))

	if !assertOrder(l) {
		t.Error("keys were not in order")
	}

	l.Destroy()
}

func TestConcurrentSequential(t *testing.T) {
	t.Parallel()
	l := NewListmap("test.concurrent_sequential")
	var wg sync.WaitGroup

	run := func(l *Listmap, n int) {
		defer wg.Done()
		for i := 0; i < N*4; i++ {
			if i%10 == n {
				checkError(l.Set([]byte(fmt.Sprintf("%020d", i)), []byte(fmt.Sprint(i))), t)
			}
		}
	}

	for i := 0; i < 10; i++ {
		wg.Add(1)
		go run(l, i)
	}

	wg.Wait()

	if !assertOrder(l) {
		t.Error("keys were not in order")
	}

	if !assertZeroMissingKeys(l) {
		t.Error("there are missing keys")
	}

	l.Destroy()
}

func TestConcurrentSequential2(t *testing.T) {
	t.Parallel()
	rand.Seed(time.Now().Unix())
	l := NewListmap("test.concurrent_sequential_2")
	var wg sync.WaitGroup

	run := func(l *Listmap, n int) {
		defer wg.Done()
		for i := 0; i < N*4; i++ {
			if rand.Float32() < 0.85 {
				l.Set([]byte(fmt.Sprintf("%020d", i)), []byte(fmt.Sprint(i)))
			}
		}
	}

	for i := 0; i < 10; i++ {
		wg.Add(1)
		go run(l, i)
	}

	wg.Wait()

	if !assertOrder(l) {
		t.Error("keys were not in order")
	}

	if !assertZeroMissingKeys(l) {
		t.Error("there are missing keys")
	}

	l.Destroy()
}

func TestConcurrentRandom(t *testing.T) {
	t.Parallel()
	l := NewListmap("test.concurrent_random")
	var wg sync.WaitGroup

	run := func(l *Listmap, n int) {
		defer wg.Done()
		for i := 0; i < N*4; i++ {
			if i%10 == n {
				checkError(l.Set([]byte(fmt.Sprint(rand.Int())), []byte(fmt.Sprint(i))), t)
			}
		}
	}

	for i := 0; i < 10; i++ {
		wg.Add(1)
		go run(l, i)
	}

	wg.Wait()

	if !assertOrder(l) {
		t.Error("keys were not in order")
	}

	l.Destroy()
}

func BenchmarkSequentialWrites(b *testing.B) {
	l := NewListmap("benchmark.sequential")

	for i := 0; i < b.N; i++ {
		l.Set([]byte(fmt.Sprintf("%020d", i)), []byte(fmt.Sprint(i)))
	}

	l.Destroy()
}

func BenchmarkRandomWrites(b *testing.B) {
	l := NewListmap("benchmark.sequential")

	for i := 0; i < b.N; i++ {
		l.Set([]byte(fmt.Sprint(rand.Int())), []byte(fmt.Sprint(i)))
	}

	l.Destroy()
}

func BenchmarkSequentialWritesWithVerification(b *testing.B) {
	l := NewListmap("benchmark.sequential")

	for i := 0; i < b.N; i++ {
		l.Set([]byte(fmt.Sprintf("%020d", i)), []byte(fmt.Sprint(i)))
	}

	if !assertOrder(l) {
		b.Error("keys were not in order")
	}

	l.Destroy()
}

func BenchmarkRandomWritesWithVerification(b *testing.B) {
	l := NewListmap("benchmark.sequential")

	for i := 0; i < b.N; i++ {
		l.Set([]byte(fmt.Sprint(rand.Int())), []byte(fmt.Sprint(i)))
	}

	if !assertOrder(l) {
		b.Error("keys were not in order")
	}

	l.Destroy()
}
<commit_msg>Fix test file names<commit_after>package listmap

import (
	"bytes"
	"fmt"
	"math/rand"
	"sync"
	"testing"
	"time"
)

const N = 1 << 11

func assertOrder(l *Listmap) bool {
	prev := []byte{}
	for c := l.NewCursor(); c != nil; c = c.Next() {
		if bytes.Compare(c.Key(), prev) < 0 {
			return false
		}
	}

	return true
}

func assertZeroMissingKeys(l *Listmap) bool {
	i := 0
	for c := l.NewCursor(); c != nil; c = c.Next() {
		expectedKey := []byte(fmt.Sprintf("%020d", i))
		if bytes.Compare(c.Key(), expectedKey) != 0 {
			return false
		}

		i++
	}

	return true
}

func checkError(err error, t *testing.T) {
	if err != nil {
		t.Error(err)
	}
}

func Test1(t *testing.T) {
	t.Parallel()
	l := NewListmap("test.1")

	checkError(l.Set([]byte("1"), []byte("bar")), t)
	checkError(l.Set([]byte("2"), []byte("foobar")), t)
	checkError(l.Set([]byte("3"), []byte("barbaz")), t)
	checkError(l.Set([]byte("4"), []byte("b")), t)
	checkError(l.Set([]byte("45"), []byte("foo")), t)

	if !assertOrder(l) {
		t.Error("keys were not in order")
	}

	l.Destroy()
}

func Test2(t *testing.T) {
	t.Parallel()
	l := NewListmap("test.2")

	checkError(l.Set([]byte("a"), []byte("AAAAA")), t)
	checkError(l.Set([]byte("c"), []byte("CCCCC")), t)
	checkError(l.Set([]byte("b"), []byte("BBBBB")), t)

	if !assertOrder(l) {
		t.Error("keys were not in order")
	}

	l.Destroy()
}

func Test3(t *testing.T) {
	t.Parallel()
	l := NewListmap("test.3")

	checkError(l.Set([]byte("1"), []byte("AAAAA")), t)
	checkError(l.Set([]byte("3"), []byte("CCCCC")), t)
	checkError(l.Set([]byte("2"), []byte("BBBBB")), t)
	checkError(l.Set([]byte("0"), []byte("00000")), t)

	if !assertOrder(l) {
		t.Error("keys were not in order")
	}

	l.Destroy()
}

func TestRemove(t *testing.T) {
	t.Parallel()
	l := NewListmap("test.remove")

	checkError(l.Set([]byte("foo"), []byte("bar")), t)
	val, err := l.Get([]byte("foo"))
	if err != nil {
		t.Error(err)
	}

	if bytes.Compare(val, []byte("bar")) != 0 {
		t.Errorf("expected value to be %v, got %v", []byte("bar"), val)
	}

	l.Remove([]byte("foo"))

	val, err = l.Get([]byte("foo"))
	if err != ErrKeyNotFound {
		t.Errorf("expected error `%v', got %v", ErrKeyNotFound, err)
	}

	if bytes.Compare(val, nil) != 0 {
		t.Errorf("expected value to be %v, got %v", nil, val)
	}

	checkError(l.Set([]byte("foo"), []byte("baz")), t)
	val, err = l.Get([]byte("foo"))
	if err != nil {
		t.Error(err)
	}

	if bytes.Compare(val, []byte("baz")) != 0 {
		t.Errorf("expected value to be %v, got %v", []byte("baz"), val)
	}

	l.Destroy()
}

func TestSequentialShort(t *testing.T) {
	l := NewListmap("test.sequential_short")

	start := time.Now()
	for i := 0; i < N; i++ {
		l.Set([]byte(fmt.Sprintf("%09d", i)), []byte(fmt.Sprint(i)))
	}
	t.Log("Time to insert", N, "sequential integers:", time.Now().Sub(start))

	if !assertOrder(l) {
		t.Error("keys were not in order")
	}

	l.Close()
}

func TestSequentialLong(t *testing.T) {
	t.Parallel()
	l := NewListmap("test.sequential_long")

	start := time.Now()
	for i := 0; i < N*8; i++ {
		checkError(l.Set([]byte(fmt.Sprintf("%09d", i)), []byte(fmt.Sprint(i))), t)
	}
	t.Log("Time to insert", N*8, "sequential integers:", time.Now().Sub(start))

	if !assertOrder(l) {
		t.Error("keys were not in order")
	}

	l.Destroy()
}

func TestRead(t *testing.T) {
	l := OpenListmap("test.sequential_short")
	if l == nil {
		t.Error("Couldn't open list")
	}

	if val, err := l.Get([]byte("000000005")); err != nil || bytes.Compare(val, []byte("5")) != 0 {
		if err != nil {
			t.Error(err)
		} else {
			t.Errorf("expected value %v, got %v", []byte("5"), val)
		}
	}

	if val, err := l.Get([]byte("000000013")); err != nil || bytes.Compare(val, []byte("13")) != 0 {
		if err != nil {
			t.Error(err)
		} else {
			t.Errorf("expected value %v, got %v", []byte("13"), val)
		}
	}

	if val, err := l.Get([]byte("5")); err == nil {
		t.Errorf("expected error `%v', got %v with value `%v'", ErrKeyNotFound,
			nil, val)
	}

	if !assertOrder(l) {
		t.Error("keys were not in order")
	}

	l.Destroy()
}

func TestRandomShort(t *testing.T) {
	t.Parallel()
	l := NewListmap("test.random_short")

	start := time.Now()
	for i := 0; i < N; i++ {
		checkError(l.Set([]byte(fmt.Sprint(rand.Int())), []byte(fmt.Sprint(i))), t)
	}
	t.Log("Time to insert", N, "random integers:", time.Now().Sub(start))

	if !assertOrder(l) {
		t.Error("keys were not in order")
	}

	l.Destroy()
}

func TestRandomLong(t *testing.T) {
	t.Parallel()
	l := NewListmap("test.random_long")

	start := time.Now()
	for i := 0; i < N*8; i++ {
		checkError(l.Set([]byte(fmt.Sprint(rand.Int())), []byte(fmt.Sprint(i))), t)
	}
	t.Log("Time to insert", N*8, "random integers:", time.Now().Sub(start))

	if !assertOrder(l) {
		t.Error("keys were not in order")
	}

	l.Destroy()
}

func TestConcurrentSequential(t *testing.T) {
	t.Parallel()
	l := NewListmap("test.concurrent_sequential")
	var wg sync.WaitGroup

	run := func(l *Listmap, n int) {
		defer wg.Done()
		for i := 0; i < N*4; i++ {
			if i%10 == n {
				checkError(l.Set([]byte(fmt.Sprintf("%020d", i)), []byte(fmt.Sprint(i))), t)
			}
		}
	}

	for i := 0; i < 10; i++ {
		wg.Add(1)
		go run(l, i)
	}

	wg.Wait()

	if !assertOrder(l) {
		t.Error("keys were not in order")
	}

	if !assertZeroMissingKeys(l) {
		t.Error("there are missing keys")
	}

	l.Destroy()
}

func TestConcurrentSequential2(t *testing.T) {
	t.Parallel()
	rand.Seed(time.Now().Unix())
	l := NewListmap("test.concurrent_sequential_2")
	var wg sync.WaitGroup

	run := func(l *Listmap, n int) {
		defer wg.Done()
		for i := 0; i < N*4; i++ {
			if rand.Float32() < 0.85 {
				l.Set([]byte(fmt.Sprintf("%020d", i)), []byte(fmt.Sprint(i)))
			}
		}
	}

	for i := 0; i < 10; i++ {
		wg.Add(1)
		go run(l, i)
	}

	wg.Wait()

	if !assertOrder(l) {
		t.Error("keys were not in order")
	}

	if !assertZeroMissingKeys(l) {
		t.Error("there are missing keys")
	}

	l.Destroy()
}

func TestConcurrentRandom(t *testing.T) {
	t.Parallel()
	l := NewListmap("test.concurrent_random")
	var wg sync.WaitGroup

	run := func(l *Listmap, n int) {
		defer wg.Done()
		for i := 0; i < N*4; i++ {
			if i%10 == n {
				checkError(l.Set([]byte(fmt.Sprint(rand.Int())), []byte(fmt.Sprint(i))), t)
			}
		}
	}

	for i := 0; i < 10; i++ {
		wg.Add(1)
		go run(l, i)
	}

	wg.Wait()

	if !assertOrder(l) {
		t.Error("keys were not in order")
	}

	l.Destroy()
}

func BenchmarkSequentialWrites(b *testing.B) {
	l := NewListmap("benchmark.sequential")

	for i := 0; i < b.N; i++ {
		l.Set([]byte(fmt.Sprintf("%020d", i)), []byte(fmt.Sprint(i)))
	}

	l.Destroy()
}

func BenchmarkRandomWrites(b *testing.B) {
	l := NewListmap("benchmark.random")

	for i := 0; i < b.N; i++ {
		l.Set([]byte(fmt.Sprint(rand.Int())), []byte(fmt.Sprint(i)))
	}

	l.Destroy()
}

func BenchmarkSequentialWritesWithVerification(b *testing.B) {
	l := NewListmap("benchmark.sequential_verify")

	for i := 0; i < b.N; i++ {
		l.Set([]byte(fmt.Sprintf("%020d", i)), []byte(fmt.Sprint(i)))
	}

	if !assertOrder(l) {
		b.Error("keys were not in order")
	}

	l.Destroy()
}

func BenchmarkRandomWritesWithVerification(b *testing.B) {
	l := NewListmap("benchmark.random_verify")

	for i := 0; i < b.N; i++ {
		l.Set([]byte(fmt.Sprint(rand.Int())), []byte(fmt.Sprint(i)))
	}

	if !assertOrder(l) {
		b.Error("keys were not in order")
	}

	l.Destroy()
}
<|endoftext|>


<commit_before>package vagrant

import (
	"fmt"

	"github.com/hashicorp/terraform/helper/schema"
)

func resourceVagrantVm() *schema.Resource {
	return &schema.Resource{
		Create: resourceVagrantVmCreate,
		Read:   resourceVagrantVmRead,
		Update: resourceVagrantVmUpdate,
		Delete: resourceVagrantVmDelete,

		Schema: map[string]*schema.Schema{
			"boot_timeout": &schema.Schema{
				Type:        schema.TypeInt,
				Optional:    true,
				Computed:    true,
				Description: "The time in seconds that Vagrant will wait for the machine to boot.",
			},
			"box": &schema.Schema{
				Type:        schema.TypeString,
				Optional:    true,
				Description: "Installed box name or Atlas box shorthand name to use.",
			},
			"box_check_update": &schema.Schema{
				Type:        schema.TypeBool,
				Optional:    true,
				Computed:    true,
				Description: "Whether or not to check for updates to the box on each `vagrant up`.",
			},
			"box_download_checksum": &schema.Schema{
				Type:        schema.TypeString,
				Optional:    true,
				Description: "The expected checksum of the box file.",
			},
			"box_download_checksum_type": &schema.Schema{
				Type:        schema.TypeString,
				Optional:    true,
				Description: "The type of checksum specified by `box_download_checksum`. Should be `md5`, `sha1`, or `sha256`.",
				ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
					value := v.(string)
					valid_values := []string{"md5", "sha1", "sha256"}

					for _, valid_value := range valid_values {
						if value == valid_value {
							return
						}
					}

					errors = append(errors, fmt.Errorf("%q must be one of md5, sha1, or sha256", k))

					return
				},
			},
			"box_url": &schema.Schema{
				Type:        schema.TypeString,
				Optional:    true,
				Description: "The URL to download the box.",
			},
			"box_version": &schema.Schema{
				Type:        schema.TypeString,
				Optional:    true,
				Description: "The version of the box to use.",
			},
			"hostname": &schema.Schema{
				Type:        schema.TypeString,
				Optional:    true,
				Description: "The hostname the machine should have.",
			},
			"forwarded_port": &schema.Schema{
				Type:     schema.TypeSet,
				Optional: true,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"auto_correct": &schema.Schema{
							Type:        schema.TypeBool,
							Optional:    true,
							Computed:    true,
							Description: "Whether or not to automatically resolve port collisions on the host.",
						},
						"guest": &schema.Schema{
							Type:        schema.TypeInt,
							Required:    true,
							Description: "The port on the guest you want to be exposed on the host.",
						},
						"guest_ip": &schema.Schema{
							Type:        schema.TypeInt,
							Optional:    true,
							Computed:    true,
							Description: "The IP the forwarded port should be bound to within the guest.",
						},
						"host": &schema.Schema{
							Type:        schema.TypeInt,
							Required:    true,
							Description: "The port on the host used to access the port on the guest.",
						},
						"host_ip": &schema.Schema{
							Type:        schema.TypeInt,
							Optional:    true,
							Computed:    true,
							Description: "The IP the forwarded port should be bound to on the host.",
						},
						"protocol": &schema.Schema{
							Type:        schema.TypeString,
							Optional:    true,
							Computed:    true,
							Description: "The network protcol to use, one of `tcp` or `udp`.",
						},
					},
				},
				Set: func(v interface{}) int {
					return 0
				},
			},
			"private_network": resourceVagrantVmPublicOrPrivateNetwork(),
			"public_network":  resourceVagrantVmPublicOrPrivateNetwork(),
			"virtualbox_provider": &schema.Schema{
				Type:     schema.TypeSet,
				Optional: true,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"cpus": &schema.Schema{
							Type:        schema.TypeInt,
							Optional:    true,
							Computed:    true,
							Description: "The number of CPUs to give the VM.",
						},
						"customize": &schema.Schema{
							Type:        schema.TypeSet,
							Optional:    true,
							Computed:    true,
							Description: "A call to customize the VM just before it is booted.",
							Elem: &schema.Resource{
								Schema: map[string]*schema.Schema{
									"arguments": &schema.Schema{
										Type:        schema.TypeList,
										Required:    true,
										Description: "The list of arguments for the customization command.",
										Elem: &schema.Schema{
											Type: schema.TypeString,
										},
									},
								},
							},
							Set: func(v interface{}) int {
								return 0
							},
						},
						"gui": &schema.Schema{
							Type:        schema.TypeBool,
							Optional:    true,
							Computed:    true,
							Description: "Whether or not to create a VM with a GUI.",
						},
						"memory": &schema.Schema{
							Type:        schema.TypeInt,
							Optional:    true,
							Computed:    true,
							Description: "The amount of memory to give the VM, in MB.",
						},
						"name": &schema.Schema{
							Type:        schema.TypeString,
							Optional:    true,
							Computed:    true,
							Description: "A custom name for the VM within VirtualBox's GUI app.",
						},
					},
				},
				Set: func(v interface{}) int {
					return 0
				},
			},
		},
	}
}

func resourceVagrantVmCreate(data *schema.ResourceData, meta interface{}) error {
	return nil
}

func resourceVagrantVmRead(data *schema.ResourceData, meta interface{}) error {
	return nil
}

func resourceVagrantVmUpdate(data *schema.ResourceData, meta interface{}) error {
	return nil
}

func resourceVagrantVmDelete(data *schema.ResourceData, meta interface{}) error {
	return nil
}

func resourceVagrantVmPublicOrPrivateNetwork() *schema.Schema {
	return &schema.Schema{
		Type:     schema.TypeSet,
		Optional: true,
		Elem: &schema.Resource{
			Schema: map[string]*schema.Schema{
				"auto_config": &schema.Schema{
					Type:        schema.TypeBool,
					Optional:    true,
					Description: "Whether or not to automatically configure the network interface.",
				},
				"dhcp": &schema.Schema{
					Type:        schema.TypeBool,
					Computed:    true,
					Description: "Whether or not to use DHCP to assign the IP on the host.",
				},
				"ip": &schema.Schema{
					Type:        schema.TypeString,
					Optional:    true,
					Computed:    true,
					Description: "The static IP to assign the interface on the host. Do not set this to use DHCP instead.",
				},
			},
		},
		Set: func(v interface{}) int {
			return 0
		},
	}
}
<commit_msg>Add the remaining VM configuration attributes.<commit_after>package vagrant

import (
	"fmt"

	"github.com/hashicorp/terraform/helper/schema"
)

func resourceVagrantVm() *schema.Resource {
	return &schema.Resource{
		Create: resourceVagrantVmCreate,
		Read:   resourceVagrantVmRead,
		Update: resourceVagrantVmUpdate,
		Delete: resourceVagrantVmDelete,

		Schema: map[string]*schema.Schema{
			"boot_timeout": &schema.Schema{
				Type:        schema.TypeInt,
				Optional:    true,
				Computed:    true,
				Description: "The time in seconds that Vagrant will wait for the machine to boot.",
			},
			"box": &schema.Schema{
				Type:        schema.TypeString,
				Optional:    true,
				Description: "Installed box name or Atlas box shorthand name to use.",
			},
			"box_check_update": &schema.Schema{
				Type:        schema.TypeBool,
				Optional:    true,
				Computed:    true,
				Description: "Whether or not to check for updates to the box on each `vagrant up`.",
			},
			"box_download_checksum": &schema.Schema{
				Type:        schema.TypeString,
				Optional:    true,
				Description: "The expected checksum of the box file.",
			},
			"box_download_checksum_type": &schema.Schema{
				Type:        schema.TypeString,
				Optional:    true,
				Description: "The type of checksum specified by `box_download_checksum`. Should be `md5`, `sha1`, or `sha256`.",
				ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
					value := v.(string)
					valid_values := []string{"md5", "sha1", "sha256"}

					for _, valid_value := range valid_values {
						if value == valid_value {
							return
						}
					}

					errors = append(errors, fmt.Errorf("%q must be one of md5, sha1, or sha256", k))

					return
				},
			},
			"box_download_client_cert": &schema.Schema{
				Type:        schema.TypeString,
				Optional:    true,
				Description: "Path to a client certificate to use.",
			},
			"box_download_ca_cert": &schema.Schema{
				Type:        schema.TypeString,
				Optional:    true,
				Description: "Path to a certificate authority certificate bundle to use.",
			},
			"box_download_ca_path": &schema.Schema{
				Type:        schema.TypeString,
				Optional:    true,
				Description: "Path to a directory containing certificate authority certificates to use.",
			},
			"box_download_insecure": &schema.Schema{
				Type:        schema.TypeBool,
				Optional:    true,
				Description: "Whether or not to skip verification of digital certificates.",
			},
			"box_download_location_trusted": &schema.Schema{
				Type:        schema.TypeBool,
				Optional:    true,
				Description: "Whether or not to allow authentication credentials to be used for subsequent HTTP requests when redirected.",
			},
			"box_url": &schema.Schema{
				Type:        schema.TypeString,
				Optional:    true,
				Description: "The URL to download the box.",
			},
			"box_version": &schema.Schema{
				Type:        schema.TypeString,
				Optional:    true,
				Description: "The version of the box to use.",
			},
			"communicator": &schema.Schema{
				Type:        schema.TypeString,
				Optional:    true,
				Description: "How to connect to the guest box.",
				ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
					value := v.(string)

					if value == "ssh" || value == "winrm" {
						return
					}

					errors = append(errors, fmt.Errorf("%q must be ssh or winrm", k))

					return
				},
			},
			"graceful_halt_timeout": &schema.Schema{
				Type:        schema.TypeInt,
				Optional:    true,
				Description: "The time in seconds to wait when `vagrant halt` is called.",
			},
			"guest": &schema.Schema{
				Type:        schema.TypeString,
				Optional:    true,
				Description: "The operating system that will be running in the guest box.",
			},
			"hostname": &schema.Schema{
				Type:        schema.TypeString,
				Optional:    true,
				Description: "The hostname the machine should have.",
			},
			"forwarded_port": &schema.Schema{
				Type:     schema.TypeSet,
				Optional: true,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"auto_correct": &schema.Schema{
							Type:        schema.TypeBool,
							Optional:    true,
							Computed:    true,
							Description: "Whether or not to automatically resolve port collisions on the host.",
						},
						"guest": &schema.Schema{
							Type:        schema.TypeInt,
							Required:    true,
							Description: "The port on the guest you want to be exposed on the host.",
						},
						"guest_ip": &schema.Schema{
							Type:        schema.TypeInt,
							Optional:    true,
							Computed:    true,
							Description: "The IP the forwarded port should be bound to within the guest.",
						},
						"host": &schema.Schema{
							Type:        schema.TypeInt,
							Required:    true,
							Description: "The port on the host used to access the port on the guest.",
						},
						"host_ip": &schema.Schema{
							Type:        schema.TypeInt,
							Optional:    true,
							Computed:    true,
							Description: "The IP the forwarded port should be bound to on the host.",
						},
						"protocol": &schema.Schema{
							Type:        schema.TypeString,
							Optional:    true,
							Computed:    true,
							Description: "The network protcol to use, one of `tcp` or `udp`.",
						},
					},
				},
				Set: func(v interface{}) int {
					return 0
				},
			},
			"post_up_message": &schema.Schema{
				Type:        schema.TypeString,
				Optional:    true,
				Description: "A message to display after `vagrant up` completes.",
			},
			"private_network": resourceVagrantVmPublicOrPrivateNetwork(),
			"public_network":  resourceVagrantVmPublicOrPrivateNetwork(),
			"usable_port_range_lower_bound": &schema.Schema{
				Type:        schema.TypeInt,
				Optional:    true,
				Description: "The lower end (inclusive) of the port range to use for handling port collisions.",
			},
			"usable_port_range_upper_bound": &schema.Schema{
				Type:        schema.TypeInt,
				Optional:    true,
				Description: "The upper end (inclusive) of the port range to use for handling port collisions.",
			},
			"virtualbox_provider": &schema.Schema{
				Type:     schema.TypeSet,
				Optional: true,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"cpus": &schema.Schema{
							Type:        schema.TypeInt,
							Optional:    true,
							Computed:    true,
							Description: "The number of CPUs to give the VM.",
						},
						"customize": &schema.Schema{
							Type:        schema.TypeSet,
							Optional:    true,
							Computed:    true,
							Description: "A call to customize the VM just before it is booted.",
							Elem: &schema.Resource{
								Schema: map[string]*schema.Schema{
									"arguments": &schema.Schema{
										Type:        schema.TypeList,
										Required:    true,
										Description: "The list of arguments for the customization command.",
										Elem: &schema.Schema{
											Type: schema.TypeString,
										},
									},
								},
							},
							Set: func(v interface{}) int {
								return 0
							},
						},
						"gui": &schema.Schema{
							Type:        schema.TypeBool,
							Optional:    true,
							Computed:    true,
							Description: "Whether or not to create a VM with a GUI.",
						},
						"memory": &schema.Schema{
							Type:        schema.TypeInt,
							Optional:    true,
							Computed:    true,
							Description: "The amount of memory to give the VM, in MB.",
						},
						"name": &schema.Schema{
							Type:        schema.TypeString,
							Optional:    true,
							Computed:    true,
							Description: "A custom name for the VM within VirtualBox's GUI app.",
						},
					},
				},
				Set: func(v interface{}) int {
					return 0
				},
			},
		},
	}
}

func resourceVagrantVmCreate(data *schema.ResourceData, meta interface{}) error {
	return nil
}

func resourceVagrantVmRead(data *schema.ResourceData, meta interface{}) error {
	return nil
}

func resourceVagrantVmUpdate(data *schema.ResourceData, meta interface{}) error {
	return nil
}

func resourceVagrantVmDelete(data *schema.ResourceData, meta interface{}) error {
	return nil
}

func resourceVagrantVmPublicOrPrivateNetwork() *schema.Schema {
	return &schema.Schema{
		Type:     schema.TypeSet,
		Optional: true,
		Elem: &schema.Resource{
			Schema: map[string]*schema.Schema{
				"auto_config": &schema.Schema{
					Type:        schema.TypeBool,
					Optional:    true,
					Description: "Whether or not to automatically configure the network interface.",
				},
				"dhcp": &schema.Schema{
					Type:        schema.TypeBool,
					Computed:    true,
					Description: "Whether or not to use DHCP to assign the IP on the host.",
				},
				"ip": &schema.Schema{
					Type:        schema.TypeString,
					Optional:    true,
					Computed:    true,
					Description: "The static IP to assign the interface on the host. Do not set this to use DHCP instead.",
				},
			},
		},
		Set: func(v interface{}) int {
			return 0
		},
	}
}
<|endoftext|>


<commit_before>package main

import (
  "encoding/json"
  "fmt"
  "net/http"
  "strconv"
  "github.com/rcrowley/go-tigertonic"
  "github.com/rkbodenner/parallel_universe/collection"
  "github.com/rkbodenner/parallel_universe/game"
  "github.com/rkbodenner/parallel_universe/session"
)

type Player struct {
  Id int `json:"id"`
  Name string `json:"name"`
}

var players = []Player{
  {1, "Player One"},
  {2, "Player Two"},
}

var gameCollection = collection.NewCollection()
var gameIndex = make(map[uint64]*game.Game)

func initGameData() {
  for i,game := range gameCollection.Games {
    game.Id = (uint)(i+1)
    gameIndex[(uint64)(i+1)] = game
  }
}

var sessions []*session.Session
var sessionIndex = make(map[uint64]*session.Session)

func initSessionData() {
  sessions = make([]*session.Session, 2)
  sessions[0] = session.NewSession(gameCollection.Games[0], 2)
  sessions[1] = session.NewSession(gameCollection.Games[1], 2)

  for i,session := range sessions {
    session.Id = (uint)(i+1)
    sessionIndex[(uint64)(i+1)] = session
  }
}

func corsHandler(handler func(http.ResponseWriter, *http.Request)) func(http.ResponseWriter, *http.Request) {
  return func(w http.ResponseWriter, r *http.Request) {
    header := w.Header()
    header.Add("Access-Control-Allow-Origin", "http://localhost:8000")
    handler(w, r)
  }
}

func collectionHandler(w http.ResponseWriter, r *http.Request) {
  err := json.NewEncoder(w).Encode(gameCollection)
  if ( nil != err ) {
    fmt.Fprintln(w, err)
  }
}

func gameHandler(w http.ResponseWriter, r *http.Request) {
  id_str := r.URL.Query().Get("id")
  id, err := strconv.ParseUint(id_str, 10, 64)
  if nil != err {
    http.Error(w, "Not found", http.StatusNotFound)
    return
  }

  game, ok := gameIndex[id]
  if ok {
    err := json.NewEncoder(w).Encode(game)
    if ( nil != err ) {
      http.Error(w, "Error", http.StatusInternalServerError)
    }
  } else {
    http.Error(w, "Not found", http.StatusNotFound)
  }
}

func playersHandler(w http.ResponseWriter, r *http.Request) {
  err := json.NewEncoder(w).Encode(players)
  if ( nil != err ) {
    fmt.Fprintln(w, err)
  }
}

func sessionsHandler(w http.ResponseWriter, r *http.Request) {
  err := json.NewEncoder(w).Encode(sessions)
  if ( nil != err ) {
    http.Error(w, "Error", http.StatusInternalServerError)
  }
}

func sessionHandler(w http.ResponseWriter, r *http.Request) {
  id_str := r.URL.Query().Get("id")
  id, err := strconv.ParseUint(id_str, 10, 64)
  if nil != err {
    http.Error(w, "Not found", http.StatusNotFound)
    return
  }

  session, ok := sessionIndex[id]
  if ok {
    err := json.NewEncoder(w).Encode(session)
    if ( nil != err ) {
      http.Error(w, "Error", http.StatusInternalServerError)
    }
  } else {
    http.Error(w, "Not found", http.StatusNotFound)
  }
}

func main() {
  initGameData()
  initSessionData()

  mux := tigertonic.NewTrieServeMux()
  mux.HandleFunc("GET", "/games", corsHandler(collectionHandler))
  mux.HandleFunc("GET", "/games/{id}", corsHandler(gameHandler))
  mux.HandleFunc("GET", "/players", corsHandler(playersHandler))
  mux.HandleFunc("GET", "/sessions", corsHandler(sessionsHandler))
  mux.HandleFunc("GET", "/sessions/{id}", corsHandler(sessionHandler))
  http.ListenAndServe(":8080", mux)
}
<commit_msg>Use player type from parallel_universe<commit_after>package main

import (
  "encoding/json"
  "fmt"
  "net/http"
  "strconv"
  "github.com/rcrowley/go-tigertonic"
  "github.com/rkbodenner/parallel_universe/collection"
  "github.com/rkbodenner/parallel_universe/game"
  "github.com/rkbodenner/parallel_universe/session"
)

var players = []*game.Player{
  &game.Player{1, "Player One"},
  &game.Player{2, "Player Two"},
}

var gameCollection = collection.NewCollection()
var gameIndex = make(map[uint64]*game.Game)

func initGameData() {
  for i,game := range gameCollection.Games {
    game.Id = (uint)(i+1)
    gameIndex[(uint64)(i+1)] = game
  }
}

var sessions []*session.Session
var sessionIndex = make(map[uint64]*session.Session)

func initSessionData() {
  sessions = make([]*session.Session, 2)
  sessions[0] = session.NewSession(gameCollection.Games[0], 2)
  sessions[1] = session.NewSession(gameCollection.Games[1], 2)

  for i,session := range sessions {
    session.Id = (uint)(i+1)
    sessionIndex[(uint64)(i+1)] = session
  }
}

func corsHandler(handler func(http.ResponseWriter, *http.Request)) func(http.ResponseWriter, *http.Request) {
  return func(w http.ResponseWriter, r *http.Request) {
    header := w.Header()
    header.Add("Access-Control-Allow-Origin", "http://localhost:8000")
    handler(w, r)
  }
}

func collectionHandler(w http.ResponseWriter, r *http.Request) {
  err := json.NewEncoder(w).Encode(gameCollection)
  if ( nil != err ) {
    fmt.Fprintln(w, err)
  }
}

func gameHandler(w http.ResponseWriter, r *http.Request) {
  id_str := r.URL.Query().Get("id")
  id, err := strconv.ParseUint(id_str, 10, 64)
  if nil != err {
    http.Error(w, "Not found", http.StatusNotFound)
    return
  }

  game, ok := gameIndex[id]
  if ok {
    err := json.NewEncoder(w).Encode(game)
    if ( nil != err ) {
      http.Error(w, "Error", http.StatusInternalServerError)
    }
  } else {
    http.Error(w, "Not found", http.StatusNotFound)
  }
}

func playersHandler(w http.ResponseWriter, r *http.Request) {
  err := json.NewEncoder(w).Encode(players)
  if ( nil != err ) {
    fmt.Fprintln(w, err)
  }
}

func sessionsHandler(w http.ResponseWriter, r *http.Request) {
  err := json.NewEncoder(w).Encode(sessions)
  if ( nil != err ) {
    http.Error(w, "Error", http.StatusInternalServerError)
  }
}

func sessionHandler(w http.ResponseWriter, r *http.Request) {
  id_str := r.URL.Query().Get("id")
  id, err := strconv.ParseUint(id_str, 10, 64)
  if nil != err {
    http.Error(w, "Not found", http.StatusNotFound)
    return
  }

  session, ok := sessionIndex[id]
  if ok {
    err := json.NewEncoder(w).Encode(session)
    if ( nil != err ) {
      http.Error(w, "Error", http.StatusInternalServerError)
    }
  } else {
    http.Error(w, "Not found", http.StatusNotFound)
  }
}

func main() {
  initGameData()
  initSessionData()

  mux := tigertonic.NewTrieServeMux()
  mux.HandleFunc("GET", "/games", corsHandler(collectionHandler))
  mux.HandleFunc("GET", "/games/{id}", corsHandler(gameHandler))
  mux.HandleFunc("GET", "/players", corsHandler(playersHandler))
  mux.HandleFunc("GET", "/sessions", corsHandler(sessionsHandler))
  mux.HandleFunc("GET", "/sessions/{id}", corsHandler(sessionHandler))
  http.ListenAndServe(":8080", mux)
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"html/template"
	"path"
	"path/filepath"
	"strings"
	"sync"

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

const (
	// defaultTitle is the site pages default title.
	defaultTitle = "Google I/O 2015"
	// descDefault is the default site description
	descDefault = "Google I/O 2015 brings together developers for an immersive, " +
		"two-day experience focused on exploring the next generation " +
		"of technology, mobile and beyond. Join us online or in person " +
		"May 28-29, 2015."
	// descExperiment is used when users share an experiment link on social.
	descExperiment = "Make music with instruments inspired by material design " +
		"for Google I/O 2015. Play, record and share."
	// images for og:image meta tag
	ogImageDefault    = "io15-color.png"
	ogImageExperiment = "io15-experiment.png"

	// layout for templateData.StartDateStr
	timeISO8601 = "Jan 02 2006 15:04:05 GMT-0700 (MST)"

	// templatesDir is the templates directory path relative to config.Dir.
	templatesDir = "templates"
)

var (
	// tmplFunc is a map of functions available to all templates.
	tmplFunc = template.FuncMap{
		"safeHTML":  func(v string) template.HTML { return template.HTML(v) },
		"canonical": canonicalURL,
	}
	// tmplCache caches HTML templates parsed in parseTemplate()
	tmplCache = &templateCache{templates: make(map[string]*template.Template)}
)

// templateCache is in-memory cache for parsed templates
type templateCache struct {
	sync.Mutex
	templates map[string]*template.Template
}

// templateData is the templates context
type templateData struct {
	Env          string
	ClientID     string
	Prefix       string
	Slug         string
	Title        string
	Desc         string
	OgTitle      string
	OgImage      string
	StartDateStr string
}

// renderTemplate executes a template found in name.html file
// using either layout_full.html or layout_partial.html as the root template.
// env is the app current environment: "dev", "stage" or "prod".
func renderTemplate(c context.Context, name string, partial bool, data *templateData) ([]byte, error) {
	tpl, err := parseTemplate(name, partial)
	if err != nil {
		return nil, err
	}
	if data == nil {
		data = &templateData{}
	}
	if data.Env == "" {
		data.Env = config.Env
	}
	data.ClientID = config.Google.Auth.Client
	data.Title = pageTitle(tpl)
	data.Slug = name
	data.Prefix = config.Prefix
	data.StartDateStr = config.Schedule.Start.In(config.Schedule.Location).Format(timeISO8601)
	if data.Desc == "" {
		data.Desc = descDefault
	}
	if data.OgImage == "" {
		data.OgImage = ogImageDefault
	}
	if data.OgTitle == "" {
		data.OgTitle = data.Title
	}

	var b bytes.Buffer
	if err := tpl.Execute(&b, data); err != nil {
		return nil, err
	}
	return b.Bytes(), nil
}

// parseTemplate creates a template identified by name, using appropriate layout.
// HTTP error layout is used for name arg prefixed with "error_", e.g. "error_404".
func parseTemplate(name string, partial bool) (*template.Template, error) {
	var layout string
	switch {
	case strings.HasPrefix(name, "error_"):
		layout = "layout_error.html"
	case name == "upgrade":
		layout = "layout_bare.html"
	case partial:
		layout = "layout_partial.html"
	default:
		layout = "layout_full.html"
	}

	key := name + layout
	tmplCache.Lock()
	defer tmplCache.Unlock()
	if t, ok := tmplCache.templates[key]; ok {
		return t, nil
	}

	t, err := template.New(layout).Delims("{%", "%}").Funcs(tmplFunc).ParseFiles(
		filepath.Join(config.Dir, templatesDir, layout),
		filepath.Join(config.Dir, templatesDir, name+".html"),
	)
	if err != nil {
		return nil, err
	}
	if !isDev() {
		tmplCache.templates[key] = t
	}
	return t, nil
}

// pageTitle executes "title" template and returns its result or defaultTitle.
func pageTitle(t *template.Template) string {
	b := new(bytes.Buffer)
	if err := t.ExecuteTemplate(b, "title", nil); err != nil || b.Len() == 0 {
		return defaultTitle
	}
	return b.String()
}

// canonicalURL returns a canonical URL of path p.
// Relative paths are based off of config.Prefix.
func canonicalURL(p string) string {
	if p == "home" || p == "/" || p == "" {
		return config.Prefix + "/"
	}
	return path.Join(config.Prefix, p)
}
<commit_msg>Fixes #921<commit_after>package main

import (
	"bytes"
	"html/template"
	"path"
	"path/filepath"
	"strings"
	"sync"

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

const (
	// defaultTitle is the site pages default title.
	defaultTitle = "Google I/O 2015"
	// descDefault is the default site description
	descDefault = "Google I/O 2015 brings together developers for an immersive," +
    " two-day experience focused on exploring the next generation of " +
    "technology, mobile and beyond. Join us online or in person May 28-29, " +
    "2015. #io15"
	// descExperiment is used when users share an experiment link on social.
	descExperiment = "Make music with instruments inspired by material design " +
		"for #io15. Play, record and share."
	// images for og:image meta tag
	ogImageDefault    = "io15-color.png"
	ogImageExperiment = "io15-experiment.png"

	// layout for templateData.StartDateStr
	timeISO8601 = "Jan 02 2006 15:04:05 GMT-0700 (MST)"

	// templatesDir is the templates directory path relative to config.Dir.
	templatesDir = "templates"
)

var (
	// tmplFunc is a map of functions available to all templates.
	tmplFunc = template.FuncMap{
		"safeHTML":  func(v string) template.HTML { return template.HTML(v) },
		"canonical": canonicalURL,
	}
	// tmplCache caches HTML templates parsed in parseTemplate()
	tmplCache = &templateCache{templates: make(map[string]*template.Template)}
)

// templateCache is in-memory cache for parsed templates
type templateCache struct {
	sync.Mutex
	templates map[string]*template.Template
}

// templateData is the templates context
type templateData struct {
	Env          string
	ClientID     string
	Prefix       string
	Slug         string
	Title        string
	Desc         string
	OgTitle      string
	OgImage      string
	StartDateStr string
}

// renderTemplate executes a template found in name.html file
// using either layout_full.html or layout_partial.html as the root template.
// env is the app current environment: "dev", "stage" or "prod".
func renderTemplate(c context.Context, name string, partial bool, data *templateData) ([]byte, error) {
	tpl, err := parseTemplate(name, partial)
	if err != nil {
		return nil, err
	}
	if data == nil {
		data = &templateData{}
	}
	if data.Env == "" {
		data.Env = config.Env
	}
	data.ClientID = config.Google.Auth.Client
	data.Title = pageTitle(tpl)
	data.Slug = name
	data.Prefix = config.Prefix
	data.StartDateStr = config.Schedule.Start.In(config.Schedule.Location).Format(timeISO8601)
	if data.Desc == "" {
		data.Desc = descDefault
	}
	if data.OgImage == "" {
		data.OgImage = ogImageDefault
	}
	if data.OgTitle == "" {
		data.OgTitle = data.Title
	}

	var b bytes.Buffer
	if err := tpl.Execute(&b, data); err != nil {
		return nil, err
	}
	return b.Bytes(), nil
}

// parseTemplate creates a template identified by name, using appropriate layout.
// HTTP error layout is used for name arg prefixed with "error_", e.g. "error_404".
func parseTemplate(name string, partial bool) (*template.Template, error) {
	var layout string
	switch {
	case strings.HasPrefix(name, "error_"):
		layout = "layout_error.html"
	case name == "upgrade":
		layout = "layout_bare.html"
	case partial:
		layout = "layout_partial.html"
	default:
		layout = "layout_full.html"
	}

	key := name + layout
	tmplCache.Lock()
	defer tmplCache.Unlock()
	if t, ok := tmplCache.templates[key]; ok {
		return t, nil
	}

	t, err := template.New(layout).Delims("{%", "%}").Funcs(tmplFunc).ParseFiles(
		filepath.Join(config.Dir, templatesDir, layout),
		filepath.Join(config.Dir, templatesDir, name+".html"),
	)
	if err != nil {
		return nil, err
	}
	if !isDev() {
		tmplCache.templates[key] = t
	}
	return t, nil
}

// pageTitle executes "title" template and returns its result or defaultTitle.
func pageTitle(t *template.Template) string {
	b := new(bytes.Buffer)
	if err := t.ExecuteTemplate(b, "title", nil); err != nil || b.Len() == 0 {
		return defaultTitle
	}
	return b.String()
}

// canonicalURL returns a canonical URL of path p.
// Relative paths are based off of config.Prefix.
func canonicalURL(p string) string {
	if p == "home" || p == "/" || p == "" {
		return config.Prefix + "/"
	}
	return path.Join(config.Prefix, p)
}
<|endoftext|>


<commit_before>package acme

import (
	"errors"
	"io/ioutil"
	"net/http"
	"os/exec"
	"regexp"
	"testing"
	"time"

	"github.com/Sirupsen/logrus"
	"github.com/golang/mock/gomock"
	"github.com/jetstack/kube-lego/pkg/mocks"
	"k8s.io/apimachinery/pkg/util/intstr"
)

func TestAcme_E2E(t *testing.T) {
	logrus.SetLevel(logrus.DebugLevel)
	log := logrus.WithField("context", "test-mock")

	ctrl := gomock.NewController(t)
	defer ctrl.Finish()
	// mock kube lego
	mockKL := mocks.NewMockKubeLego(ctrl)
	mockKL.EXPECT().Log().AnyTimes().Return(log)
	mockKL.EXPECT().Version().AnyTimes().Return("mocked-version")
	mockKL.EXPECT().LegoHTTPPort().AnyTimes().Return(intstr.FromInt(8181))
	mockKL.EXPECT().AcmeUser().MinTimes(1).Return(nil, errors.New("I am only mocked"))
	mockKL.EXPECT().LegoURL().MinTimes(1).Return("https://acme-staging.api.letsencrypt.org/directory")
	mockKL.EXPECT().LegoEmail().MinTimes(1).Return("kube-lego-e2e@example.com")
	mockKL.EXPECT().SaveAcmeUser(gomock.Any()).MinTimes(1).Return(nil)
	mockKL.EXPECT().LegoRsaKeySize().AnyTimes().Return(2048)
	mockKL.EXPECT().ExponentialBackoffMaxElapsedTime().MinTimes(1).Return(time.Minute * 5)
	mockKL.EXPECT().ExponentialBackoffInitialInterval().MinTimes(1).Return(time.Second * 30)
	mockKL.EXPECT().ExponentialBackoffMultiplier().MinTimes(1).Return(2.0)

	// set up ngrok
	command := []string{"ngrok", "http", "--bind-tls", "false", "8181"}
	cmdNgrok := exec.Command(command[0], command[1:]...)
	err := cmdNgrok.Start()
	if err != nil {
		t.Skip("Skipping e2e test as ngrok executable is not available: ", err)
	}
	defer cmdNgrok.Process.Kill()

	// get domain main for forwarding the acme validation
	regexDomain := regexp.MustCompile("http://([a-z0-9]+.\\.ngrok\\.io)")
	var domain string
	for {
		time.Sleep(100 * time.Millisecond)
		resp, err := http.Get("http://localhost:4040/status")
		if err != nil {
			log.Warn(err)
			continue
		}
		defer resp.Body.Close()

		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			log.Warn(err)
			continue
		}

		matched := regexDomain.FindStringSubmatch(string(body))
		if matched == nil {
			continue
		}

		domain = matched[1]
		log.Infof("kube-lego domain is %s", domain)

		break
	}

	stopCh := make(chan struct{})
	a := New(mockKL)
	go a.RunServer(stopCh)

	log.Infof("trying to obtain a certificate for the domain")
	a.ObtainCertificate([]string{domain})

}
<commit_msg>Skip acme e2e test due to LE staging outage<commit_after>package acme

import (
	"errors"
	"io/ioutil"
	"net/http"
	"os/exec"
	"regexp"
	"testing"
	"time"

	"github.com/Sirupsen/logrus"
	"github.com/golang/mock/gomock"
	"github.com/jetstack/kube-lego/pkg/mocks"
	"k8s.io/apimachinery/pkg/util/intstr"
)

func TestAcme_E2E(t *testing.T) {
	t.Skip("Temporarily skipping due to Let's Encrypt staging outage")
	logrus.SetLevel(logrus.DebugLevel)
	log := logrus.WithField("context", "test-mock")

	ctrl := gomock.NewController(t)
	defer ctrl.Finish()
	// mock kube lego
	mockKL := mocks.NewMockKubeLego(ctrl)
	mockKL.EXPECT().Log().AnyTimes().Return(log)
	mockKL.EXPECT().Version().AnyTimes().Return("mocked-version")
	mockKL.EXPECT().LegoHTTPPort().AnyTimes().Return(intstr.FromInt(8181))
	mockKL.EXPECT().AcmeUser().MinTimes(1).Return(nil, errors.New("I am only mocked"))
	mockKL.EXPECT().LegoURL().MinTimes(1).Return("https://acme-staging.api.letsencrypt.org/directory")
	mockKL.EXPECT().LegoEmail().MinTimes(1).Return("kube-lego-e2e@example.com")
	mockKL.EXPECT().SaveAcmeUser(gomock.Any()).MinTimes(1).Return(nil)
	mockKL.EXPECT().LegoRsaKeySize().AnyTimes().Return(2048)
	mockKL.EXPECT().ExponentialBackoffMaxElapsedTime().MinTimes(1).Return(time.Minute * 5)
	mockKL.EXPECT().ExponentialBackoffInitialInterval().MinTimes(1).Return(time.Second * 30)
	mockKL.EXPECT().ExponentialBackoffMultiplier().MinTimes(1).Return(2.0)

	// set up ngrok
	command := []string{"ngrok", "http", "--bind-tls", "false", "8181"}
	cmdNgrok := exec.Command(command[0], command[1:]...)
	err := cmdNgrok.Start()
	if err != nil {
		t.Skip("Skipping e2e test as ngrok executable is not available: ", err)
	}
	defer cmdNgrok.Process.Kill()

	// get domain main for forwarding the acme validation
	regexDomain := regexp.MustCompile("http://([a-z0-9]+.\\.ngrok\\.io)")
	var domain string
	for {
		time.Sleep(100 * time.Millisecond)
		resp, err := http.Get("http://localhost:4040/status")
		if err != nil {
			log.Warn(err)
			continue
		}
		defer resp.Body.Close()

		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			log.Warn(err)
			continue
		}

		matched := regexDomain.FindStringSubmatch(string(body))
		if matched == nil {
			continue
		}

		domain = matched[1]
		log.Infof("kube-lego domain is %s", domain)

		break
	}

	stopCh := make(chan struct{})
	a := New(mockKL)
	go a.RunServer(stopCh)

	log.Infof("trying to obtain a certificate for the domain")
	a.ObtainCertificate([]string{domain})

}
<|endoftext|>