<commit_before>package oidc

import (
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
	"time"

	"github.com/cozy/cozy-stack/pkg/config"
	"github.com/cozy/cozy-stack/pkg/instance"
	"github.com/cozy/cozy-stack/pkg/instance/lifecycle"
	"github.com/cozy/cozy-stack/pkg/logger"
	"github.com/cozy/cozy-stack/web/middlewares"
	"github.com/cozy/echo"
)

// Start is the route to start the OpenID Connect dance.
func Start(c echo.Context) error {
	inst := middlewares.GetInstance(c)
	conf, err := getConfig(inst.ContextName)
	if err != nil {
		redirect := inst.DefaultRedirection()
		return c.Redirect(http.StatusSeeOther, redirect.String())
	}
	u, err := makeStartURL(inst, conf)
	if err != nil {
		redirect := inst.DefaultRedirection()
		return c.Redirect(http.StatusSeeOther, redirect.String())
	}
	return c.Redirect(http.StatusSeeOther, u)
}

// Redirect is the route after the Identity Provider has redirected the user to
// the stack. The redirection is made to a generic domain, like
// oauthcallback.cozy.tools and the association with an instance is made via a
// call to the UserInfo endpoint.
func Redirect(c echo.Context) error {
	code := c.QueryParam("code")
	stateID := c.QueryParam("state")
	state := getStorage().Find(stateID)
	if state == nil {
		return renderError(c, nil, http.StatusNotFound, "Sorry, the session has expired.")
	}
	inst, err := lifecycle.GetInstance(state.Instance)
	if err != nil {
		return renderError(c, nil, http.StatusNotFound, "Sorry, the cozy was not found.")
	}
	conf, err := getConfig(inst.ContextName)
	if err != nil {
		return renderError(c, inst, http.StatusBadRequest, "No OpenID Connect is configured.")
	}
	token, err := getToken(conf, code)
	if err != nil {
		logger.WithNamespace("oidc").Errorf("Error on getToken: %s", err)
		return renderError(c, inst, http.StatusBadGateway, "Error from the identity provider.")
	}
	domain, err := getDomainFromUserInfo(conf, token)
	if err != nil {
		logger.WithNamespace("oidc").Errorf("Error on getDomainFromUserInfo: %s", err)
		return renderError(c, inst, http.StatusBadGateway, "Error from the identity provider.")
	}
	if domain != inst.Domain {
		logger.WithNamespace("oidc").Errorf("Invalid domains: %s != %s", domain, inst.Domain)
		return renderError(c, inst, http.StatusBadRequest, "Sorry, the cozy was not found.")
	}
	return nil
}

// Config is the config to log in a user with an OpenID Connect identity
// provider.
type Config struct {
	ClientID      string
	ClientSecret  string
	Scope         string
	RedirectURI   string
	AuthorizeURL  string
	TokenURL      string
	UserInfoURL   string
	UserInfoField string
}

func getConfig(context string) (*Config, error) {
	auth := config.GetConfig().Authentication
	delegated, ok := auth[context].(map[string]interface{})
	if !ok {
		return nil, errors.New("No authentication is configured for this context")
	}
	oidc, ok := delegated["oidc"].(map[string]interface{})
	if !ok {
		return nil, errors.New("No OIDC is configured for this context")
	}

	clientID, ok := oidc["client_id"].(string)
	if !ok {
		return nil, errors.New("The client_id is missing for this context")
	}
	clientSecret, ok := oidc["client_secret"].(string)
	if !ok {
		return nil, errors.New("The client_secret is missing for this context")
	}
	scope, ok := oidc["scope"].(string)
	if !ok {
		return nil, errors.New("The scope is missing for this context")
	}
	redirectURI, ok := oidc["redirect_uri"].(string)
	if !ok {
		return nil, errors.New("The redirect_uri is missing for this context")
	}
	authorizeURL, ok := oidc["authorize_url"].(string)
	if !ok {
		return nil, errors.New("The authorize_url is missing for this context")
	}
	tokenURL, ok := oidc["token_url"].(string)
	if !ok {
		return nil, errors.New("The token_url is missing for this context")
	}
	userInfoURL, ok := oidc["userinfo_url"].(string)
	if !ok {
		return nil, errors.New("The userinfo_url is missing for this context")
	}
	userInfoField, ok := oidc["userinfo_instance_field"].(string)
	if !ok {
		return nil, errors.New("The userinfo_instance_field is missing for this context")
	}

	config := &Config{
		ClientID:      clientID,
		ClientSecret:  clientSecret,
		Scope:         scope,
		RedirectURI:   redirectURI,
		AuthorizeURL:  authorizeURL,
		TokenURL:      tokenURL,
		UserInfoURL:   userInfoURL,
		UserInfoField: userInfoField,
	}
	return config, nil
}

func makeStartURL(inst *instance.Instance, conf *Config) (string, error) {
	u, err := url.Parse(conf.AuthorizeURL)
	if err != nil {
		return "", err
	}
	state := newStateHolder(inst.Domain)
	if err = getStorage().Add(state); err != nil {
		return "", err
	}
	vv := u.Query()
	vv.Add("response_type", "code")
	vv.Add("scope", conf.Scope)
	vv.Add("client_id", conf.ClientID)
	vv.Add("redirect_uri", conf.RedirectURI)
	vv.Add("state", state.id)
	vv.Add("nonce", state.Nonce)
	u.RawQuery = vv.Encode()
	return u.String(), nil
}

var oidcClient = &http.Client{
	Timeout: 15 * time.Second,
}

func getToken(conf *Config, code string) (string, error) {
	data := url.Values{
		"grant_type":   []string{"authorization_code"},
		"code":         []string{code},
		"redirect_uri": []string{conf.RedirectURI},
	}
	body := strings.NewReader(data.Encode())
	req, err := http.NewRequest("POST", conf.TokenURL, body)
	if err != nil {
		return "", err
	}
	auth := []byte(conf.ClientID + ":" + conf.ClientSecret)
	req.Header.Add("Authorization", "Basic "+base64.StdEncoding.EncodeToString(auth))
	req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
	req.Header.Add("Accept", "application/json")

	res, err := oidcClient.Do(req)
	if err != nil {
		return "", err
	}
	defer res.Body.Close()
	if res.StatusCode != 200 {
		return "", fmt.Errorf("OIDC service responded with %d", res.StatusCode)
	}
	resBody, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return "", err
	}

	var out struct {
		AccessToken string `json:"access_token"`
	}
	err = json.Unmarshal(resBody, &out)
	if err != nil {
		return "", err
	}
	return out.AccessToken, nil
}

func getDomainFromUserInfo(conf *Config, token string) (string, error) {
	return "", errors.New("Not implemented")
}

func renderError(c echo.Context, inst *instance.Instance, code int, msg string) error {
	return c.Render(code, "error.html", echo.Map{
		"CozyUI":      middlewares.CozyUI(inst),
		"ThemeCSS":    middlewares.ThemeCSS(inst),
		"Domain":      inst.ContextualDomain(),
		"ContextName": inst.ContextName,
		"Error":       msg,
	})
}

// Routes setup routing for OpenID Connect routes.
// Careful, the normal middlewares NeedInstance and LoadSession are not applied
// to this group in web/routing
func Routes(router *echo.Group) {
	router.GET("/start", Start, middlewares.NeedInstance)
	router.GET("/redirect", Redirect)
}
<commit_msg>Check the UserInfo for OIDC<commit_after>package oidc

import (
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
	"time"

	"github.com/cozy/cozy-stack/pkg/config"
	"github.com/cozy/cozy-stack/pkg/instance"
	"github.com/cozy/cozy-stack/pkg/instance/lifecycle"
	"github.com/cozy/cozy-stack/pkg/logger"
	"github.com/cozy/cozy-stack/web/middlewares"
	"github.com/cozy/echo"
)

// Start is the route to start the OpenID Connect dance.
func Start(c echo.Context) error {
	inst := middlewares.GetInstance(c)
	conf, err := getConfig(inst.ContextName)
	if err != nil {
		redirect := inst.DefaultRedirection()
		return c.Redirect(http.StatusSeeOther, redirect.String())
	}
	u, err := makeStartURL(inst, conf)
	if err != nil {
		redirect := inst.DefaultRedirection()
		return c.Redirect(http.StatusSeeOther, redirect.String())
	}
	return c.Redirect(http.StatusSeeOther, u)
}

// Redirect is the route after the Identity Provider has redirected the user to
// the stack. The redirection is made to a generic domain, like
// oauthcallback.cozy.tools and the association with an instance is made via a
// call to the UserInfo endpoint.
func Redirect(c echo.Context) error {
	code := c.QueryParam("code")
	stateID := c.QueryParam("state")
	state := getStorage().Find(stateID)
	if state == nil {
		return renderError(c, nil, http.StatusNotFound, "Sorry, the session has expired.")
	}
	inst, err := lifecycle.GetInstance(state.Instance)
	if err != nil {
		return renderError(c, nil, http.StatusNotFound, "Sorry, the cozy was not found.")
	}
	conf, err := getConfig(inst.ContextName)
	if err != nil {
		return renderError(c, inst, http.StatusBadRequest, "No OpenID Connect is configured.")
	}

	token, err := getToken(conf, code)
	if err != nil {
		logger.WithNamespace("oidc").Errorf("Error on getToken: %s", err)
		return renderError(c, inst, http.StatusBadGateway, "Error from the identity provider.")
	}
	domain, err := getDomainFromUserInfo(conf, token)
	if err != nil {
		logger.WithNamespace("oidc").Errorf("Error on getDomainFromUserInfo: %s", err)
		return renderError(c, inst, http.StatusBadGateway, "Error from the identity provider.")
	}
	if domain != inst.Domain {
		logger.WithNamespace("oidc").Errorf("Invalid domains: %s != %s", domain, inst.Domain)
		return renderError(c, inst, http.StatusBadRequest, "Sorry, the cozy was not found.")
	}

	// TODO log the user before the redirection
	redirect := inst.DefaultRedirection()
	return c.Redirect(http.StatusSeeOther, redirect.String())
}

// Config is the config to log in a user with an OpenID Connect identity
// provider.
type Config struct {
	ClientID      string
	ClientSecret  string
	Scope         string
	RedirectURI   string
	AuthorizeURL  string
	TokenURL      string
	UserInfoURL   string
	UserInfoField string
}

func getConfig(context string) (*Config, error) {
	auth := config.GetConfig().Authentication
	delegated, ok := auth[context].(map[string]interface{})
	if !ok {
		return nil, errors.New("No authentication is configured for this context")
	}
	oidc, ok := delegated["oidc"].(map[string]interface{})
	if !ok {
		return nil, errors.New("No OIDC is configured for this context")
	}

	clientID, ok := oidc["client_id"].(string)
	if !ok {
		return nil, errors.New("The client_id is missing for this context")
	}
	clientSecret, ok := oidc["client_secret"].(string)
	if !ok {
		return nil, errors.New("The client_secret is missing for this context")
	}
	scope, ok := oidc["scope"].(string)
	if !ok {
		return nil, errors.New("The scope is missing for this context")
	}
	redirectURI, ok := oidc["redirect_uri"].(string)
	if !ok {
		return nil, errors.New("The redirect_uri is missing for this context")
	}
	authorizeURL, ok := oidc["authorize_url"].(string)
	if !ok {
		return nil, errors.New("The authorize_url is missing for this context")
	}
	tokenURL, ok := oidc["token_url"].(string)
	if !ok {
		return nil, errors.New("The token_url is missing for this context")
	}
	userInfoURL, ok := oidc["userinfo_url"].(string)
	if !ok {
		return nil, errors.New("The userinfo_url is missing for this context")
	}
	userInfoField, ok := oidc["userinfo_instance_field"].(string)
	if !ok {
		return nil, errors.New("The userinfo_instance_field is missing for this context")
	}

	config := &Config{
		ClientID:      clientID,
		ClientSecret:  clientSecret,
		Scope:         scope,
		RedirectURI:   redirectURI,
		AuthorizeURL:  authorizeURL,
		TokenURL:      tokenURL,
		UserInfoURL:   userInfoURL,
		UserInfoField: userInfoField,
	}
	return config, nil
}

func makeStartURL(inst *instance.Instance, conf *Config) (string, error) {
	u, err := url.Parse(conf.AuthorizeURL)
	if err != nil {
		return "", err
	}
	state := newStateHolder(inst.Domain)
	if err = getStorage().Add(state); err != nil {
		return "", err
	}
	vv := u.Query()
	vv.Add("response_type", "code")
	vv.Add("scope", conf.Scope)
	vv.Add("client_id", conf.ClientID)
	vv.Add("redirect_uri", conf.RedirectURI)
	vv.Add("state", state.id)
	vv.Add("nonce", state.Nonce)
	u.RawQuery = vv.Encode()
	return u.String(), nil
}

var oidcClient = &http.Client{
	Timeout: 15 * time.Second,
}

func getToken(conf *Config, code string) (string, error) {
	data := url.Values{
		"grant_type":   []string{"authorization_code"},
		"code":         []string{code},
		"redirect_uri": []string{conf.RedirectURI},
	}
	body := strings.NewReader(data.Encode())
	req, err := http.NewRequest("POST", conf.TokenURL, body)
	if err != nil {
		return "", err
	}
	auth := []byte(conf.ClientID + ":" + conf.ClientSecret)
	req.Header.Add("Authorization", "Basic "+base64.StdEncoding.EncodeToString(auth))
	req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
	req.Header.Add("Accept", "application/json")

	res, err := oidcClient.Do(req)
	if err != nil {
		return "", err
	}
	defer res.Body.Close()
	if res.StatusCode != 200 {
		return "", fmt.Errorf("OIDC service responded with %d", res.StatusCode)
	}
	resBody, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return "", err
	}

	var out struct {
		AccessToken string `json:"access_token"`
	}
	err = json.Unmarshal(resBody, &out)
	if err != nil {
		return "", err
	}
	return out.AccessToken, nil
}

func getDomainFromUserInfo(conf *Config, token string) (string, error) {
	req, err := http.NewRequest("GET", conf.UserInfoURL, nil)
	if err != nil {
		return "", err
	}
	req.Header.Add("Authorization", "Bearer "+token)
	res, err := oidcClient.Do(req)
	if err != nil {
		return "", err
	}
	defer res.Body.Close()
	if res.StatusCode != 200 {
		return "", fmt.Errorf("OIDC service responded with %d", res.StatusCode)
	}
	resBody, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return "", err
	}

	var out map[string]interface{}
	err = json.Unmarshal(resBody, &out)
	if err != nil {
		return "", err
	}
	fmt.Printf("out = %#v\n", out)
	if domain, ok := out[conf.UserInfoField].(string); ok {
		return domain, nil
	}
	return "", errors.New("No domain was found")
}

func renderError(c echo.Context, inst *instance.Instance, code int, msg string) error {
	return c.Render(code, "error.html", echo.Map{
		"CozyUI":      middlewares.CozyUI(inst),
		"ThemeCSS":    middlewares.ThemeCSS(inst),
		"Domain":      inst.ContextualDomain(),
		"ContextName": inst.ContextName,
		"Error":       msg,
	})
}

// Routes setup routing for OpenID Connect routes.
// Careful, the normal middlewares NeedInstance and LoadSession are not applied
// to this group in web/routing
func Routes(router *echo.Group) {
	router.GET("/start", Start, middlewares.NeedInstance)
	router.GET("/redirect", Redirect)
}
<|endoftext|>


<commit_before>// +build go1.5, go1.6, go1.7, !go1.8

package main

import (
	"net/url"
	"strings"
)

// this is workaround  block for go < 1.8
func getHostname(u *url.URL) string {
	return stripPost(u)
}

func stripPost(u *url.URL) string {
	hostport := u.Host
	colon := strings.IndexByte(hostport, ':')
	if colon == -1 {
		return hostport
	}
	if i := strings.IndexByte(hostport, ']'); i != -1 {
		return strings.TrimPrefix(hostport[:i], "[")
	}
	return hostport[:colon]

<commit_msg>Correct typo.<commit_after>// +build go1.5, go1.6, go1.7, !go1.8

package main

import (
	"net/url"
	"strings"
)

// this is workaround  block for go < 1.8
func getHostname(u *url.URL) string {
	return stripPost(u)
}

func stripPost(u *url.URL) string {
	hostport := u.Host
	colon := strings.IndexByte(hostport, ':')
	if colon == -1 {
		return hostport
	}
	if i := strings.IndexByte(hostport, ']'); i != -1 {
		return strings.TrimPrefix(hostport[:i], "[")
	}
	return hostport[:colon]
}
<|endoftext|>


<commit_before>package git

import (
	"os/exec"
	"strings"
)

// Checkout executes git checkout commnad
func Checkout(branchName string) (string, error) {
	args := []string{"checkout", branchName}
	return execute(args)
}

// GetOriginURL executes git remote command to retrieve origin URL
func GetOriginURL() (string, error) {
	args := []string{"remote", "get-url", "origin"}
	return execute(args)
}

// GetStatus executes git status command
func GetStatus() (string, error) {
	args := []string{"status", "-s"}
	return execute(args)
}

// Pull executes git pull command
func Pull() (string, error) {
	args := []string{"pull"}
	return execute(args)
}

// Fetch executes git fetch command
func Fetch() (string, error) {
	args := []string{"fetch"}
	return execute(args)
}

// GetCurrentBranchName executes git symbolic-ref to retrieve current branch name
func GetCurrentBranchName() (string, error) {
	args := []string{"symbolic-ref", "--short", "HEAD"}
	output, err := execute(args)
	if err != nil {
		return output, err
	}
	name := strings.Replace(output, "\n", "", -1)
	return name, nil
}

// DeleteBranch executes git branch command to delete a branch
func DeleteBranch(branchName string) (string, error) {
	args := []string{"branch", "-D", branchName}
	return execute(args)
}

// Merge executes git merge command to merge from a branch
func Merge(branchName string) (string, error) {
	args := []string{"merge", "--no-edit", branchName}
	return execute(args)
}

// Difftool executes git difftool command
func Difftool(branchName string) error {
	args := []string{"difftool", branchName}
	_, err := execute(args)
	return err
}

// DiffStat executes git diff to retrieve diff stat
func DiffStat(branchName string) (string, error) {
	args := []string{"diff", "--stat", branchName}
	return execute(args)
}

func execute(args []string) (string, error) {
	byteOutput, err := exec.Command("git", args...).Output()
	return string(byteOutput), err
}
<commit_msg>Added git command for retrieving commit comments for creating a pull request<commit_after>package git

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

// Checkout executes git checkout commnad
func Checkout(branchName string) (string, error) {
	args := []string{"checkout", branchName}
	return execute(args)
}

// GetOriginURL executes git remote command to retrieve origin URL
func GetOriginURL() (string, error) {
	args := []string{"remote", "get-url", "origin"}
	return execute(args)
}

// GetStatus executes git status command
func GetStatus() (string, error) {
	args := []string{"status", "-s"}
	return execute(args)
}

// Pull executes git pull command
func Pull() (string, error) {
	args := []string{"pull"}
	return execute(args)
}

// Fetch executes git fetch command
func Fetch() (string, error) {
	args := []string{"fetch"}
	return execute(args)
}

// GetCurrentBranchName executes git symbolic-ref to retrieve current branch name
func GetCurrentBranchName() (string, error) {
	args := []string{"symbolic-ref", "--short", "HEAD"}
	output, err := execute(args)
	if err != nil {
		return output, err
	}
	name := strings.Replace(output, "\n", "", -1)
	return name, nil
}

// DeleteBranch executes git branch command to delete a branch
func DeleteBranch(branchName string) (string, error) {
	args := []string{"branch", "-D", branchName}
	return execute(args)
}

// Merge executes git merge command to merge from a branch
func Merge(branchName string) (string, error) {
	args := []string{"merge", "--no-edit", branchName}
	return execute(args)
}

// Difftool executes git difftool command
func Difftool(branchName string) error {
	args := []string{"difftool", branchName}
	_, err := execute(args)
	return err
}

// DiffStat executes git diff to retrieve diff stat
func DiffStat(branchName string) (string, error) {
	args := []string{"diff", "--stat", branchName}
	return execute(args)
}

// GetBranchCommitComments executes git log command to retrieve branch commit comments
func GetBranchCommitComments(sourceBranchName string, destinationBranchName string) (string, error) {
	branches := fmt.Sprintf("%s..%s", destinationBranchName, sourceBranchName)
	args := []string{"log", branches, "--no-merges", "--pretty=format:'%s %b'"}
	return execute(args)
}

func execute(args []string) (string, error) {
	byteOutput, err := exec.Command("git", args...).Output()
	return string(byteOutput), err
}
<|endoftext|>


<commit_before>// Copyright 2016 CoreOS, 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 gce

import (
	"fmt"
	"net"
	"net/http"
	"strconv"
	"strings"

	"github.com/rancher/os/config/cloudinit/datasource"
	"github.com/rancher/os/config/cloudinit/datasource/metadata"
)

const (
	DefaultAddress = "http://metadata.google.internal/"
	apiVersion     = "computeMetadata/v1/"
	metadataPath   = apiVersion
	userdataPath   = apiVersion + "instance/attributes/user-data"
)

type MetadataService struct {
	metadata.Service
}

func NewDatasource(root string) *MetadataService {
	if root == "" {
		root = DefaultAddress
	}
	return &MetadataService{metadata.NewDatasource(root, apiVersion, userdataPath, metadataPath, http.Header{"Metadata-Flavor": {"Google"}})}
}

func (ms MetadataService) FetchMetadata() (datasource.Metadata, error) {
	public, err := ms.fetchIP("instance/network-interfaces/0/access-configs/0/external-ip")
	if err != nil {
		return datasource.Metadata{}, err
	}
	local, err := ms.fetchIP("instance/network-interfaces/0/ip")
	if err != nil {
		return datasource.Metadata{}, err
	}
	hostname, err := ms.fetchString("instance/hostname")
	if err != nil {
		return datasource.Metadata{}, err
	}

	projectSSHKeys, err := ms.fetchString("project/attributes/sshKeys")
	if err != nil {
		return datasource.Metadata{}, err
	}
	instanceSSHKeys, err := ms.fetchString("instance/attributes/sshKeys")
	if err != nil {
		return datasource.Metadata{}, err
	}
	md := datasource.Metadata{
		PublicIPv4:    public,
		PrivateIPv4:   local,
		Hostname:      hostname,
		SSHPublicKeys: nil,
	}

	/* Disabled, using DHCP like in pre-0.9.1 - missing gateway and netmask, and testing time
	addresses := []string{}
	if public != nil {
		addresses = append(addresses, public.String())
	}
	if local != nil {
		addresses = append(addresses, local.String())
	}
	if len(addresses) > 0 {
		network := netconf.InterfaceConfig{
			Addresses: addresses,
		}

		md.NetworkConfig.Interfaces = make(map[string]netconf.InterfaceConfig)
		md.NetworkConfig.Interfaces["eth0"] = network
	}
	*/

	keyStrings := strings.Split(projectSSHKeys+"\n"+instanceSSHKeys, "\n")

	i := 0
	for _, keyString := range keyStrings {
		keySlice := strings.SplitN(keyString, ":", 2)
		if len(keySlice) == 2 {
			key := strings.TrimSpace(keySlice[1])
			if key != "" {
				if md.SSHPublicKeys == nil {
					md.SSHPublicKeys = map[string]string{}
				}
				md.SSHPublicKeys[strconv.Itoa(i)] = strings.TrimSpace(keySlice[1])
				i++
			}
		}
	}

	return md, nil
}

func (ms MetadataService) Type() string {
	return "gce-metadata-service"
}

func (ms MetadataService) fetchString(key string) (string, error) {
	data, err := ms.FetchData(ms.MetadataURL() + key)
	if err != nil {
		return "", err
	}

	return string(data), nil
}

func (ms MetadataService) fetchIP(key string) (net.IP, error) {
	str, err := ms.fetchString(key)
	if err != nil {
		return nil, err
	}

	if str == "" {
		return nil, nil
	}

	if ip := net.ParseIP(str); ip != nil {
		return ip, nil
	}
	return nil, fmt.Errorf("couldn't parse %q as IP address", str)
}

func (ms MetadataService) FetchUserdata() ([]byte, error) {
	// see https://github.com/number5/cloud-init/blob/master/cloudinit/sources/DataSourceGCE.py
	data, err := ms.FetchData(ms.UserdataURL())
	if err != nil {
		return nil, err
	}
	if len(data) == 0 {
		// see https://cloud.google.com/deployment-manager/docs/step-by-step-guide/setting-metadata-and-startup-scripts
		data, err = ms.FetchData(ms.MetadataURL() + "instance/attributes/startup-script")
		if err != nil {
			return nil, err
		}
	}
	return data, nil
}
<commit_msg>Fix typos for getting gcp metadata SSHKeys<commit_after>// Copyright 2016 CoreOS, 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 gce

import (
	"fmt"
	"net"
	"net/http"
	"strconv"
	"strings"

	"github.com/rancher/os/config/cloudinit/datasource"
	"github.com/rancher/os/config/cloudinit/datasource/metadata"
)

const (
	DefaultAddress = "http://metadata.google.internal/"
	apiVersion     = "computeMetadata/v1/"
	metadataPath   = apiVersion
	userdataPath   = apiVersion + "instance/attributes/user-data"
)

type MetadataService struct {
	metadata.Service
}

func NewDatasource(root string) *MetadataService {
	if root == "" {
		root = DefaultAddress
	}
	return &MetadataService{metadata.NewDatasource(root, apiVersion, userdataPath, metadataPath, http.Header{"Metadata-Flavor": {"Google"}})}
}

func (ms MetadataService) FetchMetadata() (datasource.Metadata, error) {
	public, err := ms.fetchIP("instance/network-interfaces/0/access-configs/0/external-ip")
	if err != nil {
		return datasource.Metadata{}, err
	}
	local, err := ms.fetchIP("instance/network-interfaces/0/ip")
	if err != nil {
		return datasource.Metadata{}, err
	}
	hostname, err := ms.fetchString("instance/hostname")
	if err != nil {
		return datasource.Metadata{}, err
	}

	projectSSHKeys, err := ms.fetchString("project/attributes/ssh-keys")
	if err != nil {
		return datasource.Metadata{}, err
	}
	instanceSSHKeys, err := ms.fetchString("instance/attributes/ssh-keys")
	if err != nil {
		return datasource.Metadata{}, err
	}
	md := datasource.Metadata{
		PublicIPv4:    public,
		PrivateIPv4:   local,
		Hostname:      hostname,
		SSHPublicKeys: nil,
	}

	/* Disabled, using DHCP like in pre-0.9.1 - missing gateway and netmask, and testing time
	addresses := []string{}
	if public != nil {
		addresses = append(addresses, public.String())
	}
	if local != nil {
		addresses = append(addresses, local.String())
	}
	if len(addresses) > 0 {
		network := netconf.InterfaceConfig{
			Addresses: addresses,
		}

		md.NetworkConfig.Interfaces = make(map[string]netconf.InterfaceConfig)
		md.NetworkConfig.Interfaces["eth0"] = network
	}
	*/

	keyStrings := strings.Split(projectSSHKeys+"\n"+instanceSSHKeys, "\n")

	i := 0
	for _, keyString := range keyStrings {
		keySlice := strings.SplitN(keyString, ":", 2)
		if len(keySlice) == 2 {
			key := strings.TrimSpace(keySlice[1])
			if key != "" {
				if md.SSHPublicKeys == nil {
					md.SSHPublicKeys = map[string]string{}
				}
				md.SSHPublicKeys[strconv.Itoa(i)] = strings.TrimSpace(keySlice[1])
				i++
			}
		}
	}

	return md, nil
}

func (ms MetadataService) Type() string {
	return "gce-metadata-service"
}

func (ms MetadataService) fetchString(key string) (string, error) {
	data, err := ms.FetchData(ms.MetadataURL() + key)
	if err != nil {
		return "", err
	}

	return string(data), nil
}

func (ms MetadataService) fetchIP(key string) (net.IP, error) {
	str, err := ms.fetchString(key)
	if err != nil {
		return nil, err
	}

	if str == "" {
		return nil, nil
	}

	if ip := net.ParseIP(str); ip != nil {
		return ip, nil
	}
	return nil, fmt.Errorf("couldn't parse %q as IP address", str)
}

func (ms MetadataService) FetchUserdata() ([]byte, error) {
	// see https://github.com/number5/cloud-init/blob/master/cloudinit/sources/DataSourceGCE.py
	data, err := ms.FetchData(ms.UserdataURL())
	if err != nil {
		return nil, err
	}
	if len(data) == 0 {
		// see https://cloud.google.com/deployment-manager/docs/step-by-step-guide/setting-metadata-and-startup-scripts
		data, err = ms.FetchData(ms.MetadataURL() + "instance/attributes/startup-script")
		if err != nil {
			return nil, err
		}
	}
	return data, nil
}
<|endoftext|>


<commit_before>package chat

import (
	"fmt"
	"strings"

	"github.com/keybase/client/go/chat/types"
	"github.com/keybase/client/go/chat/utils"
	"github.com/keybase/client/go/engine"
	"github.com/keybase/client/go/libkb"
	"github.com/keybase/client/go/protocol/chat1"
	"github.com/keybase/client/go/protocol/keybase1"
	"github.com/keybase/go-framed-msgpack-rpc/rpc"
	context "golang.org/x/net/context"
)

type KBFSTLFInfoSource struct {
	utils.DebugLabeler
	libkb.Contextified
	identifier types.Identifier
}

func NewKBFSTLFInfoSource(g *libkb.GlobalContext) *KBFSTLFInfoSource {
	return &KBFSTLFInfoSource{
		DebugLabeler: utils.NewDebugLabeler(g, "KBFSTLFInfoSource", false),
		Contextified: libkb.NewContextified(g),
	}
}

func NewKBFSTLFInfoSourceWithIdentifier(g *libkb.GlobalContext, identifier types.Identifier) *KBFSTLFInfoSource {
	s := NewKBFSTLFInfoSource(g)
	s.identifier = identifier
	return s
}

func (t *KBFSTLFInfoSource) tlfKeysClient() (*keybase1.TlfKeysClient, error) {
	xp := t.G().ConnectionManager.LookupByClientType(keybase1.ClientType_KBFS)
	if xp == nil {
		return nil, fmt.Errorf("KBFS client wasn't found")
	}
	return &keybase1.TlfKeysClient{
		Cli: rpc.NewClient(
			xp, libkb.ErrorUnwrapper{}, libkb.LogTagsFromContext),
	}, nil
}

func (t *KBFSTLFInfoSource) Lookup(ctx context.Context, tlfName string,
	visibility chat1.TLFVisibility) (*types.TLFInfo, error) {
	res, err := CtxKeyFinder(ctx).Find(ctx, t, tlfName, visibility == chat1.TLFVisibility_PUBLIC)
	if err != nil {
		return nil, err
	}
	info := &types.TLFInfo{
		ID:               chat1.TLFID(res.NameIDBreaks.TlfID.ToBytes()),
		CanonicalName:    res.NameIDBreaks.CanonicalName.String(),
		IdentifyFailures: res.NameIDBreaks.Breaks.Breaks,
	}
	return info, nil
}

func (t *KBFSTLFInfoSource) CryptKeys(ctx context.Context, tlfName string) (res keybase1.GetTLFCryptKeysRes, err error) {
	identBehavior, breaks, ok := IdentifyMode(ctx)
	if !ok {
		return res, fmt.Errorf("invalid context with no chat metadata")
	}
	defer t.Trace(ctx, func() error { return err },
		fmt.Sprintf("CryptKeys(tlf=%s,mode=%v)", tlfName, identBehavior))()

	query := keybase1.TLFQuery{
		TlfName:          tlfName,
		IdentifyBehavior: identBehavior,
	}
	ib, err := t.identifyTLF(ctx, query, true)
	if err != nil {
		return keybase1.GetTLFCryptKeysRes{}, err
	}

	tlfClient, err := t.tlfKeysClient()
	if err != nil {
		return res, err
	}

	// skip identify:
	query.IdentifyBehavior = keybase1.TLFIdentifyBehavior_CHAT_SKIP

	resp, err := tlfClient.GetTLFCryptKeys(ctx, query)
	if err != nil {
		return resp, err
	}

	// use id breaks calculated by identifyTLF
	resp.NameIDBreaks.Breaks.Breaks = ib

	if in := CtxIdentifyNotifier(ctx); in != nil {
		in.Send(resp.NameIDBreaks)
	}
	if ok {
		*breaks = appendBreaks(*breaks, resp.NameIDBreaks.Breaks.Breaks)
	}
	return resp, nil
}

func (t *KBFSTLFInfoSource) PublicCanonicalTLFNameAndID(ctx context.Context, tlfName string) (res keybase1.CanonicalTLFNameAndIDWithBreaks, err error) {
	identBehavior, breaks, ok := IdentifyMode(ctx)
	if !ok {
		return res, fmt.Errorf("invalid context with no chat metadata")
	}
	defer t.Trace(ctx, func() error { return err },
		fmt.Sprintf("PublicCanonicalTLFNameAndID(tlf=%s,mode=%v)", tlfName, identBehavior))()

	query := keybase1.TLFQuery{
		TlfName:          tlfName,
		IdentifyBehavior: identBehavior,
	}
	ib, err := t.identifyTLF(ctx, query, false)
	if err != nil {
		return keybase1.CanonicalTLFNameAndIDWithBreaks{}, err
	}

	tlfClient, err := t.tlfKeysClient()
	if err != nil {
		return keybase1.CanonicalTLFNameAndIDWithBreaks{}, err
	}

	// skip identify:
	query.IdentifyBehavior = keybase1.TLFIdentifyBehavior_CHAT_SKIP

	resp, err := tlfClient.GetPublicCanonicalTLFNameAndID(ctx, query)
	if err != nil {
		return resp, err
	}

	// use id breaks calculated by identifyTLF
	resp.Breaks.Breaks = ib

	if in := CtxIdentifyNotifier(ctx); in != nil {
		in.Send(resp)
	}
	if ok {
		*breaks = appendBreaks(*breaks, resp.Breaks.Breaks)
	}
	return resp, nil
}

func (t *KBFSTLFInfoSource) CompleteAndCanonicalizePrivateTlfName(ctx context.Context, tlfName string) (res keybase1.CanonicalTLFNameAndIDWithBreaks, err error) {
	username := t.G().Env.GetUsername()
	if len(username) == 0 {
		return keybase1.CanonicalTLFNameAndIDWithBreaks{}, libkb.LoginRequiredError{}
	}

	// Prepend username in case it's not present. We don't need to check if it
	// exists already since CryptKeys calls below transforms the TLF name into a
	// canonical one.
	//
	// This makes username a writer on this TLF, which might be unexpected.
	// TODO: We should think about how to handle read-only TLFs.
	tlfName = string(username) + "," + tlfName

	// TODO: do some caching so we don't end up calling this RPC
	// unnecessarily too often
	resp, err := t.CryptKeys(ctx, tlfName)
	if err != nil {
		return keybase1.CanonicalTLFNameAndIDWithBreaks{}, err
	}

	return resp.NameIDBreaks, nil
}

func (t *KBFSTLFInfoSource) identifyTLF(ctx context.Context, arg keybase1.TLFQuery, private bool) ([]keybase1.TLFIdentifyFailure, error) {
	var fails []keybase1.TLFIdentifyFailure
	pieces := strings.Split(strings.Fields(arg.TlfName)[0], ",")
	for _, p := range pieces {
		f, err := t.identifyUser(ctx, p, private, arg.IdentifyBehavior)
		if err != nil {
			return nil, err
		}
		fails = append(fails, f)
	}
	return fails, nil
}

func (t *KBFSTLFInfoSource) identifyUser(ctx context.Context, assertion string, private bool, idBehavior keybase1.TLFIdentifyBehavior) (keybase1.TLFIdentifyFailure, error) {

	// if an identify UI is registered, then use it
	sessionID, idUI, err := t.G().UIRouter.GetIdentifyUICtx(ctx)
	if err != nil {
		return keybase1.TLFIdentifyFailure{}, err
	}

	if idUI == nil {
		if t.identifier != nil {
			t.G().Log.Debug("using KBFSTLFInfoSource.identifier to identify")
			return t.identifier.Identify(ctx, assertion, private, idBehavior)
		}

		sessionID = 0
		idUI = chatNullIdentifyUI{}
	}

	reason := "You accessed a public conversation."
	if private {
		reason = fmt.Sprintf("You accessed a private conversation with %s.", assertion)
	}

	arg := keybase1.Identify2Arg{
		UserAssertion:    assertion,
		UseDelegateUI:    true,
		Reason:           keybase1.IdentifyReason{Reason: reason},
		CanSuppressUI:    true,
		IdentifyBehavior: idBehavior,
	}

	ectx := engine.Context{
		IdentifyUI: idUI,
		SessionID:  sessionID,
		NetContext: ctx,
	}

	eng := engine.NewResolveThenIdentify2(t.G(), &arg)
	err = engine.RunEngine(eng, &ectx)
	if err != nil {
		return keybase1.TLFIdentifyFailure{}, err
	}
	resp := eng.Result()

	var frep keybase1.TLFIdentifyFailure
	if resp != nil {
		frep.User = keybase1.User{
			Uid:      resp.Upk.Uid,
			Username: resp.Upk.Username,
		}
		frep.Breaks = resp.TrackBreaks
	}

	return frep, nil
}

func appendBreaks(l []keybase1.TLFIdentifyFailure, r []keybase1.TLFIdentifyFailure) []keybase1.TLFIdentifyFailure {
	m := make(map[string]bool)
	var res []keybase1.TLFIdentifyFailure
	for _, f := range l {
		m[f.User.Username] = true
		res = append(res, f)
	}
	for _, f := range r {
		if !m[f.User.Username] {
			res = append(res, f)
		}
	}
	return res
}
<commit_msg>Use t.Debug instead of t.G().Log.Debug<commit_after>package chat

import (
	"fmt"
	"strings"

	"github.com/keybase/client/go/chat/types"
	"github.com/keybase/client/go/chat/utils"
	"github.com/keybase/client/go/engine"
	"github.com/keybase/client/go/libkb"
	"github.com/keybase/client/go/protocol/chat1"
	"github.com/keybase/client/go/protocol/keybase1"
	"github.com/keybase/go-framed-msgpack-rpc/rpc"
	context "golang.org/x/net/context"
)

type KBFSTLFInfoSource struct {
	utils.DebugLabeler
	libkb.Contextified
	identifier types.Identifier
}

func NewKBFSTLFInfoSource(g *libkb.GlobalContext) *KBFSTLFInfoSource {
	return &KBFSTLFInfoSource{
		DebugLabeler: utils.NewDebugLabeler(g, "KBFSTLFInfoSource", false),
		Contextified: libkb.NewContextified(g),
	}
}

func NewKBFSTLFInfoSourceWithIdentifier(g *libkb.GlobalContext, identifier types.Identifier) *KBFSTLFInfoSource {
	s := NewKBFSTLFInfoSource(g)
	s.identifier = identifier
	return s
}

func (t *KBFSTLFInfoSource) tlfKeysClient() (*keybase1.TlfKeysClient, error) {
	xp := t.G().ConnectionManager.LookupByClientType(keybase1.ClientType_KBFS)
	if xp == nil {
		return nil, fmt.Errorf("KBFS client wasn't found")
	}
	return &keybase1.TlfKeysClient{
		Cli: rpc.NewClient(
			xp, libkb.ErrorUnwrapper{}, libkb.LogTagsFromContext),
	}, nil
}

func (t *KBFSTLFInfoSource) Lookup(ctx context.Context, tlfName string,
	visibility chat1.TLFVisibility) (*types.TLFInfo, error) {
	res, err := CtxKeyFinder(ctx).Find(ctx, t, tlfName, visibility == chat1.TLFVisibility_PUBLIC)
	if err != nil {
		return nil, err
	}
	info := &types.TLFInfo{
		ID:               chat1.TLFID(res.NameIDBreaks.TlfID.ToBytes()),
		CanonicalName:    res.NameIDBreaks.CanonicalName.String(),
		IdentifyFailures: res.NameIDBreaks.Breaks.Breaks,
	}
	return info, nil
}

func (t *KBFSTLFInfoSource) CryptKeys(ctx context.Context, tlfName string) (res keybase1.GetTLFCryptKeysRes, err error) {
	identBehavior, breaks, ok := IdentifyMode(ctx)
	if !ok {
		return res, fmt.Errorf("invalid context with no chat metadata")
	}
	defer t.Trace(ctx, func() error { return err },
		fmt.Sprintf("CryptKeys(tlf=%s,mode=%v)", tlfName, identBehavior))()

	query := keybase1.TLFQuery{
		TlfName:          tlfName,
		IdentifyBehavior: identBehavior,
	}
	ib, err := t.identifyTLF(ctx, query, true)
	if err != nil {
		return keybase1.GetTLFCryptKeysRes{}, err
	}

	tlfClient, err := t.tlfKeysClient()
	if err != nil {
		return res, err
	}

	// skip identify:
	query.IdentifyBehavior = keybase1.TLFIdentifyBehavior_CHAT_SKIP

	resp, err := tlfClient.GetTLFCryptKeys(ctx, query)
	if err != nil {
		return resp, err
	}

	// use id breaks calculated by identifyTLF
	resp.NameIDBreaks.Breaks.Breaks = ib

	if in := CtxIdentifyNotifier(ctx); in != nil {
		in.Send(resp.NameIDBreaks)
	}
	if ok {
		*breaks = appendBreaks(*breaks, resp.NameIDBreaks.Breaks.Breaks)
	}
	return resp, nil
}

func (t *KBFSTLFInfoSource) PublicCanonicalTLFNameAndID(ctx context.Context, tlfName string) (res keybase1.CanonicalTLFNameAndIDWithBreaks, err error) {
	identBehavior, breaks, ok := IdentifyMode(ctx)
	if !ok {
		return res, fmt.Errorf("invalid context with no chat metadata")
	}
	defer t.Trace(ctx, func() error { return err },
		fmt.Sprintf("PublicCanonicalTLFNameAndID(tlf=%s,mode=%v)", tlfName, identBehavior))()

	query := keybase1.TLFQuery{
		TlfName:          tlfName,
		IdentifyBehavior: identBehavior,
	}
	ib, err := t.identifyTLF(ctx, query, false)
	if err != nil {
		return keybase1.CanonicalTLFNameAndIDWithBreaks{}, err
	}

	tlfClient, err := t.tlfKeysClient()
	if err != nil {
		return keybase1.CanonicalTLFNameAndIDWithBreaks{}, err
	}

	// skip identify:
	query.IdentifyBehavior = keybase1.TLFIdentifyBehavior_CHAT_SKIP

	resp, err := tlfClient.GetPublicCanonicalTLFNameAndID(ctx, query)
	if err != nil {
		return resp, err
	}

	// use id breaks calculated by identifyTLF
	resp.Breaks.Breaks = ib

	if in := CtxIdentifyNotifier(ctx); in != nil {
		in.Send(resp)
	}
	if ok {
		*breaks = appendBreaks(*breaks, resp.Breaks.Breaks)
	}
	return resp, nil
}

func (t *KBFSTLFInfoSource) CompleteAndCanonicalizePrivateTlfName(ctx context.Context, tlfName string) (res keybase1.CanonicalTLFNameAndIDWithBreaks, err error) {
	username := t.G().Env.GetUsername()
	if len(username) == 0 {
		return keybase1.CanonicalTLFNameAndIDWithBreaks{}, libkb.LoginRequiredError{}
	}

	// Prepend username in case it's not present. We don't need to check if it
	// exists already since CryptKeys calls below transforms the TLF name into a
	// canonical one.
	//
	// This makes username a writer on this TLF, which might be unexpected.
	// TODO: We should think about how to handle read-only TLFs.
	tlfName = string(username) + "," + tlfName

	// TODO: do some caching so we don't end up calling this RPC
	// unnecessarily too often
	resp, err := t.CryptKeys(ctx, tlfName)
	if err != nil {
		return keybase1.CanonicalTLFNameAndIDWithBreaks{}, err
	}

	return resp.NameIDBreaks, nil
}

func (t *KBFSTLFInfoSource) identifyTLF(ctx context.Context, arg keybase1.TLFQuery, private bool) ([]keybase1.TLFIdentifyFailure, error) {
	var fails []keybase1.TLFIdentifyFailure
	pieces := strings.Split(strings.Fields(arg.TlfName)[0], ",")
	for _, p := range pieces {
		f, err := t.identifyUser(ctx, p, private, arg.IdentifyBehavior)
		if err != nil {
			return nil, err
		}
		fails = append(fails, f)
	}
	return fails, nil
}

func (t *KBFSTLFInfoSource) identifyUser(ctx context.Context, assertion string, private bool, idBehavior keybase1.TLFIdentifyBehavior) (keybase1.TLFIdentifyFailure, error) {

	// if an identify UI is registered, then use it
	sessionID, idUI, err := t.G().UIRouter.GetIdentifyUICtx(ctx)
	if err != nil {
		return keybase1.TLFIdentifyFailure{}, err
	}

	if idUI == nil {
		if t.identifier != nil {
			t.Debug(ctx, "using KBFSTLFInfoSource.identifier to identify")
			return t.identifier.Identify(ctx, assertion, private, idBehavior)
		}

		t.Debug(ctx, "no delegated identify ui, no KBFSTLFInfoSource.identifier: using null identify ui")
		sessionID = 0
		idUI = chatNullIdentifyUI{}
	}

	reason := "You accessed a public conversation."
	if private {
		reason = fmt.Sprintf("You accessed a private conversation with %s.", assertion)
	}

	arg := keybase1.Identify2Arg{
		UserAssertion:    assertion,
		UseDelegateUI:    true,
		Reason:           keybase1.IdentifyReason{Reason: reason},
		CanSuppressUI:    true,
		IdentifyBehavior: idBehavior,
	}

	ectx := engine.Context{
		IdentifyUI: idUI,
		SessionID:  sessionID,
		NetContext: ctx,
	}

	eng := engine.NewResolveThenIdentify2(t.G(), &arg)
	err = engine.RunEngine(eng, &ectx)
	if err != nil {
		return keybase1.TLFIdentifyFailure{}, err
	}
	resp := eng.Result()

	var frep keybase1.TLFIdentifyFailure
	if resp != nil {
		frep.User = keybase1.User{
			Uid:      resp.Upk.Uid,
			Username: resp.Upk.Username,
		}
		frep.Breaks = resp.TrackBreaks
	}

	return frep, nil
}

func appendBreaks(l []keybase1.TLFIdentifyFailure, r []keybase1.TLFIdentifyFailure) []keybase1.TLFIdentifyFailure {
	m := make(map[string]bool)
	var res []keybase1.TLFIdentifyFailure
	for _, f := range l {
		m[f.User.Username] = true
		res = append(res, f)
	}
	for _, f := range r {
		if !m[f.User.Username] {
			res = append(res, f)
		}
	}
	return res
}
<|endoftext|>


<commit_before>package goEnv

import (
	"os"
	"reflect"
	"strconv"
	"strings"

	"github.com/crgimenes/goConfig/structTag"
)

func init() {
	SetTag("env")
	SetTagDefault("envDefault")

	structTag.ParseMap[reflect.Int] = reflectInt
	structTag.ParseMap[reflect.String] = reflectString
}

// SetTag set a new tag
func SetTag(tag string) {
	structTag.Tag = tag
}

// SetTagDefault set a new TagDefault to retorn default values
func SetTagDefault(tag string) {
	structTag.TagDefault = tag
}

// Parse configuration
func Parse(config interface{}) (err error) {
	err = structTag.Parse(config, "")
	return
}

func getNewValue(field *reflect.StructField, value *reflect.Value, tag string) (ret string) {

	// get value from environment variable
	ret = os.Getenv(strings.ToUpper(tag))
	if ret != "" {
		return
	}

	// get value from default settings
	ret = field.Tag.Get(structTag.TagDefault)

	return
}

func reflectInt(field *reflect.StructField, value *reflect.Value, tag string) (err error) {
	newValue := getNewValue(field, value, tag)
	if newValue == "" {
		return
	}

	var intNewValue int64
	intNewValue, err = strconv.ParseInt(newValue, 10, 64)
	if err != nil {
		return
	}

	value.SetInt(intNewValue)

	return
}

func reflectString(field *reflect.StructField, value *reflect.Value, tag string) (err error) {
	newValue := getNewValue(field, value, tag)

	value.SetString(newValue)

	return
}
<commit_msg>add setup<commit_after>package goEnv

import (
	"os"
	"reflect"
	"strconv"
	"strings"

	"github.com/crgimenes/goConfig/structTag"
)

// Setup maps and variables
func Setup() {
	structTag.Setup()
	SetTag("env")
	SetTagDefault("envDefault")

	structTag.ParseMap[reflect.Int] = reflectInt
	structTag.ParseMap[reflect.String] = reflectString
}

// SetTag set a new tag
func SetTag(tag string) {
	structTag.Tag = tag
}

// SetTagDefault set a new TagDefault to retorn default values
func SetTagDefault(tag string) {
	structTag.TagDefault = tag
}

// Parse configuration
func Parse(config interface{}) (err error) {
	err = structTag.Parse(config, "")
	return
}

func getNewValue(field *reflect.StructField, value *reflect.Value, tag string) (ret string) {

	// get value from environment variable
	ret = os.Getenv(strings.ToUpper(tag))
	if ret != "" {
		return
	}

	// get value from default settings
	ret = field.Tag.Get(structTag.TagDefault)

	return
}

func reflectInt(field *reflect.StructField, value *reflect.Value, tag string) (err error) {
	newValue := getNewValue(field, value, tag)
	if newValue == "" {
		return
	}

	var intNewValue int64
	intNewValue, err = strconv.ParseInt(newValue, 10, 64)
	if err != nil {
		return
	}

	value.SetInt(intNewValue)

	return
}

func reflectString(field *reflect.StructField, value *reflect.Value, tag string) (err error) {
	newValue := getNewValue(field, value, tag)

	value.SetString(newValue)

	return
}
<|endoftext|>


<commit_before>// Copyright 2017 tsuru-client 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 main

import (
	"log"
	"os"

	"github.com/docker/machine/libmachine/drivers/plugin/localbinary"
	"github.com/tsuru/tsuru-client/tsuru/admin"
	"github.com/tsuru/tsuru-client/tsuru/client"
	"github.com/tsuru/tsuru-client/tsuru/installer"
	"github.com/tsuru/tsuru/cmd"
	"github.com/tsuru/tsuru/iaas/dockermachine"
	_ "github.com/tsuru/tsuru/provision/docker/cmds"
)

const (
	version = "1.5.0-rc2"
	header  = "Supported-Tsuru"
)

func buildManager(name string) *cmd.Manager {
	lookup := func(context *cmd.Context) error {
		return client.RunPlugin(context)
	}
	m := cmd.BuildBaseManager(name, version, header, lookup)
	m.Register(&client.AppRun{})
	m.Register(&client.AppInfo{})
	m.Register(&client.AppCreate{})
	m.Register(&client.AppRemove{})
	m.Register(&client.AppUpdate{})
	m.Register(&client.UnitAdd{})
	m.Register(&client.UnitRemove{})
	m.Register(&client.AppList{})
	m.Register(&client.AppLog{})
	m.Register(&client.AppGrant{})
	m.Register(&client.AppRevoke{})
	m.Register(&client.AppRestart{})
	m.Register(&client.AppStart{})
	m.Register(&client.AppStop{})
	m.Register(&admin.AppLockDelete{})
	m.Register(&client.CertificateSet{})
	m.Register(&client.CertificateUnset{})
	m.Register(&client.CertificateList{})
	m.Register(&client.CnameAdd{})
	m.Register(&client.CnameRemove{})
	m.Register(&client.EnvGet{})
	m.Register(&client.EnvSet{})
	m.Register(&client.EnvUnset{})
	m.Register(&client.KeyAdd{})
	m.Register(&client.KeyRemove{})
	m.Register(&client.KeyList{})
	m.Register(client.ServiceList{})
	m.Register(&client.ServiceInstanceAdd{})
	m.Register(&client.ServiceInstanceUpdate{})
	m.Register(&client.ServiceInstanceRemove{})
	m.Register(client.ServiceInfo{})
	m.Register(client.ServiceInstanceInfo{})
	m.Register(client.ServiceInstanceStatus{})
	m.Register(&client.ServiceInstanceGrant{})
	m.Register(&client.ServiceInstanceRevoke{})
	m.Register(&client.ServiceInstanceBind{})
	m.Register(&client.ServiceInstanceUnbind{})
	m.Register(&admin.PlatformList{})
	m.Register(&admin.PlatformAdd{})
	m.Register(&admin.PlatformUpdate{})
	m.Register(&admin.PlatformRemove{})
	m.Register(&client.PluginInstall{})
	m.Register(&client.PluginRemove{})
	m.Register(&client.PluginList{})
	m.Register(&client.AppSwap{})
	m.Register(&client.AppDeploy{})
	m.Register(&client.AppBuild{})
	m.Register(&client.PlanList{})
	m.Register(&client.UserCreate{})
	m.Register(&client.ResetPassword{})
	m.Register(&client.UserRemove{})
	m.Register(&client.ListUsers{})
	m.Register(&client.TeamCreate{})
	m.Register(&client.TeamUpdate{})
	m.Register(&client.TeamRemove{})
	m.Register(&client.TeamList{})
	m.Register(&client.TeamInfo{})
	m.Register(&client.ChangePassword{})
	m.Register(&client.ShowAPIToken{})
	m.Register(&client.RegenerateAPIToken{})
	m.Register(&client.AppDeployList{})
	m.Register(&client.AppDeployRollback{})
	m.Register(&client.AppDeployRollbackUpdate{})
	m.Register(&client.AppDeployRebuild{})
	m.Register(&cmd.ShellToContainerCmd{})
	m.Register(&client.PoolList{})
	m.Register(&client.PermissionList{})
	m.Register(&client.RoleAdd{})
	m.Register(&client.RoleUpdate{})
	m.Register(&client.RoleRemove{})
	m.Register(&client.RoleList{})
	m.Register(&client.RoleInfo{})
	m.Register(&client.RolePermissionAdd{})
	m.Register(&client.RolePermissionRemove{})
	m.Register(&client.RoleAssign{})
	m.Register(&client.RoleDissociate{})
	m.Register(&client.RoleDefaultAdd{})
	m.Register(&client.RoleDefaultList{})
	m.Register(&client.RoleDefaultRemove{})
	m.Register(&installer.Install{})
	m.Register(&installer.Uninstall{})
	m.Register(&installer.InstallHostList{})
	m.Register(&installer.InstallSSH{})
	m.Register(&installer.InstallConfigInit{})
	m.Register(&admin.AddPoolToSchedulerCmd{})
	m.Register(&client.EventList{})
	m.Register(&client.EventInfo{})
	m.Register(&client.EventCancel{})
	m.Register(&client.RoutersList{})
	m.Register(&admin.TemplateList{})
	m.Register(&admin.TemplateAdd{})
	m.Register(&admin.TemplateRemove{})
	m.Register(&admin.MachineList{})
	m.Register(&admin.MachineDestroy{})
	m.Register(&admin.TemplateUpdate{})
	m.Register(&admin.PlanCreate{})
	m.Register(&admin.PlanRemove{})
	m.Register(&admin.UpdatePoolToSchedulerCmd{})
	m.Register(&admin.RemovePoolFromSchedulerCmd{})
	m.Register(&admin.ServiceCreate{})
	m.Register(&admin.ServiceDestroy{})
	m.Register(&admin.ServiceUpdate{})
	m.Register(&admin.ServiceDocGet{})
	m.Register(&admin.ServiceDocAdd{})
	m.Register(&admin.ServiceTemplate{})
	m.Register(&admin.UserQuotaView{})
	m.Register(&admin.UserChangeQuota{})
	m.Register(&admin.AppQuotaView{})
	m.Register(&admin.AppQuotaChange{})
	m.Register(&admin.AppRoutesRebuild{})
	m.Register(&admin.PoolConstraintList{})
	m.Register(&admin.PoolConstraintSet{})
	m.Register(&admin.EventBlockList{})
	m.Register(&admin.EventBlockAdd{})
	m.Register(&admin.EventBlockRemove{})
	m.Register(&client.TagList{})
	m.Register(&admin.NodeContainerList{})
	m.Register(&admin.NodeContainerAdd{})
	m.Register(&admin.NodeContainerInfo{})
	m.Register(&admin.NodeContainerUpdate{})
	m.Register(&admin.NodeContainerDelete{})
	m.Register(&admin.NodeContainerUpgrade{})
	m.Register(&admin.ClusterAdd{})
	m.Register(&admin.ClusterUpdate{})
	m.Register(&admin.ClusterRemove{})
	m.Register(&admin.ClusterList{})
	m.Register(&client.VolumeCreate{})
	m.Register(&client.VolumeUpdate{})
	m.Register(&client.VolumeList{})
	m.Register(&client.VolumePlansList{})
	m.Register(&client.VolumeDelete{})
	m.Register(&client.VolumeBind{})
	m.Register(&client.VolumeUnbind{})
	m.Register(&client.AppRoutersList{})
	m.Register(&client.AppRoutersAdd{})
	m.Register(&client.AppRoutersRemove{})
	m.Register(&client.AppRoutersUpdate{})
	m.Register(&admin.InfoNodeCmd{})
	m.RegisterRemoved("bs-env-set", "You should use `tsuru node-container-update big-sibling` instead.")
	m.RegisterRemoved("bs-info", "You should use `tsuru node-container-info big-sibling` instead.")
	m.RegisterRemoved("bs-upgrade", "You should use `tsuru node-container-upgrade big-sibling` instead.")
	m.RegisterDeprecated(&admin.AddTeamsToPoolCmd{}, "pool-teams-add")
	m.RegisterDeprecated(&admin.RemoveTeamsFromPoolCmd{}, "pool-teams-remove")
	m.RegisterDeprecated(&admin.AddNodeCmd{}, "docker-node-add")
	m.RegisterDeprecated(&admin.RemoveNodeCmd{}, "docker-node-remove")
	m.RegisterDeprecated(&admin.UpdateNodeCmd{}, "docker-node-update")
	m.RegisterDeprecated(&admin.ListNodesCmd{}, "docker-node-list")
	m.RegisterDeprecated(&admin.GetNodeHealingConfigCmd{}, "docker-healing-info")
	m.RegisterDeprecated(&admin.SetNodeHealingConfigCmd{}, "docker-healing-update")
	m.RegisterDeprecated(&admin.DeleteNodeHealingConfigCmd{}, "docker-healing-delete")
	m.RegisterDeprecated(&admin.RebalanceNodeCmd{}, "containers-rebalance")
	m.RegisterDeprecated(&admin.AutoScaleRunCmd{}, "docker-autoscale-run")
	m.RegisterDeprecated(&admin.ListAutoScaleHistoryCmd{}, "docker-autoscale-list")
	m.RegisterDeprecated(&admin.AutoScaleInfoCmd{}, "docker-autoscale-info")
	m.RegisterDeprecated(&admin.AutoScaleSetRuleCmd{}, "docker-autoscale-rule-set")
	m.RegisterDeprecated(&admin.AutoScaleDeleteRuleCmd{}, "docker-autoscale-rule-remove")
	m.RegisterDeprecated(&admin.ListHealingHistoryCmd{}, "docker-healing-list")
	registerExtraCommands(m)
	return m
}

func registerExtraCommands(m *cmd.Manager) {
	for _, c := range cmd.ExtraCmds() {
		m.Register(c)
	}
}

func inDockerMachineDriverMode() bool {
	return os.Getenv(localbinary.PluginEnvKey) == localbinary.PluginEnvVal
}

func main() {
	if inDockerMachineDriverMode() {
		err := dockermachine.RunDriver(os.Getenv(localbinary.PluginEnvDriverName))
		if err != nil {
			log.Fatalf("Error running driver: %s", err)
		}
	} else {
		localbinary.CurrentBinaryIsDockerMachine = true
		name := cmd.ExtractProgramName(os.Args[0])
		m := buildManager(name)
		m.Run(os.Args[1:])
	}
}
<commit_msg>bump version to 1.5.0-rc3<commit_after>// Copyright 2017 tsuru-client 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 main

import (
	"log"
	"os"

	"github.com/docker/machine/libmachine/drivers/plugin/localbinary"
	"github.com/tsuru/tsuru-client/tsuru/admin"
	"github.com/tsuru/tsuru-client/tsuru/client"
	"github.com/tsuru/tsuru-client/tsuru/installer"
	"github.com/tsuru/tsuru/cmd"
	"github.com/tsuru/tsuru/iaas/dockermachine"
	_ "github.com/tsuru/tsuru/provision/docker/cmds"
)

const (
	version = "1.5.0-rc3"
	header  = "Supported-Tsuru"
)

func buildManager(name string) *cmd.Manager {
	lookup := func(context *cmd.Context) error {
		return client.RunPlugin(context)
	}
	m := cmd.BuildBaseManager(name, version, header, lookup)
	m.Register(&client.AppRun{})
	m.Register(&client.AppInfo{})
	m.Register(&client.AppCreate{})
	m.Register(&client.AppRemove{})
	m.Register(&client.AppUpdate{})
	m.Register(&client.UnitAdd{})
	m.Register(&client.UnitRemove{})
	m.Register(&client.AppList{})
	m.Register(&client.AppLog{})
	m.Register(&client.AppGrant{})
	m.Register(&client.AppRevoke{})
	m.Register(&client.AppRestart{})
	m.Register(&client.AppStart{})
	m.Register(&client.AppStop{})
	m.Register(&admin.AppLockDelete{})
	m.Register(&client.CertificateSet{})
	m.Register(&client.CertificateUnset{})
	m.Register(&client.CertificateList{})
	m.Register(&client.CnameAdd{})
	m.Register(&client.CnameRemove{})
	m.Register(&client.EnvGet{})
	m.Register(&client.EnvSet{})
	m.Register(&client.EnvUnset{})
	m.Register(&client.KeyAdd{})
	m.Register(&client.KeyRemove{})
	m.Register(&client.KeyList{})
	m.Register(client.ServiceList{})
	m.Register(&client.ServiceInstanceAdd{})
	m.Register(&client.ServiceInstanceUpdate{})
	m.Register(&client.ServiceInstanceRemove{})
	m.Register(client.ServiceInfo{})
	m.Register(client.ServiceInstanceInfo{})
	m.Register(client.ServiceInstanceStatus{})
	m.Register(&client.ServiceInstanceGrant{})
	m.Register(&client.ServiceInstanceRevoke{})
	m.Register(&client.ServiceInstanceBind{})
	m.Register(&client.ServiceInstanceUnbind{})
	m.Register(&admin.PlatformList{})
	m.Register(&admin.PlatformAdd{})
	m.Register(&admin.PlatformUpdate{})
	m.Register(&admin.PlatformRemove{})
	m.Register(&client.PluginInstall{})
	m.Register(&client.PluginRemove{})
	m.Register(&client.PluginList{})
	m.Register(&client.AppSwap{})
	m.Register(&client.AppDeploy{})
	m.Register(&client.AppBuild{})
	m.Register(&client.PlanList{})
	m.Register(&client.UserCreate{})
	m.Register(&client.ResetPassword{})
	m.Register(&client.UserRemove{})
	m.Register(&client.ListUsers{})
	m.Register(&client.TeamCreate{})
	m.Register(&client.TeamUpdate{})
	m.Register(&client.TeamRemove{})
	m.Register(&client.TeamList{})
	m.Register(&client.TeamInfo{})
	m.Register(&client.ChangePassword{})
	m.Register(&client.ShowAPIToken{})
	m.Register(&client.RegenerateAPIToken{})
	m.Register(&client.AppDeployList{})
	m.Register(&client.AppDeployRollback{})
	m.Register(&client.AppDeployRollbackUpdate{})
	m.Register(&client.AppDeployRebuild{})
	m.Register(&cmd.ShellToContainerCmd{})
	m.Register(&client.PoolList{})
	m.Register(&client.PermissionList{})
	m.Register(&client.RoleAdd{})
	m.Register(&client.RoleUpdate{})
	m.Register(&client.RoleRemove{})
	m.Register(&client.RoleList{})
	m.Register(&client.RoleInfo{})
	m.Register(&client.RolePermissionAdd{})
	m.Register(&client.RolePermissionRemove{})
	m.Register(&client.RoleAssign{})
	m.Register(&client.RoleDissociate{})
	m.Register(&client.RoleDefaultAdd{})
	m.Register(&client.RoleDefaultList{})
	m.Register(&client.RoleDefaultRemove{})
	m.Register(&installer.Install{})
	m.Register(&installer.Uninstall{})
	m.Register(&installer.InstallHostList{})
	m.Register(&installer.InstallSSH{})
	m.Register(&installer.InstallConfigInit{})
	m.Register(&admin.AddPoolToSchedulerCmd{})
	m.Register(&client.EventList{})
	m.Register(&client.EventInfo{})
	m.Register(&client.EventCancel{})
	m.Register(&client.RoutersList{})
	m.Register(&admin.TemplateList{})
	m.Register(&admin.TemplateAdd{})
	m.Register(&admin.TemplateRemove{})
	m.Register(&admin.MachineList{})
	m.Register(&admin.MachineDestroy{})
	m.Register(&admin.TemplateUpdate{})
	m.Register(&admin.PlanCreate{})
	m.Register(&admin.PlanRemove{})
	m.Register(&admin.UpdatePoolToSchedulerCmd{})
	m.Register(&admin.RemovePoolFromSchedulerCmd{})
	m.Register(&admin.ServiceCreate{})
	m.Register(&admin.ServiceDestroy{})
	m.Register(&admin.ServiceUpdate{})
	m.Register(&admin.ServiceDocGet{})
	m.Register(&admin.ServiceDocAdd{})
	m.Register(&admin.ServiceTemplate{})
	m.Register(&admin.UserQuotaView{})
	m.Register(&admin.UserChangeQuota{})
	m.Register(&admin.AppQuotaView{})
	m.Register(&admin.AppQuotaChange{})
	m.Register(&admin.AppRoutesRebuild{})
	m.Register(&admin.PoolConstraintList{})
	m.Register(&admin.PoolConstraintSet{})
	m.Register(&admin.EventBlockList{})
	m.Register(&admin.EventBlockAdd{})
	m.Register(&admin.EventBlockRemove{})
	m.Register(&client.TagList{})
	m.Register(&admin.NodeContainerList{})
	m.Register(&admin.NodeContainerAdd{})
	m.Register(&admin.NodeContainerInfo{})
	m.Register(&admin.NodeContainerUpdate{})
	m.Register(&admin.NodeContainerDelete{})
	m.Register(&admin.NodeContainerUpgrade{})
	m.Register(&admin.ClusterAdd{})
	m.Register(&admin.ClusterUpdate{})
	m.Register(&admin.ClusterRemove{})
	m.Register(&admin.ClusterList{})
	m.Register(&client.VolumeCreate{})
	m.Register(&client.VolumeUpdate{})
	m.Register(&client.VolumeList{})
	m.Register(&client.VolumePlansList{})
	m.Register(&client.VolumeDelete{})
	m.Register(&client.VolumeBind{})
	m.Register(&client.VolumeUnbind{})
	m.Register(&client.AppRoutersList{})
	m.Register(&client.AppRoutersAdd{})
	m.Register(&client.AppRoutersRemove{})
	m.Register(&client.AppRoutersUpdate{})
	m.Register(&admin.InfoNodeCmd{})
	m.RegisterRemoved("bs-env-set", "You should use `tsuru node-container-update big-sibling` instead.")
	m.RegisterRemoved("bs-info", "You should use `tsuru node-container-info big-sibling` instead.")
	m.RegisterRemoved("bs-upgrade", "You should use `tsuru node-container-upgrade big-sibling` instead.")
	m.RegisterDeprecated(&admin.AddTeamsToPoolCmd{}, "pool-teams-add")
	m.RegisterDeprecated(&admin.RemoveTeamsFromPoolCmd{}, "pool-teams-remove")
	m.RegisterDeprecated(&admin.AddNodeCmd{}, "docker-node-add")
	m.RegisterDeprecated(&admin.RemoveNodeCmd{}, "docker-node-remove")
	m.RegisterDeprecated(&admin.UpdateNodeCmd{}, "docker-node-update")
	m.RegisterDeprecated(&admin.ListNodesCmd{}, "docker-node-list")
	m.RegisterDeprecated(&admin.GetNodeHealingConfigCmd{}, "docker-healing-info")
	m.RegisterDeprecated(&admin.SetNodeHealingConfigCmd{}, "docker-healing-update")
	m.RegisterDeprecated(&admin.DeleteNodeHealingConfigCmd{}, "docker-healing-delete")
	m.RegisterDeprecated(&admin.RebalanceNodeCmd{}, "containers-rebalance")
	m.RegisterDeprecated(&admin.AutoScaleRunCmd{}, "docker-autoscale-run")
	m.RegisterDeprecated(&admin.ListAutoScaleHistoryCmd{}, "docker-autoscale-list")
	m.RegisterDeprecated(&admin.AutoScaleInfoCmd{}, "docker-autoscale-info")
	m.RegisterDeprecated(&admin.AutoScaleSetRuleCmd{}, "docker-autoscale-rule-set")
	m.RegisterDeprecated(&admin.AutoScaleDeleteRuleCmd{}, "docker-autoscale-rule-remove")
	m.RegisterDeprecated(&admin.ListHealingHistoryCmd{}, "docker-healing-list")
	registerExtraCommands(m)
	return m
}

func registerExtraCommands(m *cmd.Manager) {
	for _, c := range cmd.ExtraCmds() {
		m.Register(c)
	}
}

func inDockerMachineDriverMode() bool {
	return os.Getenv(localbinary.PluginEnvKey) == localbinary.PluginEnvVal
}

func main() {
	if inDockerMachineDriverMode() {
		err := dockermachine.RunDriver(os.Getenv(localbinary.PluginEnvDriverName))
		if err != nil {
			log.Fatalf("Error running driver: %s", err)
		}
	} else {
		localbinary.CurrentBinaryIsDockerMachine = true
		name := cmd.ExtractProgramName(os.Args[0])
		m := buildManager(name)
		m.Run(os.Args[1:])
	}
}
<|endoftext|>


<commit_before>package common

import (
	"bytes"
	"fmt"
	"log"
	"os/exec"
	"regexp"
	"strconv"
	"strings"
	"time"

	packer "github.com/hashicorp/packer/common"
)

type VBox42Driver struct {
	// This is the path to the "VBoxManage" application.
	VBoxManagePath string
}

func (d *VBox42Driver) CreateSATAController(vmName string, name string, portcount int) error {
	version, err := d.Version()
	if err != nil {
		return err
	}

	portCountArg := "--sataportcount"
	if strings.HasPrefix(version, "4.3") || strings.HasPrefix(version, "5.") || strings.HasPrefix(version, "6.") {
		portCountArg = "--portcount"
	}

	command := []string{
		"storagectl", vmName,
		"--name", name,
		"--add", "sata",
		portCountArg, strconv.Itoa(portcount),
	}

	return d.VBoxManage(command...)
}

func (d *VBox42Driver) CreateSCSIController(vmName string, name string) error {

	command := []string{
		"storagectl", vmName,
		"--name", name,
		"--add", "scsi",
		"--controller", "LSILogic",
	}

	return d.VBoxManage(command...)
}

func (d *VBox42Driver) Delete(name string) error {
	return packer.Retry(1, 1, 5, func(i uint) (bool, error) {
		if err := d.VBoxManage("unregistervm", name, "--delete"); err != nil {
			if i+1 == 5 {
				return false, err
			}
			return false, nil
		}
		return true, nil
	})
}

func (d *VBox42Driver) Iso() (string, error) {
	var stdout bytes.Buffer

	cmd := exec.Command(d.VBoxManagePath, "list", "systemproperties")
	cmd.Stdout = &stdout
	if err := cmd.Run(); err != nil {
		return "", err
	}

	DefaultGuestAdditionsRe := regexp.MustCompile("Default Guest Additions ISO:(.+)")

	for _, line := range strings.Split(stdout.String(), "\n") {
		// Need to trim off CR character when running in windows
		// Trimming whitespaces at this point helps to filter out empty value
		line = strings.TrimRight(line, " \r")

		matches := DefaultGuestAdditionsRe.FindStringSubmatch(line)
		if matches == nil {
			continue
		}

		isoname := strings.Trim(matches[1], " \r\n")
		log.Printf("Found Default Guest Additions ISO: %s", isoname)

		return isoname, nil
	}

	return "", fmt.Errorf("Cannot find \"Default Guest Additions ISO\" in vboxmanage output (or it is empty)")
}

func (d *VBox42Driver) Import(name string, path string, flags []string) error {
	args := []string{
		"import", path,
		"--vsys", "0",
		"--vmname", name,
	}
	args = append(args, flags...)

	return d.VBoxManage(args...)
}

func (d *VBox42Driver) IsRunning(name string) (bool, error) {
	var stdout bytes.Buffer

	cmd := exec.Command(d.VBoxManagePath, "showvminfo", name, "--machinereadable")
	cmd.Stdout = &stdout
	if err := cmd.Run(); err != nil {
		return false, err
	}

	for _, line := range strings.Split(stdout.String(), "\n") {
		// Need to trim off CR character when running in windows
		line = strings.TrimRight(line, "\r")

		if line == `VMState="running"` {
			return true, nil
		}

		// We consider "stopping" to still be running. We wait for it to
		// be completely stopped or some other state.
		if line == `VMState="stopping"` {
			return true, nil
		}

		// We consider "paused" to still be running. We wait for it to
		// be completely stopped or some other state.
		if line == `VMState="paused"` {
			return true, nil
		}
	}

	return false, nil
}

func (d *VBox42Driver) Stop(name string) error {
	if err := d.VBoxManage("controlvm", name, "poweroff"); err != nil {
		return err
	}

	// We sleep here for a little bit to let the session "unlock"
	time.Sleep(2 * time.Second)

	return nil
}

func (d *VBox42Driver) SuppressMessages() error {
	extraData := map[string]string{
		"GUI/RegistrationData": "triesLeft=0",
		"GUI/SuppressMessages": "confirmInputCapture,remindAboutAutoCapture,remindAboutMouseIntegrationOff,remindAboutMouseIntegrationOn,remindAboutWrongColorDepth",
		"GUI/UpdateDate":       fmt.Sprintf("1 d, %d-01-01, stable", time.Now().Year()+1),
		"GUI/UpdateCheckCount": "60",
	}

	for k, v := range extraData {
		if err := d.VBoxManage("setextradata", "global", k, v); err != nil {
			return err
		}
	}

	return nil
}

func (d *VBox42Driver) VBoxManage(args ...string) error {
	var stdout, stderr bytes.Buffer

	log.Printf("Executing VBoxManage: %#v", args)
	cmd := exec.Command(d.VBoxManagePath, args...)
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr
	err := cmd.Run()

	stdoutString := strings.TrimSpace(stdout.String())
	stderrString := strings.TrimSpace(stderr.String())

	if _, ok := err.(*exec.ExitError); ok {
		err = fmt.Errorf("VBoxManage error: %s", stderrString)
	}

	if err == nil {
		// Sometimes VBoxManage gives us an error with a zero exit code,
		// so we also regexp match an error string.
		m, _ := regexp.MatchString("VBoxManage([.a-z]+?): error:", stderrString)
		if m {
			err = fmt.Errorf("VBoxManage error: %s", stderrString)
		}
	}

	log.Printf("stdout: %s", stdoutString)
	log.Printf("stderr: %s", stderrString)

	return err
}

func (d *VBox42Driver) Verify() error {
	return nil
}

func (d *VBox42Driver) Version() (string, error) {
	var stdout bytes.Buffer

	cmd := exec.Command(d.VBoxManagePath, "--version")
	cmd.Stdout = &stdout
	if err := cmd.Run(); err != nil {
		return "", err
	}

	versionOutput := strings.TrimSpace(stdout.String())
	log.Printf("VBoxManage --version output: %s", versionOutput)

	// If the "--version" output contains vboxdrv, then this is indicative
	// of problems with the VirtualBox setup and we shouldn't really continue,
	// whether or not we can read the version.
	if strings.Contains(versionOutput, "vboxdrv") {
		return "", fmt.Errorf("VirtualBox is not properly setup: %s", versionOutput)
	}

	versionRe := regexp.MustCompile("^([.0-9]+)(?:_(?:RC|OSEr)[0-9]+)?")
	matches := versionRe.FindAllStringSubmatch(versionOutput, 1)
	if matches == nil || len(matches[0]) != 2 {
		return "", fmt.Errorf("No version found: %s", versionOutput)
	}

	log.Printf("VirtualBox version: %s", matches[0][1])
	return matches[0][1], nil
}
<commit_msg>Reverse default port count virtualbox argument<commit_after>package common

import (
	"bytes"
	"fmt"
	"log"
	"os/exec"
	"regexp"
	"strconv"
	"strings"
	"time"

	packer "github.com/hashicorp/packer/common"
)

type VBox42Driver struct {
	// This is the path to the "VBoxManage" application.
	VBoxManagePath string
}

func (d *VBox42Driver) CreateSATAController(vmName string, name string, portcount int) error {
	version, err := d.Version()
	if err != nil {
		return err
	}

	portCountArg = "--portcount"
	if strings.HasPrefix(version, "1.") || strings.HasPrefix(version, "2.") || strings.HasPrefix(version, "3.") || strings.HasPrefix(version, "4.0") || strings.HasPrefix(version, "4.1") || strings.HasPrefix(version, "4.2") {
		portCountArg := "--sataportcount"
	}

	command := []string{
		"storagectl", vmName,
		"--name", name,
		"--add", "sata",
		portCountArg, strconv.Itoa(portcount),
	}

	return d.VBoxManage(command...)
}

func (d *VBox42Driver) CreateSCSIController(vmName string, name string) error {

	command := []string{
		"storagectl", vmName,
		"--name", name,
		"--add", "scsi",
		"--controller", "LSILogic",
	}

	return d.VBoxManage(command...)
}

func (d *VBox42Driver) Delete(name string) error {
	return packer.Retry(1, 1, 5, func(i uint) (bool, error) {
		if err := d.VBoxManage("unregistervm", name, "--delete"); err != nil {
			if i+1 == 5 {
				return false, err
			}
			return false, nil
		}
		return true, nil
	})
}

func (d *VBox42Driver) Iso() (string, error) {
	var stdout bytes.Buffer

	cmd := exec.Command(d.VBoxManagePath, "list", "systemproperties")
	cmd.Stdout = &stdout
	if err := cmd.Run(); err != nil {
		return "", err
	}

	DefaultGuestAdditionsRe := regexp.MustCompile("Default Guest Additions ISO:(.+)")

	for _, line := range strings.Split(stdout.String(), "\n") {
		// Need to trim off CR character when running in windows
		// Trimming whitespaces at this point helps to filter out empty value
		line = strings.TrimRight(line, " \r")

		matches := DefaultGuestAdditionsRe.FindStringSubmatch(line)
		if matches == nil {
			continue
		}

		isoname := strings.Trim(matches[1], " \r\n")
		log.Printf("Found Default Guest Additions ISO: %s", isoname)

		return isoname, nil
	}

	return "", fmt.Errorf("Cannot find \"Default Guest Additions ISO\" in vboxmanage output (or it is empty)")
}

func (d *VBox42Driver) Import(name string, path string, flags []string) error {
	args := []string{
		"import", path,
		"--vsys", "0",
		"--vmname", name,
	}
	args = append(args, flags...)

	return d.VBoxManage(args...)
}

func (d *VBox42Driver) IsRunning(name string) (bool, error) {
	var stdout bytes.Buffer

	cmd := exec.Command(d.VBoxManagePath, "showvminfo", name, "--machinereadable")
	cmd.Stdout = &stdout
	if err := cmd.Run(); err != nil {
		return false, err
	}

	for _, line := range strings.Split(stdout.String(), "\n") {
		// Need to trim off CR character when running in windows
		line = strings.TrimRight(line, "\r")

		if line == `VMState="running"` {
			return true, nil
		}

		// We consider "stopping" to still be running. We wait for it to
		// be completely stopped or some other state.
		if line == `VMState="stopping"` {
			return true, nil
		}

		// We consider "paused" to still be running. We wait for it to
		// be completely stopped or some other state.
		if line == `VMState="paused"` {
			return true, nil
		}
	}

	return false, nil
}

func (d *VBox42Driver) Stop(name string) error {
	if err := d.VBoxManage("controlvm", name, "poweroff"); err != nil {
		return err
	}

	// We sleep here for a little bit to let the session "unlock"
	time.Sleep(2 * time.Second)

	return nil
}

func (d *VBox42Driver) SuppressMessages() error {
	extraData := map[string]string{
		"GUI/RegistrationData": "triesLeft=0",
		"GUI/SuppressMessages": "confirmInputCapture,remindAboutAutoCapture,remindAboutMouseIntegrationOff,remindAboutMouseIntegrationOn,remindAboutWrongColorDepth",
		"GUI/UpdateDate":       fmt.Sprintf("1 d, %d-01-01, stable", time.Now().Year()+1),
		"GUI/UpdateCheckCount": "60",
	}

	for k, v := range extraData {
		if err := d.VBoxManage("setextradata", "global", k, v); err != nil {
			return err
		}
	}

	return nil
}

func (d *VBox42Driver) VBoxManage(args ...string) error {
	var stdout, stderr bytes.Buffer

	log.Printf("Executing VBoxManage: %#v", args)
	cmd := exec.Command(d.VBoxManagePath, args...)
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr
	err := cmd.Run()

	stdoutString := strings.TrimSpace(stdout.String())
	stderrString := strings.TrimSpace(stderr.String())

	if _, ok := err.(*exec.ExitError); ok {
		err = fmt.Errorf("VBoxManage error: %s", stderrString)
	}

	if err == nil {
		// Sometimes VBoxManage gives us an error with a zero exit code,
		// so we also regexp match an error string.
		m, _ := regexp.MatchString("VBoxManage([.a-z]+?): error:", stderrString)
		if m {
			err = fmt.Errorf("VBoxManage error: %s", stderrString)
		}
	}

	log.Printf("stdout: %s", stdoutString)
	log.Printf("stderr: %s", stderrString)

	return err
}

func (d *VBox42Driver) Verify() error {
	return nil
}

func (d *VBox42Driver) Version() (string, error) {
	var stdout bytes.Buffer

	cmd := exec.Command(d.VBoxManagePath, "--version")
	cmd.Stdout = &stdout
	if err := cmd.Run(); err != nil {
		return "", err
	}

	versionOutput := strings.TrimSpace(stdout.String())
	log.Printf("VBoxManage --version output: %s", versionOutput)

	// If the "--version" output contains vboxdrv, then this is indicative
	// of problems with the VirtualBox setup and we shouldn't really continue,
	// whether or not we can read the version.
	if strings.Contains(versionOutput, "vboxdrv") {
		return "", fmt.Errorf("VirtualBox is not properly setup: %s", versionOutput)
	}

	versionRe := regexp.MustCompile("^([.0-9]+)(?:_(?:RC|OSEr)[0-9]+)?")
	matches := versionRe.FindAllStringSubmatch(versionOutput, 1)
	if matches == nil || len(matches[0]) != 2 {
		return "", fmt.Errorf("No version found: %s", versionOutput)
	}

	log.Printf("VirtualBox version: %s", matches[0][1])
	return matches[0][1], nil
}
<|endoftext|>


<commit_before>package gopher

import "testing"

func TestNewApp(t *testing.T) {
	app := Config()
	if app == nil {
		t.Error("Expected to get a pointer to the container, but got nil instead")
	}
}
<commit_msg>Fixed test<commit_after>package gopher

import "testing"

func TestNewApp(t *testing.T) {
	Config()
	if Render == nil {
		t.Error("Expected to get a pointer to Render, but got nil instead")
	}
}
<|endoftext|>


<commit_before>/*
Package gopherjslib provides Porcelain for gopherjs compilation without resorting to the shell.

All of them take the optional *Options argument. It can be
used to set a different GOROOT or GOPATH directory or	to enable minification.

Example compiling go code:

  import "github.com/go-on/gopherjslib"

  ...

  code := strings.NewReader(`
    package main
    import "github.com/gopherjs/gopherjs/js"
    func main() { println(js.Global.Get("window")) }
  `)

  var out bytes.Buffer

  err := gopherjslib.Build(code, &out, nil) // <- default options

Example compiling multiple files:

  var out bytes.Buffer

  builder := gopherjslib.NewBuilder(&out, nil)

  fileA := strings.NewReader(`
    package main
    import "github.com/gopherjs/gopherjs/js"
    func a() { println(js.Global.Get("window")) }
  `)

  builder.Add("a.go", fileA)

  // and so on for each file,then

  err = builder.Build()
*/
package gopherjslib

import (
	"bytes"
	"go/ast"
	"go/parser"
	"go/token"
	"io"
	"os"
	"path/filepath"

	"github.com/gopherjs/gopherjs/build"
	"github.com/gopherjs/gopherjs/compiler"
)

// Options is the subset of build.Options, that is exposed to the user of jslib
// and is totally optional.
type Options struct {
	GOROOT string // defaults to build.Default.GOROOT
	GOPATH string // defaults to build.Default.GOPATH
	Minify bool   // should the js be minified
}

// toBuildOptions converts to the real build options in build
func (o *Options) toBuildOptions() *build.Options {
	b := &build.Options{}
	if o != nil {
		b.GOROOT = o.GOROOT
		b.GOPATH = o.GOPATH
		b.Minify = o.Minify
	}
	return b
}

// BuildPackage builds JavaScript based on the go package in dir, writing the result to target.
// Note that dir is not relative to any GOPATH, but relative to the working directory.
// The first error during the built is returned.
// dir must be an existing directory containing at least one go file
//
//   target must not be nil
//   options may be nil (defaults)
func BuildPackage(dir string, target io.Writer, options *Options) error {
	b, err := NewPackageBuilder(dir, target, options)
	if err != nil {
		return err
	}
	return b.Build()
}

// Build builds JavaScript based on the go code in reader, writing the result to target.
// The first error during the built is returned. All errors are typed.
//
//   reader must not be nil
//   target must not be nil
//   options may be nil (defaults)
func Build(reader io.Reader, target io.Writer, options *Options) error {
	pb := NewBuilder(target, options)
	pb.Add("main.go", reader)
	return pb.Build()
}

// Builder builds from added files
type Builder interface {
	// Add adds the content of reader for the given filename
	Add(filename string, reader io.Reader) Builder

	// Build builds and returns the first error during the built or <nil>
	Build() error
}

// builder is an implementation of the Builder interface
type builder struct {
	files   map[string]io.Reader
	options *build.Options
	target  io.Writer
	pkgName string
}

// NewBuilder creates a new Builder that will write to target.
//
//   target must not be nil
//   options may be nil (defaults)
func NewBuilder(target io.Writer, options *Options) Builder {
	return &builder{
		files:   map[string]io.Reader{},
		options: options.toBuildOptions(),
		target:  target,
		pkgName: "main", // default, changed by BuildPackage
	}
}

// NewPackageBuilder creates a new Builder based on the go package in dir.
func NewPackageBuilder(dir string, target io.Writer, options *Options) (Builder, error) {
	abs, err := filepath.Abs(dir)
	if err != nil {
		return nil, err
	}

	b := NewBuilder(target, options).(*builder)
	b.pkgName = abs

	files, err := filepath.Glob(filepath.Join(dir, "*.go"))
	if err != nil {
		return nil, err
	}

	var f *os.File

	for _, file := range files {
		f, err = os.Open(filepath.Join(dir, filepath.Base(file)))
		if err != nil {
			return nil, err
		}

		// make a copy in order to be able to close the file
		var buf bytes.Buffer
		_, err = io.Copy(&buf, f)
		if err != nil {
			f.Close()
			return nil, err
		}

		b.Add(filepath.Base(file), &buf)
		f.Close()
	}
	return b, nil
}

// Add adds a file with the given filename and the content of reader to the builder
func (b *builder) Add(filename string, reader io.Reader) Builder {
	b.files[filename] = reader
	return b
}

// Build creates a build and returns the first error happening. All errors are typed.
func (b *builder) Build() error {
	if b.target == nil {
		return ErrorMissingTarget{}
	}
	fileSet := token.NewFileSet()

	files := []*ast.File{}

	for name, reader := range b.files {
		if reader == nil {
			return ErrorParsing{name, "reader must not be nil"}
		}
		f, err := parser.ParseFile(fileSet, name, reader, 0)
		if err != nil {
			return ErrorParsing{name, err.Error()}
		}
		files = append(files, f)
	}

	s := build.NewSession(b.options)

	archive, err := compiler.Compile(b.pkgName, files, fileSet, s.ImportContext, b.options.Minify)
	if err != nil {
		return ErrorCompiling(err.Error())
	}

	deps, err := compiler.ImportDependencies(archive, s.ImportContext.Import)
	if err != nil {
		return ErrorImportingDependencies(err.Error())
	}

	return compiler.WriteProgramCode(deps, &compiler.SourceMapFilter{Writer: b.target})
}
<commit_msg>Fix build.<commit_after>/*
Package gopherjslib provides Porcelain for gopherjs compilation without resorting to the shell.

All of them take the optional *Options argument. It can be
used to set a different GOROOT or GOPATH directory or	to enable minification.

Example compiling go code:

  import "github.com/go-on/gopherjslib"

  ...

  code := strings.NewReader(`
    package main
    import "github.com/gopherjs/gopherjs/js"
    func main() { println(js.Global.Get("window")) }
  `)

  var out bytes.Buffer

  err := gopherjslib.Build(code, &out, nil) // <- default options

Example compiling multiple files:

  var out bytes.Buffer

  builder := gopherjslib.NewBuilder(&out, nil)

  fileA := strings.NewReader(`
    package main
    import "github.com/gopherjs/gopherjs/js"
    func a() { println(js.Global.Get("window")) }
  `)

  builder.Add("a.go", fileA)

  // and so on for each file,then

  err = builder.Build()
*/
package gopherjslib

import (
	"bytes"
	"go/ast"
	"go/parser"
	"go/token"
	"io"
	"os"
	"path/filepath"

	"github.com/gopherjs/gopherjs/build"
	"github.com/gopherjs/gopherjs/compiler"
)

// Options is the subset of build.Options, that is exposed to the user of jslib
// and is totally optional.
type Options struct {
	GOROOT string // defaults to build.Default.GOROOT
	GOPATH string // defaults to build.Default.GOPATH
	Minify bool   // should the js be minified
}

// toBuildOptions converts to the real build options in build
func (o *Options) toBuildOptions() *build.Options {
	b := &build.Options{}
	if o != nil {
		b.GOROOT = o.GOROOT
		b.GOPATH = o.GOPATH
		b.Minify = o.Minify
	}
	return b
}

// BuildPackage builds JavaScript based on the go package in dir, writing the result to target.
// Note that dir is not relative to any GOPATH, but relative to the working directory.
// The first error during the built is returned.
// dir must be an existing directory containing at least one go file
//
//   target must not be nil
//   options may be nil (defaults)
func BuildPackage(dir string, target io.Writer, options *Options) error {
	b, err := NewPackageBuilder(dir, target, options)
	if err != nil {
		return err
	}
	return b.Build()
}

// Build builds JavaScript based on the go code in reader, writing the result to target.
// The first error during the built is returned. All errors are typed.
//
//   reader must not be nil
//   target must not be nil
//   options may be nil (defaults)
func Build(reader io.Reader, target io.Writer, options *Options) error {
	pb := NewBuilder(target, options)
	pb.Add("main.go", reader)
	return pb.Build()
}

// Builder builds from added files
type Builder interface {
	// Add adds the content of reader for the given filename
	Add(filename string, reader io.Reader) Builder

	// Build builds and returns the first error during the built or <nil>
	Build() error
}

// builder is an implementation of the Builder interface
type builder struct {
	files   map[string]io.Reader
	options *build.Options
	target  io.Writer
	pkgName string
}

// NewBuilder creates a new Builder that will write to target.
//
//   target must not be nil
//   options may be nil (defaults)
func NewBuilder(target io.Writer, options *Options) Builder {
	return &builder{
		files:   map[string]io.Reader{},
		options: options.toBuildOptions(),
		target:  target,
		pkgName: "main", // default, changed by BuildPackage
	}
}

// NewPackageBuilder creates a new Builder based on the go package in dir.
func NewPackageBuilder(dir string, target io.Writer, options *Options) (Builder, error) {
	abs, err := filepath.Abs(dir)
	if err != nil {
		return nil, err
	}

	b := NewBuilder(target, options).(*builder)
	b.pkgName = abs

	files, err := filepath.Glob(filepath.Join(dir, "*.go"))
	if err != nil {
		return nil, err
	}

	var f *os.File

	for _, file := range files {
		f, err = os.Open(filepath.Join(dir, filepath.Base(file)))
		if err != nil {
			return nil, err
		}

		// make a copy in order to be able to close the file
		var buf bytes.Buffer
		_, err = io.Copy(&buf, f)
		if err != nil {
			f.Close()
			return nil, err
		}

		b.Add(filepath.Base(file), &buf)
		f.Close()
	}
	return b, nil
}

// Add adds a file with the given filename and the content of reader to the builder
func (b *builder) Add(filename string, reader io.Reader) Builder {
	b.files[filename] = reader
	return b
}

// Build creates a build and returns the first error happening. All errors are typed.
func (b *builder) Build() error {
	if b.target == nil {
		return ErrorMissingTarget{}
	}
	fileSet := token.NewFileSet()

	files := []*ast.File{}

	for name, reader := range b.files {
		if reader == nil {
			return ErrorParsing{name, "reader must not be nil"}
		}
		f, err := parser.ParseFile(fileSet, name, reader, 0)
		if err != nil {
			return ErrorParsing{name, err.Error()}
		}
		files = append(files, f)
	}

	s := build.NewSession(b.options)

	importContext := &compiler.ImportContext{
		Packages: s.Types,
		Import:   s.BuildImportPath,
	}
	archive, err := compiler.Compile(b.pkgName, files, fileSet, importContext, b.options.Minify)
	if err != nil {
		return ErrorCompiling(err.Error())
	}

	deps, err := compiler.ImportDependencies(archive, s.BuildImportPath)
	if err != nil {
		return ErrorImportingDependencies(err.Error())
	}

	return compiler.WriteProgramCode(deps, &compiler.SourceMapFilter{Writer: b.target})
}
<|endoftext|>


<commit_before>package gorobokassa

import (
	"crypto/md5"
	"errors"
	"fmt"
	"io"
	"log"
	"net/http"
	"net/url"
	"strconv"
	"strings"
)

const (
	queryOutSumm     = "OutSum"
	queryInvID       = "InvId"
	queryCRC         = "SignatureValue"
	queryDescription = "Desc"
	queryLogin       = "MrchLogin"
	robokassaHost    = "auth.robokassa.ru"
	// robokassaHost = "test.robokassa.ru"
	robokassaPath = "Merchant/Index.aspx"
	robokassaPath = "Index.aspx"
	scheme        = "https"
	// scheme        = "http"
	delim = ":"
)

var (
	ErrBadRequest = errors.New("bad request")
)

// Client для генерации URL и проверки уведомлений
type Client struct {
	login          string
	firstPassword  string
	secondPassword string
}

// URL переадресации пользователя на оплату
func (client *Client) URL(invoice, value int, description string) string {
	return buildRedirectURL(client.login, client.firstPassword, invoice, value, description)
}

// CheckResult получение уведомления об исполнении операции (ResultURL)
func (client *Client) CheckResult(r *http.Request) bool {
	return verifyRequest(client.secondPassword, r)
}

func (client *Client) ResultInvoice(r *http.Request) (int, int, error) {
	return getInvoice(client.secondPassword, r)
}

// CheckSuccess проверка параметров в скрипте завершения операции (SuccessURL)
func (client *Client) CheckSuccess(r *http.Request) bool {
	return verifyRequest(client.firstPassword, r)
}

// New Client
func New(login, password1, password2 string) *Client {
	return &Client{login, password1, password2}
}

// CRC of joint values with delimeter
func CRC(v ...interface{}) string {
	s := make([]string, len(v))
	for key, value := range v {
		s[key] = fmt.Sprintf("%v", value)
	}
	h := md5.New()
	io.WriteString(h, strings.Join(s, delim))
	return fmt.Sprintf("%x", h.Sum(nil))
}

func buildRedirectURL(login, password string, invoice, value int, description string) string {
	q := url.URL{}
	q.Host = robokassaHost
	q.Scheme = scheme
	q.Path = robokassaPath

	params := url.Values{}
	params.Add(queryLogin, login)
	params.Add(queryOutSumm, strconv.Itoa(value))
	params.Add(queryInvID, strconv.Itoa(invoice))
	params.Add(queryDescription, description)
	params.Add(queryCRC, CRC(login, value, invoice, password))

	q.RawQuery = params.Encode()
	return q.String()
}

func verifyResult(password string, invoice, value int, crc string) bool {
	log.Println(crc, CRC(value, invoice, password), value, invoice, password)
	return strings.ToUpper(crc) == strings.ToUpper(CRC(value, invoice, password))
}

func getInvoice(password string, r *http.Request) (int, int, error) {
	q := r.URL.Query()
	value, err := strconv.Atoi(q.Get(queryOutSumm))
	if err != nil {
		log.Println(err)
		return 0, 0, ErrBadRequest
	}
	invoice, err := strconv.Atoi(q.Get(queryInvID))
	if err != nil {
		log.Println(err)
		return 0, 0, ErrBadRequest
	}
	crc := q.Get(queryCRC)
	if !verifyResult(password, invoice, value, crc) {
		log.Println("result not verified")
		return 0, 0, ErrBadRequest
	}
	return invoice, value, nil
}

func verifyRequest(password string, r *http.Request) bool {
	_, _, err := getInvoice(password, r)
	return err == nil
}
<commit_msg>robofix<commit_after>package gorobokassa

import (
	"crypto/md5"
	"errors"
	"fmt"
	"io"
	"log"
	"net/http"
	"net/url"
	"strconv"
	"strings"
)

const (
	queryOutSumm     = "OutSum"
	queryInvID       = "InvId"
	queryCRC         = "SignatureValue"
	queryDescription = "Desc"
	queryLogin       = "MrchLogin"
	robokassaHost    = "auth.robokassa.ru"
	// robokassaHost = "test.robokassa.ru"
	robokassaPath = "Merchant/Index.aspx"
	// robokassaPath = "Index.aspx"
	scheme = "https"
	// scheme        = "http"
	delim = ":"
)

var (
	ErrBadRequest = errors.New("bad request")
)

// Client для генерации URL и проверки уведомлений
type Client struct {
	login          string
	firstPassword  string
	secondPassword string
}

// URL переадресации пользователя на оплату
func (client *Client) URL(invoice, value int, description string) string {
	return buildRedirectURL(client.login, client.firstPassword, invoice, value, description)
}

// CheckResult получение уведомления об исполнении операции (ResultURL)
func (client *Client) CheckResult(r *http.Request) bool {
	return verifyRequest(client.secondPassword, r)
}

func (client *Client) ResultInvoice(r *http.Request) (int, int, error) {
	return getInvoice(client.secondPassword, r)
}

// CheckSuccess проверка параметров в скрипте завершения операции (SuccessURL)
func (client *Client) CheckSuccess(r *http.Request) bool {
	return verifyRequest(client.firstPassword, r)
}

// New Client
func New(login, password1, password2 string) *Client {
	return &Client{login, password1, password2}
}

// CRC of joint values with delimeter
func CRC(v ...interface{}) string {
	s := make([]string, len(v))
	for key, value := range v {
		s[key] = fmt.Sprintf("%v", value)
	}
	h := md5.New()
	io.WriteString(h, strings.Join(s, delim))
	return fmt.Sprintf("%x", h.Sum(nil))
}

func buildRedirectURL(login, password string, invoice, value int, description string) string {
	q := url.URL{}
	q.Host = robokassaHost
	q.Scheme = scheme
	q.Path = robokassaPath

	params := url.Values{}
	params.Add(queryLogin, login)
	params.Add(queryOutSumm, strconv.Itoa(value))
	params.Add(queryInvID, strconv.Itoa(invoice))
	params.Add(queryDescription, description)
	params.Add(queryCRC, CRC(login, value, invoice, password))

	q.RawQuery = params.Encode()
	return q.String()
}

func verifyResult(password string, invoice, value int, crc string) bool {
	log.Println(crc, CRC(value, invoice, password), value, invoice, password)
	return strings.ToUpper(crc) == strings.ToUpper(CRC(value, invoice, password))
}

func getInvoice(password string, r *http.Request) (int, int, error) {
	q := r.URL.Query()
	value, err := strconv.Atoi(q.Get(queryOutSumm))
	if err != nil {
		log.Println(err)
		return 0, 0, ErrBadRequest
	}
	invoice, err := strconv.Atoi(q.Get(queryInvID))
	if err != nil {
		log.Println(err)
		return 0, 0, ErrBadRequest
	}
	crc := q.Get(queryCRC)
	if !verifyResult(password, invoice, value, crc) {
		log.Println("result not verified")
		return 0, 0, ErrBadRequest
	}
	return invoice, value, nil
}

func verifyRequest(password string, r *http.Request) bool {
	_, _, err := getInvoice(password, r)
	return err == nil
}
<|endoftext|>