<commit_before>/*
 * Minimal object storage library (C) 2015 Minio, 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 minio

import (
	"bytes"
	"encoding/hex"
	"io"
	"io/ioutil"
	"net/http"
	"sort"
	"strings"
	"time"
)

// operation - rest operation
type operation struct {
	HTTPServer string
	HTTPMethod string
	HTTPPath   string
}

// request - a http request
type request struct {
	req    *http.Request
	config *Config
	body   io.ReadSeeker
}

const (
	authHeader    = "AWS4-HMAC-SHA256"
	iso8601Format = "20060102T150405Z"
	yyyymmdd      = "20060102"
)

var ignoredHeaders = map[string]bool{
	"Authorization":  true,
	"Content-Type":   true,
	"Content-Length": true,
	"User-Agent":     true,
}

// newRequest - instantiate a new request
func newRequest(op *operation, config *Config, body io.ReadSeeker) (*request, error) {
	// if no method default to POST
	method := op.HTTPMethod
	if method == "" {
		method = "POST"
	}

	// parse URL for the combination of HTTPServer + HTTPPath
	u := op.HTTPServer + op.HTTPPath

	// get a new HTTP request, for the requested method
	req, err := http.NewRequest(method, u, nil)
	if err != nil {
		return nil, err
	}

	// set UserAgent
	req.Header.Set("User-Agent", config.userAgent)

	// set Accept header for response encoding style, if available
	if config.AcceptType != "" {
		req.Header.Set("Accept", config.AcceptType)
	}

	// add body
	switch {
	case body == nil:
		req.Body = nil
	default:
		req.Body = ioutil.NopCloser(body)
	}

	// save for subsequent use
	r := new(request)
	r.config = config
	r.req = req
	r.body = body

	return r, nil
}

// Do - start the request
func (r *request) Do() (resp *http.Response, err error) {
	if r.config.AccessKeyID != "" && r.config.SecretAccessKey != "" {
		r.SignV4()
	}
	transport := http.DefaultTransport
	if r.config.Transport != nil {
		transport = r.config.Transport
	}
	// do not use http.Client{}, while it may seem intuitive but the problem seems to be
	// that http.Client{} internally follows redirects and there is no easier way to disable
	// it from outside using a configuration parameter -
	//     this auto redirect causes complications in verifying subsequent errors
	//
	// The best is to use RoundTrip() directly, so the request comes back to the caller where
	// we are going to handle such replies. And indeed that is the right thing to do here.
	//
	return transport.RoundTrip(r.req)
}

// Set - set additional headers if any
func (r *request) Set(key, value string) {
	r.req.Header.Set(key, value)
}

// Get - get header values
func (r *request) Get(key string) string {
	return r.req.Header.Get(key)
}

// getHashedPayload get the hexadecimal value of the SHA256 hash of the request payload
func (r *request) getHashedPayload() string {
	hash := func() string {
		switch {
		case r.body == nil:
			return hex.EncodeToString(sum256([]byte{}))
		default:
			sum256Bytes, _ := sum256Reader(r.body)
			return hex.EncodeToString(sum256Bytes)
		}
	}
	hashedPayload := hash()
	r.req.Header.Add("x-amz-content-sha256", hashedPayload)
	return hashedPayload
}

// getCanonicalHeaders generate a list of request headers with their values
func (r *request) getCanonicalHeaders() string {
	var headers []string
	vals := make(map[string][]string)
	for k, vv := range r.req.Header {
		if _, ok := ignoredHeaders[http.CanonicalHeaderKey(k)]; ok {
			continue // ignored header
		}
		headers = append(headers, strings.ToLower(k))
		vals[strings.ToLower(k)] = vv
	}
	headers = append(headers, "host")
	sort.Strings(headers)

	var buf bytes.Buffer
	for _, k := range headers {
		buf.WriteString(k)
		buf.WriteByte(':')
		switch {
		case k == "host":
			buf.WriteString(r.req.URL.Host)
			fallthrough
		default:
			for idx, v := range vals[k] {
				if idx > 0 {
					buf.WriteByte(',')
				}
				buf.WriteString(v)
			}
			buf.WriteByte('\n')
		}
	}
	return buf.String()
}

// getSignedHeaders generate a string i.e alphabetically sorted, semicolon-separated list of lowercase request header names
func (r *request) getSignedHeaders() string {
	var headers []string
	for k := range r.req.Header {
		if _, ok := ignoredHeaders[http.CanonicalHeaderKey(k)]; ok {
			continue // ignored header
		}
		headers = append(headers, strings.ToLower(k))
	}
	headers = append(headers, "host")
	sort.Strings(headers)
	return strings.Join(headers, ";")
}

// getCanonicalRequest generate a canonical request of style
//
// canonicalRequest =
//  <HTTPMethod>\n
//  <CanonicalURI>\n
//  <CanonicalQueryString>\n
//  <CanonicalHeaders>\n
//  <SignedHeaders>\n
//  <HashedPayload>
//
func (r *request) getCanonicalRequest(hashedPayload string) string {
	r.req.URL.RawQuery = strings.Replace(r.req.URL.Query().Encode(), "+", "%20", -1)
	encodedPath, _ := urlEncodeName(r.req.URL.Path)
	// convert any space strings back to "+"
	encodedPath = strings.Replace(encodedPath, "+", "%20", -1)
	canonicalRequest := strings.Join([]string{
		r.req.Method,
		encodedPath,
		r.req.URL.RawQuery,
		r.getCanonicalHeaders(),
		r.getSignedHeaders(),
		hashedPayload,
	}, "\n")
	return canonicalRequest
}

// getScope generate a string of a specific date, an AWS region, and a service
func (r *request) getScope(t time.Time) string {
	scope := strings.Join([]string{
		t.Format(yyyymmdd),
		r.config.Region,
		"s3",
		"aws4_request",
	}, "/")
	return scope
}

// getStringToSign a string based on selected query values
func (r *request) getStringToSign(canonicalRequest string, t time.Time) string {
	stringToSign := authHeader + "\n" + t.Format(iso8601Format) + "\n"
	stringToSign = stringToSign + r.getScope(t) + "\n"
	stringToSign = stringToSign + hex.EncodeToString(sum256([]byte(canonicalRequest)))
	return stringToSign
}

// getSigningKey hmac seed to calculate final signature
func (r *request) getSigningKey(t time.Time) []byte {
	secret := r.config.SecretAccessKey
	date := sumHMAC([]byte("AWS4"+secret), []byte(t.Format(yyyymmdd)))
	region := sumHMAC(date, []byte(r.config.Region))
	service := sumHMAC(region, []byte("s3"))
	signingKey := sumHMAC(service, []byte("aws4_request"))
	return signingKey
}

// getSignature final signature in hexadecimal form
func (r *request) getSignature(signingKey []byte, stringToSign string) string {
	return hex.EncodeToString(sumHMAC(signingKey, []byte(stringToSign)))
}

// SignV4 the request before Do(), in accordance with - http://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html
func (r *request) SignV4() {
	t := time.Now().UTC()
	// Add date if not present
	if date := r.Get("Date"); date == "" {
		r.Set("x-amz-date", t.Format(iso8601Format))
	}

	hashedPayload := r.getHashedPayload()
	signedHeaders := r.getSignedHeaders()
	canonicalRequest := r.getCanonicalRequest(hashedPayload)
	scope := r.getScope(t)
	stringToSign := r.getStringToSign(canonicalRequest, t)
	signingKey := r.getSigningKey(t)
	signature := r.getSignature(signingKey, stringToSign)

	// final Authorization header
	parts := []string{
		authHeader + " Credential=" + r.config.AccessKeyID + "/" + scope,
		"SignedHeaders=" + signedHeaders,
		"Signature=" + signature,
	}
	auth := strings.Join(parts, ", ")
	r.Set("Authorization", auth)
}
<commit_msg>Adding excerpts from aws developers - regarding ignored headers<commit_after>/*
 * Minimal object storage library (C) 2015 Minio, 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 minio

import (
	"bytes"
	"encoding/hex"
	"io"
	"io/ioutil"
	"net/http"
	"sort"
	"strings"
	"time"
)

// operation - rest operation
type operation struct {
	HTTPServer string
	HTTPMethod string
	HTTPPath   string
}

// request - a http request
type request struct {
	req    *http.Request
	config *Config
	body   io.ReadSeeker
}

const (
	authHeader    = "AWS4-HMAC-SHA256"
	iso8601Format = "20060102T150405Z"
	yyyymmdd      = "20060102"
)

///
/// Excerpts from @lsegal - https://github.com/aws/aws-sdk-js/issues/659#issuecomment-120477258
///
///  User-Agent:
///
///      This is ignored from signing because signing this causes problems with generating pre-signed URLs
///      (that are executed by other agents) or when customers pass requests through proxies, which may
///      modify the user-agent.
///
///  Content-Length:
///
///      This is ignored from signing because generating a pre-signed URL should not provide a content-length
///      constraint, specifically when vending a S3 pre-signed PUT URL. The corollary to this is that when
///      sending regular requests (non-pre-signed), the signature contains a checksum of the body, which
///      implicitly validates the payload length (since changing the number of bytes would change the checksum)
///      and therefore this header is not valuable in the signature.
///
///  Content-Type:
///
///      Signing this header causes quite a number of problems in browser environments, where browsers
///      like to modify and normalize the content-type header in different ways. There is more information
///      on this in https://github.com/aws/aws-sdk-js/issues/244. Avoiding this field simplifies logic
///      and reduces the possibility of future bugs
///
///  Authorization:
///
///      Is skipped for obvious reasons
///
var ignoredHeaders = map[string]bool{
	"Authorization":  true,
	"Content-Type":   true,
	"Content-Length": true,
	"User-Agent":     true,
}

// newRequest - instantiate a new request
func newRequest(op *operation, config *Config, body io.ReadSeeker) (*request, error) {
	// if no method default to POST
	method := op.HTTPMethod
	if method == "" {
		method = "POST"
	}

	// parse URL for the combination of HTTPServer + HTTPPath
	u := op.HTTPServer + op.HTTPPath

	// get a new HTTP request, for the requested method
	req, err := http.NewRequest(method, u, nil)
	if err != nil {
		return nil, err
	}

	// set UserAgent
	req.Header.Set("User-Agent", config.userAgent)

	// set Accept header for response encoding style, if available
	if config.AcceptType != "" {
		req.Header.Set("Accept", config.AcceptType)
	}

	// add body
	switch {
	case body == nil:
		req.Body = nil
	default:
		req.Body = ioutil.NopCloser(body)
	}

	// save for subsequent use
	r := new(request)
	r.config = config
	r.req = req
	r.body = body

	return r, nil
}

// Do - start the request
func (r *request) Do() (resp *http.Response, err error) {
	if r.config.AccessKeyID != "" && r.config.SecretAccessKey != "" {
		r.SignV4()
	}
	transport := http.DefaultTransport
	if r.config.Transport != nil {
		transport = r.config.Transport
	}
	// do not use http.Client{}, while it may seem intuitive but the problem seems to be
	// that http.Client{} internally follows redirects and there is no easier way to disable
	// it from outside using a configuration parameter -
	//     this auto redirect causes complications in verifying subsequent errors
	//
	// The best is to use RoundTrip() directly, so the request comes back to the caller where
	// we are going to handle such replies. And indeed that is the right thing to do here.
	//
	return transport.RoundTrip(r.req)
}

// Set - set additional headers if any
func (r *request) Set(key, value string) {
	r.req.Header.Set(key, value)
}

// Get - get header values
func (r *request) Get(key string) string {
	return r.req.Header.Get(key)
}

// getHashedPayload get the hexadecimal value of the SHA256 hash of the request payload
func (r *request) getHashedPayload() string {
	hash := func() string {
		switch {
		case r.body == nil:
			return hex.EncodeToString(sum256([]byte{}))
		default:
			sum256Bytes, _ := sum256Reader(r.body)
			return hex.EncodeToString(sum256Bytes)
		}
	}
	hashedPayload := hash()
	r.req.Header.Add("x-amz-content-sha256", hashedPayload)
	return hashedPayload
}

// getCanonicalHeaders generate a list of request headers with their values
func (r *request) getCanonicalHeaders() string {
	var headers []string
	vals := make(map[string][]string)
	for k, vv := range r.req.Header {
		if _, ok := ignoredHeaders[http.CanonicalHeaderKey(k)]; ok {
			continue // ignored header
		}
		headers = append(headers, strings.ToLower(k))
		vals[strings.ToLower(k)] = vv
	}
	headers = append(headers, "host")
	sort.Strings(headers)

	var buf bytes.Buffer
	for _, k := range headers {
		buf.WriteString(k)
		buf.WriteByte(':')
		switch {
		case k == "host":
			buf.WriteString(r.req.URL.Host)
			fallthrough
		default:
			for idx, v := range vals[k] {
				if idx > 0 {
					buf.WriteByte(',')
				}
				buf.WriteString(v)
			}
			buf.WriteByte('\n')
		}
	}
	return buf.String()
}

// getSignedHeaders generate a string i.e alphabetically sorted, semicolon-separated list of lowercase request header names
func (r *request) getSignedHeaders() string {
	var headers []string
	for k := range r.req.Header {
		if _, ok := ignoredHeaders[http.CanonicalHeaderKey(k)]; ok {
			continue // ignored header
		}
		headers = append(headers, strings.ToLower(k))
	}
	headers = append(headers, "host")
	sort.Strings(headers)
	return strings.Join(headers, ";")
}

// getCanonicalRequest generate a canonical request of style
//
// canonicalRequest =
//  <HTTPMethod>\n
//  <CanonicalURI>\n
//  <CanonicalQueryString>\n
//  <CanonicalHeaders>\n
//  <SignedHeaders>\n
//  <HashedPayload>
//
func (r *request) getCanonicalRequest(hashedPayload string) string {
	r.req.URL.RawQuery = strings.Replace(r.req.URL.Query().Encode(), "+", "%20", -1)
	encodedPath, _ := urlEncodeName(r.req.URL.Path)
	// convert any space strings back to "+"
	encodedPath = strings.Replace(encodedPath, "+", "%20", -1)
	canonicalRequest := strings.Join([]string{
		r.req.Method,
		encodedPath,
		r.req.URL.RawQuery,
		r.getCanonicalHeaders(),
		r.getSignedHeaders(),
		hashedPayload,
	}, "\n")
	return canonicalRequest
}

// getScope generate a string of a specific date, an AWS region, and a service
func (r *request) getScope(t time.Time) string {
	scope := strings.Join([]string{
		t.Format(yyyymmdd),
		r.config.Region,
		"s3",
		"aws4_request",
	}, "/")
	return scope
}

// getStringToSign a string based on selected query values
func (r *request) getStringToSign(canonicalRequest string, t time.Time) string {
	stringToSign := authHeader + "\n" + t.Format(iso8601Format) + "\n"
	stringToSign = stringToSign + r.getScope(t) + "\n"
	stringToSign = stringToSign + hex.EncodeToString(sum256([]byte(canonicalRequest)))
	return stringToSign
}

// getSigningKey hmac seed to calculate final signature
func (r *request) getSigningKey(t time.Time) []byte {
	secret := r.config.SecretAccessKey
	date := sumHMAC([]byte("AWS4"+secret), []byte(t.Format(yyyymmdd)))
	region := sumHMAC(date, []byte(r.config.Region))
	service := sumHMAC(region, []byte("s3"))
	signingKey := sumHMAC(service, []byte("aws4_request"))
	return signingKey
}

// getSignature final signature in hexadecimal form
func (r *request) getSignature(signingKey []byte, stringToSign string) string {
	return hex.EncodeToString(sumHMAC(signingKey, []byte(stringToSign)))
}

// SignV4 the request before Do(), in accordance with - http://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html
func (r *request) SignV4() {
	t := time.Now().UTC()
	// Add date if not present
	if date := r.Get("Date"); date == "" {
		r.Set("x-amz-date", t.Format(iso8601Format))
	}

	hashedPayload := r.getHashedPayload()
	signedHeaders := r.getSignedHeaders()
	canonicalRequest := r.getCanonicalRequest(hashedPayload)
	scope := r.getScope(t)
	stringToSign := r.getStringToSign(canonicalRequest, t)
	signingKey := r.getSigningKey(t)
	signature := r.getSignature(signingKey, stringToSign)

	// final Authorization header
	parts := []string{
		authHeader + " Credential=" + r.config.AccessKeyID + "/" + scope,
		"SignedHeaders=" + signedHeaders,
		"Signature=" + signature,
	}
	auth := strings.Join(parts, ", ")
	r.Set("Authorization", auth)
}
<|endoftext|>


<commit_before>package tsgen

import (
	"math/rand"
	"sort"

	"github.com/golang/glog"

	. "gopkg.in/check.v1"
)

type SimulatorSuite struct {
	tags []Tag
	rnd  *rand.Rand
}

var _ = Suite(&SimulatorSuite{
	rnd:  rand.New(rand.NewSource(1)),
	tags: []Tag{Tag{"tag1", "value1"}, Tag{"tag2", "value2"}},
})

func (s *SimulatorSuite) TestSimulatorTick(c *C) {
	rnd := rand.New(rand.NewSource(1))
	conf := NewConfiguration(3, 5)
	simulator := NewSimulator(rnd, conf, 0)
	c.Assert(len(simulator.machines), Equals, 3)
	glog.Info(simulator.machines)
	simulator.Run(0, 1, 1600, func(tp *[]TaggedPoints) {
		// nothing to do
	})
}

func (s *SimulatorSuite) TestDeduplicate(c *C) {
	tags := Tags{
		Tag{"tag1", "value1"}, Tag{"tag2", "value2"},
		Tag{"tag2", "value1"}, Tag{"tag1", "value1"},
	}
	sort.Sort(&tags)
	deduplicateTags(&tags)
	dupes := make(map[Tag]bool)
	for ti := range tags {
		_, ok := dupes[tags[ti]]
		c.Assert(ok, Equals, false)
		dupes[tags[ti]] = true
	}
}
<commit_msg>adding benchmark<commit_after>package tsgen

import (
	"math/rand"
	"sort"

	"github.com/golang/glog"

	. "gopkg.in/check.v1"
)

type SimulatorSuite struct {
	tags []Tag
	rnd  *rand.Rand
}

var _ = Suite(&SimulatorSuite{
	rnd:  rand.New(rand.NewSource(1)),
	tags: []Tag{Tag{"tag1", "value1"}, Tag{"tag2", "value2"}},
})

func (s *SimulatorSuite) TestSimulatorTick(c *C) {
	rnd := rand.New(rand.NewSource(1))
	conf := NewConfiguration(3, 5)
	simulator := NewSimulator(rnd, conf, 0)
	c.Assert(len(simulator.machines), Equals, 3)
	glog.Info(simulator.machines)
	simulator.Run(0, 1, 1600, func(tp *[]TaggedPoints) {
		// nothing to do
	})
}

func (s *SimulatorSuite) TestDeduplicate(c *C) {
	tags := Tags{
		Tag{"tag1", "value1"}, Tag{"tag2", "value2"},
		Tag{"tag2", "value1"}, Tag{"tag1", "value1"},
	}
	sort.Sort(&tags)
	deduplicateTags(&tags)
	dupes := make(map[Tag]bool)
	for ti := range tags {
		_, ok := dupes[tags[ti]]
		c.Assert(ok, Equals, false)
		dupes[tags[ti]] = true
	}
}

func (s *SimulatorSuite) BenchmarkSimulator(c *C) {
	rnd := rand.New(rand.NewSource(1))
	conf := NewConfiguration(c.N, 1000)
	simulator := NewSimulator(rnd, conf, 0)
	simulator.Run(0, 1, 1600, func(tp *[]TaggedPoints) {
		// nothing to do
	})
}
<|endoftext|>


<commit_before>package ansiblelocal

import (
	"fmt"
	"github.com/mitchellh/packer/common"
	"github.com/mitchellh/packer/packer"
	"os"
	"path/filepath"
	"strings"
)

const DefaultStagingDir = "/tmp/packer-provisioner-ansible-local"

type Config struct {
	common.PackerConfig `mapstructure:",squash"`
	tpl                 *packer.ConfigTemplate

	// The command to run ansible
	Command string

	// Extra options to pass to the ansible command
	ExtraArguments []string `mapstructure:"extra_arguments"`

	// Path to group_vars directory
	GroupVars string `mapstructure:"group_vars"`

	// Path to host_vars directory
	HostVars string `mapstructure:"host_vars"`

	// The main playbook file to execute.
	PlaybookFile string `mapstructure:"playbook_file"`

	// An array of local paths of playbook files to upload.
	PlaybookPaths []string `mapstructure:"playbook_paths"`

	// An array of local paths of roles to upload.
	RolePaths []string `mapstructure:"role_paths"`

	// The directory where files will be uploaded. Packer requires write
	// permissions in this directory.
	StagingDir string `mapstructure:"staging_directory"`

	// The optional inventory file
	InventoryFile string `mapstructure:"inventory_file"`
}

type Provisioner struct {
	config Config
}

func (p *Provisioner) Prepare(raws ...interface{}) error {
	md, err := common.DecodeConfig(&p.config, raws...)
	if err != nil {
		return err
	}

	p.config.tpl, err = packer.NewConfigTemplate()
	if err != nil {
		return err
	}

	p.config.tpl.UserVars = p.config.PackerUserVars

	// Accumulate any errors
	errs := common.CheckUnusedConfig(md)

	// Defaults
	if p.config.Command == "" {
		p.config.Command = "ansible-playbook"
	}

	if p.config.StagingDir == "" {
		p.config.StagingDir = DefaultStagingDir
	}

	// Templates
	templates := map[string]*string{
		"command":        &p.config.Command,
		"group_vars":     &p.config.GroupVars,
		"host_vars":      &p.config.HostVars,
		"playbook_file":  &p.config.PlaybookFile,
		"staging_dir":    &p.config.StagingDir,
		"inventory_file": &p.config.InventoryFile,
	}

	for n, ptr := range templates {
		var err error
		*ptr, err = p.config.tpl.Process(*ptr, nil)
		if err != nil {
			errs = packer.MultiErrorAppend(
				errs, fmt.Errorf("Error processing %s: %s", n, err))
		}
	}

	sliceTemplates := map[string][]string{
		"extra_arguments": p.config.ExtraArguments,
		"playbook_paths":  p.config.PlaybookPaths,
		"role_paths":      p.config.RolePaths,
	}

	for n, slice := range sliceTemplates {
		for i, elem := range slice {
			var err error
			slice[i], err = p.config.tpl.Process(elem, nil)
			if err != nil {
				errs = packer.MultiErrorAppend(
					errs, fmt.Errorf("Error processing %s[%d]: %s", n, i, err))
			}
		}
	}

	// Validation
	err = validateFileConfig(p.config.PlaybookFile, "playbook_file", true)
	if err != nil {
		errs = packer.MultiErrorAppend(errs, err)
	}

	// Check that the inventory file exists, if configured
	if len(p.config.InventoryFile) > 0 {
		err = validateFileConfig(p.config.InventoryFile, "inventory_file", true)
		if err != nil {
			errs = packer.MultiErrorAppend(errs, err)
		}
	}

	// Check that the group_vars directory exists, if configured
	if len(p.config.GroupVars) > 0 {
		if err := validateDirConfig(p.config.GroupVars, "group_vars"); err != nil {
			errs = packer.MultiErrorAppend(errs, err)
		}
	}

	// Check that the host_vars directory exists, if configured
	if len(p.config.HostVars) > 0 {
		if err := validateDirConfig(p.config.HostVars, "host_vars"); err != nil {
			errs = packer.MultiErrorAppend(errs, err)
		}
	}

	for _, path := range p.config.PlaybookPaths {
		err := validateDirConfig(path, "playbook_paths")
		if err != nil {
			errs = packer.MultiErrorAppend(errs, err)
		}
	}
	for _, path := range p.config.RolePaths {
		if err := validateDirConfig(path, "role_paths"); err != nil {
			errs = packer.MultiErrorAppend(errs, err)
		}
	}

	if errs != nil && len(errs.Errors) > 0 {
		return errs
	}
	return nil
}

func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error {
	ui.Say("Provisioning with Ansible...")

	ui.Message("Creating Ansible staging directory...")
	if err := p.createDir(ui, comm, p.config.StagingDir); err != nil {
		return fmt.Errorf("Error creating staging directory: %s", err)
	}

	ui.Message("Uploading main Playbook file...")
	src := p.config.PlaybookFile
	dst := filepath.ToSlash(filepath.Join(p.config.StagingDir, filepath.Base(src)))
	if err := p.uploadFile(ui, comm, dst, src); err != nil {
		return fmt.Errorf("Error uploading main playbook: %s", err)
	}

	if len(p.config.InventoryFile) > 0 {
		ui.Message("Uploading inventory file...")
		src := p.config.InventoryFile
		dst := filepath.Join(p.config.StagingDir, filepath.Base(src))
		if err := p.uploadFile(ui, comm, dst, src); err != nil {
			return fmt.Errorf("Error uploading inventory file: %s", err)
		}
	}

	if len(p.config.GroupVars) > 0 {
		ui.Message("Uploading group_vars directory...")
		src := p.config.GroupVars
		dst := filepath.ToSlash(filepath.Join(p.config.StagingDir, "group_vars"))
		if err := p.uploadDir(ui, comm, dst, src); err != nil {
			return fmt.Errorf("Error uploading group_vars directory: %s", err)
		}
	}

	if len(p.config.HostVars) > 0 {
		ui.Message("Uploading host_vars directory...")
		src := p.config.HostVars
		dst := filepath.ToSlash(filepath.Join(p.config.StagingDir, "host_vars"))
		if err := p.uploadDir(ui, comm, dst, src); err != nil {
			return fmt.Errorf("Error uploading host_vars directory: %s", err)
		}
	}

	if len(p.config.RolePaths) > 0 {
		ui.Message("Uploading role directories...")
		for _, src := range p.config.RolePaths {
			dst := filepath.ToSlash(filepath.Join(p.config.StagingDir, "roles", filepath.Base(src)))
			if err := p.uploadDir(ui, comm, dst, src); err != nil {
				return fmt.Errorf("Error uploading roles: %s", err)
			}
		}
	}

	if len(p.config.PlaybookPaths) > 0 {
		ui.Message("Uploading additional Playbooks...")
		playbookDir := filepath.ToSlash(filepath.Join(p.config.StagingDir, "playbooks"))
		if err := p.createDir(ui, comm, playbookDir); err != nil {
			return fmt.Errorf("Error creating playbooks directory: %s", err)
		}
		for _, src := range p.config.PlaybookPaths {
			dst := filepath.ToSlash(filepath.Join(playbookDir, filepath.Base(src)))
			if err := p.uploadDir(ui, comm, dst, src); err != nil {
				return fmt.Errorf("Error uploading playbooks: %s", err)
			}
		}
	}

	if err := p.executeAnsible(ui, comm); err != nil {
		return fmt.Errorf("Error executing Ansible: %s", err)
	}
	return nil
}

func (p *Provisioner) Cancel() {
	// Just hard quit. It isn't a big deal if what we're doing keeps
	// running on the other side.
	os.Exit(0)
}

func (p *Provisioner) executeAnsible(ui packer.Ui, comm packer.Communicator) error {
	playbook := filepath.ToSlash(filepath.Join(p.config.StagingDir, filepath.Base(p.config.PlaybookFile)))

	// The inventory must be set to "127.0.0.1,".  The comma is important
	// as its the only way to override the ansible inventory when dealing
	// with a single host.
	inventory := "\"127.0.0.1,\""
	if len(p.config.InventoryFile) > 0 {
		inventory = filepath.Join(p.config.StagingDir, filepath.Base(p.config.InventoryFile))
	}

	extraArgs := ""
	if len(p.config.ExtraArguments) > 0 {
		extraArgs = " " + strings.Join(p.config.ExtraArguments, " ")
	}

	command := fmt.Sprintf("cd %s && %s %s%s -c local -i %s",
		p.config.StagingDir, p.config.Command, playbook, extraArgs, inventory)
	ui.Message(fmt.Sprintf("Executing Ansible: %s", command))
	cmd := &packer.RemoteCmd{
		Command: command,
	}
	if err := cmd.StartWithUi(comm, ui); err != nil {
		return err
	}
	if cmd.ExitStatus != 0 {
		if cmd.ExitStatus == 127 {
			return fmt.Errorf("%s could not be found. Verify that it is available on the\n"+
				"PATH after connecting to the machine.",
				p.config.Command)
		}

		return fmt.Errorf("Non-zero exit status: %d", cmd.ExitStatus)
	}
	return nil
}

func validateDirConfig(path string, config string) error {
	info, err := os.Stat(path)
	if err != nil {
		return fmt.Errorf("%s: %s is invalid: %s", config, path, err)
	} else if !info.IsDir() {
		return fmt.Errorf("%s: %s must point to a directory", config, path)
	}
	return nil
}

func validateFileConfig(name string, config string, req bool) error {
	if req {
		if name == "" {
			return fmt.Errorf("%s must be specified.", config)
		}
	}
	info, err := os.Stat(name)
	if err != nil {
		return fmt.Errorf("%s: %s is invalid: %s", config, name, err)
	} else if info.IsDir() {
		return fmt.Errorf("%s: %s must point to a file", config, name)
	}
	return nil
}

func (p *Provisioner) uploadFile(ui packer.Ui, comm packer.Communicator, dst, src string) error {
	f, err := os.Open(src)
	if err != nil {
		return fmt.Errorf("Error opening: %s", err)
	}
	defer f.Close()

	if err = comm.Upload(dst, f); err != nil {
		return fmt.Errorf("Error uploading %s: %s", src, err)
	}
	return nil
}

func (p *Provisioner) createDir(ui packer.Ui, comm packer.Communicator, dir string) error {
	ui.Message(fmt.Sprintf("Creating directory: %s", dir))
	cmd := &packer.RemoteCmd{
		Command: fmt.Sprintf("mkdir -p '%s'", dir),
	}
	if err := cmd.StartWithUi(comm, ui); err != nil {
		return err
	}
	if cmd.ExitStatus != 0 {
		return fmt.Errorf("Non-zero exit status.")
	}
	return nil
}

func (p *Provisioner) uploadDir(ui packer.Ui, comm packer.Communicator, dst, src string) error {
	if err := p.createDir(ui, comm, dst); err != nil {
		return err
	}

	// Make sure there is a trailing "/" so that the directory isn't
	// created on the other side.
	if src[len(src)-1] != '/' {
		src = src + "/"
	}
	return comm.UploadDir(dst, src, nil)
}
<commit_msg>Uploading the whole ansible playbook directory<commit_after>package ansiblelocal

import (
	"fmt"
	"github.com/mitchellh/packer/common"
	"github.com/mitchellh/packer/packer"
	"os"
	"path/filepath"
	"strings"
)

const DefaultStagingDir = "/tmp/packer-provisioner-ansible-local"

type Config struct {
	common.PackerConfig `mapstructure:",squash"`
	tpl                 *packer.ConfigTemplate

	// The command to run ansible
	Command string

	// Extra options to pass to the ansible command
	ExtraArguments []string `mapstructure:"extra_arguments"`

	// Path to group_vars directory
	GroupVars string `mapstructure:"group_vars"`

	// Path to host_vars directory
	HostVars string `mapstructure:"host_vars"`

	// The playbook dir to upload.
	PlaybookDir string `mapstructure:"playbook_dir"`

	// The main playbook file to execute.
	PlaybookFile string `mapstructure:"playbook_file"`

	// An array of local paths of playbook files to upload.
	PlaybookPaths []string `mapstructure:"playbook_paths"`

	// An array of local paths of roles to upload.
	RolePaths []string `mapstructure:"role_paths"`

	// The directory where files will be uploaded. Packer requires write
	// permissions in this directory.
	StagingDir string `mapstructure:"staging_directory"`

	// The optional inventory file
	InventoryFile string `mapstructure:"inventory_file"`
}

type Provisioner struct {
	config Config
}

func (p *Provisioner) Prepare(raws ...interface{}) error {
	md, err := common.DecodeConfig(&p.config, raws...)
	if err != nil {
		return err
	}

	p.config.tpl, err = packer.NewConfigTemplate()
	if err != nil {
		return err
	}

	p.config.tpl.UserVars = p.config.PackerUserVars

	// Accumulate any errors
	errs := common.CheckUnusedConfig(md)

	// Defaults
	if p.config.Command == "" {
		p.config.Command = "ansible-playbook"
	}

	if p.config.StagingDir == "" {
		p.config.StagingDir = DefaultStagingDir
	}

	// Templates
	templates := map[string]*string{
		"command":        &p.config.Command,
		"group_vars":     &p.config.GroupVars,
		"host_vars":      &p.config.HostVars,
		"playbook_file":  &p.config.PlaybookFile,
		"playbook_dir":   &p.config.PlaybookDir,
		"staging_dir":    &p.config.StagingDir,
		"inventory_file": &p.config.InventoryFile,
	}

	for n, ptr := range templates {
		var err error
		*ptr, err = p.config.tpl.Process(*ptr, nil)
		if err != nil {
			errs = packer.MultiErrorAppend(
				errs, fmt.Errorf("Error processing %s: %s", n, err))
		}
	}

	sliceTemplates := map[string][]string{
		"extra_arguments": p.config.ExtraArguments,
		"playbook_paths":  p.config.PlaybookPaths,
		"role_paths":      p.config.RolePaths,
	}

	for n, slice := range sliceTemplates {
		for i, elem := range slice {
			var err error
			slice[i], err = p.config.tpl.Process(elem, nil)
			if err != nil {
				errs = packer.MultiErrorAppend(
					errs, fmt.Errorf("Error processing %s[%d]: %s", n, i, err))
			}
		}
	}

	// Validation
	err = validateFileConfig(p.config.PlaybookFile, "playbook_file", true)
	if err != nil {
		errs = packer.MultiErrorAppend(errs, err)
	}

	// Check that the inventory file exists, if configured
	if len(p.config.InventoryFile) > 0 {
		err = validateFileConfig(p.config.InventoryFile, "inventory_file", true)
		if err != nil {
			errs = packer.MultiErrorAppend(errs, err)
		}
	}

	// Check that the playbook_dir directory exists, if configured
	if len(p.config.PlaybookDir) > 0 {
		if err := validateDirConfig(p.config.PlaybookDir, "playbook_dir"); err != nil {
			errs = packer.MultiErrorAppend(errs, err)
		}
	}

	// Check that the group_vars directory exists, if configured
	if len(p.config.GroupVars) > 0 {
		if err := validateDirConfig(p.config.GroupVars, "group_vars"); err != nil {
			errs = packer.MultiErrorAppend(errs, err)
		}
	}

	// Check that the host_vars directory exists, if configured
	if len(p.config.HostVars) > 0 {
		if err := validateDirConfig(p.config.HostVars, "host_vars"); err != nil {
			errs = packer.MultiErrorAppend(errs, err)
		}
	}

	for _, path := range p.config.PlaybookPaths {
		err := validateDirConfig(path, "playbook_paths")
		if err != nil {
			errs = packer.MultiErrorAppend(errs, err)
		}
	}
	for _, path := range p.config.RolePaths {
		if err := validateDirConfig(path, "role_paths"); err != nil {
			errs = packer.MultiErrorAppend(errs, err)
		}
	}

	if errs != nil && len(errs.Errors) > 0 {
		return errs
	}
	return nil
}

func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error {
	ui.Say("Provisioning with Ansible...")

	if len(p.config.PlaybookDir) > 0 {
		ui.Message("Uploading Playbook directory to Ansible staging directory...")
		if err := p.uploadDir(ui, comm, p.config.StagingDir, p.config.PlaybookDir); err != nil {
			return fmt.Errorf("Error uploading playbook_dir directory: %s", err)
		}
	} else {
		ui.Message("Creating Ansible staging directory...")
		if err := p.createDir(ui, comm, p.config.StagingDir); err != nil {
			return fmt.Errorf("Error creating staging directory: %s", err)
		}
	}

	ui.Message("Uploading main Playbook file...")
	src := p.config.PlaybookFile
	dst := filepath.ToSlash(filepath.Join(p.config.StagingDir, filepath.Base(src)))
	if err := p.uploadFile(ui, comm, dst, src); err != nil {
		return fmt.Errorf("Error uploading main playbook: %s", err)
	}

	if len(p.config.InventoryFile) > 0 {
		ui.Message("Uploading inventory file...")
		src := p.config.InventoryFile
		dst := filepath.Join(p.config.StagingDir, filepath.Base(src))
		if err := p.uploadFile(ui, comm, dst, src); err != nil {
			return fmt.Errorf("Error uploading inventory file: %s", err)
		}
	}

	if len(p.config.GroupVars) > 0 {
		ui.Message("Uploading group_vars directory...")
		src := p.config.GroupVars
		dst := filepath.ToSlash(filepath.Join(p.config.StagingDir, "group_vars"))
		if err := p.uploadDir(ui, comm, dst, src); err != nil {
			return fmt.Errorf("Error uploading group_vars directory: %s", err)
		}
	}

	if len(p.config.HostVars) > 0 {
		ui.Message("Uploading host_vars directory...")
		src := p.config.HostVars
		dst := filepath.ToSlash(filepath.Join(p.config.StagingDir, "host_vars"))
		if err := p.uploadDir(ui, comm, dst, src); err != nil {
			return fmt.Errorf("Error uploading host_vars directory: %s", err)
		}
	}

	if len(p.config.RolePaths) > 0 {
		ui.Message("Uploading role directories...")
		for _, src := range p.config.RolePaths {
			dst := filepath.ToSlash(filepath.Join(p.config.StagingDir, "roles", filepath.Base(src)))
			if err := p.uploadDir(ui, comm, dst, src); err != nil {
				return fmt.Errorf("Error uploading roles: %s", err)
			}
		}
	}

	if len(p.config.PlaybookPaths) > 0 {
		ui.Message("Uploading additional Playbooks...")
		playbookDir := filepath.ToSlash(filepath.Join(p.config.StagingDir, "playbooks"))
		if err := p.createDir(ui, comm, playbookDir); err != nil {
			return fmt.Errorf("Error creating playbooks directory: %s", err)
		}
		for _, src := range p.config.PlaybookPaths {
			dst := filepath.ToSlash(filepath.Join(playbookDir, filepath.Base(src)))
			if err := p.uploadDir(ui, comm, dst, src); err != nil {
				return fmt.Errorf("Error uploading playbooks: %s", err)
			}
		}
	}

	if err := p.executeAnsible(ui, comm); err != nil {
		return fmt.Errorf("Error executing Ansible: %s", err)
	}
	return nil
}

func (p *Provisioner) Cancel() {
	// Just hard quit. It isn't a big deal if what we're doing keeps
	// running on the other side.
	os.Exit(0)
}

func (p *Provisioner) executeAnsible(ui packer.Ui, comm packer.Communicator) error {
	playbook := filepath.ToSlash(filepath.Join(p.config.StagingDir, filepath.Base(p.config.PlaybookFile)))

	// The inventory must be set to "127.0.0.1,".  The comma is important
	// as its the only way to override the ansible inventory when dealing
	// with a single host.
	inventory := "\"127.0.0.1,\""
	if len(p.config.InventoryFile) > 0 {
		inventory = filepath.Join(p.config.StagingDir, filepath.Base(p.config.InventoryFile))
	}

	extraArgs := ""
	if len(p.config.ExtraArguments) > 0 {
		extraArgs = " " + strings.Join(p.config.ExtraArguments, " ")
	}

	command := fmt.Sprintf("cd %s && %s %s%s -c local -i %s",
		p.config.StagingDir, p.config.Command, playbook, extraArgs, inventory)
	ui.Message(fmt.Sprintf("Executing Ansible: %s", command))
	cmd := &packer.RemoteCmd{
		Command: command,
	}
	if err := cmd.StartWithUi(comm, ui); err != nil {
		return err
	}
	if cmd.ExitStatus != 0 {
		if cmd.ExitStatus == 127 {
			return fmt.Errorf("%s could not be found. Verify that it is available on the\n"+
				"PATH after connecting to the machine.",
				p.config.Command)
		}

		return fmt.Errorf("Non-zero exit status: %d", cmd.ExitStatus)
	}
	return nil
}

func validateDirConfig(path string, config string) error {
	info, err := os.Stat(path)
	if err != nil {
		return fmt.Errorf("%s: %s is invalid: %s", config, path, err)
	} else if !info.IsDir() {
		return fmt.Errorf("%s: %s must point to a directory", config, path)
	}
	return nil
}

func validateFileConfig(name string, config string, req bool) error {
	if req {
		if name == "" {
			return fmt.Errorf("%s must be specified.", config)
		}
	}
	info, err := os.Stat(name)
	if err != nil {
		return fmt.Errorf("%s: %s is invalid: %s", config, name, err)
	} else if info.IsDir() {
		return fmt.Errorf("%s: %s must point to a file", config, name)
	}
	return nil
}

func (p *Provisioner) uploadFile(ui packer.Ui, comm packer.Communicator, dst, src string) error {
	f, err := os.Open(src)
	if err != nil {
		return fmt.Errorf("Error opening: %s", err)
	}
	defer f.Close()

	if err = comm.Upload(dst, f); err != nil {
		return fmt.Errorf("Error uploading %s: %s", src, err)
	}
	return nil
}

func (p *Provisioner) createDir(ui packer.Ui, comm packer.Communicator, dir string) error {
	ui.Message(fmt.Sprintf("Creating directory: %s", dir))
	cmd := &packer.RemoteCmd{
		Command: fmt.Sprintf("mkdir -p '%s'", dir),
	}
	if err := cmd.StartWithUi(comm, ui); err != nil {
		return err
	}
	if cmd.ExitStatus != 0 {
		return fmt.Errorf("Non-zero exit status.")
	}
	return nil
}

func (p *Provisioner) uploadDir(ui packer.Ui, comm packer.Communicator, dst, src string) error {
	if err := p.createDir(ui, comm, dst); err != nil {
		return err
	}

	// Make sure there is a trailing "/" so that the directory isn't
	// created on the other side.
	if src[len(src)-1] != '/' {
		src = src + "/"
	}
	return comm.UploadDir(dst, src, nil)
}
<|endoftext|>


<commit_before>package dao

import (
	"encoding/base64"
	"encoding/json"
	"fmt"
	"log"
	"time"

	"github.com/franela/goreq"

	. "github.com/mnhkahn/maodou/models"
)

type DuoShuoConfig struct {
	ShortName string `json:"short_name"`
	Secret    string `json:"secret"`
	ThreadKey string `json:"thread_key"`
}

type DuoShuoDao struct {
}

func (this *DuoShuoDao) NewDaoImpl(dsn string) (DaoContainer, error) {
	d := new(DuoShuoDaoContainer)
	config := new(DuoShuoConfig)
	err := json.Unmarshal([]byte(dsn), config)
	d.config = config
	if err != nil {
		return d, fmt.Errorf("Config for duoshuo is error: %v", err)
	}

	return d, nil
}

type DuoShuoDaoContainer struct {
	config   *DuoShuoConfig
	is_debug bool
	req      goreq.Request
}

func (this *DuoShuoDaoContainer) Debug(is_debug bool) {
	this.req.ShowDebug = is_debug
}

func (this *DuoShuoDaoContainer) AddResult(p *Result) {
	this.req.Method = "POST"
	this.req.Uri = "http://api.duoshuo.com/posts/import.json"
	this.req.ContentType = "application/x-www-form-urlencoded"
	this.req.Timeout = time.Duration(10) * time.Second

	duoshuo_byte, _ := json.Marshal(*p)
	this.req.Body = fmt.Sprintf("short_name=%s&secret=%s&posts[0][post_key]=%s&posts[0][thread_key]=%s&posts[0][message]=%s", this.config.ShortName, this.config.Secret, p.Id, this.config.ThreadKey, base64.URLEncoding.EncodeToString(duoshuo_byte))
	resp, err := this.req.Do()
	if err != nil {
		log.Println(err.Error())
	}
	if resp == nil || resp.StatusCode != 200 {
		var err_str string
		if resp != nil {
			err_str, _ = resp.Body.ToString()
		}
		log.Printf("Error: %s\n", err_str)
	} else {
		log.Println("Add to DuoShuo Success.")
	}
}

func (this *DuoShuoDaoContainer) AddResults(p []Result) {

}

func (this *DuoShuoDaoContainer) DelResult(id interface{}) {

}

func (this *DuoShuoDaoContainer) DelResults(source string) {

}

func (this *DuoShuoDaoContainer) UpdateResult(p *Result) {

}

func (this *DuoShuoDaoContainer) AddOrUpdate(p *Result) {
	this.AddResult(p)
}

func (this *DuoShuoDaoContainer) GetResultById(id int) *Result {
	p := new(Result)
	return p
}

func (this *DuoShuoDaoContainer) GetResultByLink(url string) *Result {
	p := new(Result)
	return p
}

func (this *DuoShuoDaoContainer) GetResult(author, sort string, limit, start int) []Result {
	return nil
}

func (this *DuoShuoDaoContainer) IsResultUpdate(p *Result) bool {
	is_update := false
	return is_update
}

func (this *DuoShuoDaoContainer) Search(q string, limit, start int) (int, float64, []Result) {
	this.req.Method = "GET"
	this.req.Uri = "http://api.duoshuo.com/threads/listResults.json"
	this.req.ContentType = "application/x-www-form-urlencoded"

	// addDuoShuo := url.Values{}
	// addDuoShuo.Add("short_name", this.config.ShortName)
	// addDuoShuo.Add("secret", this.config.Secret)
	// addDuoShuo.Add("Results[0][Result_key]", p.Id)
	// addDuoShuo.Add("Results[0][thread_key]", "haixiuzu-cyeam")

	// duoshuo_byte, _ := json.Marshal(addDuoShuo)
	// addDuoShuo.Add("Results[0][message]", base64.URLEncoding.EncodeToString(duoshuo_byte))
	// this.req.Body = addDuoShuo.Encode()

	// resp, err := this.req.Do()
	// if err != nil {
	// 	panic(err)
	// }
	// if resp.StatusCode != 200 {
	// 	err_str, _ := resp.Body.ToString()
	// 	panic(err_str)
	// }
	return 0, 0, nil
}

func init() {
	Register("duoshuo", &DuoShuoDao{})
}
<commit_msg>add status code<commit_after>package dao

import (
	"encoding/base64"
	"encoding/json"
	"fmt"
	"log"
	"time"

	"github.com/franela/goreq"

	. "github.com/mnhkahn/maodou/models"
)

type DuoShuoConfig struct {
	ShortName string `json:"short_name"`
	Secret    string `json:"secret"`
	ThreadKey string `json:"thread_key"`
}

type DuoShuoDao struct {
}

func (this *DuoShuoDao) NewDaoImpl(dsn string) (DaoContainer, error) {
	d := new(DuoShuoDaoContainer)
	config := new(DuoShuoConfig)
	err := json.Unmarshal([]byte(dsn), config)
	d.config = config
	if err != nil {
		return d, fmt.Errorf("Config for duoshuo is error: %v", err)
	}

	return d, nil
}

type DuoShuoDaoContainer struct {
	config   *DuoShuoConfig
	is_debug bool
	req      goreq.Request
}

func (this *DuoShuoDaoContainer) Debug(is_debug bool) {
	this.req.ShowDebug = is_debug
}

func (this *DuoShuoDaoContainer) AddResult(p *Result) {
	this.req.Method = "POST"
	this.req.Uri = "http://api.duoshuo.com/posts/import.json"
	this.req.ContentType = "application/x-www-form-urlencoded"
	this.req.Timeout = time.Duration(10) * time.Second

	duoshuo_byte, _ := json.Marshal(*p)
	this.req.Body = fmt.Sprintf("short_name=%s&secret=%s&posts[0][post_key]=%s&posts[0][thread_key]=%s&posts[0][message]=%s", this.config.ShortName, this.config.Secret, p.Id, this.config.ThreadKey, base64.URLEncoding.EncodeToString(duoshuo_byte))
	resp, err := this.req.Do()
	if err != nil {
		log.Println(err.Error())
	}
	if resp == nil || resp.StatusCode != 200 {
		var err_str string
		if resp != nil {
			err_str, _ = fmt.Sprintf("%d %s", resp.StatusCode, resp.Body.ToString())
		}
		log.Printf("Error: %s\n", err_str)
	} else {
		log.Println("Add to DuoShuo Success.")
	}
}

func (this *DuoShuoDaoContainer) AddResults(p []Result) {

}

func (this *DuoShuoDaoContainer) DelResult(id interface{}) {

}

func (this *DuoShuoDaoContainer) DelResults(source string) {

}

func (this *DuoShuoDaoContainer) UpdateResult(p *Result) {

}

func (this *DuoShuoDaoContainer) AddOrUpdate(p *Result) {
	this.AddResult(p)
}

func (this *DuoShuoDaoContainer) GetResultById(id int) *Result {
	p := new(Result)
	return p
}

func (this *DuoShuoDaoContainer) GetResultByLink(url string) *Result {
	p := new(Result)
	return p
}

func (this *DuoShuoDaoContainer) GetResult(author, sort string, limit, start int) []Result {
	return nil
}

func (this *DuoShuoDaoContainer) IsResultUpdate(p *Result) bool {
	is_update := false
	return is_update
}

func (this *DuoShuoDaoContainer) Search(q string, limit, start int) (int, float64, []Result) {
	this.req.Method = "GET"
	this.req.Uri = "http://api.duoshuo.com/threads/listResults.json"
	this.req.ContentType = "application/x-www-form-urlencoded"

	// addDuoShuo := url.Values{}
	// addDuoShuo.Add("short_name", this.config.ShortName)
	// addDuoShuo.Add("secret", this.config.Secret)
	// addDuoShuo.Add("Results[0][Result_key]", p.Id)
	// addDuoShuo.Add("Results[0][thread_key]", "haixiuzu-cyeam")

	// duoshuo_byte, _ := json.Marshal(addDuoShuo)
	// addDuoShuo.Add("Results[0][message]", base64.URLEncoding.EncodeToString(duoshuo_byte))
	// this.req.Body = addDuoShuo.Encode()

	// resp, err := this.req.Do()
	// if err != nil {
	// 	panic(err)
	// }
	// if resp.StatusCode != 200 {
	// 	err_str, _ := resp.Body.ToString()
	// 	panic(err_str)
	// }
	return 0, 0, nil
}

func init() {
	Register("duoshuo", &DuoShuoDao{})
}
<|endoftext|>


<commit_before>// Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.

package provider

import (
	"testing"

	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"

	"fmt"

	"github.com/oracle/oci-go-sdk/core"
	"github.com/stretchr/testify/suite"
)

type DatasourceCoreImageTestSuite struct {
	suite.Suite
	Config                 string
	Providers              map[string]terraform.ResourceProvider
	ResourceName           string
	FilterExpression       string
	OperatingSystem        string
	OperatingSystemVersion string
}

func (s *DatasourceCoreImageTestSuite) SetupTest() {
	s.Providers = testAccProviders
	testAccPreCheck(s.T())
	s.Config = testProviderConfig()
	s.ResourceName = "data.oci_core_images.t"
	s.OperatingSystem = "Oracle Linux"
}

func (s *DatasourceCoreImageTestSuite) TestAccImage_basic() {
	resource.Test(s.T(), resource.TestCase{
		PreventPostDestroyRefresh: true,
		Providers:                 s.Providers,
		Steps: []resource.TestStep{
			{
				Config: s.Config + fmt.Sprintf(`
				data "oci_core_images" "allOracleImages" {
					compartment_id = "${var.tenancy_ocid}"
					operating_system = "%s"
					shape = "VM.Standard1.1"
				}

				data "oci_core_images" "t" {
					compartment_id = "${var.tenancy_ocid}"
					operating_system = "${lookup(data.oci_core_images.allOracleImages.images[0], "operating_system")}"
					operating_system_version = "${lookup(data.oci_core_images.allOracleImages.images[0], "operating_system_version")}"

					filter {
						name = "display_name"
						values = ["${lookup(data.oci_core_images.allOracleImages.images[0], "display_name")}"]
						regex = true
					}
				}`, s.OperatingSystem),
				Check: resource.ComposeAggregateTestCheckFunc(
					resource.TestCheckResourceAttr(s.ResourceName, "images.#", "1"),
					TestCheckResourceAttributesEqual(s.ResourceName, "images.0.id", "data.oci_core_images.allOracleImages", "images.0.id"),
					resource.TestCheckResourceAttr(s.ResourceName, "images.0.create_image_allowed", "true"),
					TestCheckResourceAttributesEqual(s.ResourceName, "images.0.display_name", "data.oci_core_images.allOracleImages", "images.0.display_name"),
					resource.TestCheckResourceAttr(s.ResourceName, "images.0.state", string(core.ImageLifecycleStateAvailable)),
					resource.TestCheckResourceAttr(s.ResourceName, "images.0.launch_mode", "NATIVE"),
					resource.TestCheckResourceAttr(s.ResourceName, "images.0.launch_options.#", "1"),
					resource.TestCheckResourceAttr(s.ResourceName, "images.0.launch_options.0.boot_volume_type", "ISCSI"),
					resource.TestCheckResourceAttr(s.ResourceName, "images.0.launch_options.0.firmware", "UEFI_64"),
					resource.TestCheckResourceAttr(s.ResourceName, "images.0.launch_options.0.network_type", "VFIO"),
					resource.TestCheckResourceAttr(s.ResourceName, "images.0.launch_options.0.remote_data_volume_type", "PARAVIRTUALIZED"),
					resource.TestCheckResourceAttr(s.ResourceName, "images.0.operating_system", s.OperatingSystem),
					TestCheckResourceAttributesEqual(s.ResourceName, "images.0.operating_system_version", "data.oci_core_images.allOracleImages", "images.0.operating_system_version"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "images.0.time_created"),
					// This test filters to official images, which do not derive from another so the below properties are expected to be null
					resource.TestCheckResourceAttr(s.ResourceName, "images.0.base_image_id", ""),
					resource.TestCheckResourceAttr(s.ResourceName, "images.0.instance_id", ""),
					resource.TestCheckResourceAttr(s.ResourceName, "images.0.compartment_id", ""),
				),
			},
		},
	},
	)
}

func TestDatasourceCoreImageTestSuite(t *testing.T) {
	suite.Run(t, new(DatasourceCoreImageTestSuite))
}
<commit_msg>Fix image datasource test to avoid checking for specific launch options<commit_after>// Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.

package provider

import (
	"testing"

	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"

	"fmt"

	"github.com/oracle/oci-go-sdk/core"
	"github.com/stretchr/testify/suite"
)

type DatasourceCoreImageTestSuite struct {
	suite.Suite
	Config                 string
	Providers              map[string]terraform.ResourceProvider
	ResourceName           string
	FilterExpression       string
	OperatingSystem        string
	OperatingSystemVersion string
}

func (s *DatasourceCoreImageTestSuite) SetupTest() {
	s.Providers = testAccProviders
	testAccPreCheck(s.T())
	s.Config = testProviderConfig()
	s.ResourceName = "data.oci_core_images.t"
	s.OperatingSystem = "Oracle Linux"
}

func (s *DatasourceCoreImageTestSuite) TestAccImage_basic() {
	resource.Test(s.T(), resource.TestCase{
		PreventPostDestroyRefresh: true,
		Providers:                 s.Providers,
		Steps: []resource.TestStep{
			{
				Config: s.Config + fmt.Sprintf(`
				data "oci_core_images" "allOracleImages" {
					compartment_id = "${var.tenancy_ocid}"
					operating_system = "%s"
					shape = "VM.Standard1.1"
				}

				data "oci_core_images" "t" {
					compartment_id = "${var.tenancy_ocid}"
					operating_system = "${lookup(data.oci_core_images.allOracleImages.images[0], "operating_system")}"
					operating_system_version = "${lookup(data.oci_core_images.allOracleImages.images[0], "operating_system_version")}"

					filter {
						name = "display_name"
						values = ["${lookup(data.oci_core_images.allOracleImages.images[0], "display_name")}"]
						regex = true
					}
				}`, s.OperatingSystem),
				Check: resource.ComposeAggregateTestCheckFunc(
					resource.TestCheckResourceAttr(s.ResourceName, "images.#", "1"),
					TestCheckResourceAttributesEqual(s.ResourceName, "images.0.id", "data.oci_core_images.allOracleImages", "images.0.id"),
					resource.TestCheckResourceAttr(s.ResourceName, "images.0.create_image_allowed", "true"),
					TestCheckResourceAttributesEqual(s.ResourceName, "images.0.display_name", "data.oci_core_images.allOracleImages", "images.0.display_name"),
					resource.TestCheckResourceAttr(s.ResourceName, "images.0.state", string(core.ImageLifecycleStateAvailable)),
					resource.TestCheckResourceAttrSet(s.ResourceName, "images.0.launch_mode"),
					resource.TestCheckResourceAttr(s.ResourceName, "images.0.launch_options.#", "1"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "images.0.launch_options.0.boot_volume_type"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "images.0.launch_options.0.firmware"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "images.0.launch_options.0.network_type"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "images.0.launch_options.0.remote_data_volume_type"),
					resource.TestCheckResourceAttr(s.ResourceName, "images.0.operating_system", s.OperatingSystem),
					TestCheckResourceAttributesEqual(s.ResourceName, "images.0.operating_system_version", "data.oci_core_images.allOracleImages", "images.0.operating_system_version"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "images.0.time_created"),
					// This test filters to official images, which do not derive from another so the below properties are expected to be null
					resource.TestCheckResourceAttr(s.ResourceName, "images.0.base_image_id", ""),
					resource.TestCheckResourceAttr(s.ResourceName, "images.0.instance_id", ""),
					resource.TestCheckResourceAttr(s.ResourceName, "images.0.compartment_id", ""),
				),
			},
		},
	},
	)
}

func TestDatasourceCoreImageTestSuite(t *testing.T) {
	suite.Run(t, new(DatasourceCoreImageTestSuite))
}
<|endoftext|>


<commit_before>// This package implements a provisioner for Packer that executes
// shell scripts within the remote machine.
package shell

import (
	"bufio"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"sort"
	"strings"
	"time"

	"github.com/mitchellh/packer/common"
	"github.com/mitchellh/packer/helper/config"
	"github.com/mitchellh/packer/packer"
	"github.com/mitchellh/packer/template/interpolate"
)

const DefaultRemotePath = "c:/Windows/Temp/script.bat"

var retryableSleep = 2 * time.Second

type Config struct {
	common.PackerConfig `mapstructure:",squash"`

	// If true, the script contains binary and line endings will not be
	// converted from Windows to Unix-style.
	Binary bool

	// An inline script to execute. Multiple strings are all executed
	// in the context of a single shell.
	Inline []string

	// The local path of the shell script to upload and execute.
	Script string

	// An array of multiple scripts to run.
	Scripts []string

	// An array of environment variables that will be injected before
	// your command(s) are executed.
	Vars []string `mapstructure:"environment_vars"`

	// The remote path where the local shell script will be uploaded to.
	// This should be set to a writable file that is in a pre-existing directory.
	RemotePath string `mapstructure:"remote_path"`

	// The command used to execute the script. The '{{ .Path }}' variable
	// should be used to specify where the script goes, {{ .Vars }}
	// can be used to inject the environment_vars into the environment.
	ExecuteCommand string `mapstructure:"execute_command"`

	// The timeout for retrying to start the process. Until this timeout
	// is reached, if the provisioner can't start a process, it retries.
	// This can be set high to allow for reboots.
	StartRetryTimeout time.Duration `mapstructure:"start_retry_timeout"`

	// This is used in the template generation to format environment variables
	// inside the `ExecuteCommand` template.
	EnvVarFormat string

	ctx interpolate.Context
}

type Provisioner struct {
	config Config
}

type ExecuteCommandTemplate struct {
	Vars string
	Path string
}

func (p *Provisioner) Prepare(raws ...interface{}) error {
	err := config.Decode(&p.config, &config.DecodeOpts{
		Interpolate:        true,
		InterpolateContext: &p.config.ctx,
		InterpolateFilter: &interpolate.RenderFilter{
			Exclude: []string{
				"execute_command",
			},
		},
	}, raws...)
	if err != nil {
		return err
	}

	if p.config.EnvVarFormat == "" {
		p.config.EnvVarFormat = `set "%s=%s" && `
	}

	if p.config.ExecuteCommand == "" {
		p.config.ExecuteCommand = `{{.Vars}}"{{.Path}}"`
	}

	if p.config.Inline != nil && len(p.config.Inline) == 0 {
		p.config.Inline = nil
	}

	if p.config.StartRetryTimeout == 0 {
		p.config.StartRetryTimeout = 5 * time.Minute
	}

	if p.config.RemotePath == "" {
		p.config.RemotePath = DefaultRemotePath
	}

	if p.config.Scripts == nil {
		p.config.Scripts = make([]string, 0)
	}

	if p.config.Vars == nil {
		p.config.Vars = make([]string, 0)
	}

	var errs error
	if p.config.Script != "" && len(p.config.Scripts) > 0 {
		errs = packer.MultiErrorAppend(errs,
			errors.New("Only one of script or scripts can be specified."))
	}

	if p.config.Script != "" {
		p.config.Scripts = []string{p.config.Script}
	}

	if len(p.config.Scripts) == 0 && p.config.Inline == nil {
		errs = packer.MultiErrorAppend(errs,
			errors.New("Either a script file or inline script must be specified."))
	} else if len(p.config.Scripts) > 0 && p.config.Inline != nil {
		errs = packer.MultiErrorAppend(errs,
			errors.New("Only a script file or an inline script can be specified, not both."))
	}

	for _, path := range p.config.Scripts {
		if _, err := os.Stat(path); err != nil {
			errs = packer.MultiErrorAppend(errs,
				fmt.Errorf("Bad script '%s': %s", path, err))
		}
	}

	// Do a check for bad environment variables, such as '=foo', 'foobar'
	for _, kv := range p.config.Vars {
		vs := strings.SplitN(kv, "=", 2)
		if len(vs) != 2 || vs[0] == "" {
			errs = packer.MultiErrorAppend(errs,
				fmt.Errorf("Environment variable not in format 'key=value': %s", kv))
		}
	}

	if errs != nil {
		return errs
	}

	return nil
}

// This function takes the inline scripts, concatenates them
// into a temporary file and returns a string containing the location
// of said file.
func extractScript(p *Provisioner) (string, error) {
	temp, err := ioutil.TempFile(os.TempDir(), "packer-windows-shell-provisioner")
	if err != nil {
		log.Printf("Unable to create temporary file for inline scripts: %s", err)
		return "", err
	}
	writer := bufio.NewWriter(temp)
	for _, command := range p.config.Inline {
		log.Printf("Found command: %s", command)
		if _, err := writer.WriteString(command + "\n"); err != nil {
			return "", fmt.Errorf("Error preparing shell script: %s", err)
		}
	}

	if err := writer.Flush(); err != nil {
		return "", fmt.Errorf("Error preparing shell script: %s", err)
	}

	temp.Close()

	return temp.Name(), nil
}

func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error {
	ui.Say(fmt.Sprintf("Provisioning with windows-shell..."))
	scripts := make([]string, len(p.config.Scripts))
	copy(scripts, p.config.Scripts)

	if p.config.Inline != nil {
		temp, err := extractScript(p)
		if err != nil {
			ui.Error(fmt.Sprintf("Unable to extract inline scripts into a file: %s", err))
		}
		scripts = append(scripts, temp)
	}

	for _, path := range scripts {
		ui.Say(fmt.Sprintf("Provisioning with shell script: %s", path))

		log.Printf("Opening %s for reading", path)
		f, err := os.Open(path)
		if err != nil {
			return fmt.Errorf("Error opening shell script: %s", err)
		}
		defer f.Close()

		// Create environment variables to set before executing the command
		flattendVars, err := p.createFlattenedEnvVars()
		if err != nil {
			return err
		}

		// Compile the command
		p.config.ctx.Data = &ExecuteCommandTemplate{
			Vars: flattendVars,
			Path: p.config.RemotePath,
		}
		command, err := interpolate.Render(p.config.ExecuteCommand, &p.config.ctx)
		if err != nil {
			return fmt.Errorf("Error processing command: %s", err)
		}

		// Upload the file and run the command. Do this in the context of
		// a single retryable function so that we don't end up with
		// the case that the upload succeeded, a restart is initiated,
		// and then the command is executed but the file doesn't exist
		// any longer.
		var cmd *packer.RemoteCmd
		err = p.retryable(func() error {
			if _, err := f.Seek(0, 0); err != nil {
				return err
			}

			if err := comm.Upload(p.config.RemotePath, f, nil); err != nil {
				return fmt.Errorf("Error uploading script: %s", err)
			}

			cmd = &packer.RemoteCmd{Command: command}
			return cmd.StartWithUi(comm, ui)
		})
		if err != nil {
			return err
		}

		// Close the original file since we copied it
		f.Close()

		if cmd.ExitStatus != 0 {
			return fmt.Errorf("Script exited with non-zero exit status: %d", cmd.ExitStatus)
		}
	}

	return nil
}

func (p *Provisioner) Cancel() {
	// Just hard quit. It isn't a big deal if what we're doing keeps
	// running on the other side.
	os.Exit(0)
}

// retryable will retry the given function over and over until a
// non-error is returned.
func (p *Provisioner) retryable(f func() error) error {
	startTimeout := time.After(p.config.StartRetryTimeout)
	for {
		var err error
		if err = f(); err == nil {
			return nil
		}

		// Create an error and log it
		err = fmt.Errorf("Retryable error: %s", err)
		log.Printf(err.Error())

		// Check if we timed out, otherwise we retry. It is safe to
		// retry since the only error case above is if the command
		// failed to START.
		select {
		case <-startTimeout:
			return err
		default:
			time.Sleep(retryableSleep)
		}
	}
}

func (p *Provisioner) createFlattenedEnvVars() (flattened string, err error) {
	flattened = ""
	envVars := make(map[string]string)

	// Always available Packer provided env vars
	envVars["PACKER_BUILD_NAME"] = p.config.PackerBuildName
	envVars["PACKER_BUILDER_TYPE"] = p.config.PackerBuilderType
	httpAddr := common.GetHTTPAddr()
	if httpAddr != "" {
		envVars["PACKER_HTTP_ADDR"] = httpAddr
	}

	// Split vars into key/value components
	for _, envVar := range p.config.Vars {
		keyValue := strings.Split(envVar, "=")
		if len(keyValue) != 2 || keyValue[0] == "" {
			err = errors.New(fmt.Sprintf("Shell provisioner environment variables must be in key=value format. Currently it is '%s'", envVar))
			return
		}
		envVars[keyValue[0]] = keyValue[1]
	}
	// Create a list of env var keys in sorted order
	var keys []string
	for k := range envVars {
		keys = append(keys, k)
	}
	sort.Strings(keys)
	// Re-assemble vars using OS specific format pattern and flatten
	for _, key := range keys {
		flattened += fmt.Sprintf(p.config.EnvVarFormat, key, envVars[key])
	}
	return
}
<commit_msg>Fix to allow equals in value of environment variable. Mirrors #4328<commit_after>// This package implements a provisioner for Packer that executes
// shell scripts within the remote machine.
package shell

import (
	"bufio"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"sort"
	"strings"
	"time"

	"github.com/mitchellh/packer/common"
	"github.com/mitchellh/packer/helper/config"
	"github.com/mitchellh/packer/packer"
	"github.com/mitchellh/packer/template/interpolate"
)

const DefaultRemotePath = "c:/Windows/Temp/script.bat"

var retryableSleep = 2 * time.Second

type Config struct {
	common.PackerConfig `mapstructure:",squash"`

	// If true, the script contains binary and line endings will not be
	// converted from Windows to Unix-style.
	Binary bool

	// An inline script to execute. Multiple strings are all executed
	// in the context of a single shell.
	Inline []string

	// The local path of the shell script to upload and execute.
	Script string

	// An array of multiple scripts to run.
	Scripts []string

	// An array of environment variables that will be injected before
	// your command(s) are executed.
	Vars []string `mapstructure:"environment_vars"`

	// The remote path where the local shell script will be uploaded to.
	// This should be set to a writable file that is in a pre-existing directory.
	RemotePath string `mapstructure:"remote_path"`

	// The command used to execute the script. The '{{ .Path }}' variable
	// should be used to specify where the script goes, {{ .Vars }}
	// can be used to inject the environment_vars into the environment.
	ExecuteCommand string `mapstructure:"execute_command"`

	// The timeout for retrying to start the process. Until this timeout
	// is reached, if the provisioner can't start a process, it retries.
	// This can be set high to allow for reboots.
	StartRetryTimeout time.Duration `mapstructure:"start_retry_timeout"`

	// This is used in the template generation to format environment variables
	// inside the `ExecuteCommand` template.
	EnvVarFormat string

	ctx interpolate.Context
}

type Provisioner struct {
	config Config
}

type ExecuteCommandTemplate struct {
	Vars string
	Path string
}

func (p *Provisioner) Prepare(raws ...interface{}) error {
	err := config.Decode(&p.config, &config.DecodeOpts{
		Interpolate:        true,
		InterpolateContext: &p.config.ctx,
		InterpolateFilter: &interpolate.RenderFilter{
			Exclude: []string{
				"execute_command",
			},
		},
	}, raws...)
	if err != nil {
		return err
	}

	if p.config.EnvVarFormat == "" {
		p.config.EnvVarFormat = `set "%s=%s" && `
	}

	if p.config.ExecuteCommand == "" {
		p.config.ExecuteCommand = `{{.Vars}}"{{.Path}}"`
	}

	if p.config.Inline != nil && len(p.config.Inline) == 0 {
		p.config.Inline = nil
	}

	if p.config.StartRetryTimeout == 0 {
		p.config.StartRetryTimeout = 5 * time.Minute
	}

	if p.config.RemotePath == "" {
		p.config.RemotePath = DefaultRemotePath
	}

	if p.config.Scripts == nil {
		p.config.Scripts = make([]string, 0)
	}

	if p.config.Vars == nil {
		p.config.Vars = make([]string, 0)
	}

	var errs error
	if p.config.Script != "" && len(p.config.Scripts) > 0 {
		errs = packer.MultiErrorAppend(errs,
			errors.New("Only one of script or scripts can be specified."))
	}

	if p.config.Script != "" {
		p.config.Scripts = []string{p.config.Script}
	}

	if len(p.config.Scripts) == 0 && p.config.Inline == nil {
		errs = packer.MultiErrorAppend(errs,
			errors.New("Either a script file or inline script must be specified."))
	} else if len(p.config.Scripts) > 0 && p.config.Inline != nil {
		errs = packer.MultiErrorAppend(errs,
			errors.New("Only a script file or an inline script can be specified, not both."))
	}

	for _, path := range p.config.Scripts {
		if _, err := os.Stat(path); err != nil {
			errs = packer.MultiErrorAppend(errs,
				fmt.Errorf("Bad script '%s': %s", path, err))
		}
	}

	// Do a check for bad environment variables, such as '=foo', 'foobar'
	for _, kv := range p.config.Vars {
		vs := strings.SplitN(kv, "=", 2)
		if len(vs) != 2 || vs[0] == "" {
			errs = packer.MultiErrorAppend(errs,
				fmt.Errorf("Environment variable not in format 'key=value': %s", kv))
		}
	}

	if errs != nil {
		return errs
	}

	return nil
}

// This function takes the inline scripts, concatenates them
// into a temporary file and returns a string containing the location
// of said file.
func extractScript(p *Provisioner) (string, error) {
	temp, err := ioutil.TempFile(os.TempDir(), "packer-windows-shell-provisioner")
	if err != nil {
		log.Printf("Unable to create temporary file for inline scripts: %s", err)
		return "", err
	}
	writer := bufio.NewWriter(temp)
	for _, command := range p.config.Inline {
		log.Printf("Found command: %s", command)
		if _, err := writer.WriteString(command + "\n"); err != nil {
			return "", fmt.Errorf("Error preparing shell script: %s", err)
		}
	}

	if err := writer.Flush(); err != nil {
		return "", fmt.Errorf("Error preparing shell script: %s", err)
	}

	temp.Close()

	return temp.Name(), nil
}

func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error {
	ui.Say(fmt.Sprintf("Provisioning with windows-shell..."))
	scripts := make([]string, len(p.config.Scripts))
	copy(scripts, p.config.Scripts)

	if p.config.Inline != nil {
		temp, err := extractScript(p)
		if err != nil {
			ui.Error(fmt.Sprintf("Unable to extract inline scripts into a file: %s", err))
		}
		scripts = append(scripts, temp)
	}

	for _, path := range scripts {
		ui.Say(fmt.Sprintf("Provisioning with shell script: %s", path))

		log.Printf("Opening %s for reading", path)
		f, err := os.Open(path)
		if err != nil {
			return fmt.Errorf("Error opening shell script: %s", err)
		}
		defer f.Close()

		// Create environment variables to set before executing the command
		flattendVars, err := p.createFlattenedEnvVars()
		if err != nil {
			return err
		}

		// Compile the command
		p.config.ctx.Data = &ExecuteCommandTemplate{
			Vars: flattendVars,
			Path: p.config.RemotePath,
		}
		command, err := interpolate.Render(p.config.ExecuteCommand, &p.config.ctx)
		if err != nil {
			return fmt.Errorf("Error processing command: %s", err)
		}

		// Upload the file and run the command. Do this in the context of
		// a single retryable function so that we don't end up with
		// the case that the upload succeeded, a restart is initiated,
		// and then the command is executed but the file doesn't exist
		// any longer.
		var cmd *packer.RemoteCmd
		err = p.retryable(func() error {
			if _, err := f.Seek(0, 0); err != nil {
				return err
			}

			if err := comm.Upload(p.config.RemotePath, f, nil); err != nil {
				return fmt.Errorf("Error uploading script: %s", err)
			}

			cmd = &packer.RemoteCmd{Command: command}
			return cmd.StartWithUi(comm, ui)
		})
		if err != nil {
			return err
		}

		// Close the original file since we copied it
		f.Close()

		if cmd.ExitStatus != 0 {
			return fmt.Errorf("Script exited with non-zero exit status: %d", cmd.ExitStatus)
		}
	}

	return nil
}

func (p *Provisioner) Cancel() {
	// Just hard quit. It isn't a big deal if what we're doing keeps
	// running on the other side.
	os.Exit(0)
}

// retryable will retry the given function over and over until a
// non-error is returned.
func (p *Provisioner) retryable(f func() error) error {
	startTimeout := time.After(p.config.StartRetryTimeout)
	for {
		var err error
		if err = f(); err == nil {
			return nil
		}

		// Create an error and log it
		err = fmt.Errorf("Retryable error: %s", err)
		log.Printf(err.Error())

		// Check if we timed out, otherwise we retry. It is safe to
		// retry since the only error case above is if the command
		// failed to START.
		select {
		case <-startTimeout:
			return err
		default:
			time.Sleep(retryableSleep)
		}
	}
}

func (p *Provisioner) createFlattenedEnvVars() (flattened string, err error) {
	flattened = ""
	envVars := make(map[string]string)

	// Always available Packer provided env vars
	envVars["PACKER_BUILD_NAME"] = p.config.PackerBuildName
	envVars["PACKER_BUILDER_TYPE"] = p.config.PackerBuilderType
	httpAddr := common.GetHTTPAddr()
	if httpAddr != "" {
		envVars["PACKER_HTTP_ADDR"] = httpAddr
	}

	// Split vars into key/value components
	for _, envVar := range p.config.Vars {
		keyValue := strings.SplitN(envVar, "=", 2)
		if len(keyValue) != 2 || keyValue[0] == "" {
			err = errors.New(fmt.Sprintf("Shell provisioner environment variables must be in key=value format. Currently it is '%s'", envVar))
			return
		}
		envVars[keyValue[0]] = keyValue[1]
	}
	// Create a list of env var keys in sorted order
	var keys []string
	for k := range envVars {
		keys = append(keys, k)
	}
	sort.Strings(keys)
	// Re-assemble vars using OS specific format pattern and flatten
	for _, key := range keys {
		flattened += fmt.Sprintf(p.config.EnvVarFormat, key, envVars[key])
	}
	return
}
<|endoftext|>


<commit_before>package app

import (
	"errors"

	"github.com/ubclaunchpad/cumulus/blockchain"
	"github.com/ubclaunchpad/cumulus/msg"

	crand "crypto/rand"
)

// User holds basic user information.
type User struct {
	*blockchain.Wallet
	BlockSize uint32
}

// NewUser creates a new user
func NewUser() *User {
	return &User{
		Wallet:    blockchain.NewWallet(),
		BlockSize: blockchain.DefaultBlockSize,
	}
}

// getCurrentUser gets the current user function only used for app initalization.
func getCurrentUser() *User {
	// TODO: Check for local user information on disk,
	// If doesnt exist, create new user.
	return NewUser()
}

// Pay pays an amount of coin to an address `to`.
func (a *App) Pay(to string, amount uint64) error {
	// Four atomic steps must occur.
	wallet := a.CurrentUser.Wallet
	pool := a.Pool

	// A legitimate transaction must be built.
	tbody := blockchain.TxBody{
		Sender: wallet.Public(),
		// TODO: Collect inputs.
		Input: blockchain.TxHashPointer{},
		Outputs: []blockchain.TxOutput{
			blockchain.TxOutput{
				Recipient: to,
				Amount:    amount,
			},
		},
	}

	// The transaction must be signed.
	if txn, err := tbody.Sign(*a.CurrentUser.Wallet, crand.Reader); err == nil {

		// The transaction must be broadcasted to the peers.
		if err := wallet.SetPending(txn); err != nil {
			return err
		}

		// The transaction must be added to the pool.
		if !pool.Push(txn, a.Chain) {
			return errors.New("transaction validation failed")
		}

		// The transaction must be broadcasted to the network.
		a.PeerStore.Broadcast(msg.Push{
			ResourceType: msg.ResourceTransaction,
			Resource:     txn,
		})

	} else {
		return err
	}

	return nil
}
<commit_msg>comments<commit_after>package app

import (
	"errors"

	"github.com/ubclaunchpad/cumulus/blockchain"
	"github.com/ubclaunchpad/cumulus/msg"

	crand "crypto/rand"
)

// User holds basic user information.
type User struct {
	*blockchain.Wallet
	BlockSize uint32
}

// NewUser creates a new user
func NewUser() *User {
	return &User{
		Wallet:    blockchain.NewWallet(),
		BlockSize: blockchain.DefaultBlockSize,
	}
}

// getCurrentUser gets the current user function only used for app initalization.
func getCurrentUser() *User {
	// TODO: Check for local user information on disk,
	// If doesnt exist, create new user.
	return NewUser()
}

// Pay pays an amount of coin to an address `to`.
func (a *App) Pay(to string, amount uint64) error {
	// Four steps must occur.
	wallet := a.CurrentUser.Wallet
	pool := a.Pool

	// A legitimate transaction must be built.
	tbody := blockchain.TxBody{
		Sender: wallet.Public(),
		// TODO: Collect inputs.
		Input: blockchain.TxHashPointer{},
		Outputs: []blockchain.TxOutput{
			blockchain.TxOutput{
				Recipient: to,
				Amount:    amount,
			},
		},
	}

	// The transaction must be signed.
	if txn, err := tbody.Sign(*a.CurrentUser.Wallet, crand.Reader); err == nil {

		// The transaction must be broadcasted to the peers.
		if err := wallet.SetPending(txn); err != nil {
			return err
		}

		// The transaction must be added to the pool.
		if !pool.Push(txn, a.Chain) {
			return errors.New("transaction validation failed")
		}

		// The transaction must be broadcasted to the network.
		a.PeerStore.Broadcast(msg.Push{
			ResourceType: msg.ResourceTransaction,
			Resource:     txn,
		})

	} else {
		return err
	}

	return nil
}
<|endoftext|>


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

package pals

import (
	"code.google.com/p/biogo/align/pals/dp"
	"code.google.com/p/biogo/feat"
	"code.google.com/p/biogo/io/featio/gff"
	"code.google.com/p/biogo/seq"

	"fmt"
	"strconv"
	"strings"
)

// A Pair holds a pair of features with additional information relating the two.
type Pair struct {
	A, B   feat.Feature
	Score  int        // Score of alignment between features.
	Error  float64    // Identity difference between feature sequences.
	Strand seq.Strand // Strand relationship: seq.Plus indicates same strand, seq.Minus indicates opposite strand.
}

func (fp *Pair) String() string {
	return fmt.Sprintf("%s/%s[%d,%d)--%s/%s[%d,%d)",
		fp.A.Location().Location().Name(), fp.A.Name(), fp.A.Start(), fp.A.End(),
		fp.B.Location().Location().Name(), fp.B.Name(), fp.B.Start(), fp.B.End(),
	)
}

// NewPair converts a DPHit and two packed sequences into a Pair.
func NewPair(target, query *Packed, hit dp.DPHit, comp bool) (*Pair, error) {
	t, err := target.feature(hit.Abpos, hit.Aepos, false)
	if err != nil {
		return nil, err
	}
	q, err := query.feature(hit.Bbpos, hit.Bepos, comp)
	if err != nil {
		return nil, err
	}

	var strand seq.Strand
	if comp {
		strand = -1
	} else {
		strand = 1
	}

	return &Pair{
		A:      t,
		B:      q,
		Score:  hit.Score,
		Error:  hit.Error,
		Strand: strand,
	}, nil
}

// ExpandFeature converts an old-style *feat.Feature (package temporarily renamed to gff for collision avoidance) containing a PALS-type feature attribute
// into a Pair.
func ExpandFeature(f *gff.Feature) (*Pair, error) {
	targ := f.FeatAttributes.Get("Target")
	if targ == "" {
		return nil, fmt.Errorf("pals: not a feature pair")
	}
	fields := strings.Fields(targ)
	if len(fields) != 3 {
		return nil, fmt.Errorf("pals: not a feature pair")
	}

	s, err := strconv.Atoi(fields[1])
	if err != nil {
		return nil, err
	}
	s--
	e, err := strconv.Atoi(fields[2])
	if err != nil {
		return nil, err
	}

	maxe, err := strconv.ParseFloat(f.FeatAttributes.Get("maxe"), 64)
	if err != nil {
		return nil, err
	}

	fp := &Pair{
		A: &Feature{
			ID:   fmt.Sprintf("%s:%d..%d", f.SeqName, f.FeatStart, f.FeatEnd),
			Loc:  Contig(f.SeqName),
			From: f.FeatStart,
			To:   f.FeatEnd,
		},
		B: &Feature{
			ID:   fmt.Sprintf("%s:%d..%d", fields[0], s, e),
			Loc:  Contig(fields[0]),
			From: s,
			To:   e,
		},
		Score:  int(*f.FeatScore),
		Error:  maxe,
		Strand: f.FeatStrand,
	}
	f.FeatScore = nil
	f.FeatAttributes = nil
	f.FeatStrand = seq.None

	return fp, nil
}

// Invert returns a reversed copy of the feature pair such that A', B' = B, A.
func (fp *Pair) Invert() *Pair {
	return &Pair{
		A:      fp.B,
		B:      fp.A,
		Score:  fp.Score,
		Error:  fp.Error,
		Strand: fp.Strand,
	}
}
<commit_msg>Don't call Itoa when not necessary<commit_after>// Copyright ©2011-2012 The bíogo Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package pals

import (
	"code.google.com/p/biogo/align/pals/dp"
	"code.google.com/p/biogo/feat"
	"code.google.com/p/biogo/io/featio/gff"
	"code.google.com/p/biogo/seq"

	"fmt"
	"strconv"
	"strings"
)

// A Pair holds a pair of features with additional information relating the two.
type Pair struct {
	A, B   feat.Feature
	Score  int        // Score of alignment between features.
	Error  float64    // Identity difference between feature sequences.
	Strand seq.Strand // Strand relationship: seq.Plus indicates same strand, seq.Minus indicates opposite strand.
}

func (fp *Pair) String() string {
	return fmt.Sprintf("%s/%s[%d,%d)--%s/%s[%d,%d)",
		fp.A.Location().Location().Name(), fp.A.Name(), fp.A.Start(), fp.A.End(),
		fp.B.Location().Location().Name(), fp.B.Name(), fp.B.Start(), fp.B.End(),
	)
}

// NewPair converts a DPHit and two packed sequences into a Pair.
func NewPair(target, query *Packed, hit dp.DPHit, comp bool) (*Pair, error) {
	t, err := target.feature(hit.Abpos, hit.Aepos, false)
	if err != nil {
		return nil, err
	}
	q, err := query.feature(hit.Bbpos, hit.Bepos, comp)
	if err != nil {
		return nil, err
	}

	var strand seq.Strand
	if comp {
		strand = -1
	} else {
		strand = 1
	}

	return &Pair{
		A:      t,
		B:      q,
		Score:  hit.Score,
		Error:  hit.Error,
		Strand: strand,
	}, nil
}

// ExpandFeature converts an old-style *feat.Feature (package temporarily renamed to gff for collision avoidance) containing a PALS-type feature attribute
// into a Pair.
func ExpandFeature(f *gff.Feature) (*Pair, error) {
	targ := f.FeatAttributes.Get("Target")
	if targ == "" {
		return nil, fmt.Errorf("pals: not a feature pair")
	}
	fields := strings.Fields(targ)
	if len(fields) != 3 {
		return nil, fmt.Errorf("pals: not a feature pair")
	}

	s, err := strconv.Atoi(fields[1])
	if err != nil {
		return nil, err
	}
	s--
	e, err := strconv.Atoi(fields[2])
	if err != nil {
		return nil, err
	}

	maxe, err := strconv.ParseFloat(f.FeatAttributes.Get("maxe"), 64)
	if err != nil {
		return nil, err
	}

	fp := &Pair{
		A: &Feature{
			ID:   fmt.Sprintf("%s:%d..%d", f.SeqName, f.FeatStart, f.FeatEnd),
			Loc:  Contig(f.SeqName),
			From: f.FeatStart,
			To:   f.FeatEnd,
		},
		B: &Feature{
			ID:   fmt.Sprintf("%s:%d..%s", fields[0], s, fields[2]),
			Loc:  Contig(fields[0]),
			From: s,
			To:   e,
		},
		Score:  int(*f.FeatScore),
		Error:  maxe,
		Strand: f.FeatStrand,
	}
	f.FeatScore = nil
	f.FeatAttributes = nil
	f.FeatStrand = seq.None

	return fp, nil
}

// Invert returns a reversed copy of the feature pair such that A', B' = B, A.
func (fp *Pair) Invert() *Pair {
	return &Pair{
		A:      fp.B,
		B:      fp.A,
		Score:  fp.Score,
		Error:  fp.Error,
		Strand: fp.Strand,
	}
}
<|endoftext|>


<commit_before>// Example of how to upload sensor data from SmartThings sensors to ThingSpeak
// using the GoSmart libraries.
//
// This file is part of gosmart, a set of libraries to communicate with
// the Samsumg SmartThings API using Go (golang).
//
// http://github.com/marcopaganini/gosmart
// (C) 2016 by Marco Paganini <paganini@paganini.net>

package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"github.com/marcopaganini/gosmart"
	"golang.org/x/net/context"
	"golang.org/x/oauth2"
	"io/ioutil"
	"log"
	"net/http"
)

const (
	tokenFile         = ".smartthings-thingspeak.json"
	thingSpeakBaseURL = "https://api.thingspeak.com/update?api_key="
)

// TempCapability represents the information returned by the
// Temperature Capability in Smartthings.
type TempCapability struct {
	Name  string `json:"name"`
	Value int    `json:"value"`
}

// tsChannelMap maps a SmartThings sensor name to a ThingSpeak field ID.
type tsChannelMap map[string]int

var (
	flagClient = flag.String("client", "", "OAuth Client ID")
	flagSecret = flag.String("secret", "", "OAuth Secret")
	flagAPIKey = flag.String("apikey", "", "ThingSpeak write API key")

	// tscmap maps the sensor names to the ThingSpeak channel field numbers.
	// All SmartThings temperature capable sensors must be added here.
	tscmap = tsChannelMap{
		"Front Door Sensor":           1,
		"Garage Door Sensor":          2,
		"Laundry Door Sensor":         3,
		"Upper Hallway Motion Sensor": 4,
	}

	config *oauth2.Config
)

func main() {
	flag.Parse()

	// No date on log messages
	log.SetFlags(0)

	// Command line processing
	if *flagAPIKey == "" {
		log.Fatalln("Need API key (--apikey)")
	}

	// Retrieve token
	config = gosmart.NewOAuthConfig(*flagClient, *flagSecret)
	token, err := gosmart.GetToken(tokenFile, config)
	if err != nil {
		log.Fatalln(err)
	}

	// Create a client with token.
	ctx := context.Background()
	client := config.Client(ctx, token)

	// Retrieve Endpoints URI.
	endpoint, err := gosmart.GetEndPointsURI(client)
	if err != nil {
		log.Fatalln(err)
		return
	}
	temps, err := fetchTemperature(client, endpoint)
	if err != nil {
		log.Fatalln(err)
	}
	if err = updateThingSpeak(tscmap, temps, *flagAPIKey); err != nil {
		log.Fatalln(err)
	}
}

// fetchTemperature retrieves the temperature from all sensors in SmartThings.
func fetchTemperature(client *http.Client, endpoint string) ([]TempCapability, error) {
	// Fetch temperature from ST
	resp, err := client.Get(endpoint + "/temperature")
	if err != nil {
		return nil, err
	}

	contents, err := ioutil.ReadAll(resp.Body)
	resp.Body.Close()

	// Convert to JSON
	var temps []TempCapability
	err = json.Unmarshal(contents, &temps)
	if err != nil {
		return nil, fmt.Errorf("error decoding JSON: %q", err)
	}
	return temps, nil
}

// updateThingSpeak updates a thingspeak channel with the relevant data.
func updateThingSpeak(tscmap tsChannelMap, temps []TempCapability, apikey string) error {
	var fieldno int

	// Thingspeak uses fieldN fieldnames in their channels.  We use
	// tsChannelMap to retrieve the correspondence between sensor name and
	// ThingSpeak channel field number.
	req := ""
	for _, t := range temps {
		ok := false
		if fieldno, ok = tscmap[t.Name]; !ok {
			log.Printf("Unable to find ThingSpeak field for %q", t.Name)
			continue
		}
		req += fmt.Sprintf("&field%d=%d", fieldno, t.Value)
	}
	// Make request
	url := thingSpeakBaseURL + apikey + req
	resp, err := http.Get(url)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	// Check for application level errors
	if resp.StatusCode < 200 || resp.StatusCode > 299 {
		return fmt.Errorf("Got HTTP return code %d for %q\n", resp.StatusCode, url)
	}
	return nil
}
<commit_msg>Small code fixes.<commit_after>// Example of how to upload sensor data from SmartThings sensors to ThingSpeak
// using the GoSmart libraries.
//
// This file is part of gosmart, a set of libraries to communicate with
// the Samsumg SmartThings API using Go (golang).
//
// http://github.com/marcopaganini/gosmart
// (C) 2016 by Marco Paganini <paganini@paganini.net>

package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"github.com/marcopaganini/gosmart"
	"golang.org/x/net/context"
	"io/ioutil"
	"log"
	"net/http"
)

const (
	tokenFile         = ".smartthings-thingspeak.json"
	thingSpeakBaseURL = "https://api.thingspeak.com/update?api_key="
)

// TempCapability represents the information returned by the
// Temperature Capability in SmartThings.
type TempCapability struct {
	Name  string `json:"name"`
	Value int    `json:"value"`
}

// tsChannelMap maps a SmartThings sensor name to a ThingSpeak field ID.
type tsChannelMap map[string]int

var (
	flagClient = flag.String("client", "", "OAuth Client ID")
	flagSecret = flag.String("secret", "", "OAuth Secret")
	flagAPIKey = flag.String("apikey", "", "ThingSpeak write API key")

	// tscmap maps the sensor names to the ThingSpeak channel field numbers.
	// All SmartThings temperature capable sensors must be added here. The
	// values here are just examples.
	tscmap = tsChannelMap{
		"Front Door Sensor":           1,
		"Garage Door Sensor":          2,
		"Laundry Door Sensor":         3,
		"Upper Hallway Motion Sensor": 4,
	}
)

func main() {
	flag.Parse()

	// No date on log messages
	log.SetFlags(0)

	// Command line processing
	if *flagAPIKey == "" {
		log.Fatalln("Need ThingSpeak write API key (--apikey)")
	}

	// Retrieve token
	config := gosmart.NewOAuthConfig(*flagClient, *flagSecret)
	token, err := gosmart.GetToken(tokenFile, config)
	if err != nil {
		log.Fatalln(err)
	}

	// Create a client with token.
	ctx := context.Background()
	client := config.Client(ctx, token)

	// Retrieve Endpoints URI.
	endpoint, err := gosmart.GetEndPointsURI(client)
	if err != nil {
		log.Fatalln(err)
		return
	}
	temps, err := fetchTemperature(client, endpoint)
	if err != nil {
		log.Fatalln(err)
	}
	if err = updateThingSpeak(tscmap, temps, *flagAPIKey); err != nil {
		log.Fatalln(err)
	}
}

// fetchTemperature retrieves the temperature from all sensors in SmartThings.
func fetchTemperature(client *http.Client, endpoint string) ([]TempCapability, error) {
	// Fetch temperature from ST
	resp, err := client.Get(endpoint + "/temperature")
	if err != nil {
		return nil, err
	}

	contents, err := ioutil.ReadAll(resp.Body)
	resp.Body.Close()

	// Convert to JSON
	var temps []TempCapability
	err = json.Unmarshal(contents, &temps)
	if err != nil {
		return nil, fmt.Errorf("error decoding JSON: %q", err)
	}
	return temps, nil
}

// updateThingSpeak updates a thingspeak channel with the relevant data.
func updateThingSpeak(tscmap tsChannelMap, temps []TempCapability, apikey string) error {
	// Thingspeak uses fieldN fieldnames in their channels.  We use
	// tsChannelMap to retrieve the correspondence between sensor name and
	// ThingSpeak channel field number.
	req := ""
	for _, t := range temps {
		fieldno, ok := tscmap[t.Name]
		if !ok {
			log.Printf("Unable to find ThingSpeak field for %q", t.Name)
			continue
		}
		req += fmt.Sprintf("&field%d=%d", fieldno, t.Value)
	}
	// Make request
	url := thingSpeakBaseURL + apikey + req
	resp, err := http.Get(url)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	// Check for application level errors
	if resp.StatusCode < 200 || resp.StatusCode > 299 {
		return fmt.Errorf("Got HTTP return code %d for %q\n", resp.StatusCode, url)
	}
	return nil
}
<|endoftext|>


<commit_before>package gitlab

import (
	"encoding/json"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
)

var configFilePath = filepath.Join(os.Getenv("HOME"), ".tglconfig")

type Gitlab struct {
	Url   string
	Token string
}

type Project struct {
	id                   int    `json:"id,omitempty`
	WebUrl               string `json:"web_url,omitempty`
	Name                 string `json:"name,omitempty`
	MergeRequestsEnabled bool   `json:"merge_requests_enabled,omitempty`
	lastActivity         string `json:"last_activity_at,omitempty`
}

type Session struct {
	PrivateToken string `json:"private_token,omitempty"`
}

func NewGitlab(a_url string) *Gitlab {
	return &Gitlab{
		Url: a_url,
	}
}

func (g *Gitlab) apiUrlFor(path string) string {
	return g.Url + "/api/v3" + path + "?private_token=" + g.Token
}

func (g *Gitlab) save() (err error) {
	f, err := os.Create(configFilePath)
	if err != nil {
		return
	}
	defer f.Close()

	enc := json.NewEncoder(f)
	return enc.Encode(g)
}

func (g *Gitlab) Login(login string, password string) (err error) {
	request_url := g.apiUrlFor("/session")

	values := make(url.Values)
	values.Set("login", login)
	values.Set("password", password)

	resp, err := http.PostForm(request_url, values)
	if err != nil {
		return
	}
	defer resp.Body.Close()

	contents, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return
	}

	var session *Session

	err = json.Unmarshal(contents, &session)
	if err != nil {
		return
	}

	g.Token = session.PrivateToken
	g.save()

	return
}

func (g *Gitlab) Projects() (projects []*Project, err error) {
	url := g.apiUrlFor("/projects")

	resp, err := http.Get(url)
	if err != nil {
		return
	}

	defer resp.Body.Close()
	contents, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return
	}

	err = json.Unmarshal(contents, &projects)

	return
}
<commit_msg>Read gitlab config from ~/.tglconfig<commit_after>package gitlab

import (
	"encoding/json"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
)

var configFilePath = filepath.Join(os.Getenv("HOME"), ".tglconfig")

type Gitlab struct {
	Url   string
	Token string
}

type Project struct {
	id                   int    `json:"id,omitempty`
	WebUrl               string `json:"web_url,omitempty`
	Name                 string `json:"name,omitempty`
	MergeRequestsEnabled bool   `json:"merge_requests_enabled,omitempty`
	lastActivity         string `json:"last_activity_at,omitempty`
}

type Session struct {
	PrivateToken string `json:"private_token,omitempty"`
}

func NewGitlab(a_url string) *Gitlab {
	g := &Gitlab{}
	g.load()
	return g
}

func (g *Gitlab) apiUrlFor(path string) string {
	return g.Url + "/api/v3" + path + "?private_token=" + g.Token
}

func (g *Gitlab) load() error {
	f, err := os.Open(configFilePath)
	if err != nil {
		return err
	}
	defer f.Close()

	dec := json.NewDecoder(f)
	for {
		if err := dec.Decode(g); err == io.EOF {
			break
		} else if err != nil {
			return err
		}
	}

	return nil
}

func (g *Gitlab) save() (err error) {
	f, err := os.Create(configFilePath)
	if err != nil {
		return
	}
	defer f.Close()

	enc := json.NewEncoder(f)
	return enc.Encode(g)
}

func (g *Gitlab) Login(login string, password string) (err error) {
	request_url := g.apiUrlFor("/session")

	values := make(url.Values)
	values.Set("login", login)
	values.Set("password", password)

	resp, err := http.PostForm(request_url, values)
	if err != nil {
		return
	}
	defer resp.Body.Close()

	contents, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return
	}

	var session *Session

	err = json.Unmarshal(contents, &session)
	if err != nil {
		return
	}

	g.Token = session.PrivateToken
	g.save()

	return
}

func (g *Gitlab) Projects() (projects []*Project, err error) {
	url := g.apiUrlFor("/projects")

	resp, err := http.Get(url)
	if err != nil {
		return
	}

	defer resp.Body.Close()
	contents, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return
	}

	err = json.Unmarshal(contents, &projects)

	return
}
<|endoftext|>


<commit_before>package userstored

import (
	"context"

	"github.com/rancher/norman/store/subtype"
	"github.com/rancher/norman/types"
	"github.com/rancher/rancher/pkg/api/customization/workload"
	"github.com/rancher/rancher/pkg/api/store/ingress"
	"github.com/rancher/rancher/pkg/api/store/namespace"
	"github.com/rancher/rancher/pkg/api/store/pod"
	"github.com/rancher/rancher/pkg/api/store/projectsetter"
	"github.com/rancher/rancher/pkg/api/store/secret"
	"github.com/rancher/rancher/pkg/api/store/service"
	"github.com/rancher/types/apis/project.cattle.io/v3/schema"
	clusterClient "github.com/rancher/types/client/cluster/v3"
	"github.com/rancher/types/client/project/v3"
	"github.com/rancher/types/config"
)

func Setup(ctx context.Context, mgmt *config.ScaledContext) error {
	// Here we setup all types that will be stored in the User cluster

	schemas := mgmt.Schemas

	addProxyStore(schemas, mgmt, client.DaemonSetType, "apps/v1beta2", workload.New)
	addProxyStore(schemas, mgmt, client.DeploymentType, "apps/v1beta2", workload.New)
	addProxyStore(schemas, mgmt, client.PersistentVolumeClaimType, "v1", nil)
	addProxyStore(schemas, mgmt, client.PodType, "v1", pod.New)
	addProxyStore(schemas, mgmt, client.ReplicaSetType, "apps/v1beta2", workload.New)
	addProxyStore(schemas, mgmt, client.ReplicationControllerType, "v1", workload.New)
	addProxyStore(schemas, mgmt, client.ServiceType, "v1", service.New)
	addProxyStore(schemas, mgmt, client.StatefulSetType, "apps/v1beta2", nil)
	addProxyStore(schemas, mgmt, client.JobType, "batch/v1", workload.New)
	addProxyStore(schemas, mgmt, client.CronJobType, "batch/v1beta1", workload.New)
	addProxyStore(schemas, mgmt, clusterClient.NamespaceType, "v1", namespace.New)
	addProxyStore(schemas, mgmt, clusterClient.PersistentVolumeType, "v1", nil)
	addProxyStore(schemas, mgmt, client.IngressType, "extensions/v1beta1", ingress.Wrap)

	Secret(mgmt, schemas)
	Service(schemas)
	Workload(schemas)

	SetProjectID(schemas)

	return nil
}

func SetProjectID(schemas *types.Schemas) {
	for _, schema := range schemas.SchemasForVersion(schema.Version) {
		if schema.Store == nil || schema.Store.Context() != config.UserStorageContext {
			continue
		}

		if !schema.CanList(nil) {
			continue
		}

		if _, ok := schema.ResourceFields["namespaceId"]; !ok {
			panic(schema.ID + " does not have namespaceId")
		}

		if _, ok := schema.ResourceFields["projectId"]; !ok {
			panic(schema.ID + " does not have projectId")
		}

		schema.Store = projectsetter.Wrap(schema.Store)
	}
}

func Workload(schemas *types.Schemas) {
	workload.ConfigureStore(schemas)
}

func Service(schemas *types.Schemas) {
	serviceSchema := schemas.Schema(&schema.Version, "service")
	dnsSchema := schemas.Schema(&schema.Version, "dnsRecord")
	dnsSchema.Store = serviceSchema.Store
}

func Secret(management *config.ScaledContext, schemas *types.Schemas) {
	schema := schemas.Schema(&schema.Version, "namespacedSecret")
	schema.Store = secret.NewNamespacedSecretStore(management.ClientGetter)

	for _, subSchema := range schemas.Schemas() {
		if subSchema.BaseType == schema.ID && subSchema.ID != schema.ID {
			subSchema.Store = subtype.NewSubTypeStore(subSchema.ID, schema.Store)
		}
	}
}
<commit_msg>Add store for storageClass<commit_after>package userstored

import (
	"context"

	"github.com/rancher/norman/store/subtype"
	"github.com/rancher/norman/types"
	"github.com/rancher/rancher/pkg/api/customization/workload"
	"github.com/rancher/rancher/pkg/api/store/ingress"
	"github.com/rancher/rancher/pkg/api/store/namespace"
	"github.com/rancher/rancher/pkg/api/store/pod"
	"github.com/rancher/rancher/pkg/api/store/projectsetter"
	"github.com/rancher/rancher/pkg/api/store/secret"
	"github.com/rancher/rancher/pkg/api/store/service"
	"github.com/rancher/types/apis/project.cattle.io/v3/schema"
	clusterClient "github.com/rancher/types/client/cluster/v3"
	"github.com/rancher/types/client/project/v3"
	"github.com/rancher/types/config"
)

func Setup(ctx context.Context, mgmt *config.ScaledContext) error {
	// Here we setup all types that will be stored in the User cluster

	schemas := mgmt.Schemas

	addProxyStore(schemas, mgmt, client.CronJobType, "batch/v1beta1", workload.New)
	addProxyStore(schemas, mgmt, client.DaemonSetType, "apps/v1beta2", workload.New)
	addProxyStore(schemas, mgmt, client.DeploymentType, "apps/v1beta2", workload.New)
	addProxyStore(schemas, mgmt, client.IngressType, "extensions/v1beta1", ingress.Wrap)
	addProxyStore(schemas, mgmt, client.JobType, "batch/v1", workload.New)
	addProxyStore(schemas, mgmt, client.PersistentVolumeClaimType, "v1", nil)
	addProxyStore(schemas, mgmt, client.PodType, "v1", pod.New)
	addProxyStore(schemas, mgmt, client.ReplicaSetType, "apps/v1beta2", workload.New)
	addProxyStore(schemas, mgmt, client.ReplicationControllerType, "v1", workload.New)
	addProxyStore(schemas, mgmt, client.ServiceType, "v1", service.New)
	addProxyStore(schemas, mgmt, client.StatefulSetType, "apps/v1beta2", nil)
	addProxyStore(schemas, mgmt, clusterClient.NamespaceType, "v1", namespace.New)
	addProxyStore(schemas, mgmt, clusterClient.PersistentVolumeType, "v1", nil)
	addProxyStore(schemas, mgmt, clusterClient.StorageClassType, "storage.k8s.io/v1", nil)

	Secret(mgmt, schemas)
	Service(schemas)
	Workload(schemas)

	SetProjectID(schemas)

	return nil
}

func SetProjectID(schemas *types.Schemas) {
	for _, schema := range schemas.SchemasForVersion(schema.Version) {
		if schema.Store == nil || schema.Store.Context() != config.UserStorageContext {
			continue
		}

		if !schema.CanList(nil) {
			continue
		}

		if _, ok := schema.ResourceFields["namespaceId"]; !ok {
			panic(schema.ID + " does not have namespaceId")
		}

		if _, ok := schema.ResourceFields["projectId"]; !ok {
			panic(schema.ID + " does not have projectId")
		}

		schema.Store = projectsetter.Wrap(schema.Store)
	}
}

func Workload(schemas *types.Schemas) {
	workload.ConfigureStore(schemas)
}

func Service(schemas *types.Schemas) {
	serviceSchema := schemas.Schema(&schema.Version, "service")
	dnsSchema := schemas.Schema(&schema.Version, "dnsRecord")
	dnsSchema.Store = serviceSchema.Store
}

func Secret(management *config.ScaledContext, schemas *types.Schemas) {
	schema := schemas.Schema(&schema.Version, "namespacedSecret")
	schema.Store = secret.NewNamespacedSecretStore(management.ClientGetter)

	for _, subSchema := range schemas.Schemas() {
		if subSchema.BaseType == schema.ID && subSchema.ID != schema.ID {
			subSchema.Store = subtype.NewSubTypeStore(subSchema.ID, schema.Store)
		}
	}
}
<|endoftext|>