<commit_before>// Copyright 2016 The Cockroach Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License.
//
// Author: Matt Jibson (mjibson@cockroachlabs.com)

package cli

import (
	"bytes"
	"database/sql/driver"
	"fmt"
	"io"
	"os"
	"strings"
	"time"

	"github.com/cockroachdb/cockroach/sql/parser"
	"github.com/cockroachdb/cockroach/sql/sqlbase"
	"github.com/gogo/protobuf/proto"
	"github.com/pkg/errors"
	"github.com/spf13/cobra"
)

// dumpCmd dumps SQL tables.
var dumpCmd = &cobra.Command{
	Use:   "dump [options] <database> <table>",
	Short: "dump sql tables\n",
	Long: `
Dump SQL tables of a cockroach database.
`,
	RunE:         runDump,
	SilenceUsage: true,
}

func runDump(cmd *cobra.Command, args []string) error {
	if len(args) != 2 {
		mustUsage(cmd)
		return errMissingParams
	}

	conn, err := makeSQLClient()
	if err != nil {
		return err
	}
	defer conn.Close()

	return dumpTable(os.Stdout, conn, args[0], args[1])
}

func dumpTable(w io.Writer, conn *sqlConn, origDBName, origTableName string) error {
	const limit = 100

	// Escape names since they can't be used in placeholders.
	dbname := parser.Name(origDBName).String()
	tablename := parser.Name(origTableName).String()

	if err := conn.Exec(fmt.Sprintf("SET DATABASE = %s", dbname), nil); err != nil {
		return err
	}

	// Fetch all table metadata in a transaction and its time to guarantee it
	// doesn't change between the various SHOW statements.
	if err := conn.Exec("BEGIN", nil); err != nil {
		return err
	}

	vals, err := conn.QueryRow("SELECT cluster_logical_timestamp()::int", nil)
	if err != nil {
		return err
	}
	clusterTSStart := vals[0].(int64)
	clusterTS := time.Unix(0, clusterTSStart).Format(time.RFC3339Nano)

	// Fetch table descriptor.
	vals, err = conn.QueryRow(`
		SELECT descriptor
		FROM system.descriptor
		JOIN system.namespace tables
			ON tables.id = descriptor.id
		JOIN system.namespace dbs
			ON dbs.id = tables.parentid
		WHERE tables.name = $1 AND dbs.name = $2`,
		[]driver.Value{origTableName, origDBName})
	if err == io.EOF {
		return errors.Errorf("unknown database or table %s.%s", origTableName, origDBName)
	} else if err != nil {
		return err
	}
	b := vals[0].([]byte)
	var desc sqlbase.Descriptor
	if err := proto.Unmarshal(b, &desc); err != nil {
		return err
	}
	table := desc.GetTable()
	if table == nil {
		return errors.New("internal error: expected table descriptor")
	}

	coltypes := make(map[string]string)
	for _, c := range table.Columns {
		coltypes[c.Name] = c.Type.SQLString()
	}

	primaryIndex := table.PrimaryIndex.Name
	index := table.PrimaryIndex.ColumnNames
	indexes := strings.Join(index, ", ")

	// Build the SELECT query.
	var sbuf bytes.Buffer
	fmt.Fprintf(&sbuf, "SELECT %s, * FROM %s@%s AS OF SYSTEM TIME '%s'", indexes, tablename, primaryIndex, clusterTS)

	var wbuf bytes.Buffer
	fmt.Fprintf(&wbuf, " WHERE ROW (%s) > ROW (", indexes)
	for i := range index {
		if i > 0 {
			wbuf.WriteString(", ")
		}
		fmt.Fprintf(&wbuf, "$%d", i+1)
	}
	wbuf.WriteString(")")
	// No WHERE clause first time, so add a place to inject it.
	fmt.Fprintf(&sbuf, "%%s ORDER BY %s LIMIT %d", indexes, limit)
	bs := sbuf.String()

	vals, err = conn.QueryRow(fmt.Sprintf("SHOW CREATE TABLE %s", tablename), nil)
	if err != nil {
		return err
	}
	create := vals[1].(string)
	if _, err := w.Write([]byte(create)); err != nil {
		return err
	}
	if _, err := w.Write([]byte(";\n")); err != nil {
		return err
	}

	if err := conn.Exec("COMMIT", nil); err != nil {
		return err
	}

	// pk holds the last values of the fetched primary keys
	var pk []driver.Value
	q := fmt.Sprintf(bs, "")
	for {
		rows, err := conn.Query(q, pk)
		if err != nil {
			return err
		}
		cols := rows.Columns()
		pkcols := cols[:len(index)]
		cols = cols[len(index):]
		inserts := make([][]string, 0, limit)
		i := 0
		for i < limit {
			vals := make([]driver.Value, len(cols)+len(pkcols))
			if err := rows.Next(vals); err == io.EOF {
				break
			} else if err != nil {
				return err
			}
			if pk == nil {
				q = fmt.Sprintf(bs, wbuf.String())
			}
			pk = vals[:len(index)]
			vals = vals[len(index):]
			ivals := make([]string, len(vals))
			// Values need to be correctly encoded for INSERT statements in a text file.
			for si, sv := range vals {
				switch t := sv.(type) {
				case nil:
					ivals[si] = "NULL"
				case bool:
					ivals[si] = parser.MakeDBool(parser.DBool(t)).String()
				case int64:
					ivals[si] = parser.NewDInt(parser.DInt(t)).String()
				case float64:
					ivals[si] = parser.NewDFloat(parser.DFloat(t)).String()
				case string:
					ivals[si] = parser.NewDString(t).String()
				case []byte:
					switch ct := coltypes[cols[si]]; ct {
					case "INTERVAL":
						ivals[si] = fmt.Sprintf("'%s'", t)
					case "BYTES":
						ivals[si] = parser.NewDBytes(parser.DBytes(t)).String()
					default:
						// STRING and DECIMAL types can have optional length
						// suffixes, so only examine the prefix of the type.
						if strings.HasPrefix(coltypes[cols[si]], "STRING") {
							ivals[si] = parser.NewDString(string(t)).String()
						} else if strings.HasPrefix(coltypes[cols[si]], "DECIMAL") {
							ivals[si] = string(t)
						} else {
							panic(errors.Errorf("unknown []byte type: %s, %v: %s", t, cols[si], coltypes[cols[si]]))
						}
					}
				case time.Time:
					var d parser.Datum
					ct := coltypes[cols[si]]
					switch ct {
					case "DATE":
						d = parser.NewDDateFromTime(t, time.UTC)
					case "TIMESTAMP":
						d = parser.MakeDTimestamp(t, time.Nanosecond)
					case "TIMESTAMP WITH TIME ZONE":
						d = parser.MakeDTimestampTZ(t, time.Nanosecond)
					default:
						panic(errors.Errorf("unknown timestamp type: %s, %v: %s", t, cols[si], coltypes[cols[si]]))
					}
					ivals[si] = fmt.Sprintf("'%s'", d)
				default:
					panic(errors.Errorf("unknown field type: %T (%s)", t, cols[si]))
				}
			}
			inserts = append(inserts, ivals)
			i++
		}
		for si, sv := range pk {
			b, ok := sv.([]byte)
			if ok && strings.HasPrefix(coltypes[pkcols[si]], "STRING") {
				// Primary key strings need to be converted to a go string, but not SQL
				// encoded since they aren't being written to a text file.
				pk[si] = string(b)
			}
		}
		if err := rows.Close(); err != nil {
			return err
		}
		if i == 0 {
			break
		}
		fmt.Fprintf(w, "\nINSERT INTO %s VALUES", tablename)
		for idx, values := range inserts {
			if idx > 0 {
				fmt.Fprint(w, ",")
			}
			fmt.Fprint(w, "\n\t(")
			for vi, v := range values {
				if vi > 0 {
					fmt.Fprint(w, ", ")
				}
				fmt.Fprint(w, v)
			}
			fmt.Fprint(w, ")")
		}
		fmt.Fprintln(w, ";")
		if i < limit {
			break
		}
	}
	return nil
}
<commit_msg>cli: allow dump to be used by any user with SELECT<commit_after>// Copyright 2016 The Cockroach Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License.
//
// Author: Matt Jibson (mjibson@cockroachlabs.com)

package cli

import (
	"bytes"
	"database/sql/driver"
	"fmt"
	"io"
	"os"
	"strings"
	"time"

	"github.com/cockroachdb/cockroach/sql/parser"
	"github.com/pkg/errors"
	"github.com/spf13/cobra"
)

// dumpCmd dumps SQL tables.
var dumpCmd = &cobra.Command{
	Use:   "dump [options] <database> <table>",
	Short: "dump sql tables\n",
	Long: `
Dump SQL tables of a cockroach database.
`,
	RunE:         runDump,
	SilenceUsage: true,
}

func runDump(cmd *cobra.Command, args []string) error {
	if len(args) != 2 {
		mustUsage(cmd)
		return errMissingParams
	}

	conn, err := makeSQLClient()
	if err != nil {
		return err
	}
	defer conn.Close()

	return dumpTable(os.Stdout, conn, args[0], args[1])
}

func dumpTable(w io.Writer, conn *sqlConn, origDBName, origTableName string) error {
	const limit = 100

	// Escape names since they can't be used in placeholders.
	dbname := parser.Name(origDBName).String()
	tablename := parser.Name(origTableName).String()

	if err := conn.Exec(fmt.Sprintf("SET DATABASE = %s", dbname), nil); err != nil {
		return err
	}

	// Fetch all table metadata in a transaction and its time to guarantee it
	// doesn't change between the various SHOW statements.
	if err := conn.Exec("BEGIN", nil); err != nil {
		return err
	}

	vals, err := conn.QueryRow("SELECT cluster_logical_timestamp()::int", nil)
	if err != nil {
		return err
	}
	clusterTSStart := vals[0].(int64)
	clusterTS := time.Unix(0, clusterTSStart).Format(time.RFC3339Nano)

	// A previous version of the code did a SELECT on system.descriptor. This
	// required the SELECT privilege to the descriptor table, which only root
	// has. Allowing non-root to do this would let users see other users' table
	// descriptors which is a problem in multi-tenancy.

	// Fetch column types.
	rows, err := conn.Query(fmt.Sprintf("SHOW COLUMNS FROM %s", tablename), nil)
	if err != nil {
		return err
	}
	vals = make([]driver.Value, 2)
	coltypes := make(map[string]string)
	for {
		if err := rows.Next(vals); err == io.EOF {
			break
		} else if err != nil {
			return err
		}
		name, ok := vals[0].(string)
		if !ok {
			return fmt.Errorf("unexpected value: %T", vals[1])

		}
		typ, ok := vals[1].(string)
		if !ok {
			return fmt.Errorf("unexpected value: %T", vals[4])

		}
		coltypes[name] = typ
	}
	if err := rows.Close(); err != nil {
		return err
	}

	// index holds the names, in order, of the primary key columns.
	var index []string
	// Primary index is always the first index returned by SHOW INDEX.
	rows, err = conn.Query(fmt.Sprintf("SHOW INDEX FROM %s", tablename), nil)
	if err != nil {
		return err
	}
	vals = make([]driver.Value, 5)
	var primaryIndex string
	// Find the primary index columns.
	for {
		if err := rows.Next(vals); err == io.EOF {
			break
		} else if err != nil {
			return err
		}
		b, ok := vals[1].(string)
		if !ok {
			return fmt.Errorf("unexpected value: %T", vals[1])
		}
		if primaryIndex == "" {
			primaryIndex = b
		} else if primaryIndex != b {
			break
		}
		b, ok = vals[4].(string)
		if !ok {
			return fmt.Errorf("unexpected value: %T", vals[4])
		}
		index = append(index, parser.Name(b).String())
	}
	if err := rows.Close(); err != nil {
		return err
	}
	if len(index) == 0 {
		return fmt.Errorf("no primary key index found")
	}
	indexes := strings.Join(index, ", ")

	// Build the SELECT query.
	var sbuf bytes.Buffer
	fmt.Fprintf(&sbuf, "SELECT %s, * FROM %s@%s AS OF SYSTEM TIME '%s'", indexes, tablename, primaryIndex, clusterTS)

	var wbuf bytes.Buffer
	fmt.Fprintf(&wbuf, " WHERE ROW (%s) > ROW (", indexes)
	for i := range index {
		if i > 0 {
			wbuf.WriteString(", ")
		}
		fmt.Fprintf(&wbuf, "$%d", i+1)
	}
	wbuf.WriteString(")")
	// No WHERE clause first time, so add a place to inject it.
	fmt.Fprintf(&sbuf, "%%s ORDER BY %s LIMIT %d", indexes, limit)
	bs := sbuf.String()

	vals, err = conn.QueryRow(fmt.Sprintf("SHOW CREATE TABLE %s", tablename), nil)
	if err != nil {
		return err
	}
	create := vals[1].(string)
	if _, err := w.Write([]byte(create)); err != nil {
		return err
	}
	if _, err := w.Write([]byte(";\n")); err != nil {
		return err
	}

	if err := conn.Exec("COMMIT", nil); err != nil {
		return err
	}

	// pk holds the last values of the fetched primary keys
	var pk []driver.Value
	q := fmt.Sprintf(bs, "")
	for {
		rows, err := conn.Query(q, pk)
		if err != nil {
			return err
		}
		cols := rows.Columns()
		pkcols := cols[:len(index)]
		cols = cols[len(index):]
		inserts := make([][]string, 0, limit)
		i := 0
		for i < limit {
			vals := make([]driver.Value, len(cols)+len(pkcols))
			if err := rows.Next(vals); err == io.EOF {
				break
			} else if err != nil {
				return err
			}
			if pk == nil {
				q = fmt.Sprintf(bs, wbuf.String())
			}
			pk = vals[:len(index)]
			vals = vals[len(index):]
			ivals := make([]string, len(vals))
			// Values need to be correctly encoded for INSERT statements in a text file.
			for si, sv := range vals {
				switch t := sv.(type) {
				case nil:
					ivals[si] = "NULL"
				case bool:
					ivals[si] = parser.MakeDBool(parser.DBool(t)).String()
				case int64:
					ivals[si] = parser.NewDInt(parser.DInt(t)).String()
				case float64:
					ivals[si] = parser.NewDFloat(parser.DFloat(t)).String()
				case string:
					ivals[si] = parser.NewDString(t).String()
				case []byte:
					switch ct := coltypes[cols[si]]; ct {
					case "INTERVAL":
						ivals[si] = fmt.Sprintf("'%s'", t)
					case "BYTES":
						ivals[si] = parser.NewDBytes(parser.DBytes(t)).String()
					default:
						// STRING and DECIMAL types can have optional length
						// suffixes, so only examine the prefix of the type.
						if strings.HasPrefix(coltypes[cols[si]], "STRING") {
							ivals[si] = parser.NewDString(string(t)).String()
						} else if strings.HasPrefix(coltypes[cols[si]], "DECIMAL") {
							ivals[si] = string(t)
						} else {
							panic(errors.Errorf("unknown []byte type: %s, %v: %s", t, cols[si], coltypes[cols[si]]))
						}
					}
				case time.Time:
					var d parser.Datum
					ct := coltypes[cols[si]]
					switch ct {
					case "DATE":
						d = parser.NewDDateFromTime(t, time.UTC)
					case "TIMESTAMP":
						d = parser.MakeDTimestamp(t, time.Nanosecond)
					case "TIMESTAMP WITH TIME ZONE":
						d = parser.MakeDTimestampTZ(t, time.Nanosecond)
					default:
						panic(errors.Errorf("unknown timestamp type: %s, %v: %s", t, cols[si], coltypes[cols[si]]))
					}
					ivals[si] = fmt.Sprintf("'%s'", d)
				default:
					panic(errors.Errorf("unknown field type: %T (%s)", t, cols[si]))
				}
			}
			inserts = append(inserts, ivals)
			i++
		}
		for si, sv := range pk {
			b, ok := sv.([]byte)
			if ok && strings.HasPrefix(coltypes[pkcols[si]], "STRING") {
				// Primary key strings need to be converted to a go string, but not SQL
				// encoded since they aren't being written to a text file.
				pk[si] = string(b)
			}
		}
		if err := rows.Close(); err != nil {
			return err
		}
		if i == 0 {
			break
		}
		fmt.Fprintf(w, "\nINSERT INTO %s VALUES", tablename)
		for idx, values := range inserts {
			if idx > 0 {
				fmt.Fprint(w, ",")
			}
			fmt.Fprint(w, "\n\t(")
			for vi, v := range values {
				if vi > 0 {
					fmt.Fprint(w, ", ")
				}
				fmt.Fprint(w, v)
			}
			fmt.Fprint(w, ")")
		}
		fmt.Fprintln(w, ";")
		if i < limit {
			break
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package routeservice

import (
	"errors"
	"fmt"
	"net/http"
	"net/url"
	"time"

	"github.com/uber-go/zap"

	"code.cloudfoundry.org/gorouter/common/secure"
	"code.cloudfoundry.org/gorouter/logger"
	"code.cloudfoundry.org/gorouter/routeservice/header"
)

const (
	RouteServiceSignature    = "X-CF-Proxy-Signature"
	RouteServiceForwardedURL = "X-CF-Forwarded-Url"
	RouteServiceMetadata     = "X-CF-Proxy-Metadata"
)

var RouteServiceExpired = errors.New("Route service request expired")
var RouteServiceForwardedURLMismatch = errors.New("Route service forwarded url mismatch")

type RouteServiceConfig struct {
	routeServiceEnabled bool
	routeServiceTimeout time.Duration
	crypto              secure.Crypto
	cryptoPrev          secure.Crypto
	logger              logger.Logger
	recommendHttps      bool
}

type RouteServiceRequest struct {
	URLString      string
	ParsedUrl      *url.URL
	Signature      string
	Metadata       string
	ForwardedURL   string
	RecommendHttps bool
}

func NewRouteServiceConfig(
	logger logger.Logger,
	enabled bool,
	timeout time.Duration,
	crypto secure.Crypto,
	cryptoPrev secure.Crypto,
	recommendHttps bool,
) *RouteServiceConfig {
	return &RouteServiceConfig{
		routeServiceEnabled: enabled,
		routeServiceTimeout: timeout,
		crypto:              crypto,
		cryptoPrev:          cryptoPrev,
		logger:              logger,
		recommendHttps:      recommendHttps,
	}
}

func (rs *RouteServiceConfig) RouteServiceEnabled() bool {
	return rs.routeServiceEnabled
}

func (rs *RouteServiceConfig) RouteServiceRecommendHttps() bool {
	return rs.recommendHttps
}

func (rs *RouteServiceConfig) Request(rsUrl, forwardedUrl string) (RouteServiceRequest, error) {
	var routeServiceArgs RouteServiceRequest
	sig, metadata, err := rs.generateSignatureAndMetadata(forwardedUrl)
	if err != nil {
		return routeServiceArgs, err
	}

	routeServiceArgs.URLString = rsUrl
	routeServiceArgs.Signature = sig
	routeServiceArgs.Metadata = metadata
	routeServiceArgs.ForwardedURL = forwardedUrl

	rsURL, err := url.Parse(rsUrl)
	if err != nil {
		return routeServiceArgs, err
	}
	routeServiceArgs.ParsedUrl = rsURL

	return routeServiceArgs, nil
}

func (rs *RouteServiceConfig) SetupRouteServiceRequest(request *http.Request, args RouteServiceRequest) {
}

func (rs *RouteServiceConfig) ValidateSignature(headers *http.Header, requestUrl string) error {
	metadataHeader := headers.Get(RouteServiceMetadata)
	signatureHeader := headers.Get(RouteServiceSignature)

	signature, err := header.SignatureFromHeaders(signatureHeader, metadataHeader, rs.crypto)
	if err != nil {
		rs.logger.Error("proxy-route-service-current-key", zap.Error(err))
		if rs.cryptoPrev == nil {
			return err
		}

		// Decrypt the head again trying to use the old key.
		signature, err = header.SignatureFromHeaders(signatureHeader, metadataHeader, rs.cryptoPrev)

		if err != nil {
			rs.logger.Error("proxy-route-service-previous-key", zap.Error(err))
			return err
		}
	}

	err = rs.validateSignatureTimeout(signature)
	if err != nil {
		return err
	}

	return rs.validateForwardedURL(signature, requestUrl)
}

func (rs *RouteServiceConfig) generateSignatureAndMetadata(forwardedUrlRaw string) (string, string, error) {
	decodedURL, err := url.QueryUnescape(forwardedUrlRaw)
	if err != nil {
		rs.logger.Error("proxy-route-service-invalidForwardedURL", zap.Error(err))
		return "", "", err
	}
	signature := &header.Signature{
		RequestedTime: time.Now(),
		ForwardedUrl:  decodedURL,
	}

	signatureHeader, metadataHeader, err := header.BuildSignatureAndMetadata(rs.crypto, signature)
	if err != nil {
		return "", "", err
	}
	return signatureHeader, metadataHeader, nil
}

func (rs *RouteServiceConfig) validateSignatureTimeout(signature header.Signature) error {
	if time.Since(signature.RequestedTime) > rs.routeServiceTimeout {
		rs.logger.Error("proxy-route-service-timeout",
			zap.Error(RouteServiceExpired),
			zap.String("forwarded-url", signature.ForwardedUrl),
			zap.Time("request-time", signature.RequestedTime),
		)
		return RouteServiceExpired
	}
	return nil
}

func (rs *RouteServiceConfig) validateForwardedURL(signature header.Signature, requestUrl string) error {
	var err error
	forwardedUrl := signature.ForwardedUrl
	requestUrl, err = url.QueryUnescape(requestUrl)
	if err != nil {
		rsErr := fmt.Errorf("%s: %s", RouteServiceForwardedURLMismatch, err)
		rs.logger.Error("proxy-route-service-forwarded-url-mismatch", zap.Error(rsErr))
		return err
	}

	if requestUrl != forwardedUrl {
		var err = RouteServiceForwardedURLMismatch
		rs.logger.Error("proxy-route-service-forwarded-url-mismatch", zap.Error(err),
			zap.String("request-url", requestUrl),
			zap.String("forwarded-url", forwardedUrl),
		)
		return err
	}
	return nil
}
<commit_msg>Remove unused method<commit_after>package routeservice

import (
	"errors"
	"fmt"
	"net/http"
	"net/url"
	"time"

	"github.com/uber-go/zap"

	"code.cloudfoundry.org/gorouter/common/secure"
	"code.cloudfoundry.org/gorouter/logger"
	"code.cloudfoundry.org/gorouter/routeservice/header"
)

const (
	RouteServiceSignature    = "X-CF-Proxy-Signature"
	RouteServiceForwardedURL = "X-CF-Forwarded-Url"
	RouteServiceMetadata     = "X-CF-Proxy-Metadata"
)

var RouteServiceExpired = errors.New("Route service request expired")
var RouteServiceForwardedURLMismatch = errors.New("Route service forwarded url mismatch")

type RouteServiceConfig struct {
	routeServiceEnabled bool
	routeServiceTimeout time.Duration
	crypto              secure.Crypto
	cryptoPrev          secure.Crypto
	logger              logger.Logger
	recommendHttps      bool
}

type RouteServiceRequest struct {
	URLString      string
	ParsedUrl      *url.URL
	Signature      string
	Metadata       string
	ForwardedURL   string
	RecommendHttps bool
}

func NewRouteServiceConfig(
	logger logger.Logger,
	enabled bool,
	timeout time.Duration,
	crypto secure.Crypto,
	cryptoPrev secure.Crypto,
	recommendHttps bool,
) *RouteServiceConfig {
	return &RouteServiceConfig{
		routeServiceEnabled: enabled,
		routeServiceTimeout: timeout,
		crypto:              crypto,
		cryptoPrev:          cryptoPrev,
		logger:              logger,
		recommendHttps:      recommendHttps,
	}
}

func (rs *RouteServiceConfig) RouteServiceEnabled() bool {
	return rs.routeServiceEnabled
}

func (rs *RouteServiceConfig) RouteServiceRecommendHttps() bool {
	return rs.recommendHttps
}

func (rs *RouteServiceConfig) Request(rsUrl, forwardedUrl string) (RouteServiceRequest, error) {
	var routeServiceArgs RouteServiceRequest
	sig, metadata, err := rs.generateSignatureAndMetadata(forwardedUrl)
	if err != nil {
		return routeServiceArgs, err
	}

	routeServiceArgs.URLString = rsUrl
	routeServiceArgs.Signature = sig
	routeServiceArgs.Metadata = metadata
	routeServiceArgs.ForwardedURL = forwardedUrl

	rsURL, err := url.Parse(rsUrl)
	if err != nil {
		return routeServiceArgs, err
	}
	routeServiceArgs.ParsedUrl = rsURL

	return routeServiceArgs, nil
}

func (rs *RouteServiceConfig) ValidateSignature(headers *http.Header, requestUrl string) error {
	metadataHeader := headers.Get(RouteServiceMetadata)
	signatureHeader := headers.Get(RouteServiceSignature)

	signature, err := header.SignatureFromHeaders(signatureHeader, metadataHeader, rs.crypto)
	if err != nil {
		rs.logger.Error("proxy-route-service-current-key", zap.Error(err))
		if rs.cryptoPrev == nil {
			return err
		}

		// Decrypt the head again trying to use the old key.
		signature, err = header.SignatureFromHeaders(signatureHeader, metadataHeader, rs.cryptoPrev)

		if err != nil {
			rs.logger.Error("proxy-route-service-previous-key", zap.Error(err))
			return err
		}
	}

	err = rs.validateSignatureTimeout(signature)
	if err != nil {
		return err
	}

	return rs.validateForwardedURL(signature, requestUrl)
}

func (rs *RouteServiceConfig) generateSignatureAndMetadata(forwardedUrlRaw string) (string, string, error) {
	decodedURL, err := url.QueryUnescape(forwardedUrlRaw)
	if err != nil {
		rs.logger.Error("proxy-route-service-invalidForwardedURL", zap.Error(err))
		return "", "", err
	}
	signature := &header.Signature{
		RequestedTime: time.Now(),
		ForwardedUrl:  decodedURL,
	}

	signatureHeader, metadataHeader, err := header.BuildSignatureAndMetadata(rs.crypto, signature)
	if err != nil {
		return "", "", err
	}
	return signatureHeader, metadataHeader, nil
}

func (rs *RouteServiceConfig) validateSignatureTimeout(signature header.Signature) error {
	if time.Since(signature.RequestedTime) > rs.routeServiceTimeout {
		rs.logger.Error("proxy-route-service-timeout",
			zap.Error(RouteServiceExpired),
			zap.String("forwarded-url", signature.ForwardedUrl),
			zap.Time("request-time", signature.RequestedTime),
		)
		return RouteServiceExpired
	}
	return nil
}

func (rs *RouteServiceConfig) validateForwardedURL(signature header.Signature, requestUrl string) error {
	var err error
	forwardedUrl := signature.ForwardedUrl
	requestUrl, err = url.QueryUnescape(requestUrl)
	if err != nil {
		rsErr := fmt.Errorf("%s: %s", RouteServiceForwardedURLMismatch, err)
		rs.logger.Error("proxy-route-service-forwarded-url-mismatch", zap.Error(rsErr))
		return err
	}

	if requestUrl != forwardedUrl {
		var err = RouteServiceForwardedURLMismatch
		rs.logger.Error("proxy-route-service-forwarded-url-mismatch", zap.Error(err),
			zap.String("request-url", requestUrl),
			zap.String("forwarded-url", forwardedUrl),
		)
		return err
	}
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"net"
	"os"

	"github.com/urfave/cli"

	"github.com/danmarg/smtp-sts"
)

func main() {
	app := cli.NewApp()
	app.Name = "sts tester"

	app.Commands = []cli.Command{
		{
			Name: "getdns",
			Action: func(c *cli.Context) error {
				if c.Args().First() == "" {
					return fmt.Errorf("must specify domain")
				}
				v, e := sts.PolicyVersionForDomain(c.Args().First())
				if e != nil {
					return e
				}
				fmt.Printf("Version: %v\n", v)
				return nil
			},
		},
		{
			Name: "getpolicy",
			Action: func(c *cli.Context) error {
				if c.Args().First() == "" {
					return fmt.Errorf("must specify domain")
				}
				p, e := sts.PolicyForDomain(c.Args().First())
				if e != nil {
					return e
				}
				fmt.Printf("Policy: %v\n", p)
				return nil
			},
		},
		{
			Name: "getmxs",
			Action: func(c *cli.Context) error {
				if c.Args().First() == "" {
					return fmt.Errorf("must specify domain")
				}
				p, e := sts.PolicyForDomain(c.Args().First())
				if e != nil {
					return e
				}
				fmt.Printf("Policy: %v\n", p)
				mxs, e := net.LookupMX(c.Args().First())
				if e != nil {
					return e
				}
				mxs, e = sts.FilterMXs(mxs, p)
				fmt.Printf("Matching MXes: \n")
				for _, m := range mxs {
					fmt.Printf("\t%s\t%d\n", m.Host, m.Pref)
				}
				if e != nil {
					fmt.Printf("Errors: %v\n", e)
				}
				return nil
			},
		},
		{
			Name: "testsmtp",
			Action: func(c *cli.Context) error {
				if c.Args().First() == "" {
					return fmt.Errorf("must specify domain")
				}
				p, e := sts.PolicyForDomain(c.Args().First())
				if e != nil {
					return e
				}
				fmt.Printf("Policy: %v\n", p)
				mxs, e := net.LookupMX(c.Args().First())
				if e != nil {
					return e
				}
				mxs, e = sts.FilterMXs(mxs, p)
				fmt.Printf("Matching MXes: \n")
				for _, m := range mxs {
					fmt.Printf("\t%s\t%d\n", m.Host, m.Pref)
				}
				if e != nil {
					fmt.Printf("Errors: %v\n", e)
				}
				for _, mx := range mxs {
					fmt.Printf("Testing MX %v...", mx.Host)
					if e := sts.CheckMXViaSMTP(mx); e != nil {
						fmt.Printf("ERROR: %v\n", e)
					} else {
						fmt.Printf("OK!\n")
					}
				}
				return nil
			},
		},
	}

	app.Run(os.Args)
}
<commit_msg>Add usage<commit_after>package main

import (
	"fmt"
	"net"
	"os"

	"github.com/urfave/cli"

	"github.com/danmarg/smtp-sts"
)

func main() {
	app := cli.NewApp()
	app.Name = "sts tester"

	app.Commands = []cli.Command{
		{
			Name:  "getdns",
			Usage: "fetch the domain's policy *version* and print it",
			Action: func(c *cli.Context) error {
				if c.Args().First() == "" {
					return fmt.Errorf("must specify domain")
				}
				v, e := sts.PolicyVersionForDomain(c.Args().First())
				if e != nil {
					return e
				}
				fmt.Printf("Version: %v\n", v)
				return nil
			},
		},
		{
			Name:  "getpolicy",
			Usage: "fetch the domain's policy and print it",
			Action: func(c *cli.Context) error {
				if c.Args().First() == "" {
					return fmt.Errorf("must specify domain")
				}
				p, e := sts.PolicyForDomain(c.Args().First())
				if e != nil {
					return e
				}
				fmt.Printf("Policy: %v\n", p)
				return nil
			},
		},
		{
			Name:  "getmxs",
			Usage: "fetch the domain's policy and MXs, and filter the MXs against the policy, reporting any which are invalid",
			Action: func(c *cli.Context) error {
				if c.Args().First() == "" {
					return fmt.Errorf("must specify domain")
				}
				p, e := sts.PolicyForDomain(c.Args().First())
				if e != nil {
					return e
				}
				fmt.Printf("Policy: %v\n", p)
				mxs, e := net.LookupMX(c.Args().First())
				if e != nil {
					return e
				}
				mxs, e = sts.FilterMXs(mxs, p)
				fmt.Printf("Matching MXes: \n")
				for _, m := range mxs {
					fmt.Printf("\t%s\t%d\n", m.Host, m.Pref)
				}
				if e != nil {
					fmt.Printf("Errors: %v\n", e)
				}
				return nil
			},
		},
		{
			Name:  "testsmtp",
			Usage: "fetch the domain's policy and MXs, filter the MXs, and test STARTTLS",
			Action: func(c *cli.Context) error {
				if c.Args().First() == "" {
					return fmt.Errorf("must specify domain")
				}
				p, e := sts.PolicyForDomain(c.Args().First())
				if e != nil {
					return e
				}
				fmt.Printf("Policy: %v\n", p)
				mxs, e := net.LookupMX(c.Args().First())
				if e != nil {
					return e
				}
				mxs, e = sts.FilterMXs(mxs, p)
				fmt.Printf("Matching MXes: \n")
				for _, m := range mxs {
					fmt.Printf("\t%s\t%d\n", m.Host, m.Pref)
				}
				if e != nil {
					fmt.Printf("Errors: %v\n", e)
				}
				for _, mx := range mxs {
					fmt.Printf("Testing MX %v...", mx.Host)
					if e := sts.CheckMXViaSMTP(mx); e != nil {
						fmt.Printf("ERROR: %v\n", e)
					} else {
						fmt.Printf("OK!\n")
					}
				}
				return nil
			},
		},
	}

	app.Run(os.Args)
}
<|endoftext|>


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

package ssh

import (
	"fmt"
	"io"
)

// authenticate authenticates with the remote server. See RFC 4252.
func (c *ClientConn) authenticate(session []byte) error {
	// initiate user auth session
	if err := c.writePacket(marshal(msgServiceRequest, serviceRequestMsg{serviceUserAuth})); err != nil {
		return err
	}
	packet, err := c.readPacket()
	if err != nil {
		return err
	}
	var serviceAccept serviceAcceptMsg
	if err := unmarshal(&serviceAccept, packet, msgServiceAccept); err != nil {
		return err
	}
	// during the authentication phase the client first attempts the "none" method
	// then any untried methods suggested by the server.
	tried, remain := make(map[string]bool), make(map[string]bool)
	for auth := ClientAuth(new(noneAuth)); auth != nil; {
		ok, methods, err := auth.auth(session, c.config.User, c.transport, c.config.rand())
		if err != nil {
			return err
		}
		if ok {
			// success
			return nil
		}
		tried[auth.method()] = true
		delete(remain, auth.method())
		for _, meth := range methods {
			if tried[meth] {
				// if we've tried meth already, skip it.
				continue
			}
			remain[meth] = true
		}
		auth = nil
		for _, a := range c.config.Auth {
			if remain[a.method()] {
				auth = a
				break
			}
		}
	}
	return fmt.Errorf("ssh: unable to authenticate, attempted methods %v, no supported methods remain", keys(tried))
}

func keys(m map[string]bool) (s []string) {
	for k, _ := range m {
		s = append(s, k)
	}
	return
}

// A ClientAuth represents an instance of an RFC 4252 authentication method.
type ClientAuth interface {
	// auth authenticates user over transport t.
	// Returns true if authentication is successful.
	// If authentication is not successful, a []string of alternative
	// method names is returned.
	auth(session []byte, user string, t *transport, rand io.Reader) (bool, []string, error)

	// method returns the RFC 4252 method name.
	method() string
}

// "none" authentication, RFC 4252 section 5.2.
type noneAuth int

func (n *noneAuth) auth(session []byte, user string, t *transport, rand io.Reader) (bool, []string, error) {
	if err := t.writePacket(marshal(msgUserAuthRequest, userAuthRequestMsg{
		User:    user,
		Service: serviceSSH,
		Method:  "none",
	})); err != nil {
		return false, nil, err
	}

	return handleAuthResponse(t)
}

func (n *noneAuth) method() string {
	return "none"
}

// "password" authentication, RFC 4252 Section 8.
type passwordAuth struct {
	ClientPassword
}

func (p *passwordAuth) auth(session []byte, user string, t *transport, rand io.Reader) (bool, []string, error) {
	type passwordAuthMsg struct {
		User     string
		Service  string
		Method   string
		Reply    bool
		Password string
	}

	pw, err := p.Password(user)
	if err != nil {
		return false, nil, err
	}

	if err := t.writePacket(marshal(msgUserAuthRequest, passwordAuthMsg{
		User:     user,
		Service:  serviceSSH,
		Method:   "password",
		Reply:    false,
		Password: pw,
	})); err != nil {
		return false, nil, err
	}

	return handleAuthResponse(t)
}

func (p *passwordAuth) method() string {
	return "password"
}

// A ClientPassword implements access to a client's passwords.
type ClientPassword interface {
	// Password returns the password to use for user.
	Password(user string) (password string, err error)
}

// ClientAuthPassword returns a ClientAuth using password authentication.
func ClientAuthPassword(impl ClientPassword) ClientAuth {
	return &passwordAuth{impl}
}

// ClientKeyring implements access to a client key ring.
type ClientKeyring interface {
	// Key returns the i'th *rsa.Publickey or *dsa.Publickey, or nil if
	// no key exists at i.
	Key(i int) (key interface{}, err error)

	// Sign returns a signature of the given data using the i'th key
	// and the supplied random source.
	Sign(i int, rand io.Reader, data []byte) (sig []byte, err error)
}

// "publickey" authentication, RFC 4252 Section 7.
type publickeyAuth struct {
	ClientKeyring
}

type publickeyAuthMsg struct {
	User    string
	Service string
	Method  string
	// HasSig indicates to the reciver packet that the auth request is signed and
	// should be used for authentication of the request.
	HasSig   bool
	Algoname string
	Pubkey   string
	// Sig is defined as []byte so marshal will exclude it during validateKey
	Sig []byte `ssh:"rest"`
}

func (p *publickeyAuth) auth(session []byte, user string, t *transport, rand io.Reader) (bool, []string, error) {
	// Authentication is performed in two stages. The first stage sends an
	// enquiry to test if each key is acceptable to the remote. The second
	// stage attempts to authenticate with the valid keys obtained in the
	// first stage.

	var index int
	// a map of public keys to their index in the keyring
	validKeys := make(map[int]interface{})
	for {
		key, err := p.Key(index)
		if err != nil {
			return false, nil, err
		}
		if key == nil {
			// no more keys in the keyring
			break
		}

		if ok, err := p.validateKey(key, user, t); ok {
			validKeys[index] = key
		} else {
			if err != nil {
				return false, nil, err
			}
		}
		index++
	}

	// methods that may continue if this auth is not successful.
	var methods []string
	for i, key := range validKeys {
		pubkey := serializePublickey(key)
		algoname := algoName(key)
		sign, err := p.Sign(i, rand, buildDataSignedForAuth(session, userAuthRequestMsg{
			User:    user,
			Service: serviceSSH,
			Method:  p.method(),
		}, []byte(algoname), pubkey))
		if err != nil {
			return false, nil, err
		}
		// manually wrap the serialized signature in a string
		s := serializeSignature(algoname, sign)
		sig := make([]byte, stringLength(len(s)))
		marshalString(sig, s)
		msg := publickeyAuthMsg{
			User:     user,
			Service:  serviceSSH,
			Method:   p.method(),
			HasSig:   true,
			Algoname: algoname,
			Pubkey:   string(pubkey),
			Sig:      sig,
		}
		p := marshal(msgUserAuthRequest, msg)
		if err := t.writePacket(p); err != nil {
			return false, nil, err
		}
		success, methods, err := handleAuthResponse(t)
		if err != nil {
			return false, nil, err
		}
		if success {
			return success, methods, err
		}
	}
	return false, methods, nil
}

// validateKey validates the key provided it is acceptable to the server.
func (p *publickeyAuth) validateKey(key interface{}, user string, t *transport) (bool, error) {
	pubkey := serializePublickey(key)
	algoname := algoName(key)
	msg := publickeyAuthMsg{
		User:     user,
		Service:  serviceSSH,
		Method:   p.method(),
		HasSig:   false,
		Algoname: algoname,
		Pubkey:   string(pubkey),
	}
	if err := t.writePacket(marshal(msgUserAuthRequest, msg)); err != nil {
		return false, err
	}

	return p.confirmKeyAck(key, t)
}

func (p *publickeyAuth) confirmKeyAck(key interface{}, t *transport) (bool, error) {
	pubkey := serializePublickey(key)
	algoname := algoName(key)

	for {
		packet, err := t.readPacket()
		if err != nil {
			return false, err
		}
		switch packet[0] {
		case msgUserAuthBanner:
			// TODO(gpaul): add callback to present the banner to the user
		case msgUserAuthPubKeyOk:
			msg := decode(packet).(*userAuthPubKeyOkMsg)
			if msg.Algo != algoname || msg.PubKey != string(pubkey) {
				return false, nil
			}
			return true, nil
		case msgUserAuthFailure:
			return false, nil
		default:
			return false, UnexpectedMessageError{msgUserAuthSuccess, packet[0]}
		}
	}
	panic("unreachable")
}

func (p *publickeyAuth) method() string {
	return "publickey"
}

// ClientAuthKeyring returns a ClientAuth using public key authentication.
func ClientAuthKeyring(impl ClientKeyring) ClientAuth {
	return &publickeyAuth{impl}
}

// handleAuthResponse returns whether the preceding authentication request succeeded
// along with a list of remaining authentication methods to try next and
// an error if an unexpected response was received.
func handleAuthResponse(t *transport) (bool, []string, error) {
	for {
		packet, err := t.readPacket()
		if err != nil {
			return false, nil, err
		}

		switch packet[0] {
		case msgUserAuthBanner:
			// TODO: add callback to present the banner to the user
		case msgUserAuthFailure:
			msg := decode(packet).(*userAuthFailureMsg)
			return false, msg.Methods, nil
		case msgUserAuthSuccess:
			return true, nil, nil
		case msgDisconnect:
			return false, nil, io.EOF
		default:
			return false, nil, UnexpectedMessageError{msgUserAuthSuccess, packet[0]}
		}
	}
	panic("unreachable")
}
<commit_msg>go.crypto/ssh: add ClientAuthAgent<commit_after>// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package ssh

import (
	"errors"
	"fmt"
	"io"
)

// authenticate authenticates with the remote server. See RFC 4252.
func (c *ClientConn) authenticate(session []byte) error {
	// initiate user auth session
	if err := c.writePacket(marshal(msgServiceRequest, serviceRequestMsg{serviceUserAuth})); err != nil {
		return err
	}
	packet, err := c.readPacket()
	if err != nil {
		return err
	}
	var serviceAccept serviceAcceptMsg
	if err := unmarshal(&serviceAccept, packet, msgServiceAccept); err != nil {
		return err
	}
	// during the authentication phase the client first attempts the "none" method
	// then any untried methods suggested by the server.
	tried, remain := make(map[string]bool), make(map[string]bool)
	for auth := ClientAuth(new(noneAuth)); auth != nil; {
		ok, methods, err := auth.auth(session, c.config.User, c.transport, c.config.rand())
		if err != nil {
			return err
		}
		if ok {
			// success
			return nil
		}
		tried[auth.method()] = true
		delete(remain, auth.method())
		for _, meth := range methods {
			if tried[meth] {
				// if we've tried meth already, skip it.
				continue
			}
			remain[meth] = true
		}
		auth = nil
		for _, a := range c.config.Auth {
			if remain[a.method()] {
				auth = a
				break
			}
		}
	}
	return fmt.Errorf("ssh: unable to authenticate, attempted methods %v, no supported methods remain", keys(tried))
}

func keys(m map[string]bool) (s []string) {
	for k, _ := range m {
		s = append(s, k)
	}
	return
}

// A ClientAuth represents an instance of an RFC 4252 authentication method.
type ClientAuth interface {
	// auth authenticates user over transport t.
	// Returns true if authentication is successful.
	// If authentication is not successful, a []string of alternative
	// method names is returned.
	auth(session []byte, user string, t *transport, rand io.Reader) (bool, []string, error)

	// method returns the RFC 4252 method name.
	method() string
}

// "none" authentication, RFC 4252 section 5.2.
type noneAuth int

func (n *noneAuth) auth(session []byte, user string, t *transport, rand io.Reader) (bool, []string, error) {
	if err := t.writePacket(marshal(msgUserAuthRequest, userAuthRequestMsg{
		User:    user,
		Service: serviceSSH,
		Method:  "none",
	})); err != nil {
		return false, nil, err
	}

	return handleAuthResponse(t)
}

func (n *noneAuth) method() string {
	return "none"
}

// "password" authentication, RFC 4252 Section 8.
type passwordAuth struct {
	ClientPassword
}

func (p *passwordAuth) auth(session []byte, user string, t *transport, rand io.Reader) (bool, []string, error) {
	type passwordAuthMsg struct {
		User     string
		Service  string
		Method   string
		Reply    bool
		Password string
	}

	pw, err := p.Password(user)
	if err != nil {
		return false, nil, err
	}

	if err := t.writePacket(marshal(msgUserAuthRequest, passwordAuthMsg{
		User:     user,
		Service:  serviceSSH,
		Method:   "password",
		Reply:    false,
		Password: pw,
	})); err != nil {
		return false, nil, err
	}

	return handleAuthResponse(t)
}

func (p *passwordAuth) method() string {
	return "password"
}

// A ClientPassword implements access to a client's passwords.
type ClientPassword interface {
	// Password returns the password to use for user.
	Password(user string) (password string, err error)
}

// ClientAuthPassword returns a ClientAuth using password authentication.
func ClientAuthPassword(impl ClientPassword) ClientAuth {
	return &passwordAuth{impl}
}

// ClientKeyring implements access to a client key ring.
type ClientKeyring interface {
	// Key returns the i'th *rsa.Publickey or *dsa.Publickey, or nil if
	// no key exists at i.
	Key(i int) (key interface{}, err error)

	// Sign returns a signature of the given data using the i'th key
	// and the supplied random source.
	Sign(i int, rand io.Reader, data []byte) (sig []byte, err error)
}

// "publickey" authentication, RFC 4252 Section 7.
type publickeyAuth struct {
	ClientKeyring
}

type publickeyAuthMsg struct {
	User    string
	Service string
	Method  string
	// HasSig indicates to the reciver packet that the auth request is signed and
	// should be used for authentication of the request.
	HasSig   bool
	Algoname string
	Pubkey   string
	// Sig is defined as []byte so marshal will exclude it during validateKey
	Sig []byte `ssh:"rest"`
}

func (p *publickeyAuth) auth(session []byte, user string, t *transport, rand io.Reader) (bool, []string, error) {
	// Authentication is performed in two stages. The first stage sends an
	// enquiry to test if each key is acceptable to the remote. The second
	// stage attempts to authenticate with the valid keys obtained in the
	// first stage.

	var index int
	// a map of public keys to their index in the keyring
	validKeys := make(map[int]interface{})
	for {
		key, err := p.Key(index)
		if err != nil {
			return false, nil, err
		}
		if key == nil {
			// no more keys in the keyring
			break
		}

		if ok, err := p.validateKey(key, user, t); ok {
			validKeys[index] = key
		} else {
			if err != nil {
				return false, nil, err
			}
		}
		index++
	}

	// methods that may continue if this auth is not successful.
	var methods []string
	for i, key := range validKeys {
		pubkey := serializePublickey(key)
		algoname := algoName(key)
		sign, err := p.Sign(i, rand, buildDataSignedForAuth(session, userAuthRequestMsg{
			User:    user,
			Service: serviceSSH,
			Method:  p.method(),
		}, []byte(algoname), pubkey))
		if err != nil {
			return false, nil, err
		}
		// manually wrap the serialized signature in a string
		s := serializeSignature(algoname, sign)
		sig := make([]byte, stringLength(len(s)))
		marshalString(sig, s)
		msg := publickeyAuthMsg{
			User:     user,
			Service:  serviceSSH,
			Method:   p.method(),
			HasSig:   true,
			Algoname: algoname,
			Pubkey:   string(pubkey),
			Sig:      sig,
		}
		p := marshal(msgUserAuthRequest, msg)
		if err := t.writePacket(p); err != nil {
			return false, nil, err
		}
		success, methods, err := handleAuthResponse(t)
		if err != nil {
			return false, nil, err
		}
		if success {
			return success, methods, err
		}
	}
	return false, methods, nil
}

// validateKey validates the key provided it is acceptable to the server.
func (p *publickeyAuth) validateKey(key interface{}, user string, t *transport) (bool, error) {
	pubkey := serializePublickey(key)
	algoname := algoName(key)
	msg := publickeyAuthMsg{
		User:     user,
		Service:  serviceSSH,
		Method:   p.method(),
		HasSig:   false,
		Algoname: algoname,
		Pubkey:   string(pubkey),
	}
	if err := t.writePacket(marshal(msgUserAuthRequest, msg)); err != nil {
		return false, err
	}

	return p.confirmKeyAck(key, t)
}

func (p *publickeyAuth) confirmKeyAck(key interface{}, t *transport) (bool, error) {
	pubkey := serializePublickey(key)
	algoname := algoName(key)

	for {
		packet, err := t.readPacket()
		if err != nil {
			return false, err
		}
		switch packet[0] {
		case msgUserAuthBanner:
			// TODO(gpaul): add callback to present the banner to the user
		case msgUserAuthPubKeyOk:
			msg := decode(packet).(*userAuthPubKeyOkMsg)
			if msg.Algo != algoname || msg.PubKey != string(pubkey) {
				return false, nil
			}
			return true, nil
		case msgUserAuthFailure:
			return false, nil
		default:
			return false, UnexpectedMessageError{msgUserAuthSuccess, packet[0]}
		}
	}
	panic("unreachable")
}

func (p *publickeyAuth) method() string {
	return "publickey"
}

// ClientAuthKeyring returns a ClientAuth using public key authentication.
func ClientAuthKeyring(impl ClientKeyring) ClientAuth {
	return &publickeyAuth{impl}
}

// handleAuthResponse returns whether the preceding authentication request succeeded
// along with a list of remaining authentication methods to try next and
// an error if an unexpected response was received.
func handleAuthResponse(t *transport) (bool, []string, error) {
	for {
		packet, err := t.readPacket()
		if err != nil {
			return false, nil, err
		}

		switch packet[0] {
		case msgUserAuthBanner:
			// TODO: add callback to present the banner to the user
		case msgUserAuthFailure:
			msg := decode(packet).(*userAuthFailureMsg)
			return false, msg.Methods, nil
		case msgUserAuthSuccess:
			return true, nil, nil
		case msgDisconnect:
			return false, nil, io.EOF
		default:
			return false, nil, UnexpectedMessageError{msgUserAuthSuccess, packet[0]}
		}
	}
	panic("unreachable")
}

// ClientAuthKeyring returns a ClientAuth using public key authentication via
// an agent.
func ClientAuthAgent(agent *AgentClient) ClientAuth {
	return ClientAuthKeyring(&agentKeyring{agent: agent})
}

// agentKeyring implements ClientKeyring.
type agentKeyring struct {
	agent *AgentClient
	keys  []*AgentKey
}

func (kr *agentKeyring) Key(i int) (key interface{}, err error) {
	if kr.keys == nil {
		if kr.keys, err = kr.agent.RequestIdentities(); err != nil {
			return
		}
	}
	if i >= len(kr.keys) {
		return
	}
	return kr.keys[i].Key()
}

func (kr *agentKeyring) Sign(i int, rand io.Reader, data []byte) (sig []byte, err error) {
	var key interface{}
	if key, err = kr.Key(i); err != nil {
		return
	}
	if key == nil {
		return nil, errors.New("ssh: key index out of range")
	}
	if sig, err = kr.agent.SignRequest(key, data); err != nil {
		return
	}

	// Unmarshal the signature.

	var ok bool
	if _, sig, ok = parseString(sig); !ok {
		return nil, errors.New("ssh: malformed signature response from agent")
	}
	if sig, _, ok = parseString(sig); !ok {
		return nil, errors.New("ssh: malformed signature response from agent")
	}
	return sig, nil
}
<|endoftext|>


<commit_before>// Package fastrand implements a cryptographically secure pseudorandom number
// generator. The generator is seeded using the system's default entropy
// source, and thereafter produces random values via repeated hashing. As a
// result, fastrand can generate randomness much faster than crypto/rand, and
// generation cannot fail.
package fastrand

import (
	"crypto/rand"
	"hash"
	"math"
	"sync"
	"unsafe"

	"github.com/minio/blake2b-simd"
)

// A randReader produces random values via repeated hashing. The entropy field
// is the concatenation of an initial seed and a 128-bit counter. Each time
// the entropy is hashed, the counter is incremented.
type randReader struct {
	entropy  []byte
	h        hash.Hash
	hashSize int
	buf      [32]byte
	mu       sync.Mutex
}

// Read fills b with random data. It always returns len(b), nil.
func (r *randReader) Read(b []byte) (int, error) {
	r.mu.Lock()
	for i := 0; i < len(b); i += r.hashSize {
		// Increment counter.
		*(*uint64)(unsafe.Pointer(&r.entropy[0]))++
		if *(*uint64)(unsafe.Pointer(&r.entropy[0])) == 0 {
			*(*uint64)(unsafe.Pointer(&r.entropy[8]))++
		}
		// Hash the counter + initial seed.
		r.h.Reset()
		r.h.Write(r.entropy)
		r.h.Sum(r.buf[:0])

		// Fill out 'b'.
		copy(b[i:], r.buf[:])
	}
	r.mu.Unlock()
	return len(b), nil
}

// Reader is a global, shared instance of a cryptographically strong pseudo-
// random generator. It uses blake2b as its hashing function. Reader is safe
// for concurrent use by multiple goroutines.
var Reader = func() *randReader {
	// Use 64 bytes in case the first 32 aren't completely random.
	base := make([]byte, 64)
	_, err := rand.Read(base)
	if err != nil {
		panic("fastrand: no entropy available")
	}
	e := blake2b.Sum256(base)
	return &randReader{
		entropy:  append(make([]byte, 16), e[:]...),
		h:        blake2b.New256(),
		hashSize: len(e),
	}
}()

// Read is a helper function that calls Reader.Read on b. It always fills b
// completely.
func Read(b []byte) { Reader.Read(b) }

// Bytes is a helper function that returns n bytes of random data.
func Bytes(n int) []byte {
	b := make([]byte, n)
	Read(b)
	return b
}

// Intn returns a uniform random value in [0,n). It panics if n <= 0.
func Intn(n int) int {
	if n <= 0 {
		panic("fastrand: argument to Intn is <= 0")
	}
	// To eliminate modulo bias, keep selecting at random until we fall within
	// a range that is evenly divisible by n.
	// NOTE: since n is at most math.MaxUint64/2, max is minimized when:
	//    n = math.MaxUint64/4 + 1 -> max = math.MaxUint64 - math.MaxUint64/4
	// This gives an expected 1.333 tries before choosing a value < max.
	max := math.MaxUint64 - math.MaxUint64%uint64(n)
	b := Bytes(8)
	r := *(*uint64)(unsafe.Pointer(&b[0]))
	for r >= max {
		Read(b)
		r = *(*uint64)(unsafe.Pointer(&b[0]))
	}
	return int(r % uint64(n))
}

// Perm returns a random permutation of the integers [0,n).
func Perm(n int) []int {
	m := make([]int, n)
	for i := 1; i < n; i++ {
		j := Intn(i + 1)
		m[i] = m[j]
		m[j] = i
	}
	return m
}
<commit_msg>cosmetic changes<commit_after>// Package fastrand implements a cryptographically secure pseudorandom number
// generator. The generator is seeded using the system's default entropy
// source, and thereafter produces random values via repeated hashing. As a
// result, fastrand can generate randomness much faster than crypto/rand, and
// generation cannot fail.
package fastrand

import (
	"crypto/rand"
	"hash"
	"io"
	"math"
	"sync"
	"unsafe"

	"github.com/minio/blake2b-simd"
)

// A randReader produces random values via repeated hashing. The entropy field
// is the concatenation of an initial seed and a 128-bit counter. Each time
// the entropy is hashed, the counter is incremented.
type randReader struct {
	entropy []byte
	h       hash.Hash
	buf     []byte
	mu      sync.Mutex
}

// Read fills b with random data. It always returns len(b), nil.
func (r *randReader) Read(b []byte) (int, error) {
	r.mu.Lock()
	n := 0
	for n < len(b) {
		// Increment counter.
		*(*uint64)(unsafe.Pointer(&r.entropy[0]))++
		if *(*uint64)(unsafe.Pointer(&r.entropy[0])) == 0 {
			*(*uint64)(unsafe.Pointer(&r.entropy[8]))++
		}
		// Hash the counter + initial seed.
		r.h.Reset()
		r.h.Write(r.entropy)
		r.buf = r.h.Sum(r.buf[:0])

		// Fill out 'b'.
		n += copy(b[n:], r.buf[:])
	}
	r.mu.Unlock()
	return n, nil
}

// Reader is a global, shared instance of a cryptographically strong pseudo-
// random generator. It uses blake2b as its hashing function. Reader is safe
// for concurrent use by multiple goroutines.
var Reader = func() *randReader {
	r := &randReader{h: blake2b.New256()}
	// Use 64 bytes in case the first 32 aren't completely random.
	_, err := io.CopyN(r.h, rand.Reader, 64)
	if err != nil {
		panic("crypto: no entropy available")
	}
	r.entropy = make([]byte, 16+32) // blake2b produces [32]byte hashes
	r.h.Sum(r.entropy[16:])
	return r
}()

// Read is a helper function that calls Reader.Read on b. It always fills b
// completely.
func Read(b []byte) { Reader.Read(b) }

// Bytes is a helper function that returns n bytes of random data.
func Bytes(n int) []byte {
	b := make([]byte, n)
	Read(b)
	return b
}

// Intn returns a uniform random value in [0,n). It panics if n <= 0.
func Intn(n int) int {
	if n <= 0 {
		panic("fastrand: argument to Intn is <= 0")
	}
	// To eliminate modulo bias, keep selecting at random until we fall within
	// a range that is evenly divisible by n.
	// NOTE: since n is at most math.MaxUint64/2, max is minimized when:
	//    n = math.MaxUint64/4 + 1 -> max = math.MaxUint64 - math.MaxUint64/4
	// This gives an expected 1.333 tries before choosing a value < max.
	max := math.MaxUint64 - math.MaxUint64%uint64(n)
	b := Bytes(8)
	r := *(*uint64)(unsafe.Pointer(&b[0]))
	for r >= max {
		Read(b)
		r = *(*uint64)(unsafe.Pointer(&b[0]))
	}
	return int(r % uint64(n))
}

// Perm returns a random permutation of the integers [0,n).
func Perm(n int) []int {
	m := make([]int, n)
	for i := 1; i < n; i++ {
		j := Intn(i + 1)
		m[i] = m[j]
		m[j] = i
	}
	return m
}
<|endoftext|>


<commit_before>package config

import (
	"os/user"
	"path/filepath"
)

func defaultConfig() Config {
	return Config{
		TabString: "\t",
		TabWidth:  4,
		AutoTab:   true,
		TabDetect: true,

		TabString_set: true,
		TabWidth_set:  true,
		AutoTab_set:   true,
		TabDetect_set: true,

		Parent: "",

		ExtMap:      defaultExtMap(),
		FileConfigs: defaultFileConfigs(),
		SyntaxRules: defaultSyntaxRules(),
	}
}

func defaultExtMap() map[string]string {
	em := map[string]string{}
	for _, ext := range []string{"csh", "ksh"} {
		em[ext] = "sh"
	}
	for _, ext := range []string{"h", "cc", "C", "c++", "cpp"} {
		em[ext] = "c"
	}
	return em
}

func defaultSyntaxRules() map[string]Color {
	sr := map[string]Color{
		"[ \t]+$": {BG: "yellow", Clobber: true},
	}
	return sr
}

func defaultFileConfigs() map[string]Config {
	fc := map[string]Config{}
	fc["code"] = Config{
		SyntaxRules: map[string]Color{
			"'.*?'": {FG: "yellow"},
			`".*?"`: {FG: "yellow"},
		},
	}
	fc["sh"] = Config{
		Parent: "code",
		SyntaxRules: map[string]Color{
			"#.*$": {FG: "cyan"},
		},
	}
	fc["c"] = Config{
		Parent: "code",
		SyntaxRules: map[string]Color{
			"//.*$":     {FG: "cyan"},
			`/\*.*?\*/`: {FG: "cyan"},
		},
	}
	fc["go"] = Config{
		Parent: "code",
		SyntaxRules: map[string]Color{
			"//.*$": {FG: "cyan"},
			"'.*?'": {FG: "red"},
			"`.*?`": {FG: "yellow"},
		},
	}
	fc["md"] = Config{
		SyntaxRules: map[string]Color{
			"^#+.*$": {FG: "green"},
			"^===*$": {FG: "green"},
			"^---*$": {FG: "green"},
		},
	}
	fc["toml"] = Config{
		Parent: "sh",
		SyntaxRules: map[string]Color{
			`\[.*?\]`: {FG: "green"},
		},
	}
	fc["git"] = Config{
		SyntaxRules: map[string]Color{
			"#.*?$": {FG: "cyan"},
		},
	}

	return fc
}

func CreateConfig() Config {
	cfg := readConfig()
	return defaultConfig().Merge(cfg)
}

func readConfig() Config {
	user, err := user.Current()
	if err != nil {
		return Config{}
	}
	home := user.HomeDir
	cfg := Read(
		filepath.Join(home, ".sith.toml"),
		filepath.Join(home, ".sith/config.toml"),
		filepath.Join(home, ".config/sith/config.toml"),
	)
	return cfg
}
<commit_msg>separate c syntax into 'c-style' and 'c'<commit_after>package config

import (
	"os/user"
	"path/filepath"
)

func defaultConfig() Config {
	return Config{
		TabString: "\t",
		TabWidth:  4,
		AutoTab:   true,
		TabDetect: true,

		TabString_set: true,
		TabWidth_set:  true,
		AutoTab_set:   true,
		TabDetect_set: true,

		Parent: "",

		ExtMap:      defaultExtMap(),
		FileConfigs: defaultFileConfigs(),
		SyntaxRules: defaultSyntaxRules(),
	}
}

func defaultExtMap() map[string]string {
	em := map[string]string{}
	for _, ext := range []string{"csh", "ksh"} {
		em[ext] = "sh"
	}
	for _, ext := range []string{"h", "cc", "C", "c++", "cpp"} {
		em[ext] = "c"
	}
	return em
}

func defaultSyntaxRules() map[string]Color {
	sr := map[string]Color{
		"[ \t]+$": {BG: "yellow", Clobber: true},
	}
	return sr
}

func defaultFileConfigs() map[string]Config {
	fc := map[string]Config{}
	fc["code"] = Config{
		SyntaxRules: map[string]Color{
			"'.*?'": {FG: "yellow"},
			`".*?"`: {FG: "yellow"},
		},
	}
	fc["sh"] = Config{
		Parent: "code",
		SyntaxRules: map[string]Color{
			"#.*$": {FG: "cyan"},
		},
	}
	fc["c-style"] = Config{
		Parent: "code",
		SyntaxRules: map[string]Color{
			"//.*$":     {FG: "cyan"},
			`/\*.*?\*/`: {FG: "cyan"},
		},
	}
	fc["c"] = Config{
		Parent: "c-style",
		SyntaxRules: map[string]Color{
			"^#[a-z]*": {FG: "blue"},
		},
	}
	fc["go"] = Config{
		Parent: "code",
		SyntaxRules: map[string]Color{
			"//.*$": {FG: "cyan"},
			"'.*?'": {FG: "red"},
			"`.*?`": {FG: "yellow"},
		},
	}
	fc["md"] = Config{
		SyntaxRules: map[string]Color{
			"^#+.*$": {FG: "green"},
			"^===*$": {FG: "green"},
			"^---*$": {FG: "green"},
		},
	}
	fc["toml"] = Config{
		Parent: "sh",
		SyntaxRules: map[string]Color{
			`\[.*?\]`: {FG: "green"},
		},
	}
	fc["git"] = Config{
		SyntaxRules: map[string]Color{
			"#.*?$": {FG: "cyan"},
		},
	}

	return fc
}

func CreateConfig() Config {
	cfg := readConfig()
	return defaultConfig().Merge(cfg)
}

func readConfig() Config {
	user, err := user.Current()
	if err != nil {
		return Config{}
	}
	home := user.HomeDir
	cfg := Read(
		filepath.Join(home, ".sith.toml"),
		filepath.Join(home, ".sith/config.toml"),
		filepath.Join(home, ".config/sith/config.toml"),
	)
	return cfg
}
<|endoftext|>


<commit_before>package aws

import (
	"fmt"
	"testing"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
)

func TestAccAWSVpnGateway_basic(t *testing.T) {
	var v, v2 ec2.VpnGateway

	testNotEqual := func(*terraform.State) error {
		if len(v.VpcAttachments) == 0 {
			return fmt.Errorf("VPN gateway A is not attached")
		}
		if len(v2.VpcAttachments) == 0 {
			return fmt.Errorf("VPN gateway B is not attached")
		}

		id1 := v.VpcAttachments[0].VpcId
		id2 := v2.VpcAttachments[0].VpcId
		if id1 == id2 {
			return fmt.Errorf("Both attachment IDs are the same")
		}

		return nil
	}

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckVpnGatewayDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccVpnGatewayConfig,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckVpnGatewayExists(
						"aws_vpn_gateway.foo", &v),
				),
			},

			resource.TestStep{
				Config: testAccVpnGatewayConfigChangeVPC,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckVpnGatewayExists(
						"aws_vpn_gateway.foo", &v2),
					testNotEqual,
				),
			},
		},
	})
}

func TestAccAWSVpnGateway_delete(t *testing.T) {
	var vpnGateway ec2.VpnGateway

	testDeleted := func(r string) resource.TestCheckFunc {
		return func(s *terraform.State) error {
			_, ok := s.RootModule().Resources[r]
			if ok {
				return fmt.Errorf("VPN Gateway %q should have been deleted", r)
			}
			return nil
		}
	}

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckVpnGatewayDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccVpnGatewayConfig,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckVpnGatewayExists("aws_vpn_gateway.foo", &vpnGateway)),
			},
			resource.TestStep{
				Config: testAccNoVpnGatewayConfig,
				Check:  resource.ComposeTestCheckFunc(testDeleted("aws_vpn_gateway.foo")),
			},
		},
	})
}

func TestAccAWSVpnGateway_tags(t *testing.T) {
	var v ec2.VpnGateway

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckVpnGatewayDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccCheckVpnGatewayConfigTags,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckVpnGatewayExists("aws_vpn_gateway.foo", &v),
					testAccCheckTags(&v.Tags, "foo", "bar"),
				),
			},

			resource.TestStep{
				Config: testAccCheckVpnGatewayConfigTagsUpdate,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckVpnGatewayExists("aws_vpn_gateway.foo", &v),
					testAccCheckTags(&v.Tags, "foo", ""),
					testAccCheckTags(&v.Tags, "bar", "baz"),
				),
			},
		},
	})
}

func testAccCheckVpnGatewayDestroy(s *terraform.State) error {
	ec2conn := testAccProvider.Meta().(*AWSClient).ec2conn

	for _, rs := range s.RootModule().Resources {
		if rs.Type != "aws_vpn_gateway" {
			continue
		}

		// Try to find the resource
		resp, err := ec2conn.DescribeVpnGateways(&ec2.DescribeVpnGatewaysInput{
			VpnGatewayIds: []*string{aws.String(rs.Primary.ID)},
		})
		if err == nil {
			var v *ec2.VpnGateway
			for _, g := range resp.VpnGateways {
				if *g.VpnGatewayId == rs.Primary.ID {
					v = g
				}
			}

			if v == nil {
				// wasn't found
				return nil
			}

			if *v.State != "deleted" {
				return fmt.Errorf("Expected VpnGateway to be in deleted state, but was not: %s", v)
			}
			return nil
		}

		// Verify the error is what we want
		ec2err, ok := err.(awserr.Error)
		if !ok {
			return err
		}
		if ec2err.Code() != "InvalidVpnGatewayID.NotFound" {
			return err
		}
	}

	return nil
}

func testAccCheckVpnGatewayExists(n string, ig *ec2.VpnGateway) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources[n]
		if !ok {
			return fmt.Errorf("Not found: %s", n)
		}

		if rs.Primary.ID == "" {
			return fmt.Errorf("No ID is set")
		}

		ec2conn := testAccProvider.Meta().(*AWSClient).ec2conn
		resp, err := ec2conn.DescribeVpnGateways(&ec2.DescribeVpnGatewaysInput{
			VpnGatewayIds: []*string{aws.String(rs.Primary.ID)},
		})
		if err != nil {
			return err
		}
		if len(resp.VpnGateways) == 0 {
			return fmt.Errorf("VPNGateway not found")
		}

		*ig = *resp.VpnGateways[0]

		return nil
	}
}

const testAccNoVpnGatewayConfig = `
resource "aws_vpc" "foo" {
	cidr_block = "10.1.0.0/16"
}
`

const testAccVpnGatewayConfig = `
resource "aws_vpc" "foo" {
	cidr_block = "10.1.0.0/16"
}

resource "aws_vpn_gateway" "foo" {
	vpc_id = "${aws_vpc.foo.id}"
}
`

const testAccVpnGatewayConfigChangeVPC = `
resource "aws_vpc" "bar" {
	cidr_block = "10.2.0.0/16"
}

resource "aws_vpn_gateway" "foo" {
	vpc_id = "${aws_vpc.bar.id}"
}
`

const testAccCheckVpnGatewayConfigTags = `
resource "aws_vpc" "foo" {
	cidr_block = "10.1.0.0/16"
}

resource "aws_vpn_gateway" "foo" {
	vpc_id = "${aws_vpc.foo.id}"
	tags {
		foo = "bar"
	}
}
`

const testAccCheckVpnGatewayConfigTagsUpdate = `
resource "aws_vpc" "foo" {
	cidr_block = "10.1.0.0/16"
}

resource "aws_vpn_gateway" "foo" {
	vpc_id = "${aws_vpc.foo.id}"
	tags {
		bar = "baz"
	}
}
`
<commit_msg>providers/aws/vpn_gateway id-only refresh<commit_after>package aws

import (
	"fmt"
	"testing"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
)

func TestAccAWSVpnGateway_basic(t *testing.T) {
	var v, v2 ec2.VpnGateway

	testNotEqual := func(*terraform.State) error {
		if len(v.VpcAttachments) == 0 {
			return fmt.Errorf("VPN gateway A is not attached")
		}
		if len(v2.VpcAttachments) == 0 {
			return fmt.Errorf("VPN gateway B is not attached")
		}

		id1 := v.VpcAttachments[0].VpcId
		id2 := v2.VpcAttachments[0].VpcId
		if id1 == id2 {
			return fmt.Errorf("Both attachment IDs are the same")
		}

		return nil
	}

	resource.Test(t, resource.TestCase{
		PreCheck:      func() { testAccPreCheck(t) },
		IDRefreshName: "aws_vpn_gateway.foo",
		Providers:     testAccProviders,
		CheckDestroy:  testAccCheckVpnGatewayDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccVpnGatewayConfig,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckVpnGatewayExists(
						"aws_vpn_gateway.foo", &v),
				),
			},

			resource.TestStep{
				Config: testAccVpnGatewayConfigChangeVPC,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckVpnGatewayExists(
						"aws_vpn_gateway.foo", &v2),
					testNotEqual,
				),
			},
		},
	})
}

func TestAccAWSVpnGateway_delete(t *testing.T) {
	var vpnGateway ec2.VpnGateway

	testDeleted := func(r string) resource.TestCheckFunc {
		return func(s *terraform.State) error {
			_, ok := s.RootModule().Resources[r]
			if ok {
				return fmt.Errorf("VPN Gateway %q should have been deleted", r)
			}
			return nil
		}
	}

	resource.Test(t, resource.TestCase{
		PreCheck:      func() { testAccPreCheck(t) },
		IDRefreshName: "aws_vpn_gateway.foo",
		Providers:     testAccProviders,
		CheckDestroy:  testAccCheckVpnGatewayDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccVpnGatewayConfig,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckVpnGatewayExists("aws_vpn_gateway.foo", &vpnGateway)),
			},
			resource.TestStep{
				Config: testAccNoVpnGatewayConfig,
				Check:  resource.ComposeTestCheckFunc(testDeleted("aws_vpn_gateway.foo")),
			},
		},
	})
}

func TestAccAWSVpnGateway_tags(t *testing.T) {
	var v ec2.VpnGateway

	resource.Test(t, resource.TestCase{
		PreCheck:      func() { testAccPreCheck(t) },
		IDRefreshName: "aws_vpn_gateway.foo",
		Providers:     testAccProviders,
		CheckDestroy:  testAccCheckVpnGatewayDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccCheckVpnGatewayConfigTags,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckVpnGatewayExists("aws_vpn_gateway.foo", &v),
					testAccCheckTags(&v.Tags, "foo", "bar"),
				),
			},

			resource.TestStep{
				Config: testAccCheckVpnGatewayConfigTagsUpdate,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckVpnGatewayExists("aws_vpn_gateway.foo", &v),
					testAccCheckTags(&v.Tags, "foo", ""),
					testAccCheckTags(&v.Tags, "bar", "baz"),
				),
			},
		},
	})
}

func testAccCheckVpnGatewayDestroy(s *terraform.State) error {
	ec2conn := testAccProvider.Meta().(*AWSClient).ec2conn

	for _, rs := range s.RootModule().Resources {
		if rs.Type != "aws_vpn_gateway" {
			continue
		}

		// Try to find the resource
		resp, err := ec2conn.DescribeVpnGateways(&ec2.DescribeVpnGatewaysInput{
			VpnGatewayIds: []*string{aws.String(rs.Primary.ID)},
		})
		if err == nil {
			var v *ec2.VpnGateway
			for _, g := range resp.VpnGateways {
				if *g.VpnGatewayId == rs.Primary.ID {
					v = g
				}
			}

			if v == nil {
				// wasn't found
				return nil
			}

			if *v.State != "deleted" {
				return fmt.Errorf("Expected VpnGateway to be in deleted state, but was not: %s", v)
			}
			return nil
		}

		// Verify the error is what we want
		ec2err, ok := err.(awserr.Error)
		if !ok {
			return err
		}
		if ec2err.Code() != "InvalidVpnGatewayID.NotFound" {
			return err
		}
	}

	return nil
}

func testAccCheckVpnGatewayExists(n string, ig *ec2.VpnGateway) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources[n]
		if !ok {
			return fmt.Errorf("Not found: %s", n)
		}

		if rs.Primary.ID == "" {
			return fmt.Errorf("No ID is set")
		}

		ec2conn := testAccProvider.Meta().(*AWSClient).ec2conn
		resp, err := ec2conn.DescribeVpnGateways(&ec2.DescribeVpnGatewaysInput{
			VpnGatewayIds: []*string{aws.String(rs.Primary.ID)},
		})
		if err != nil {
			return err
		}
		if len(resp.VpnGateways) == 0 {
			return fmt.Errorf("VPNGateway not found")
		}

		*ig = *resp.VpnGateways[0]

		return nil
	}
}

const testAccNoVpnGatewayConfig = `
resource "aws_vpc" "foo" {
	cidr_block = "10.1.0.0/16"
}
`

const testAccVpnGatewayConfig = `
resource "aws_vpc" "foo" {
	cidr_block = "10.1.0.0/16"
}

resource "aws_vpn_gateway" "foo" {
	vpc_id = "${aws_vpc.foo.id}"
}
`

const testAccVpnGatewayConfigChangeVPC = `
resource "aws_vpc" "bar" {
	cidr_block = "10.2.0.0/16"
}

resource "aws_vpn_gateway" "foo" {
	vpc_id = "${aws_vpc.bar.id}"
}
`

const testAccCheckVpnGatewayConfigTags = `
resource "aws_vpc" "foo" {
	cidr_block = "10.1.0.0/16"
}

resource "aws_vpn_gateway" "foo" {
	vpc_id = "${aws_vpc.foo.id}"
	tags {
		foo = "bar"
	}
}
`

const testAccCheckVpnGatewayConfigTagsUpdate = `
resource "aws_vpc" "foo" {
	cidr_block = "10.1.0.0/16"
}

resource "aws_vpn_gateway" "foo" {
	vpc_id = "${aws_vpc.foo.id}"
	tags {
		bar = "baz"
	}
}
`
<|endoftext|>


<commit_before>package aws

import (
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/dynamodb"
)

// DynamoDB implementation for DB interface.
type DynamoDB struct {
	config  *aws.Config
	session *session.Session
	db      *dynamodb.DynamoDB
}

// NewDynamoDB creates a new AWS DynamoDB instance.
// region = Optional region setting. Will overwrite AWS_REGION env var if available.
// endpoint = Optional endpoint URL setting. Useful for specifying local/development service URL.
func NewDynamoDB(region string, endpoint string) *DynamoDB {
	db := DynamoDB{}

	// carefully crafting config elements not to mess with the defaults
	if region != "" || endpoint != "" {
		db.config = aws.NewConfig()

		if region != "" {
			db.config.WithRegion(region)
		}
		if endpoint != "" {
			db.config.WithEndpoint(endpoint)
		}

		db.session = session.New(db.config)
	} else {
		db.session = session.New()
	}

	db.db = dynamodb.New(db.session)

	return &db
}

func (db *DynamoDB) listTables() ([]string, error) {
	res, err := db.db.ListTables(&dynamodb.ListTablesInput{Limit: aws.Int64(100)})
	if err != nil {
		return nil, err
	}

	names := []string{}
	for _, name := range res.TableNames {
		names = append(names, *name)
	}

	return names, nil
}

func (db *DynamoDB) deleteTables() error {
	tables, err := db.listTables()
	if err != nil {
		return err
	}

	for _, tbl := range tables {
		if _, err := db.db.DeleteTable(&dynamodb.DeleteTableInput{TableName: aws.String(tbl)}); err != nil {
			return err
		}
	}

	for _, tbl := range tables {
		if err := db.db.WaitUntilTableNotExists(&dynamodb.DescribeTableInput{TableName: aws.String(tbl)}); err != nil {
			return err
		}
	}

	return nil
}

// Seed creates and populates the database, overwriting existing data if specified.
func (db *DynamoDB) Seed(overwrite bool) error {
	tables := []string{"users"}

	if overwrite {
		if err := db.deleteTables(); err != nil {
			return err
		}
	}

	for _, tbl := range tables {
		tableParams := &dynamodb.CreateTableInput{
			TableName: aws.String(tbl),
			AttributeDefinitions: []*dynamodb.AttributeDefinition{
				{
					AttributeName: aws.String("id"),
					AttributeType: aws.String("S"),
				},
			},
			KeySchema: []*dynamodb.KeySchemaElement{
				{
					AttributeName: aws.String("id"),
					KeyType:       aws.String("HASH"),
				},
			},
			ProvisionedThroughput: &dynamodb.ProvisionedThroughput{
				ReadCapacityUnits:  aws.Int64(1),
				WriteCapacityUnits: aws.Int64(1),
			},
			// GlobalSecondaryIndexes: []*dynamodb.GlobalSecondaryIndex{
			// 	{
			// 		IndexName: aws.String("IndexName"),
			// 		KeySchema: []*dynamodb.KeySchemaElement{
			// 			{
			// 				AttributeName: aws.String("KeySchemaAttributeName"),
			// 				KeyType:       aws.String("KeyType"),
			// 			},
			//
			// 		},
			// 		Projection: &dynamodb.Projection{
			// 			NonKeyAttributes: []*string{
			// 				aws.String("NonKeyAttributeName"),
			//
			// 			},
			// 			ProjectionType: aws.String("ProjectionType"),
			// 		},
			// 		ProvisionedThroughput: &dynamodb.ProvisionedThroughput{
			// 			ReadCapacityUnits:  aws.Int64(1),
			// 			WriteCapacityUnits: aws.Int64(1),
			// 		},
			// 	},
			// 	// More values...
			// },
			// LocalSecondaryIndexes: []*dynamodb.LocalSecondaryIndex{
			// 	{
			// 		IndexName: aws.String("IndexName"),
			// 		KeySchema: []*dynamodb.KeySchemaElement{
			// 			{
			// 				AttributeName: aws.String("KeySchemaAttributeName"),
			// 				KeyType:       aws.String("KeyType"),
			// 			},
			//
			// 		},
			// 		Projection: &dynamodb.Projection{
			// 			NonKeyAttributes: []*string{
			// 				aws.String("NonKeyAttributeName"),
			//
			// 			},
			// 			ProjectionType: aws.String("ProjectionType"),
			// 		},
			// 	},
			// 	// More values...
			// },
			// StreamSpecification: &dynamodb.StreamSpecification{
			// 	StreamEnabled:  aws.Bool(true),
			// 	StreamViewType: aws.String("StreamViewType"),
			// },
		}

		_, err := db.db.CreateTable(tableParams)
		if err != nil {
			return err
		}

		// tables with secondary indexes need to be created sequentially so wait till table is ready
		if err := db.db.WaitUntilTableExists(&dynamodb.DescribeTableInput{TableName: aws.String(tbl)}); err != nil {
			return err
		}
	}

	return nil
}
<commit_msg>expose db fields<commit_after>package aws

import (
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/dynamodb"
)

// DynamoDB implementation for DB interface.
type DynamoDB struct {
	DB      *dynamodb.DynamoDB
	Tables  []string
	Config  *aws.Config
	Session *session.Session
}

// NewDynamoDB creates a new AWS DynamoDB instance.
// region = Optional region setting. Will overwrite AWS_REGION env var if available.
// endpoint = Optional endpoint URL setting. Useful for specifying local/development service URL.
func NewDynamoDB(region string, endpoint string) *DynamoDB {
	db := DynamoDB{}
	db.Tables = []string{"users"}

	// carefully crafting config elements not to mess with the defaults
	if region != "" || endpoint != "" {
		db.Config = aws.NewConfig()

		if region != "" {
			db.Config.WithRegion(region)
		}
		if endpoint != "" {
			db.Config.WithEndpoint(endpoint)
		}

		db.Session = session.New(db.Config)
	} else {
		db.Session = session.New()
	}

	db.DB = dynamodb.New(db.Session)

	return &db
}

func (db *DynamoDB) listTables() ([]string, error) {
	res, err := db.DB.ListTables(&dynamodb.ListTablesInput{Limit: aws.Int64(100)})
	if err != nil {
		return nil, err
	}

	names := []string{}
	for _, name := range res.TableNames {
		names = append(names, *name)
	}

	return names, nil
}

func (db *DynamoDB) deleteTables() error {
	tables, err := db.listTables()
	if err != nil {
		return err
	}

	for _, tbl := range tables {
		if _, err := db.DB.DeleteTable(&dynamodb.DeleteTableInput{TableName: aws.String(tbl)}); err != nil {
			return err
		}
	}

	for _, tbl := range tables {
		if err := db.DB.WaitUntilTableNotExists(&dynamodb.DescribeTableInput{TableName: aws.String(tbl)}); err != nil {
			return err
		}
	}

	return nil
}

// Seed creates and populates the database, overwriting existing data if specified.
func (db *DynamoDB) Seed(overwrite bool) error {
	if overwrite {
		if err := db.deleteTables(); err != nil {
			return err
		}
	}

	for _, tbl := range db.Tables {
		tableParams := &dynamodb.CreateTableInput{
			TableName: aws.String(tbl),
			AttributeDefinitions: []*dynamodb.AttributeDefinition{
				{
					AttributeName: aws.String("id"),
					AttributeType: aws.String("S"),
				},
			},
			KeySchema: []*dynamodb.KeySchemaElement{
				{
					AttributeName: aws.String("id"),
					KeyType:       aws.String("HASH"),
				},
			},
			ProvisionedThroughput: &dynamodb.ProvisionedThroughput{
				ReadCapacityUnits:  aws.Int64(1),
				WriteCapacityUnits: aws.Int64(1),
			},
			// GlobalSecondaryIndexes: []*dynamodb.GlobalSecondaryIndex{
			// 	{
			// 		IndexName: aws.String("IndexName"),
			// 		KeySchema: []*dynamodb.KeySchemaElement{
			// 			{
			// 				AttributeName: aws.String("KeySchemaAttributeName"),
			// 				KeyType:       aws.String("KeyType"),
			// 			},
			//
			// 		},
			// 		Projection: &dynamodb.Projection{
			// 			NonKeyAttributes: []*string{
			// 				aws.String("NonKeyAttributeName"),
			//
			// 			},
			// 			ProjectionType: aws.String("ProjectionType"),
			// 		},
			// 		ProvisionedThroughput: &dynamodb.ProvisionedThroughput{
			// 			ReadCapacityUnits:  aws.Int64(1),
			// 			WriteCapacityUnits: aws.Int64(1),
			// 		},
			// 	},
			// 	// More values...
			// },
			// LocalSecondaryIndexes: []*dynamodb.LocalSecondaryIndex{
			// 	{
			// 		IndexName: aws.String("IndexName"),
			// 		KeySchema: []*dynamodb.KeySchemaElement{
			// 			{
			// 				AttributeName: aws.String("KeySchemaAttributeName"),
			// 				KeyType:       aws.String("KeyType"),
			// 			},
			//
			// 		},
			// 		Projection: &dynamodb.Projection{
			// 			NonKeyAttributes: []*string{
			// 				aws.String("NonKeyAttributeName"),
			//
			// 			},
			// 			ProjectionType: aws.String("ProjectionType"),
			// 		},
			// 	},
			// 	// More values...
			// },
			// StreamSpecification: &dynamodb.StreamSpecification{
			// 	StreamEnabled:  aws.Bool(true),
			// 	StreamViewType: aws.String("StreamViewType"),
			// },
		}

		_, err := db.DB.CreateTable(tableParams)
		if err != nil {
			return err
		}

		// tables with secondary indexes need to be created sequentially so wait till table is ready
		if err := db.DB.WaitUntilTableExists(&dynamodb.DescribeTableInput{TableName: aws.String(tbl)}); err != nil {
			return err
		}
	}

	return nil
}
<|endoftext|>


<commit_before>// Copyright Google 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 backend

import (
	"bytes"
	"fmt"
	"net/http"
	"strings"
)

const NEW_ADDRESS = "https://ampbyexample.com"

func RedirectToSecureVersion(w http.ResponseWriter, r *http.Request) {
	http.Redirect(w, r, NEW_ADDRESS+r.URL.Path, http.StatusMovedPermanently)
}

func IsInsecureRequest(r *http.Request) bool {
	return r.TLS == nil && !strings.HasPrefix(r.Host, "localhost")
}

func buildSourceOrigin(host string) string {
	var sourceOrigin bytes.Buffer
	if strings.HasPrefix(host, "localhost") {
		sourceOrigin.WriteString("http://")
	} else {
		sourceOrigin.WriteString("https://")
	}
	sourceOrigin.WriteString(host)
	return sourceOrigin.String()
}

func isFormPostRequest(method string, w http.ResponseWriter) bool {
	if method != "POST" {
		http.Error(w, "post only", http.StatusMethodNotAllowed)
		return false
	}
	return true
}

func EnableCors(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Access-Control-Allow-Origin", "*")
	w.Header().Set("AMP-Access-Control-Allow-Source-Origin", buildSourceOrigin(r.Host))
}

func SetContentTypeJson(w http.ResponseWriter) {
	w.Header().Set("Content-Type", "application/json")
}

func SetDefaultMaxAge(w http.ResponseWriter) {
	w.Header().Set("cache-control", fmt.Sprintf("max-age=%d, public, must-revalidate", 60))
}

func handlePost(w http.ResponseWriter, r *http.Request, postHandler func(http.ResponseWriter, *http.Request)) {
	if r.Method != "POST" {
		http.Error(w, "post only", http.StatusMethodNotAllowed)
		return
	}
	postHandler(w, r)
}
<commit_msg>Supports CDN on response (#470)<commit_after>// Copyright Google 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 backend

import (
	"bytes"
	"fmt"
	"net/http"
	"strings"
)

const NEW_ADDRESS = "https://ampbyexample.com"

func RedirectToSecureVersion(w http.ResponseWriter, r *http.Request) {
	http.Redirect(w, r, NEW_ADDRESS+r.URL.Path, http.StatusMovedPermanently)
}

func IsInsecureRequest(r *http.Request) bool {
	return r.TLS == nil && !strings.HasPrefix(r.Host, "localhost")
}

func buildSourceOrigin(host string) string {
	var sourceOrigin bytes.Buffer
	if strings.HasPrefix(host, "localhost") {
		sourceOrigin.WriteString("http://")
	} else {
		sourceOrigin.WriteString("https://")
	}
	sourceOrigin.WriteString(host)
	return sourceOrigin.String()
}

func isFormPostRequest(method string, w http.ResponseWriter) bool {
	if method != "POST" {
		http.Error(w, "post only", http.StatusMethodNotAllowed)
		return false
	}
	return true
}

func EnableCors(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Access-Control-Allow-Origin", "https://cdn.ampproject.org")
	w.Header().Set("Access-Control-Expose-Headers", "AMP-Access-Control-Allow-Source-Origin")
	w.Header().Set("AMP-Access-Control-Allow-Source-Origin", buildSourceOrigin(r.Host))
	w.Header().Set("Access-Control-Allow-Credentials", "true")
}

func SetContentTypeJson(w http.ResponseWriter) {
	w.Header().Set("Content-Type", "application/json")
}

func SetDefaultMaxAge(w http.ResponseWriter) {
	w.Header().Set("cache-control", fmt.Sprintf("max-age=%d, public, must-revalidate", 60))
}

func handlePost(w http.ResponseWriter, r *http.Request, postHandler func(http.ResponseWriter, *http.Request)) {
	if r.Method != "POST" {
		http.Error(w, "post only", http.StatusMethodNotAllowed)
		return
	}
	postHandler(w, r)
}
<|endoftext|>


<commit_before>package main

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

func isInstalled(app string) bool {
	path := fmt.Sprintf("/Applications/%s.app", app)
	_, err := os.Stat(path)
	if err == nil {
		return true
	}
	return false
}

func main() {
	// list of applications to install
	// keys represent the folder name in the `/Applications` directory
	// values are the App Store urls (replace the `https` scheme for `itms-apps`)
	applications := map[string]string{
		"1Password 7":    "itms-apps://apps.apple.com/us/app/1password-password-manager/id568903335",
		"Developer":      "itms-apps://apps.apple.com/br/app/apple-developer/id640199958",
		"Gifox":          "itms-apps://apps.apple.com/br/app/gifox-2/id1461845568",
		"Kindle":         "itms-apps://apps.apple.com/br/app/kindle/id405399194",
		"Keynote":        "itms-apps://apps.apple.com/br/app/keynote/id409183694",
		"Numbers":        "itms-apps://apps.apple.com/br/app/numbers/id409203825",
		"Pages":          "itms-apps://apps.apple.com/br/app/pages/id409201541",
		"Skitch":         "itms-apps://apps.apple.com/br/app/skitch-snap-mark-up-share/id425955336",
		"Snappy":         "itms-apps://apps.apple.com/us/app/snappy-snapshots-the-smart-way/id512617038",
		"Slack":          "itms-apps://apps.apple.com/us/app/slack/id618783545",
		"Speedtest":      "itms-apps://apps.apple.com/br/app/speedtest-by-ookla/id1153157709",
		"The Unarchiver": "itms-apps://apps.apple.com/us/app/the-unarchiver/id425424353",
		"Xcode":          "itms-apps://apps.apple.com/us/app/xcode/id497799835",
	}

	for app, url := range applications {
		if isInstalled(app) {
			fmt.Printf("%s is already installed\n", app)
		} else {
			fmt.Printf("Installing %s...\n", app)

			// open application url on app store
			exec.Command("open", url).Start()

			// wait until the application is installed
			for {
				time.Sleep(1 * time.Second)

				// break this wait loop, going to the next application in the map
				if isInstalled(app) {
					break
				}
			}
		}
	}

	fmt.Println("Everything is installed!")
}
<commit_msg>Install swift playgrounds and boop<commit_after>package main

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

func isInstalled(app string) bool {
	path := fmt.Sprintf("/Applications/%s.app", app)
	_, err := os.Stat(path)
	if err == nil {
		return true
	}
	return false
}

func main() {
	// list of applications to install
	// keys represent the folder name in the `/Applications` directory
	// values are the App Store urls (replace the `https` scheme for `itms-apps`)
	applications := map[string]string{
		"1Password 7":    "itms-apps://apps.apple.com/us/app/1password-password-manager/id568903335",
		"Boop":           "itms-apps://apps.apple.com/br/app/boop/id1518425043",
		"Developer":      "itms-apps://apps.apple.com/br/app/apple-developer/id640199958",
		"Gifox":          "itms-apps://apps.apple.com/br/app/gifox-2/id1461845568",
		"Kindle":         "itms-apps://apps.apple.com/br/app/kindle/id405399194",
		"Keynote":        "itms-apps://apps.apple.com/br/app/keynote/id409183694",
		"Numbers":        "itms-apps://apps.apple.com/br/app/numbers/id409203825",
		"Pages":          "itms-apps://apps.apple.com/br/app/pages/id409201541",
		"Skitch":         "itms-apps://apps.apple.com/br/app/skitch-snap-mark-up-share/id425955336",
		"Snappy":         "itms-apps://apps.apple.com/us/app/snappy-snapshots-the-smart-way/id512617038",
		"Slack":          "itms-apps://apps.apple.com/us/app/slack/id618783545",
		"Speedtest":      "itms-apps://apps.apple.com/br/app/speedtest-by-ookla/id1153157709",
		"The Unarchiver": "itms-apps://apps.apple.com/us/app/the-unarchiver/id425424353",
		"Xcode":          "itms-apps://apps.apple.com/us/app/xcode/id497799835",
		"Playgrounds":    "itms-apps://apps.apple.com/br/app/swift-playgrounds/id1496833156",
	}

	for app, url := range applications {
		if isInstalled(app) {
			fmt.Printf("%s is already installed\n", app)
		} else {
			fmt.Printf("Installing %s...\n", app)

			// open application url on app store
			exec.Command("open", url).Start()

			// wait until the application is installed
			for {
				time.Sleep(1 * time.Second)

				// break this wait loop, going to the next application in the map
				if isInstalled(app) {
					break
				}
			}
		}
	}

	fmt.Println("Everything is installed!")
}
<|endoftext|>


<commit_before>package cmd

import (
	"archive/tar"
	"bytes"
	"context"
	"errors"
	"github.com/docker/docker/api"
	"github.com/docker/docker/api/types"
	"github.com/docker/docker/client"
	"github.com/laincloud/dockerfiles/src/core"
	"github.com/spf13/cobra"
	"io/ioutil"
	"log"
)

var (
	oldRegistryHost  string
	oldOrganization  string
	newRegistryHost  string
	newOrganization  string
	aptMirrorHost    string
	dockerHost       string
	dockerApiVersion string
)

var retagCmd = &cobra.Command{
	Use:   "retag",
	Short: "retag images from ${oldRegistryHost}/${oldOrganization}/${repository}:${tag} to ${newRegistryHost}/${newOrganization}/${repository}:${tag}",
	RunE:  retag,
}

func init() {
	retagCmd.Flags().StringVar(&oldRegistryHost, "old-registry-host", "docker.io", "the old registry host who serves this image")
	retagCmd.Flags().StringVar(&oldOrganization, "old-organization", "laincloud", "the old organization build this image")
	retagCmd.Flags().StringVar(&newRegistryHost, "new-registry-host", "", "the new registry host who serves this image")
	retagCmd.Flags().StringVar(&newOrganization, "new-organization", "", "the new organization build this image")
	retagCmd.Flags().StringVar(&aptMirrorHost, "apt-mirror-host", "", "apt mirror host")
	retagCmd.Flags().StringVar(&dockerHost, "docker-host", "/var/run/docker.sock", "docker host")
	retagCmd.Flags().StringVar(&dockerApiVersion, "docker-api-version", "", "docker api version")
	rootCmd.AddCommand(retagCmd)
}

func retag(cmd *cobra.Command, args []string) error {

	if oldOrganization == "" {
		return errors.New("--old-organization is required")
	}

	if newOrganization == "" {
		return errors.New("--new-organization is required")
	}

	if dockerApiVersion == "" {
		dockerApiVersion = api.DefaultVersion
	}

	if oldRegistryHost == newRegistryHost && oldOrganization == newOrganization {
		return errors.New("old-registry-host == new-registry-host && old-organization == new-organization")
	}

	dockerClient, err := client.NewClient(client.DefaultDockerHost, dockerApiVersion, nil, nil)
	if err != nil {
		return err
	}

	allFiles, err := util.Walk(".")
	if err != nil {
		return err
	}

	allImages, err := util.GetContext2Images(allFiles)
	if err != nil {
		return err
	}

	for _, image := range allImages {
		for _, tag := range image.Tags {
			log.Println("retag " + image.Repository + ":" + tag)
			if aptMirrorHost != "" {
				dockerfile := "FROM " + oldRegistryHost + "/" + oldOrganization + "/" + image.Repository + ":" + tag +
					"\nRUN sed -i 's|deb.debian.org|" + aptMirrorHost + "|g' /etc/apt/sources.list && sed -i 's|security.debian.org|" + aptMirrorHost + "/debian-security|g' /etc/apt/sources.list"

				buf := new(bytes.Buffer)

				tw := tar.NewWriter(buf)

				hdr := &tar.Header{
					Name: "Dockerfile",
					Mode: 0600,
					Size: int64(len(dockerfile)),
				}
				if err := tw.WriteHeader(hdr); err != nil {
					return err
				}
				if _, err := tw.Write([]byte(dockerfile)); err != nil {
					return err
				}
				if err := tw.Close(); err != nil {
					return err
				}
				buildOptions := types.ImageBuildOptions{Tags: []string{newRegistryHost + "/" + newOrganization + "/" + image.Repository + ":" + tag}}
				buildResponse, err := dockerClient.ImageBuild(context.Background(), buf, buildOptions)
				if err != nil {
					return err
				}
				response, err := ioutil.ReadAll(buildResponse.Body)
				if err != nil {
					return err
				}
				if err := buildResponse.Body.Close(); err != nil {
					return err
				}
				log.Println(string(response))
			} else {
				err := dockerClient.ImageTag(context.Background(), oldRegistryHost+"/"+oldOrganization+"/"+image.Repository+":"+tag, newRegistryHost+"/"+newOrganization+"/"+image.Repository+":"+tag)
				if err != nil {
					return err
				}
			}
		}
	}

	return nil
}
<commit_msg>only retag diff images<commit_after>package cmd

import (
	"archive/tar"
	"bytes"
	"context"
	"errors"
	"github.com/docker/docker/api"
	"github.com/docker/docker/api/types"
	"github.com/docker/docker/client"
	"github.com/laincloud/dockerfiles/src/core"
	"github.com/spf13/cobra"
	"io/ioutil"
	"log"
)

var (
	oldRegistryHost  string
	oldOrganization  string
	newRegistryHost  string
	newOrganization  string
	aptMirrorHost    string
	dockerHost       string
	dockerApiVersion string
)

var retagCmd = &cobra.Command{
	Use:   "retag",
	Short: "retag images from ${oldRegistryHost}/${oldOrganization}/${repository}:${tag} to ${newRegistryHost}/${newOrganization}/${repository}:${tag}",
	RunE:  retag,
}

func init() {
	retagCmd.Flags().StringVar(&commit1, "commit1", "origin/master", "previous commit")
	retagCmd.Flags().StringVar(&commit2, "commit2", "HEAD", "current commit")
	retagCmd.Flags().StringVar(&oldRegistryHost, "old-registry-host", "docker.io", "the old registry host who serves this image")
	retagCmd.Flags().StringVar(&oldOrganization, "old-organization", "laincloud", "the old organization build this image")
	retagCmd.Flags().StringVar(&newRegistryHost, "new-registry-host", "", "the new registry host who serves this image")
	retagCmd.Flags().StringVar(&newOrganization, "new-organization", "", "the new organization build this image")
	retagCmd.Flags().StringVar(&aptMirrorHost, "apt-mirror-host", "", "apt mirror host")
	retagCmd.Flags().StringVar(&dockerHost, "docker-host", "/var/run/docker.sock", "docker host")
	retagCmd.Flags().StringVar(&dockerApiVersion, "docker-api-version", "", "docker api version")
	rootCmd.AddCommand(retagCmd)
}

func retag(cmd *cobra.Command, args []string) error {
	if commit1 == "" {
		return errors.New("--commit1 is required")
	}

	if commit2 == "" {
		return errors.New("--commit2 is required")
	}

	if oldOrganization == "" {
		return errors.New("--old-organization is required")
	}

	if newOrganization == "" {
		return errors.New("--new-organization is required")
	}

	if dockerApiVersion == "" {
		dockerApiVersion = api.DefaultVersion
	}

	if oldRegistryHost == newRegistryHost && oldOrganization == newOrganization {
		return errors.New("old-registry-host == new-registry-host && old-organization == new-organization")
	}

	dockerClient, err := client.NewClient(client.DefaultDockerHost, dockerApiVersion, nil, nil)
	if err != nil {
		return err
	}

	diffFiles, err := util.Diff(commit1, commit2)
	if err != nil {
		return err
	}

	diffImages, err := util.GetContext2Images(diffFiles)
	if err != nil {
		return err
	}

	for _, image := range diffImages {
		for _, tag := range image.Tags {
			log.Println("retag " + image.Repository + ":" + tag)
			if aptMirrorHost != "" {
				dockerfile := "FROM " + oldRegistryHost + "/" + oldOrganization + "/" + image.Repository + ":" + tag +
					"\nRUN sed -i 's|deb.debian.org|" + aptMirrorHost + "|g' /etc/apt/sources.list && sed -i 's|security.debian.org|" + aptMirrorHost + "/debian-security|g' /etc/apt/sources.list"

				buf := new(bytes.Buffer)

				tw := tar.NewWriter(buf)

				hdr := &tar.Header{
					Name: "Dockerfile",
					Mode: 0600,
					Size: int64(len(dockerfile)),
				}
				if err := tw.WriteHeader(hdr); err != nil {
					return err
				}
				if _, err := tw.Write([]byte(dockerfile)); err != nil {
					return err
				}
				if err := tw.Close(); err != nil {
					return err
				}
				buildOptions := types.ImageBuildOptions{Tags: []string{newRegistryHost + "/" + newOrganization + "/" + image.Repository + ":" + tag}}
				buildResponse, err := dockerClient.ImageBuild(context.Background(), buf, buildOptions)
				if err != nil {
					return err
				}
				response, err := ioutil.ReadAll(buildResponse.Body)
				if err != nil {
					return err
				}
				if err := buildResponse.Body.Close(); err != nil {
					return err
				}
				log.Println(string(response))
			} else {
				err := dockerClient.ImageTag(context.Background(), oldRegistryHost+"/"+oldOrganization+"/"+image.Repository+":"+tag, newRegistryHost+"/"+newOrganization+"/"+image.Repository+":"+tag)
				if err != nil {
					return err
				}
			}
		}
	}

	return nil
}
<|endoftext|>