<commit_before>// Copyright 2020 Google LLC
//
// 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 acceptance

import (
	"flag"
	"os"
	"testing"

	"github.com/GoogleCloudPlatform/buildpacks/internal/acceptance"
)

func init() {
	acceptance.DefineFlags()
}

func TestAcceptance(t *testing.T) {
	builder, cleanup := acceptance.CreateBuilder(t)
	t.Cleanup(cleanup)

	// In general we fail if we see the string WARNING, because it should be possible to have a project that produces no warnings.
	// In a few cases that is hard and we omit the check.
	testCases := []acceptance.Test{
		{
			Name:          "custom entrypoint",
			App:           "custom_entrypoint",
			Env:           []string{"GOOGLE_ENTRYPOINT=java Main.java"},
			MustNotOutput: []string{"WARNING"},
		},
		{
			Name:          "single jar",
			App:           "single_jar",
			MustNotOutput: []string{"WARNING"},
		},
		{
			Name:          "Java11 compat web app",
			App:           "java11_compat_webapp",
			MustNotOutput: []string{"WARNING"},
		},
		{
			Name:          "hello quarkus maven",
			App:           "hello_quarkus_maven",
			MustNotOutput: []string{"WARNING"},
		},
		{
			Name:          "hello springboot maven",
			App:           "springboot-helloworld",
			MustNotOutput: []string{"WARNING"},
		},
		{
			Name:          "hello sparkjava maven",
			App:           "sparkjava-helloworld",
			MustNotOutput: []string{"WARNING"},
		},
		{
			Name: "hello micronaut maven",
			App:  "micronaut-helloworld",
			// We don't check for WARNING, because we get a bunch of them from maven-shade-plugin that would be hard to eliminate.
		},
		{
			Name:          "hello vertx maven",
			App:           "vertx-helloworld",
			MustNotOutput: []string{"WARNING"},
		},
		{
			Name:          "http server",
			App:           "http-server",
			MustNotOutput: []string{"WARNING"},
		},
		{
			Name: "Ktor Kotlin maven mwnw",
			App:  "ktordemo",
			Env:  []string{"GOOGLE_ENTRYPOINT=java -jar target/ktor-0.0.1-jar-with-dependencies.jar"},
			// We don't check for WARNING, because our project-artifact-generated code produces several of them.
		},
		{
			Name:          "gradle micronaut",
			App:           "gradle_micronaut",
			MustNotOutput: []string{"WARNING"},
		},
		{
			Name:          "gradlew micronaut",
			App:           "gradlew_micronaut",
			MustNotOutput: []string{"WARNING"},
		},
		{
			Name:          "gradle kotlin",
			App:           "gradle-kotlin",
			MustNotOutput: []string{"WARNING"},
		},
		{
			Name:              "hello quarkus maven with source clearing",
			App:               "hello_quarkus_maven",
			Env:               []string{"GOOGLE_CLEAR_SOURCE=true"},
			MustNotOutput:     []string{"WARNING"},
			FilesMustNotExist: []string{"/workspace/src/main/java/hello/Hello.java", "/workspace/pom.xml"},
		},
		{
			Name:              "Gradle with source clearing",
			App:               "gradle_micronaut",
			Env:               []string{"GOOGLE_CLEAR_SOURCE=true", "GOOGLE_ENTRYPOINT=java -jar build/libs/helloworld-0.1-all.jar"},
			MustNotOutput:     []string{"WARNING"},
			FilesMustNotExist: []string{"/workspace/src/main/java/example/Application.java", "/workspace/build.gradle"},
		},
		{
			Name:          "Java gradle quarkus",
			App:           "gradle_quarkus",
			MustNotOutput: []string{"WARNING"},
		},
	}
	for _, tc := range testCases {
		tc := tc
		tc.FlakyBuildAttempts = 3

		t.Run(tc.Name, func(t *testing.T) {
			t.Parallel()

			tc.Env = append(tc.Env, "GOOGLE_RUNTIME=java11")

			acceptance.TestApp(t, builder, tc)
		})
	}
}

func TestMain(m *testing.M) {
	flag.Parse()
	cleanup := acceptance.UnarchiveTestData()
	// We can't use defer cleanup() here because os.Exit prevents deferred functions from running.
	status := m.Run()
	cleanup()
	os.Exit(status)
}
<commit_msg>The kotlin compiler starts emitting a warning.<commit_after>// Copyright 2020 Google LLC
//
// 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 acceptance

import (
	"flag"
	"os"
	"testing"

	"github.com/GoogleCloudPlatform/buildpacks/internal/acceptance"
)

func init() {
	acceptance.DefineFlags()
}

func TestAcceptance(t *testing.T) {
	builder, cleanup := acceptance.CreateBuilder(t)
	t.Cleanup(cleanup)

	// In general we fail if we see the string WARNING, because it should be possible to have a project that produces no warnings.
	// In a few cases that is hard and we omit the check.
	testCases := []acceptance.Test{
		{
			Name:          "custom entrypoint",
			App:           "custom_entrypoint",
			Env:           []string{"GOOGLE_ENTRYPOINT=java Main.java"},
			MustNotOutput: []string{"WARNING"},
		},
		{
			Name:          "single jar",
			App:           "single_jar",
			MustNotOutput: []string{"WARNING"},
		},
		{
			Name:          "Java11 compat web app",
			App:           "java11_compat_webapp",
			MustNotOutput: []string{"WARNING"},
		},
		{
			Name:          "hello quarkus maven",
			App:           "hello_quarkus_maven",
			MustNotOutput: []string{"WARNING"},
		},
		{
			Name:          "hello springboot maven",
			App:           "springboot-helloworld",
			MustNotOutput: []string{"WARNING"},
		},
		{
			Name:          "hello sparkjava maven",
			App:           "sparkjava-helloworld",
			MustNotOutput: []string{"WARNING"},
		},
		{
			Name: "hello micronaut maven",
			App:  "micronaut-helloworld",
			// We don't check for WARNING, because we get a bunch of them from maven-shade-plugin that would be hard to eliminate.
		},
		{
			Name:          "hello vertx maven",
			App:           "vertx-helloworld",
			MustNotOutput: []string{"WARNING"},
		},
		{
			Name:          "http server",
			App:           "http-server",
			MustNotOutput: []string{"WARNING"},
		},
		{
			Name: "Ktor Kotlin maven mwnw",
			App:  "ktordemo",
			Env:  []string{"GOOGLE_ENTRYPOINT=java -jar target/ktor-0.0.1-jar-with-dependencies.jar"},
			// We don't check for WARNING, because our project-artifact-generated code produces several of them.
		},
		{
			Name:          "gradle micronaut",
			App:           "gradle_micronaut",
			MustNotOutput: []string{"WARNING"},
		},
		{
			Name:          "gradlew micronaut",
			App:           "gradlew_micronaut",
			MustNotOutput: []string{"WARNING"},
		},
		{
			Name: "gradle kotlin",
			App:  "gradle-kotlin",
		},
		{
			Name:              "hello quarkus maven with source clearing",
			App:               "hello_quarkus_maven",
			Env:               []string{"GOOGLE_CLEAR_SOURCE=true"},
			MustNotOutput:     []string{"WARNING"},
			FilesMustNotExist: []string{"/workspace/src/main/java/hello/Hello.java", "/workspace/pom.xml"},
		},
		{
			Name:              "Gradle with source clearing",
			App:               "gradle_micronaut",
			Env:               []string{"GOOGLE_CLEAR_SOURCE=true", "GOOGLE_ENTRYPOINT=java -jar build/libs/helloworld-0.1-all.jar"},
			MustNotOutput:     []string{"WARNING"},
			FilesMustNotExist: []string{"/workspace/src/main/java/example/Application.java", "/workspace/build.gradle"},
		},
		{
			Name:          "Java gradle quarkus",
			App:           "gradle_quarkus",
			MustNotOutput: []string{"WARNING"},
		},
	}
	for _, tc := range testCases {
		tc := tc
		tc.FlakyBuildAttempts = 3

		t.Run(tc.Name, func(t *testing.T) {
			t.Parallel()

			tc.Env = append(tc.Env, "GOOGLE_RUNTIME=java11")

			acceptance.TestApp(t, builder, tc)
		})
	}
}

func TestMain(m *testing.M) {
	flag.Parse()
	cleanup := acceptance.UnarchiveTestData()
	// We can't use defer cleanup() here because os.Exit prevents deferred functions from running.
	status := m.Run()
	cleanup()
	os.Exit(status)
}
<|endoftext|>


<commit_before>package api

import (
	"context"
	"fmt"
	"sync"

	gethcommon "github.com/ethereum/go-ethereum/common"
	"github.com/status-im/status-go/geth/account"
	"github.com/status-im/status-go/geth/common"
	"github.com/status-im/status-go/geth/jail"
	"github.com/status-im/status-go/geth/log"
	"github.com/status-im/status-go/geth/node"
	"github.com/status-im/status-go/geth/notification/fcm"
	"github.com/status-im/status-go/geth/params"
	"github.com/status-im/status-go/geth/signal"
	"github.com/status-im/status-go/geth/transactions"
)

const (
	//todo(jeka): should be removed
	fcmServerKey = "AAAAxwa-r08:APA91bFtMIToDVKGAmVCm76iEXtA4dn9MPvLdYKIZqAlNpLJbd12EgdBI9DSDSXKdqvIAgLodepmRhGVaWvhxnXJzVpE6MoIRuKedDV3kfHSVBhWFqsyoLTwXY4xeufL9Sdzb581U-lx"
)

// StatusBackend implements Status.im service
type StatusBackend struct {
	mu              sync.Mutex
	nodeManager     *node.NodeManager
	accountManager  common.AccountManager
	txQueueManager  *transactions.Manager
	jailManager     common.JailManager
	newNotification common.NotificationConstructor
	connectionState ConnectionState
}

// NewStatusBackend create a new NewStatusBackend instance
func NewStatusBackend() *StatusBackend {
	defer log.Info("Status backend initialized")

	nodeManager := node.NewNodeManager()
	accountManager := account.NewManager(nodeManager)
	txQueueManager := transactions.NewManager(nodeManager, accountManager)
	jailManager := jail.New(nodeManager)
	notificationManager := fcm.NewNotification(fcmServerKey)

	return &StatusBackend{
		nodeManager:     nodeManager,
		accountManager:  accountManager,
		jailManager:     jailManager,
		txQueueManager:  txQueueManager,
		newNotification: notificationManager,
	}
}

// NodeManager returns reference to node manager
func (b *StatusBackend) NodeManager() common.NodeManager {
	return b.nodeManager
}

// AccountManager returns reference to account manager
func (b *StatusBackend) AccountManager() common.AccountManager {
	return b.accountManager
}

// JailManager returns reference to jail
func (b *StatusBackend) JailManager() common.JailManager {
	return b.jailManager
}

// TxQueueManager returns reference to transactions manager
func (b *StatusBackend) TxQueueManager() *transactions.Manager {
	return b.txQueueManager
}

// IsNodeRunning confirm that node is running
func (b *StatusBackend) IsNodeRunning() bool {
	return b.nodeManager.IsNodeRunning()
}

// StartNode start Status node, fails if node is already started
func (b *StatusBackend) StartNode(config *params.NodeConfig) error {
	b.mu.Lock()
	defer b.mu.Unlock()
	return b.startNode(config)
}

func (b *StatusBackend) startNode(config *params.NodeConfig) (err error) {
	defer func() {
		if r := recover(); r != nil {
			err = fmt.Errorf("node crashed on start: %v", err)
		}
	}()
	err = b.nodeManager.StartNode(config)
	if err != nil {
		switch err.(type) {
		case node.RPCClientError:
			err = node.ErrRPCClient
		case node.EthNodeError:
			err = fmt.Errorf("%v: %v", node.ErrNodeStartFailure, err)
		}
		signal.Send(signal.Envelope{
			Type: signal.EventNodeCrashed,
			Event: signal.NodeCrashEvent{
				Error: err,
			},
		})
		return err
	}
	signal.Send(signal.Envelope{Type: signal.EventNodeStarted})
	// tx queue manager should be started after node is started, it depends
	// on rpc client being created
	b.txQueueManager.Start()
	if err := b.registerHandlers(); err != nil {
		log.Error("Handler registration failed", "err", err)
	}
	if err := b.accountManager.ReSelectAccount(); err != nil {
		log.Error("Reselect account failed", "err", err)
	}
	log.Info("Account reselected")
	signal.Send(signal.Envelope{Type: signal.EventNodeReady})
	return nil
}

// StopNode stop Status node. Stopped node cannot be resumed.
func (b *StatusBackend) StopNode() error {
	b.mu.Lock()
	defer b.mu.Unlock()
	return b.stopNode()
}

func (b *StatusBackend) stopNode() error {
	if !b.IsNodeRunning() {
		return node.ErrNoRunningNode
	}
	b.txQueueManager.Stop()
	b.jailManager.Stop()
	defer signal.Send(signal.Envelope{Type: signal.EventNodeStopped})
	return b.nodeManager.StopNode()
}

// RestartNode restart running Status node, fails if node is not running
func (b *StatusBackend) RestartNode() error {
	if !b.IsNodeRunning() {
		return node.ErrNoRunningNode
	}
	config, err := b.nodeManager.NodeConfig()
	if err != nil {
		return err
	}
	newcfg := *config
	if err := b.stopNode(); err != nil {
		return err
	}
	return b.startNode(&newcfg)
}

// ResetChainData remove chain data from data directory.
// Node is stopped, and new node is started, with clean data directory.
func (b *StatusBackend) ResetChainData() error {
	b.mu.Lock()
	defer b.mu.Unlock()
	config, err := b.nodeManager.NodeConfig()
	if err != nil {
		return err
	}
	newcfg := *config
	if err := b.stopNode(); err != nil {
		return err
	}
	// config is cleaned when node is stopped
	if err := b.nodeManager.ResetChainData(&newcfg); err != nil {
		return err
	}
	signal.Send(signal.Envelope{Type: signal.EventChainDataRemoved})
	return b.startNode(&newcfg)
}

// CallRPC executes RPC request on node's in-proc RPC server
func (b *StatusBackend) CallRPC(inputJSON string) string {
	client := b.nodeManager.RPCClient()
	return client.CallRaw(inputJSON)
}

// SendTransaction creates a new transaction and waits until it's complete.
func (b *StatusBackend) SendTransaction(ctx context.Context, args common.SendTxArgs) (hash gethcommon.Hash, err error) {
	if ctx == nil {
		ctx = context.Background()
	}
	tx := common.CreateTransaction(ctx, args)
	if err = b.txQueueManager.QueueTransaction(tx); err != nil {
		return hash, err
	}
	rst := b.txQueueManager.WaitForTransaction(tx)
	if rst.Error != nil {
		return hash, rst.Error
	}
	return rst.Hash, nil
}

// CompleteTransaction instructs backend to complete sending of a given transaction
func (b *StatusBackend) CompleteTransaction(id common.QueuedTxID, password string) (gethcommon.Hash, error) {
	return b.txQueueManager.CompleteTransaction(id, password)
}

// CompleteTransactions instructs backend to complete sending of multiple transactions
func (b *StatusBackend) CompleteTransactions(ids []common.QueuedTxID, password string) map[common.QueuedTxID]common.TransactionResult {
	return b.txQueueManager.CompleteTransactions(ids, password)
}

// DiscardTransaction discards a given transaction from transaction queue
func (b *StatusBackend) DiscardTransaction(id common.QueuedTxID) error {
	return b.txQueueManager.DiscardTransaction(id)
}

// DiscardTransactions discards given multiple transactions from transaction queue
func (b *StatusBackend) DiscardTransactions(ids []common.QueuedTxID) map[common.QueuedTxID]common.RawDiscardTransactionResult {
	return b.txQueueManager.DiscardTransactions(ids)
}

// registerHandlers attaches Status callback handlers to running node
func (b *StatusBackend) registerHandlers() error {
	rpcClient := b.NodeManager().RPCClient()
	if rpcClient == nil {
		return node.ErrRPCClient
	}
	rpcClient.RegisterHandler("eth_accounts", b.accountManager.AccountsRPCHandler())
	rpcClient.RegisterHandler("eth_sendTransaction", b.txQueueManager.SendTransactionRPCHandler)
	return nil
}

// ConnectionChange handles network state changes logic.
func (m *StatusBackend) ConnectionChange(state ConnectionState) {
	log.Info("Network state change", "old", m.connectionState, "new", state)
	m.connectionState = state

	// logic of handling state changes here
	// restart node? force peers reconnect? etc
}
<commit_msg>Fix linter warnings for StatusBackend. (#675)<commit_after>package api

import (
	"context"
	"fmt"
	"sync"

	gethcommon "github.com/ethereum/go-ethereum/common"
	"github.com/status-im/status-go/geth/account"
	"github.com/status-im/status-go/geth/common"
	"github.com/status-im/status-go/geth/jail"
	"github.com/status-im/status-go/geth/log"
	"github.com/status-im/status-go/geth/node"
	"github.com/status-im/status-go/geth/notification/fcm"
	"github.com/status-im/status-go/geth/params"
	"github.com/status-im/status-go/geth/signal"
	"github.com/status-im/status-go/geth/transactions"
)

const (
	//todo(jeka): should be removed
	fcmServerKey = "AAAAxwa-r08:APA91bFtMIToDVKGAmVCm76iEXtA4dn9MPvLdYKIZqAlNpLJbd12EgdBI9DSDSXKdqvIAgLodepmRhGVaWvhxnXJzVpE6MoIRuKedDV3kfHSVBhWFqsyoLTwXY4xeufL9Sdzb581U-lx"
)

// StatusBackend implements Status.im service
type StatusBackend struct {
	mu              sync.Mutex
	nodeManager     *node.NodeManager
	accountManager  common.AccountManager
	txQueueManager  *transactions.Manager
	jailManager     common.JailManager
	newNotification common.NotificationConstructor
	connectionState ConnectionState
}

// NewStatusBackend create a new NewStatusBackend instance
func NewStatusBackend() *StatusBackend {
	defer log.Info("Status backend initialized")

	nodeManager := node.NewNodeManager()
	accountManager := account.NewManager(nodeManager)
	txQueueManager := transactions.NewManager(nodeManager, accountManager)
	jailManager := jail.New(nodeManager)
	notificationManager := fcm.NewNotification(fcmServerKey)

	return &StatusBackend{
		nodeManager:     nodeManager,
		accountManager:  accountManager,
		jailManager:     jailManager,
		txQueueManager:  txQueueManager,
		newNotification: notificationManager,
	}
}

// NodeManager returns reference to node manager
func (b *StatusBackend) NodeManager() common.NodeManager {
	return b.nodeManager
}

// AccountManager returns reference to account manager
func (b *StatusBackend) AccountManager() common.AccountManager {
	return b.accountManager
}

// JailManager returns reference to jail
func (b *StatusBackend) JailManager() common.JailManager {
	return b.jailManager
}

// TxQueueManager returns reference to transactions manager
func (b *StatusBackend) TxQueueManager() *transactions.Manager {
	return b.txQueueManager
}

// IsNodeRunning confirm that node is running
func (b *StatusBackend) IsNodeRunning() bool {
	return b.nodeManager.IsNodeRunning()
}

// StartNode start Status node, fails if node is already started
func (b *StatusBackend) StartNode(config *params.NodeConfig) error {
	b.mu.Lock()
	defer b.mu.Unlock()
	return b.startNode(config)
}

func (b *StatusBackend) startNode(config *params.NodeConfig) (err error) {
	defer func() {
		if r := recover(); r != nil {
			err = fmt.Errorf("node crashed on start: %v", err)
		}
	}()
	err = b.nodeManager.StartNode(config)
	if err != nil {
		switch err.(type) {
		case node.RPCClientError:
			err = node.ErrRPCClient
		case node.EthNodeError:
			err = fmt.Errorf("%v: %v", node.ErrNodeStartFailure, err)
		}
		signal.Send(signal.Envelope{
			Type: signal.EventNodeCrashed,
			Event: signal.NodeCrashEvent{
				Error: err,
			},
		})
		return err
	}
	signal.Send(signal.Envelope{Type: signal.EventNodeStarted})
	// tx queue manager should be started after node is started, it depends
	// on rpc client being created
	b.txQueueManager.Start()
	if err := b.registerHandlers(); err != nil {
		log.Error("Handler registration failed", "err", err)
	}
	if err := b.accountManager.ReSelectAccount(); err != nil {
		log.Error("Reselect account failed", "err", err)
	}
	log.Info("Account reselected")
	signal.Send(signal.Envelope{Type: signal.EventNodeReady})
	return nil
}

// StopNode stop Status node. Stopped node cannot be resumed.
func (b *StatusBackend) StopNode() error {
	b.mu.Lock()
	defer b.mu.Unlock()
	return b.stopNode()
}

func (b *StatusBackend) stopNode() error {
	if !b.IsNodeRunning() {
		return node.ErrNoRunningNode
	}
	b.txQueueManager.Stop()
	b.jailManager.Stop()
	defer signal.Send(signal.Envelope{Type: signal.EventNodeStopped})
	return b.nodeManager.StopNode()
}

// RestartNode restart running Status node, fails if node is not running
func (b *StatusBackend) RestartNode() error {
	if !b.IsNodeRunning() {
		return node.ErrNoRunningNode
	}
	config, err := b.nodeManager.NodeConfig()
	if err != nil {
		return err
	}
	newcfg := *config
	if err := b.stopNode(); err != nil {
		return err
	}
	return b.startNode(&newcfg)
}

// ResetChainData remove chain data from data directory.
// Node is stopped, and new node is started, with clean data directory.
func (b *StatusBackend) ResetChainData() error {
	b.mu.Lock()
	defer b.mu.Unlock()
	config, err := b.nodeManager.NodeConfig()
	if err != nil {
		return err
	}
	newcfg := *config
	if err := b.stopNode(); err != nil {
		return err
	}
	// config is cleaned when node is stopped
	if err := b.nodeManager.ResetChainData(&newcfg); err != nil {
		return err
	}
	signal.Send(signal.Envelope{Type: signal.EventChainDataRemoved})
	return b.startNode(&newcfg)
}

// CallRPC executes RPC request on node's in-proc RPC server
func (b *StatusBackend) CallRPC(inputJSON string) string {
	client := b.nodeManager.RPCClient()
	return client.CallRaw(inputJSON)
}

// SendTransaction creates a new transaction and waits until it's complete.
func (b *StatusBackend) SendTransaction(ctx context.Context, args common.SendTxArgs) (hash gethcommon.Hash, err error) {
	if ctx == nil {
		ctx = context.Background()
	}
	tx := common.CreateTransaction(ctx, args)
	if err = b.txQueueManager.QueueTransaction(tx); err != nil {
		return hash, err
	}
	rst := b.txQueueManager.WaitForTransaction(tx)
	if rst.Error != nil {
		return hash, rst.Error
	}
	return rst.Hash, nil
}

// CompleteTransaction instructs backend to complete sending of a given transaction
func (b *StatusBackend) CompleteTransaction(id common.QueuedTxID, password string) (gethcommon.Hash, error) {
	return b.txQueueManager.CompleteTransaction(id, password)
}

// CompleteTransactions instructs backend to complete sending of multiple transactions
func (b *StatusBackend) CompleteTransactions(ids []common.QueuedTxID, password string) map[common.QueuedTxID]common.TransactionResult {
	return b.txQueueManager.CompleteTransactions(ids, password)
}

// DiscardTransaction discards a given transaction from transaction queue
func (b *StatusBackend) DiscardTransaction(id common.QueuedTxID) error {
	return b.txQueueManager.DiscardTransaction(id)
}

// DiscardTransactions discards given multiple transactions from transaction queue
func (b *StatusBackend) DiscardTransactions(ids []common.QueuedTxID) map[common.QueuedTxID]common.RawDiscardTransactionResult {
	return b.txQueueManager.DiscardTransactions(ids)
}

// registerHandlers attaches Status callback handlers to running node
func (b *StatusBackend) registerHandlers() error {
	rpcClient := b.NodeManager().RPCClient()
	if rpcClient == nil {
		return node.ErrRPCClient
	}
	rpcClient.RegisterHandler("eth_accounts", b.accountManager.AccountsRPCHandler())
	rpcClient.RegisterHandler("eth_sendTransaction", b.txQueueManager.SendTransactionRPCHandler)
	return nil
}

// ConnectionChange handles network state changes logic.
func (b *StatusBackend) ConnectionChange(state ConnectionState) {
	log.Info("Network state change", "old", b.connectionState, "new", state)
	b.connectionState = state

	// logic of handling state changes here
	// restart node? force peers reconnect? etc
}
<|endoftext|>


<commit_before>package nsone

import (
	"fmt"
	"testing"

	"github.com/bobtfish/go-nsone-api"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
)

func TestAccDataFeed_basic(t *testing.T) {
	var dataFeed nsone.DataFeed
	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckDataFeedDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccDataFeed_basic,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckDataFeedState("name", "terraform test"),
					testAccCheckDataFeedExists("nsone_datafeed.foobar", "nsone_datasource.api", &dataFeed),
					testAccCheckDataFeedAttributes(&dataFeed),
				),
			},
		},
	})
}

func TestAccDataFeed_updated(t *testing.T) {
	var dataFeed nsone.DataFeed
	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckDataFeedDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccDataFeed_basic,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckDataFeedState("name", "terraform test"),
					testAccCheckDataFeedExists("nsone_datafeed.foobar", "nsone_datasource.api", &dataFeed),
					testAccCheckDataFeedAttributes(&dataFeed),
				),
			},
			resource.TestStep{
				Config: testAccDataFeed_updated,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckDataFeedState("name", "terraform test"),
					testAccCheckDataFeedExists("nsone_datafeed.foobar", "nsone_datasource.api", &dataFeed),
					testAccCheckDataFeedAttributesUpdated(&dataFeed),
				),
			},
		},
	})
}

func testAccCheckDataFeedState(key, value string) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources["nsone_datafeed.foobar"]
		if !ok {
			return fmt.Errorf("Not found: %s", "nsone_datafeed.foobar")
		}

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

		p := rs.Primary
		if p.Attributes[key] != value {
			return fmt.Errorf(
				"%s != %s (actual: %s)", key, value, p.Attributes[key])
		}

		return nil
	}
}

func testAccCheckDataFeedExists(n string, dsrc string, dataFeed *nsone.DataFeed) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources[n]
		ds, ok := s.RootModule().Resources[dsrc]

		if !ok {
			return fmt.Errorf("Not found: %s", n)
		}

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

		if ds.Primary.ID == "" {
			return fmt.Errorf("NoID is set for the datasource")
		}

		client := testAccProvider.Meta().(*nsone.APIClient)

		foundFeed, err := client.GetDataFeed(ds.Primary.Attributes["id"], rs.Primary.Attributes["id"])

		p := rs.Primary

		if err != nil {
			return err
		}

		if foundFeed.Name != p.Attributes["name"] {
			return fmt.Errorf("DataFeed not found")
		}

		*dataFeed = *foundFeed

		return nil
	}
}

func testAccCheckDataFeedDestroy(s *terraform.State) error {
	client := testAccProvider.Meta().(*nsone.APIClient)

	var dataFeedId string
	var dataSourceId string

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

		if rs.Type == "nsone_datasource" {
			dataSourceId = rs.Primary.Attributes["id"]
		}

		if rs.Type == "nsone_datafeed" {
			dataFeedId = rs.Primary.Attributes["id"]
		}
	}

	df, _ := client.GetDataFeed(dataSourceId, dataFeedId)

	if df.Id != "" {
		return fmt.Errorf("DataFeed still exists")
	}

	return nil
}

func testAccCheckDataFeedAttributes(dataFeed *nsone.DataFeed) resource.TestCheckFunc {
	return func(s *terraform.State) error {

		if dataFeed.Config["label"] != "exampledc2" {
			return fmt.Errorf("Bad value : %s", dataFeed.Config["label"])
		}

		return nil
	}
}

func testAccCheckDataFeedAttributesUpdated(dataFeed *nsone.DataFeed) resource.TestCheckFunc {
	return func(s *terraform.State) error {

		if dataFeed.Config["label"] != "exampledc3" {
			return fmt.Errorf("Bad value : %s", dataFeed.Config["label"])
		}

		return nil
	}
}

const testAccDataFeed_basic = `
resource "nsone_datasource" "api" {
	name = "terraform test"
	sourcetype = "nsone_v1"
}

resource "nsone_datafeed" "foobar" {
	name = "terraform test"
	source_id = "${nsone_datasource.api.id}"
	config {
		label = "exampledc2"
	}
}`

const testAccDataFeed_updated = `
resource "nsone_datasource" "api" {
	name = "terraform test"
	sourcetype = "nsone_v1"
}

resource "nsone_datafeed" "foobar" {
	name = "terraform test"
	source_id = "${nsone_datasource.api.id}"
  config {
		label = "exampledc3"
	}
}`
<commit_msg>Fix condition to clear vet tests<commit_after>package nsone

import (
	"fmt"
	"testing"

	"github.com/bobtfish/go-nsone-api"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
)

func TestAccDataFeed_basic(t *testing.T) {
	var dataFeed nsone.DataFeed
	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckDataFeedDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccDataFeed_basic,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckDataFeedState("name", "terraform test"),
					testAccCheckDataFeedExists("nsone_datafeed.foobar", "nsone_datasource.api", &dataFeed),
					testAccCheckDataFeedAttributes(&dataFeed),
				),
			},
		},
	})
}

func TestAccDataFeed_updated(t *testing.T) {
	var dataFeed nsone.DataFeed
	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckDataFeedDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccDataFeed_basic,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckDataFeedState("name", "terraform test"),
					testAccCheckDataFeedExists("nsone_datafeed.foobar", "nsone_datasource.api", &dataFeed),
					testAccCheckDataFeedAttributes(&dataFeed),
				),
			},
			resource.TestStep{
				Config: testAccDataFeed_updated,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckDataFeedState("name", "terraform test"),
					testAccCheckDataFeedExists("nsone_datafeed.foobar", "nsone_datasource.api", &dataFeed),
					testAccCheckDataFeedAttributesUpdated(&dataFeed),
				),
			},
		},
	})
}

func testAccCheckDataFeedState(key, value string) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources["nsone_datafeed.foobar"]
		if !ok {
			return fmt.Errorf("Not found: %s", "nsone_datafeed.foobar")
		}

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

		p := rs.Primary
		if p.Attributes[key] != value {
			return fmt.Errorf(
				"%s != %s (actual: %s)", key, value, p.Attributes[key])
		}

		return nil
	}
}

func testAccCheckDataFeedExists(n string, dsrc string, dataFeed *nsone.DataFeed) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources[n]
		ds, ok := s.RootModule().Resources[dsrc]

		if !ok {
			return fmt.Errorf("Not found: %s", n)
		}

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

		if ds.Primary.ID == "" {
			return fmt.Errorf("NoID is set for the datasource")
		}

		client := testAccProvider.Meta().(*nsone.APIClient)

		foundFeed, err := client.GetDataFeed(ds.Primary.Attributes["id"], rs.Primary.Attributes["id"])

		p := rs.Primary

		if err != nil {
			return err
		}

		if foundFeed.Name != p.Attributes["name"] {
			return fmt.Errorf("DataFeed not found")
		}

		*dataFeed = *foundFeed

		return nil
	}
}

func testAccCheckDataFeedDestroy(s *terraform.State) error {
	client := testAccProvider.Meta().(*nsone.APIClient)

	var dataFeedId string
	var dataSourceId string

	for _, rs := range s.RootModule().Resources {

		if rs.Type == "nsone_datasource" {
			dataSourceId = rs.Primary.Attributes["id"]
		}

		if rs.Type == "nsone_datafeed" {
			dataFeedId = rs.Primary.Attributes["id"]
		}
	}

	df, _ := client.GetDataFeed(dataSourceId, dataFeedId)

	if df.Id != "" {
		return fmt.Errorf("DataFeed still exists")
	}

	return nil
}

func testAccCheckDataFeedAttributes(dataFeed *nsone.DataFeed) resource.TestCheckFunc {
	return func(s *terraform.State) error {

		if dataFeed.Config["label"] != "exampledc2" {
			return fmt.Errorf("Bad value : %s", dataFeed.Config["label"])
		}

		return nil
	}
}

func testAccCheckDataFeedAttributesUpdated(dataFeed *nsone.DataFeed) resource.TestCheckFunc {
	return func(s *terraform.State) error {

		if dataFeed.Config["label"] != "exampledc3" {
			return fmt.Errorf("Bad value : %s", dataFeed.Config["label"])
		}

		return nil
	}
}

const testAccDataFeed_basic = `
resource "nsone_datasource" "api" {
	name = "terraform test"
	sourcetype = "nsone_v1"
}

resource "nsone_datafeed" "foobar" {
	name = "terraform test"
	source_id = "${nsone_datasource.api.id}"
	config {
		label = "exampledc2"
	}
}`

const testAccDataFeed_updated = `
resource "nsone_datasource" "api" {
	name = "terraform test"
	sourcetype = "nsone_v1"
}

resource "nsone_datafeed" "foobar" {
	name = "terraform test"
	source_id = "${nsone_datasource.api.id}"
  config {
		label = "exampledc3"
	}
}`
<|endoftext|>


<commit_before>package digitalocean

import (
	"fmt"
	"log"
	"strconv"

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

func resourceDigitalOceanSSHKey() *schema.Resource {
	return &schema.Resource{
		Create: resourceDigitalOceanSSHKeyCreate,
		Read:   resourceDigitalOceanSSHKeyRead,
		Update: resourceDigitalOceanSSHKeyUpdate,
		Delete: resourceDigitalOceanSSHKeyDelete,

		Schema: map[string]*schema.Schema{
			"id": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},

			"name": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
			},

			"public_key": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},

			"fingerprint": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},
		},
	}
}

func resourceDigitalOceanSSHKeyCreate(d *schema.ResourceData, meta interface{}) error {
	client := meta.(*godo.Client)

	// Build up our creation options
	opts := &godo.KeyCreateRequest{
		Name:      d.Get("name").(string),
		PublicKey: d.Get("public_key").(string),
	}

	log.Printf("[DEBUG] SSH Key create configuration: %#v", opts)
	key, _, err := client.Keys.Create(opts)
	if err != nil {
		return fmt.Errorf("Error creating SSH Key: %s", err)
	}

	d.SetId(strconv.Itoa(key.ID))
	log.Printf("[INFO] SSH Key: %d", key.ID)

	return resourceDigitalOceanSSHKeyRead(d, meta)
}

func resourceDigitalOceanSSHKeyRead(d *schema.ResourceData, meta interface{}) error {
	client := meta.(*godo.Client)

	id, err := strconv.Atoi(d.Id())
	if err != nil {
		return fmt.Errorf("invalid SSH key id: %v", err)
	}

	key, resp, err := client.Keys.GetByID(id)
	if err != nil {
		// If the key is somehow already destroyed, mark as
		// successfully gone
		if resp.StatusCode == 404 {
			d.SetId("")
			return nil
		}

		return fmt.Errorf("Error retrieving SSH key: %s", err)
	}

	d.Set("name", key.Name)
	d.Set("fingerprint", key.Fingerprint)

	return nil
}

func resourceDigitalOceanSSHKeyUpdate(d *schema.ResourceData, meta interface{}) error {
	client := meta.(*godo.Client)

	id, err := strconv.Atoi(d.Id())
	if err != nil {
		return fmt.Errorf("invalid SSH key id: %v", err)
	}

	var newName string
	if v, ok := d.GetOk("name"); ok {
		newName = v.(string)
	}

	log.Printf("[DEBUG] SSH key update name: %#v", newName)
	opts := &godo.KeyUpdateRequest{
		Name: newName,
	}
	_, _, err = client.Keys.UpdateByID(id, opts)
	if err != nil {
		return fmt.Errorf("Failed to update SSH key: %s", err)
	}

	return resourceDigitalOceanSSHKeyRead(d, meta)
}

func resourceDigitalOceanSSHKeyDelete(d *schema.ResourceData, meta interface{}) error {
	client := meta.(*godo.Client)

	id, err := strconv.Atoi(d.Id())
	if err != nil {
		return fmt.Errorf("invalid SSH key id: %v", err)
	}

	log.Printf("[INFO] Deleting SSH key: %d", id)
	_, err = client.Keys.DeleteByID(id)
	if err != nil {
		return fmt.Errorf("Error deleting SSH key: %s", err)
	}

	d.SetId("")
	return nil
}
<commit_msg>provider/digitalocean: Check for nil response<commit_after>package digitalocean

import (
	"fmt"
	"log"
	"strconv"

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

func resourceDigitalOceanSSHKey() *schema.Resource {
	return &schema.Resource{
		Create: resourceDigitalOceanSSHKeyCreate,
		Read:   resourceDigitalOceanSSHKeyRead,
		Update: resourceDigitalOceanSSHKeyUpdate,
		Delete: resourceDigitalOceanSSHKeyDelete,

		Schema: map[string]*schema.Schema{
			"id": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},

			"name": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
			},

			"public_key": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},

			"fingerprint": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},
		},
	}
}

func resourceDigitalOceanSSHKeyCreate(d *schema.ResourceData, meta interface{}) error {
	client := meta.(*godo.Client)

	// Build up our creation options
	opts := &godo.KeyCreateRequest{
		Name:      d.Get("name").(string),
		PublicKey: d.Get("public_key").(string),
	}

	log.Printf("[DEBUG] SSH Key create configuration: %#v", opts)
	key, _, err := client.Keys.Create(opts)
	if err != nil {
		return fmt.Errorf("Error creating SSH Key: %s", err)
	}

	d.SetId(strconv.Itoa(key.ID))
	log.Printf("[INFO] SSH Key: %d", key.ID)

	return resourceDigitalOceanSSHKeyRead(d, meta)
}

func resourceDigitalOceanSSHKeyRead(d *schema.ResourceData, meta interface{}) error {
	client := meta.(*godo.Client)

	id, err := strconv.Atoi(d.Id())
	if err != nil {
		return fmt.Errorf("invalid SSH key id: %v", err)
	}

	key, resp, err := client.Keys.GetByID(id)
	if err != nil {
		// If the key is somehow already destroyed, mark as
		// successfully gone
		if resp != nil && resp.StatusCode == 404 {
			d.SetId("")
			return nil
		}

		return fmt.Errorf("Error retrieving SSH key: %s", err)
	}

	d.Set("name", key.Name)
	d.Set("fingerprint", key.Fingerprint)

	return nil
}

func resourceDigitalOceanSSHKeyUpdate(d *schema.ResourceData, meta interface{}) error {
	client := meta.(*godo.Client)

	id, err := strconv.Atoi(d.Id())
	if err != nil {
		return fmt.Errorf("invalid SSH key id: %v", err)
	}

	var newName string
	if v, ok := d.GetOk("name"); ok {
		newName = v.(string)
	}

	log.Printf("[DEBUG] SSH key update name: %#v", newName)
	opts := &godo.KeyUpdateRequest{
		Name: newName,
	}
	_, _, err = client.Keys.UpdateByID(id, opts)
	if err != nil {
		return fmt.Errorf("Failed to update SSH key: %s", err)
	}

	return resourceDigitalOceanSSHKeyRead(d, meta)
}

func resourceDigitalOceanSSHKeyDelete(d *schema.ResourceData, meta interface{}) error {
	client := meta.(*godo.Client)

	id, err := strconv.Atoi(d.Id())
	if err != nil {
		return fmt.Errorf("invalid SSH key id: %v", err)
	}

	log.Printf("[INFO] Deleting SSH key: %d", id)
	_, err = client.Keys.DeleteByID(id)
	if err != nil {
		return fmt.Errorf("Error deleting SSH key: %s", err)
	}

	d.SetId("")
	return nil
}
<|endoftext|>


<commit_before>package auth

import (
	"crypto/tls"
	"encoding/json"
	"net/http"
	"net/url"

	"github.com/gravitational/teleport"
	"github.com/gravitational/teleport/lib/httplib"
	"github.com/gravitational/teleport/lib/services"

	"github.com/gravitational/roundtrip"
	"github.com/gravitational/trace"

	log "github.com/sirupsen/logrus"
)

// UpsertTrustedCluster will either create a new services.TrustedCluster or
// can be used to toggle a services.TrustedCluster on and off.
func (a *AuthServer) UpsertTrustedCluster(t services.TrustedCluster) error {
	// check if the trusted cluster exists already
	var exists bool
	_, err := a.Presence.GetTrustedCluster(t.GetName())
	if err == nil {
		exists = true
	}

	// if the trusted cluster does not exist, do the initial token exchange
	// to establish trust relationship and return.
	if !exists {
		err = a.establishTrust(t)
		if err != nil {
			return trace.Wrap(err)
		}

		err = a.Presence.UpsertTrustedCluster(t)
		if err != nil {
			return trace.Wrap(err)
		}

		return nil
	}

	// if the trusted cluster exists already, the user is just trying to toggle
	// the trusted cluster
	if t.GetEnabled() {
		err = a.EnableTrustedCluster(t)
		if err != nil {
			return trace.Wrap(err)
		}
	} else {
		err = a.DisableTrustedCluster(t)
		if err != nil {
			return trace.Wrap(err)
		}
	}

	return nil
}

// DeleteTrustedCluster removes services.CertAuthority, services.ReverseTunnel,
// and services.TrustedCluster resources.
func (a *AuthServer) DeleteTrustedCluster(name string) error {
	err := a.DeleteCertAuthority(services.CertAuthID{Type: services.HostCA, DomainName: name})
	if err != nil {
		if !trace.IsNotFound(err) {
			return trace.Wrap(err)
		}
	}

	err = a.DeleteCertAuthority(services.CertAuthID{Type: services.UserCA, DomainName: name})
	if err != nil {
		if !trace.IsNotFound(err) {
			return trace.Wrap(err)
		}
	}

	err = a.DeleteReverseTunnel(name)
	if err != nil {
		if !trace.IsNotFound(err) {
			return trace.Wrap(err)
		}
	}

	err = a.Presence.DeleteTrustedCluster(name)
	if err != nil {
		if !trace.IsNotFound(err) {
			return trace.Wrap(err)
		}
	}

	return nil
}

// EnableTrustedCluster will enable a TrustedCluster that is already in the backend.
func (a *AuthServer) EnableTrustedCluster(trustedCluster services.TrustedCluster) error {
	err := a.ActivateCertAuthority(services.CertAuthID{Type: services.UserCA, DomainName: trustedCluster.GetName()})
	if err != nil {
		return trace.Wrap(err)
	}

	err = a.ActivateCertAuthority(services.CertAuthID{Type: services.HostCA, DomainName: trustedCluster.GetName()})
	if err != nil {
		return trace.Wrap(err)
	}

	// the remote auth server has verified our token. add the
	// reverse tunnel into our backend
	reverseTunnel := services.NewReverseTunnel(
		trustedCluster.GetName(),
		[]string{trustedCluster.GetReverseTunnelAddress()},
	)
	err = a.UpsertReverseTunnel(reverseTunnel)
	if err != nil {
		return trace.Wrap(err)
	}

	err = a.Presence.EnableTrustedCluster(trustedCluster)
	if err != nil {
		return trace.Wrap(err)
	}

	return nil
}

// DisableTrustedCluster will disable a TrustedCluster that is already in the backend.
func (a *AuthServer) DisableTrustedCluster(trustedCluster services.TrustedCluster) error {
	err := a.DeactivateCertAuthority(services.CertAuthID{Type: services.UserCA, DomainName: trustedCluster.GetName()})
	if err != nil {
		return trace.Wrap(err)
	}

	err = a.DeactivateCertAuthority(services.CertAuthID{Type: services.HostCA, DomainName: trustedCluster.GetName()})
	if err != nil {
		return trace.Wrap(err)
	}

	err = a.DeleteReverseTunnel(trustedCluster.GetName())
	if err != nil {
		return trace.Wrap(err)
	}

	err = a.Presence.DisableTrustedCluster(trustedCluster)
	if err != nil {
		return trace.Wrap(err)
	}

	return nil
}

func (a *AuthServer) establishTrust(trustedCluster services.TrustedCluster) error {
	var localCertAuthorities []services.CertAuthority

	domainName, err := a.GetDomainName()
	if err != nil {
		return trace.Wrap(err)
	}

	// get a list of certificate authorities for this auth server
	allLocalCAs, err := a.GetCertAuthorities(services.HostCA, false)
	if err != nil {
		return trace.Wrap(err)
	}
	for _, lca := range allLocalCAs {
		if lca.GetClusterName() == domainName {
			localCertAuthorities = append(localCertAuthorities, lca)
		}
	}

	// create a request to validate a trusted cluster (token and local certificate authorities)
	validateRequest := ValidateTrustedClusterRequest{
		Token: trustedCluster.GetToken(),
		CAs:   localCertAuthorities,
	}

	// log the local certificate authorities that we are sending
	log.Debugf("[TRUSTED CLUSTER] Sending validate request; token=%v, CAs=%v", validateRequest.Token, validateRequest.CAs)

	// send the request to the remote auth server via the proxy
	validateResponse, err := a.sendValidateRequestToProxy(trustedCluster.GetProxyAddress(), &validateRequest)
	if err != nil {
		return trace.Wrap(err)
	}

	// log the remote certificate authorities we are adding
	log.Debugf("[TRUSTED CLUSTER] Received validate response; CAs=%v", validateResponse.CAs)

	// the remote auth server has verified our token. add the
	// remote certificate authority to our backend
	for _, remoteCertAuthority := range validateResponse.CAs {
		// add roles into user certificates
		// ignore roles set locally by the cert authority
		remoteCertAuthority.SetRoles(nil)
		if remoteCertAuthority.GetType() == services.UserCA {
			for _, r := range trustedCluster.GetRoles() {
				remoteCertAuthority.AddRole(r)
			}
			remoteCertAuthority.SetRoleMap(trustedCluster.GetRoleMap())
		}

		err = a.UpsertCertAuthority(remoteCertAuthority)
		if err != nil {
			return trace.Wrap(err)
		}
	}

	// the remote auth server has verified our token. add the
	// reverse tunnel into our backend
	reverseTunnel := services.NewReverseTunnel(
		trustedCluster.GetName(),
		[]string{trustedCluster.GetReverseTunnelAddress()},
	)
	err = a.UpsertReverseTunnel(reverseTunnel)
	if err != nil {
		return trace.Wrap(err)
	}

	return nil
}

func (a *AuthServer) validateTrustedCluster(validateRequest *ValidateTrustedClusterRequest) (*ValidateTrustedClusterResponse, error) {
	domainName, err := a.GetDomainName()
	if err != nil {
		return nil, trace.Wrap(err)
	}

	// validate that we generated the token
	err = a.validateTrustedClusterToken(validateRequest.Token)
	if err != nil {
		return nil, trace.Wrap(err)
	}

	// log the remote certificate authorities we are adding
	log.Debugf("[TRUSTED CLUSTER] Received validate request: token=%v, CAs=%v", validateRequest.Token, validateRequest.CAs)

	// token has been validated, upsert the given certificate authority
	for _, certAuthority := range validateRequest.CAs {
		err = a.UpsertCertAuthority(certAuthority)
		if err != nil {
			return nil, trace.Wrap(err)
		}
	}

	// export our certificate authority and return it to the cluster
	validateResponse := ValidateTrustedClusterResponse{
		CAs: []services.CertAuthority{},
	}
	for _, caType := range []services.CertAuthType{services.HostCA, services.UserCA} {
		certAuthorities, err := a.GetCertAuthorities(caType, false)
		if err != nil {
			return nil, trace.Wrap(err)
		}

		for _, certAuthority := range certAuthorities {
			if certAuthority.GetClusterName() == domainName {
				validateResponse.CAs = append(validateResponse.CAs, certAuthority)
			}
		}
	}

	// log the local certificate authorities we are sending
	log.Debugf("[TRUSTED CLUSTER] Sending validate response: CAs=%v", validateResponse.CAs)

	return &validateResponse, nil
}

func (a *AuthServer) validateTrustedClusterToken(token string) error {
	roles, err := a.ValidateToken(token)
	if err != nil {
		return trace.AccessDenied("invalid token")
	}

	if !roles.Include(teleport.RoleTrustedCluster) {
		return trace.AccessDenied("role does not match")
	}

	if !a.checkTokenTTL(token) {
		return trace.AccessDenied("expired token")
	}

	return nil
}

func (s *AuthServer) sendValidateRequestToProxy(host string, validateRequest *ValidateTrustedClusterRequest) (*ValidateTrustedClusterResponse, error) {
	proxyAddr := url.URL{
		Scheme: "https",
		Host:   host,
	}

	var opts []roundtrip.ClientParam
	if s.DeveloperMode {
		log.Warn("InsecureSkipVerify used to communicate with proxy.")
		log.Warn("Make sure you intend to run Teleport in debug mode.")

		// get the default transport (so we can get the proxy from environment)
		// but disable tls certificate checking.
		tr, ok := http.DefaultTransport.(*http.Transport)
		if !ok {
			return nil, trace.BadParameter("unable to get default transport")
		}
		tr.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}

		insecureWebClient := &http.Client{
			Transport: tr,
		}
		opts = append(opts, roundtrip.HTTPClient(insecureWebClient))
	}

	clt, err := roundtrip.NewClient(proxyAddr.String(), teleport.WebAPIVersion, opts...)
	if err != nil {
		return nil, trace.Wrap(err)
	}

	validateRequestRaw, err := validateRequest.ToRaw()
	if err != nil {
		return nil, trace.Wrap(err)
	}

	out, err := httplib.ConvertResponse(clt.PostJSON(clt.Endpoint("webapi", "trustedclusters", "validate"), validateRequestRaw))
	if err != nil {
		return nil, trace.Wrap(err)
	}

	var validateResponseRaw *ValidateTrustedClusterResponseRaw
	err = json.Unmarshal(out.Bytes(), &validateResponseRaw)
	if err != nil {
		return nil, trace.Wrap(err)
	}

	validateResponse, err := validateResponseRaw.ToNative()
	if err != nil {
		return nil, trace.Wrap(err)
	}

	return validateResponse, nil
}

type ValidateTrustedClusterRequest struct {
	Token string                   `json:"token"`
	CAs   []services.CertAuthority `json:"certificate_authorities"`
}

func (v *ValidateTrustedClusterRequest) ToRaw() (*ValidateTrustedClusterRequestRaw, error) {
	cas := [][]byte{}

	for _, certAuthority := range v.CAs {
		data, err := services.GetCertAuthorityMarshaler().MarshalCertAuthority(certAuthority)
		if err != nil {
			return nil, trace.Wrap(err)
		}

		cas = append(cas, data)
	}

	return &ValidateTrustedClusterRequestRaw{
		Token: v.Token,
		CAs:   cas,
	}, nil
}

type ValidateTrustedClusterRequestRaw struct {
	Token string   `json:"token"`
	CAs   [][]byte `json:"certificate_authorities"`
}

func (v *ValidateTrustedClusterRequestRaw) ToNative() (*ValidateTrustedClusterRequest, error) {
	cas := []services.CertAuthority{}

	for _, rawCertAuthority := range v.CAs {
		certAuthority, err := services.GetCertAuthorityMarshaler().UnmarshalCertAuthority(rawCertAuthority)
		if err != nil {
			return nil, trace.Wrap(err)
		}

		cas = append(cas, certAuthority)
	}

	return &ValidateTrustedClusterRequest{
		Token: v.Token,
		CAs:   cas,
	}, nil
}

type ValidateTrustedClusterResponse struct {
	CAs []services.CertAuthority `json:"certificate_authorities"`
}

func (v *ValidateTrustedClusterResponse) ToRaw() (*ValidateTrustedClusterResponseRaw, error) {
	cas := [][]byte{}

	for _, certAuthority := range v.CAs {
		data, err := services.GetCertAuthorityMarshaler().MarshalCertAuthority(certAuthority)
		if err != nil {
			return nil, trace.Wrap(err)
		}

		cas = append(cas, data)
	}

	return &ValidateTrustedClusterResponseRaw{
		CAs: cas,
	}, nil
}

type ValidateTrustedClusterResponseRaw struct {
	CAs [][]byte `json:"certificate_authorities"`
}

func (v *ValidateTrustedClusterResponseRaw) ToNative() (*ValidateTrustedClusterResponse, error) {
	cas := []services.CertAuthority{}

	for _, rawCertAuthority := range v.CAs {
		certAuthority, err := services.GetCertAuthorityMarshaler().UnmarshalCertAuthority(rawCertAuthority)
		if err != nil {
			return nil, trace.Wrap(err)
		}

		cas = append(cas, certAuthority)
	}

	return &ValidateTrustedClusterResponse{
		CAs: cas,
	}, nil
}
<commit_msg>Minor code changes: better error messages + comments<commit_after>/*
Copyright 2017 Gravitational, Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

*/

package auth

import (
	"crypto/tls"
	"encoding/json"
	"net/http"
	"net/url"

	"github.com/gravitational/teleport"
	"github.com/gravitational/teleport/lib/httplib"
	"github.com/gravitational/teleport/lib/services"

	"github.com/gravitational/roundtrip"
	"github.com/gravitational/trace"

	log "github.com/sirupsen/logrus"
)

// UpsertTrustedCluster will either create a new services.TrustedCluster or
// can be used to toggle a services.TrustedCluster on and off.
func (a *AuthServer) UpsertTrustedCluster(t services.TrustedCluster) error {
	// check if the trusted cluster exists already
	var exists bool
	_, err := a.Presence.GetTrustedCluster(t.GetName())
	if err == nil {
		exists = true
	}

	// if the trusted cluster does not exist, do the initial token exchange
	// to establish trust relationship and return.
	if !exists {
		err = a.establishTrust(t)
		if err != nil {
			return trace.Wrap(err)
		}

		err = a.Presence.UpsertTrustedCluster(t)
		if err != nil {
			return trace.Wrap(err)
		}

		return nil
	}

	// if the trusted cluster exists already, the user is just trying to toggle
	// the trusted cluster
	if t.GetEnabled() {
		err = a.EnableTrustedCluster(t)
		if err != nil {
			return trace.Wrap(err)
		}
	} else {
		err = a.DisableTrustedCluster(t)
		if err != nil {
			return trace.Wrap(err)
		}
	}

	return nil
}

// DeleteTrustedCluster removes services.CertAuthority, services.ReverseTunnel,
// and services.TrustedCluster resources.
func (a *AuthServer) DeleteTrustedCluster(name string) error {
	err := a.DeleteCertAuthority(services.CertAuthID{Type: services.HostCA, DomainName: name})
	if err != nil {
		if !trace.IsNotFound(err) {
			return trace.Wrap(err)
		}
	}

	err = a.DeleteCertAuthority(services.CertAuthID{Type: services.UserCA, DomainName: name})
	if err != nil {
		if !trace.IsNotFound(err) {
			return trace.Wrap(err)
		}
	}

	err = a.DeleteReverseTunnel(name)
	if err != nil {
		if !trace.IsNotFound(err) {
			return trace.Wrap(err)
		}
	}

	err = a.Presence.DeleteTrustedCluster(name)
	if err != nil {
		if !trace.IsNotFound(err) {
			return trace.Wrap(err)
		}
	}

	return nil
}

// EnableTrustedCluster will enable a TrustedCluster that is already in the backend.
func (a *AuthServer) EnableTrustedCluster(trustedCluster services.TrustedCluster) error {
	err := a.ActivateCertAuthority(services.CertAuthID{Type: services.UserCA, DomainName: trustedCluster.GetName()})
	if err != nil {
		return trace.Wrap(err)
	}

	err = a.ActivateCertAuthority(services.CertAuthID{Type: services.HostCA, DomainName: trustedCluster.GetName()})
	if err != nil {
		return trace.Wrap(err)
	}

	// the remote auth server has verified our token. add the
	// reverse tunnel into our backend
	reverseTunnel := services.NewReverseTunnel(
		trustedCluster.GetName(),
		[]string{trustedCluster.GetReverseTunnelAddress()},
	)
	err = a.UpsertReverseTunnel(reverseTunnel)
	if err != nil {
		return trace.Wrap(err)
	}

	err = a.Presence.EnableTrustedCluster(trustedCluster)
	if err != nil {
		return trace.Wrap(err)
	}

	return nil
}

// DisableTrustedCluster will disable a TrustedCluster that is already in the backend.
func (a *AuthServer) DisableTrustedCluster(trustedCluster services.TrustedCluster) error {
	err := a.DeactivateCertAuthority(services.CertAuthID{Type: services.UserCA, DomainName: trustedCluster.GetName()})
	if err != nil {
		return trace.Wrap(err)
	}

	err = a.DeactivateCertAuthority(services.CertAuthID{Type: services.HostCA, DomainName: trustedCluster.GetName()})
	if err != nil {
		return trace.Wrap(err)
	}

	err = a.DeleteReverseTunnel(trustedCluster.GetName())
	if err != nil {
		return trace.Wrap(err)
	}

	err = a.Presence.DisableTrustedCluster(trustedCluster)
	if err != nil {
		return trace.Wrap(err)
	}

	return nil
}

func (a *AuthServer) establishTrust(trustedCluster services.TrustedCluster) error {
	var localCertAuthorities []services.CertAuthority

	domainName, err := a.GetDomainName()
	if err != nil {
		return trace.Wrap(err)
	}

	// get a list of certificate authorities for this auth server
	allLocalCAs, err := a.GetCertAuthorities(services.HostCA, false)
	if err != nil {
		return trace.Wrap(err)
	}
	for _, lca := range allLocalCAs {
		if lca.GetClusterName() == domainName {
			localCertAuthorities = append(localCertAuthorities, lca)
		}
	}

	// create a request to validate a trusted cluster (token and local certificate authorities)
	validateRequest := ValidateTrustedClusterRequest{
		Token: trustedCluster.GetToken(),
		CAs:   localCertAuthorities,
	}

	// log the local certificate authorities that we are sending
	log.Debugf("[TRUSTED CLUSTER] Sending validate request; token=%v, CAs=%v", validateRequest.Token, validateRequest.CAs)

	// send the request to the remote auth server via the proxy
	validateResponse, err := a.sendValidateRequestToProxy(trustedCluster.GetProxyAddress(), &validateRequest)
	if err != nil {
		return trace.Wrap(err)
	}

	// log the remote certificate authorities we are adding
	log.Debugf("[TRUSTED CLUSTER] Received validate response; CAs=%v", validateResponse.CAs)

	// the remote auth server has verified our token. add the
	// remote certificate authority to our backend
	for _, remoteCertAuthority := range validateResponse.CAs {
		// add roles into user certificates
		// ignore roles set locally by the cert authority
		remoteCertAuthority.SetRoles(nil)
		if remoteCertAuthority.GetType() == services.UserCA {
			for _, r := range trustedCluster.GetRoles() {
				remoteCertAuthority.AddRole(r)
			}
			remoteCertAuthority.SetRoleMap(trustedCluster.GetRoleMap())
		}

		err = a.UpsertCertAuthority(remoteCertAuthority)
		if err != nil {
			return trace.Wrap(err)
		}
	}

	// the remote auth server has verified our token. add the
	// reverse tunnel into our backend
	reverseTunnel := services.NewReverseTunnel(
		trustedCluster.GetName(),
		[]string{trustedCluster.GetReverseTunnelAddress()},
	)
	err = a.UpsertReverseTunnel(reverseTunnel)
	if err != nil {
		return trace.Wrap(err)
	}

	return nil
}

func (a *AuthServer) validateTrustedCluster(validateRequest *ValidateTrustedClusterRequest) (*ValidateTrustedClusterResponse, error) {
	domainName, err := a.GetDomainName()
	if err != nil {
		return nil, trace.Wrap(err)
	}

	// validate that we generated the token
	err = a.validateTrustedClusterToken(validateRequest.Token)
	if err != nil {
		return nil, trace.Wrap(err)
	}

	// log the remote certificate authorities we are adding
	log.Debugf("[TRUSTED CLUSTER] Received validate request: token=%v, CAs=%v", validateRequest.Token, validateRequest.CAs)

	// token has been validated, upsert the given certificate authority
	for _, certAuthority := range validateRequest.CAs {
		err = a.UpsertCertAuthority(certAuthority)
		if err != nil {
			return nil, trace.Wrap(err)
		}
	}

	// export our certificate authority and return it to the cluster
	validateResponse := ValidateTrustedClusterResponse{
		CAs: []services.CertAuthority{},
	}
	for _, caType := range []services.CertAuthType{services.HostCA, services.UserCA} {
		certAuthorities, err := a.GetCertAuthorities(caType, false)
		if err != nil {
			return nil, trace.Wrap(err)
		}

		for _, certAuthority := range certAuthorities {
			if certAuthority.GetClusterName() == domainName {
				validateResponse.CAs = append(validateResponse.CAs, certAuthority)
			}
		}
	}

	// log the local certificate authorities we are sending
	log.Debugf("[TRUSTED CLUSTER] Sending validate response: CAs=%v", validateResponse.CAs)

	return &validateResponse, nil
}

func (a *AuthServer) validateTrustedClusterToken(token string) error {
	roles, err := a.ValidateToken(token)
	if err != nil {
		return trace.AccessDenied("invalid token")
	}

	if !roles.Include(teleport.RoleTrustedCluster) {
		return trace.AccessDenied("role does not match")
	}

	if !a.checkTokenTTL(token) {
		return trace.AccessDenied("expired token")
	}

	return nil
}

func (s *AuthServer) sendValidateRequestToProxy(host string, validateRequest *ValidateTrustedClusterRequest) (*ValidateTrustedClusterResponse, error) {
	proxyAddr := url.URL{
		Scheme: "https",
		Host:   host,
	}

	var opts []roundtrip.ClientParam
	if s.DeveloperMode {
		log.Warn("insecureSkipVerify is used to communicate with proxy. make sure you intend to run Teleport in insecure mode!")

		// get the default transport (so we can get the proxy from environment)
		// but disable tls certificate checking.
		tr, ok := http.DefaultTransport.(*http.Transport)
		if !ok {
			return nil, trace.BadParameter("unable to get default transport")
		}
		tr.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}

		insecureWebClient := &http.Client{
			Transport: tr,
		}
		opts = append(opts, roundtrip.HTTPClient(insecureWebClient))
	}

	clt, err := roundtrip.NewClient(proxyAddr.String(), teleport.WebAPIVersion, opts...)
	if err != nil {
		return nil, trace.Wrap(err)
	}

	validateRequestRaw, err := validateRequest.ToRaw()
	if err != nil {
		return nil, trace.Wrap(err)
	}

	out, err := httplib.ConvertResponse(clt.PostJSON(clt.Endpoint("webapi", "trustedclusters", "validate"), validateRequestRaw))
	if err != nil {
		return nil, trace.Wrap(err)
	}

	var validateResponseRaw *ValidateTrustedClusterResponseRaw
	err = json.Unmarshal(out.Bytes(), &validateResponseRaw)
	if err != nil {
		return nil, trace.Wrap(err)
	}

	validateResponse, err := validateResponseRaw.ToNative()
	if err != nil {
		return nil, trace.Wrap(err)
	}

	return validateResponse, nil
}

type ValidateTrustedClusterRequest struct {
	Token string                   `json:"token"`
	CAs   []services.CertAuthority `json:"certificate_authorities"`
}

func (v *ValidateTrustedClusterRequest) ToRaw() (*ValidateTrustedClusterRequestRaw, error) {
	cas := [][]byte{}

	for _, certAuthority := range v.CAs {
		data, err := services.GetCertAuthorityMarshaler().MarshalCertAuthority(certAuthority)
		if err != nil {
			return nil, trace.Wrap(err)
		}

		cas = append(cas, data)
	}

	return &ValidateTrustedClusterRequestRaw{
		Token: v.Token,
		CAs:   cas,
	}, nil
}

type ValidateTrustedClusterRequestRaw struct {
	Token string   `json:"token"`
	CAs   [][]byte `json:"certificate_authorities"`
}

func (v *ValidateTrustedClusterRequestRaw) ToNative() (*ValidateTrustedClusterRequest, error) {
	cas := []services.CertAuthority{}

	for _, rawCertAuthority := range v.CAs {
		certAuthority, err := services.GetCertAuthorityMarshaler().UnmarshalCertAuthority(rawCertAuthority)
		if err != nil {
			return nil, trace.Wrap(err)
		}

		cas = append(cas, certAuthority)
	}

	return &ValidateTrustedClusterRequest{
		Token: v.Token,
		CAs:   cas,
	}, nil
}

type ValidateTrustedClusterResponse struct {
	CAs []services.CertAuthority `json:"certificate_authorities"`
}

func (v *ValidateTrustedClusterResponse) ToRaw() (*ValidateTrustedClusterResponseRaw, error) {
	cas := [][]byte{}

	for _, certAuthority := range v.CAs {
		data, err := services.GetCertAuthorityMarshaler().MarshalCertAuthority(certAuthority)
		if err != nil {
			return nil, trace.Wrap(err)
		}

		cas = append(cas, data)
	}

	return &ValidateTrustedClusterResponseRaw{
		CAs: cas,
	}, nil
}

type ValidateTrustedClusterResponseRaw struct {
	CAs [][]byte `json:"certificate_authorities"`
}

func (v *ValidateTrustedClusterResponseRaw) ToNative() (*ValidateTrustedClusterResponse, error) {
	cas := []services.CertAuthority{}

	for _, rawCertAuthority := range v.CAs {
		certAuthority, err := services.GetCertAuthorityMarshaler().UnmarshalCertAuthority(rawCertAuthority)
		if err != nil {
			return nil, trace.Wrap(err)
		}

		cas = append(cas, certAuthority)
	}

	return &ValidateTrustedClusterResponse{
		CAs: cas,
	}, nil
}
<|endoftext|>


<commit_before>package logs

import (
	"encoding/json"
	_ "encoding/xml"
	"fmt"
	"github.com/crowdmob/goamz/aws"
	"io/ioutil"
	"log"
	"net/http"
	"sort"
	"strings"
	"time"
)

const debug = false

type CloudWatchLogs struct {
	Endpoint string
	Auth     aws.Auth
	Region   aws.Region
}

// Create a new CloudWatchLogs object for a given namespace
func New(auth aws.Auth, endpoint string, region string) (*CloudWatchLogs, error) {
	return &CloudWatchLogs{
		Endpoint: endpoint,
		Auth:     auth,
		Region:   aws.Region{Name: region},
	}, nil
}

func buildError(r *http.Response, jsonBody []byte) error {
	kinesisError := &Error{
		StatusCode: r.StatusCode,
		Status:     r.Status,
	}

	err := json.Unmarshal(jsonBody, kinesisError)
	if err != nil {
		log.Printf("Failed to parse body as JSON")
		return err
	}

	return kinesisError
}

// Error represents an error in an operation with Kinesis(following goamz/Dynamodb)
type Error struct {
	StatusCode int // HTTP status code (200, 403, ...)
	Status     string
	Code       string `json:"__type"`
	Message    string `json:"message"`
}

func (e Error) Error() string {
	return fmt.Sprintf("[HTTP %d] %s : %s\n", e.StatusCode, e.Code, e.Message)
}

func (k *CloudWatchLogs) query(target string, payload interface{}) ([]byte, error) {

	jsonBody, _ := json.Marshal(payload)

	data := strings.NewReader(string(jsonBody))
	hreq, err := http.NewRequest("POST", k.Endpoint+"/", data)

	if err != nil {
		return nil, err
	}

	hreq.Header.Set("Content-Type", "application/x-amz-json-1.1")
	hreq.Header.Set("X-Amz-Date", time.Now().UTC().Format(aws.ISO8601BasicFormat))
	hreq.Header.Set("X-Amz-Target", target)

	signer := aws.NewV4Signer(k.Auth, "logs", k.Region)
	signer.Sign(hreq)

	resp, err := http.DefaultClient.Do(hreq)

	if err != nil {
		log.Printf("Error calling Amazon\n: %v", err)
		return nil, err
	}

	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Printf("Could not read response body\n")
		return nil, err
	}

	if resp.StatusCode != 200 {
		err = buildError(resp, body)
		return nil, err
	}

	return body, nil
}

type LogGroup struct {
	Arn               string
	CreationTime      int64
	LogGroupName      string
	MetricFilterCount int
	RetentionInDays   int
	StoredBytes       int64
}

type DescribeLogGroupsResponse struct {
	NextToken string
	LogGroups []*LogGroup
}

type DescribeLogGroupsRequest struct {
	Limit              string
	LogGroupNamePrefix string
	NextToken          string
}

func (c *CloudWatchLogs) DescribeLogGroups(req *DescribeLogGroupsRequest) (r []*LogGroup, err error) {
	data, err := c.query("Logs_20140328.DescribeLogGroups", req)
	if err != nil {
		fmt.Printf("%v\n", err)
		return nil, err
	}
	var result DescribeLogGroupsResponse
	json.Unmarshal(data, &result)
	return result.LogGroups, nil
}

type LogStream struct {
	Arn                 string
	CreationTime        int64
	FirstEventTimestamp int64
	LastEventTimestamp  int64
	LastIngestionTime   int64
	LogStreamName       string
	StoredBytes         int64
	UploadSequenceToken string
}

type DescribeLogStreamsResponse struct {
	NextToken  string
	LogStreams []*LogStream
}

type DescribeLogStreamsRequest struct {
	Limit               int    `json:"limit,omitempty"`
	LogGroupName        string `json:"logGroupName,omitempty"`
	LogStreamNamePrefix string `json:"logStreamNamePrefix,omitempty"`
	NextToken           string `json:"nextToken,omitempty"`
}

func (c *CloudWatchLogs) DescribeLogStreams(req *DescribeLogStreamsRequest) (r []*LogStream, err error) {
	data, err := c.query("Logs_20140328.DescribeLogStreams", req)
	if err != nil {
		fmt.Printf("%v\n", err)
		return nil, err
	}
	var result DescribeLogStreamsResponse
	json.Unmarshal(data, &result)
	if len(result.NextToken) > 0 {
		req.NextToken = result.NextToken
		return c.DescribeLogStreams(req)
	}
	return result.LogStreams, nil
}

type Event struct {
	IngestionTime int
	Message       string
	Timestamp     int64
}

type GetLogEventsResponse struct {
	Events            []*Event
	NextForwardToken  string
	NextBackwardToken string
}

type GetLogEventsRequest struct {
	Limit         int    `json:"limit,omitempty"`
	EndTime       int64  `json:"endTime,omitempty"`
	LogGroupName  string `json:"logGroupName,omitempty"`
	LogStreamName string `json:"logStreamName,omitempty"`
	NextToken     string `json:"nextToken,omitempty"`
	StartFromHead bool   `json:"startFromHead"`
	StartTime     int64  `json:"startTime"`
}

func (c *CloudWatchLogs) GetLogEvents(req *GetLogEventsRequest) (r *GetLogEventsResponse, err error) {
	data, err := c.query("Logs_20140328.GetLogEvents", req)
	if err != nil {
		return nil, err
	}
	var result GetLogEventsResponse
	json.Unmarshal(data, &result)
	return &result, nil
}

type CreateLogGroupRequest struct {
	LogGroupName string `json:"logGroupName"`
}

func (c *CloudWatchLogs) CreateLogGroup(req *CreateLogGroupRequest) error {
	_, err := c.query("Logs_20140328.CreateLogGroup", req)
	if err != nil {
		return err
	}
	return nil
}

type CreateLogStreamRequest struct {
	LogGroupName  string `json:"logGroupName"`
	LogStreamName string `json:"logStreamName"`
}

func (c *CloudWatchLogs) CreateLogStream(req *CreateLogStreamRequest) error {
	_, err := c.query("Logs_20140328.CreateLogStream", req)
	if err != nil {
		return err
	}
	return nil
}

type LogEvent struct {
	Message   string `json:"message"`
	Timestamp int64  `json:"timestamp"`
}

type ByTimestamp []LogEvent

func (events ByTimestamp) Len() int           { return len(events) }
func (events ByTimestamp) Swap(i, j int)      { events[i], events[j] = events[j], events[i] }
func (events ByTimestamp) Less(i, j int) bool { return events[i].Timestamp < events[j].Timestamp }

type PutLogEventsRequest struct {
	LogEvents     []LogEvent `json:"logEvents"`
	LogGroupName  string     `json:"logGroupName"`
	LogStreamName string     `json:"logStreamName"`
	SequenceToken string     `json:"sequenceToken,omitempty"`
}

type PutLogEventsResponse struct {
	NextSequenceToken string `json:"nextSequenceToken"`
}

func (c *CloudWatchLogs) PutLogEvents(req *PutLogEventsRequest) (string, error) {
	sort.Sort(ByTimestamp(req.LogEvents))
	data, err := c.query("Logs_20140328.PutLogEvents", req)
	if err != nil {
		return "", err
	}
	var result PutLogEventsResponse
	json.Unmarshal(data, &result)
	return result.NextSequenceToken, nil
}
<commit_msg>+ listing<commit_after>package logs

import (
	"encoding/json"
	_ "encoding/xml"
	"fmt"
	"github.com/crowdmob/goamz/aws"
	"io/ioutil"
	"log"
	"net/http"
	"sort"
	"strings"
	"time"
)

const debug = false

type CloudWatchLogs struct {
	Endpoint string
	Auth     aws.Auth
	Region   aws.Region
}

// Create a new CloudWatchLogs object for a given namespace
func New(auth aws.Auth, endpoint string, region string) (*CloudWatchLogs, error) {
	return &CloudWatchLogs{
		Endpoint: endpoint,
		Auth:     auth,
		Region:   aws.Region{Name: region},
	}, nil
}

func buildError(r *http.Response, jsonBody []byte) error {
	kinesisError := &Error{
		StatusCode: r.StatusCode,
		Status:     r.Status,
	}

	err := json.Unmarshal(jsonBody, kinesisError)
	if err != nil {
		log.Printf("Failed to parse body as JSON")
		return err
	}

	return kinesisError
}

// Error represents an error in an operation with Kinesis(following goamz/Dynamodb)
type Error struct {
	StatusCode int // HTTP status code (200, 403, ...)
	Status     string
	Code       string `json:"__type"`
	Message    string `json:"message"`
}

func (e Error) Error() string {
	return fmt.Sprintf("[HTTP %d] %s : %s\n", e.StatusCode, e.Code, e.Message)
}

func (k *CloudWatchLogs) query(target string, payload interface{}) ([]byte, error) {

	jsonBody, _ := json.Marshal(payload)

	data := strings.NewReader(string(jsonBody))
	hreq, err := http.NewRequest("POST", k.Endpoint+"/", data)

	if err != nil {
		return nil, err
	}

	hreq.Header.Set("Content-Type", "application/x-amz-json-1.1")
	hreq.Header.Set("X-Amz-Date", time.Now().UTC().Format(aws.ISO8601BasicFormat))
	hreq.Header.Set("X-Amz-Target", target)

	signer := aws.NewV4Signer(k.Auth, "logs", k.Region)
	signer.Sign(hreq)

	resp, err := http.DefaultClient.Do(hreq)

	if err != nil {
		log.Printf("Error calling Amazon\n: %v", err)
		return nil, err
	}

	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Printf("Could not read response body\n")
		return nil, err
	}

	if resp.StatusCode != 200 {
		err = buildError(resp, body)
		return nil, err
	}

	return body, nil
}

type LogGroup struct {
	Arn               string
	CreationTime      int64
	LogGroupName      string
	MetricFilterCount int
	RetentionInDays   int
	StoredBytes       int64
}

type DescribeLogGroupsResponse struct {
	NextToken string
	LogGroups []*LogGroup
}

type DescribeLogGroupsRequest struct {
	Limit              string
	LogGroupNamePrefix string
	NextToken          string
}

func (c *CloudWatchLogs) DescribeLogGroups(req *DescribeLogGroupsRequest) (r []*LogGroup, err error) {
	data, err := c.query("Logs_20140328.DescribeLogGroups", req)
	if err != nil {
		fmt.Printf("%v\n", err)
		return nil, err
	}
	var result DescribeLogGroupsResponse
	json.Unmarshal(data, &result)
	return result.LogGroups, nil
}

type LogStream struct {
	Arn                 string
	CreationTime        int64
	FirstEventTimestamp int64
	LastEventTimestamp  int64
	LastIngestionTime   int64
	LogStreamName       string
	StoredBytes         int64
	UploadSequenceToken string
}

type DescribeLogStreamsResponse struct {
	NextToken  string
	LogStreams []*LogStream
}

type DescribeLogStreamsRequest struct {
	Limit               int    `json:"limit,omitempty"`
	LogGroupName        string `json:"logGroupName,omitempty"`
	LogStreamNamePrefix string `json:"logStreamNamePrefix,omitempty"`
	NextToken           string `json:"nextToken,omitempty"`
}

func (c *CloudWatchLogs) DescribeLogStreams(req *DescribeLogStreamsRequest) (r []*LogStream, err error) {
	data, err := c.query("Logs_20140328.DescribeLogStreams", req)
	if err != nil {
		fmt.Printf("%v\n", err)
		return nil, err
	}
	var result DescribeLogStreamsResponse
	json.Unmarshal(data, &result)
	if len(result.NextToken) > 0 {
		req.NextToken = result.NextToken
		tmp, err := c.DescribeLogStreams(req)
		if err != nil {
			return nil, err
		}
		result.LogStreams = append(result.LogStreams, tmp...)
	}
	return result.LogStreams, nil
}

type Event struct {
	IngestionTime int
	Message       string
	Timestamp     int64
}

type GetLogEventsResponse struct {
	Events            []*Event
	NextForwardToken  string
	NextBackwardToken string
}

type GetLogEventsRequest struct {
	Limit         int    `json:"limit,omitempty"`
	EndTime       int64  `json:"endTime,omitempty"`
	LogGroupName  string `json:"logGroupName,omitempty"`
	LogStreamName string `json:"logStreamName,omitempty"`
	NextToken     string `json:"nextToken,omitempty"`
	StartFromHead bool   `json:"startFromHead"`
	StartTime     int64  `json:"startTime"`
}

func (c *CloudWatchLogs) GetLogEvents(req *GetLogEventsRequest) (r *GetLogEventsResponse, err error) {
	data, err := c.query("Logs_20140328.GetLogEvents", req)
	if err != nil {
		return nil, err
	}
	var result GetLogEventsResponse
	json.Unmarshal(data, &result)
	return &result, nil
}

type CreateLogGroupRequest struct {
	LogGroupName string `json:"logGroupName"`
}

func (c *CloudWatchLogs) CreateLogGroup(req *CreateLogGroupRequest) error {
	_, err := c.query("Logs_20140328.CreateLogGroup", req)
	if err != nil {
		return err
	}
	return nil
}

type CreateLogStreamRequest struct {
	LogGroupName  string `json:"logGroupName"`
	LogStreamName string `json:"logStreamName"`
}

func (c *CloudWatchLogs) CreateLogStream(req *CreateLogStreamRequest) error {
	_, err := c.query("Logs_20140328.CreateLogStream", req)
	if err != nil {
		return err
	}
	return nil
}

type LogEvent struct {
	Message   string `json:"message"`
	Timestamp int64  `json:"timestamp"`
}

type ByTimestamp []LogEvent

func (events ByTimestamp) Len() int           { return len(events) }
func (events ByTimestamp) Swap(i, j int)      { events[i], events[j] = events[j], events[i] }
func (events ByTimestamp) Less(i, j int) bool { return events[i].Timestamp < events[j].Timestamp }

type PutLogEventsRequest struct {
	LogEvents     []LogEvent `json:"logEvents"`
	LogGroupName  string     `json:"logGroupName"`
	LogStreamName string     `json:"logStreamName"`
	SequenceToken string     `json:"sequenceToken,omitempty"`
}

type PutLogEventsResponse struct {
	NextSequenceToken string `json:"nextSequenceToken"`
}

func (c *CloudWatchLogs) PutLogEvents(req *PutLogEventsRequest) (string, error) {
	sort.Sort(ByTimestamp(req.LogEvents))
	data, err := c.query("Logs_20140328.PutLogEvents", req)
	if err != nil {
		return "", err
	}
	var result PutLogEventsResponse
	json.Unmarshal(data, &result)
	return result.NextSequenceToken, nil
}
<|endoftext|>


<commit_before>package job

import (
	"io"
	"net/http"
	"os"
	"strings"
	"time"

	"github.com/Sirupsen/logrus"
	"github.com/modcloth/go-fileutils"
	"github.com/modcloth/kamino"
	gouuid "github.com/nu7hatch/gouuid"
	"github.com/sylphon/build-runner"
	"github.com/sylphon/build-runner/unit-config"
)

const (
	defaultTail         = "100"
	defaultBobfile      = "Bobfile"
	specFixturesRepoDir = "./Specs/fixtures/repodir"
)

var (
	// TestMode monkeys with certain things for tests so bad things don't happen
	TestMode bool

	logger *logrus.Logger
)

/*
Job is the struct representation of a build job.  Intended to be
created with NewJob, but exported so it can be used for tests.
*/
type Job struct {
	Account            string         `json:"account,omitempty"`
	Bobfile            string         `json:"bobfile,omitempty"`
	Completed          time.Time      `json:"completed,omitempty"`
	Created            time.Time      `json:"created"`
	Error              error          `json:"error,omitempty"`
	GitCloneDepth      string         `json:"clone_depth,omitempty"`
	GitHubAPIToken     string         `json:"-"`
	ID                 string         `json:"id,omitempty"`
	LogRoute           string         `json:"log_route,omitempty"`
	Logger             *logrus.Logger `json:"-"`
	Ref                string         `json:"ref,omitempty"`
	Repo               string         `json:"repo,omitempty"`
	Status             string         `json:"status"`
	Workdir            string         `json:"-"`
	InfoRoute          string         `json:"info_route,omitempty"`
	logDir             string         `json:"-"`
	logFile            *os.File       `json:"-"`
	clonedRepoLocation string         `json:"-"`
}

/*
Config contains global configuration options for jobs
*/
type Config struct {
	Workdir        string
	Logger         *logrus.Logger
	GitHubAPIToken string
}

//Logger sets the (global) logger for the server package
func Logger(l *logrus.Logger) {
	logger = l
}

func (job *Job) addHostToRoutes(req *http.Request) {
	var host string

	if req.Host != "" {
		host = req.Host
	} else {
		host = req.URL.Host
	}

	var scheme string
	if req.TLS == nil {
		scheme = "http"
	} else {
		scheme = "https"
	}

	if strings.HasPrefix(job.LogRoute, "/") {
		job.LogRoute = scheme + "://" + host + job.LogRoute
	}

	if strings.HasPrefix(job.InfoRoute, "/") {
		job.InfoRoute = scheme + "://" + host + job.InfoRoute
	}
}

/*
NewJob creates a new job from the config as well as a job spec.  After creating
the job, calling job.Process() will actually perform the work.
*/
func NewJob(cfg *Config, spec *Spec, req *http.Request) *Job {
	idUUID, err := gouuid.NewV4()
	if err != nil {
		cfg.Logger.WithField("error", err).Error("error creating uuid")
	}
	id := idUUID.String()

	bobfile := spec.Bobfile
	if bobfile == "" {
		bobfile = defaultBobfile
	}

	ret := &Job{
		Bobfile:        bobfile,
		ID:             id,
		Account:        spec.RepoOwner,
		GitHubAPIToken: spec.GitHubAPIToken,
		Ref:            spec.GitRef,
		Repo:           spec.RepoName,
		Workdir:        cfg.Workdir,
		InfoRoute:      "/jobs/" + id,
		LogRoute:       "/jobs/" + id + "/tail?n=" + defaultTail,
		logDir:         cfg.Workdir + "/" + id,
		Status:         "created",
		Created:        time.Now(),
	}
	ret.addHostToRoutes(req)

	out, file, err := newMultiWriter(ret.logDir)
	if err != nil {
		cfg.Logger.WithField("error", err).Error("error creating log dir")
		id = ""
	}

	ret.logFile = file
	ret.Logger = &logrus.Logger{
		Formatter: cfg.Logger.Formatter,
		Level:     cfg.Logger.Level,
		Out:       out,
	}

	if ret.GitHubAPIToken == "" {
		ret.GitHubAPIToken = cfg.GitHubAPIToken
	}

	if id != "" {
		jobs[id] = ret
	}

	return ret
}

func newMultiWriter(logDir string) (io.Writer, *os.File, error) {
	var out io.Writer

	if err := fileutils.MkdirP(logDir, 0755); err != nil {
		return nil, nil, err
	}

	file, err := os.Create(logDir + "/log.log")
	if err != nil {
		return nil, nil, err
	}

	if TestMode {
		out = file
	} else {
		out = io.MultiWriter(os.Stdout, file)
	}

	return out, file, nil
}

func (job *Job) clone() (string, error) {
	job.Logger.WithFields(logrus.Fields{
		"api_token_present":  job.GitHubAPIToken != "",
		"account":            job.Account,
		"ref":                job.Ref,
		"repo":               job.Repo,
		"clone_cache_option": kamino.No,
	}).Info("starting clone process")

	genome := &kamino.Genome{
		APIToken: job.GitHubAPIToken,
		Account:  job.Account,
		Ref:      job.Ref,
		Repo:     job.Repo,
		UseCache: kamino.No,
	}

	factory, err := kamino.NewCloneFactory(job.Workdir)
	if err != nil {
		job.Logger.WithFields(logrus.Fields{
			"api_token_present":  job.GitHubAPIToken != "",
			"account":            job.Account,
			"ref":                job.Ref,
			"repo":               job.Repo,
			"clone_cache_option": kamino.No,
			"error":              err,
		}).Error("issue creating clone factory")

		return "", err
	}

	job.Logger.Debug("attempting to clone")

	path, err := factory.Clone(genome)
	if err != nil {
		job.Logger.WithFields(logrus.Fields{
			"api_token_present":  job.GitHubAPIToken != "",
			"account":            job.Account,
			"ref":                job.Ref,
			"repo":               job.Repo,
			"clone_cache_option": kamino.No,
			"error":              err,
		}).Error("issue cloning")

		return "", err
	}

	job.Logger.WithFields(logrus.Fields{
		"api_token_present":  job.GitHubAPIToken != "",
		"account":            job.Account,
		"ref":                job.Ref,
		"repo":               job.Repo,
		"clone_cache_option": kamino.No,
	}).Info("cloning successful")

	return path, nil
}

func (job *Job) build() error {

	job.Logger.Debug("attempting to create a builder")
	unitConfig, err := unitconfig.ReadFromFile(job.clonedRepoLocation+"/"+job.Bobfile, unitconfig.TOML)
	if err != nil {
		job.Logger.WithField("error", err).Error("issue parsing Bobfile")
		return err
	}

	job.Logger.WithField("file", job.Bobfile).Info("building from file")
	// set skip-push

	if err := runner.RunBuild(unitConfig, job.clonedRepoLocation); err != nil {
		return err
	}
	return nil
}

/*
Process does the actual job processing work, including:

	1. clone the repo
	2. build from the Bobfile at the top level
	3. clean up the cloned repo
*/
func (job *Job) Process() error {
	if TestMode {
		return job.processTestMode()
	}

	defer func() {
		if job.logFile != nil {
			job.logFile.Close()
		}
	}()

	// step 1: clone
	job.Status = "cloning"
	path, err := job.clone()
	if err != nil {
		job.Logger.WithField("error", err).Error("unable to process job synchronously")
		job.Status = "errored"
		job.Error = err
		return err
	}
	job.clonedRepoLocation = path

	// step 2: build
	job.Status = "building"
	if err = job.build(); err != nil {
		job.Logger.WithField("error", err).Error("unable to process job synchronously")
		job.Status = "errored"
		job.Error = err
		return err
	}

	job.Status = "completed"
	job.Completed = time.Now()
	fileutils.RmRF(path)
	return nil
}

func (job *Job) processTestMode() error {
	// If this function is used correctly,
	// we should never see this warning message.
	job.Logger.Warn("processing job in test mode")

	// set status to validating in anticipation of performing validation step
	job.Status = "validating"

	// set clone path to fixtures dir
	job.clonedRepoLocation = specFixturesRepoDir

	// log something for test purposes
	levelBefore := job.Logger.Level
	job.Logger.Level = logrus.DebugLevel
	job.Logger.Debug("FOO")
	job.Logger.Level = levelBefore

	// mark job as completed
	job.Status = "completed"
	job.Completed = time.Now()

	return nil
}
<commit_msg>Using correct fake uuid for tests<commit_after>package job

import (
	"io"
	"net/http"
	"os"
	"strings"
	"time"

	"github.com/Sirupsen/logrus"
	"github.com/modcloth/go-fileutils"
	"github.com/modcloth/kamino"
	gouuid "github.com/nu7hatch/gouuid"
	"github.com/sylphon/build-runner"
	"github.com/sylphon/build-runner/unit-config"
)

const (
	defaultTail         = "100"
	defaultBobfile      = "Bobfile"
	specFixturesRepoDir = "./Specs/fixtures/repodir"
)

var (
	// TestMode monkeys with certain things for tests so bad things don't happen
	TestMode bool

	logger *logrus.Logger
)

/*
Job is the struct representation of a build job.  Intended to be
created with NewJob, but exported so it can be used for tests.
*/
type Job struct {
	Account            string         `json:"account,omitempty"`
	Bobfile            string         `json:"bobfile,omitempty"`
	Completed          time.Time      `json:"completed,omitempty"`
	Created            time.Time      `json:"created"`
	Error              error          `json:"error,omitempty"`
	GitCloneDepth      string         `json:"clone_depth,omitempty"`
	GitHubAPIToken     string         `json:"-"`
	ID                 string         `json:"id,omitempty"`
	LogRoute           string         `json:"log_route,omitempty"`
	Logger             *logrus.Logger `json:"-"`
	Ref                string         `json:"ref,omitempty"`
	Repo               string         `json:"repo,omitempty"`
	Status             string         `json:"status"`
	Workdir            string         `json:"-"`
	InfoRoute          string         `json:"info_route,omitempty"`
	logDir             string         `json:"-"`
	logFile            *os.File       `json:"-"`
	clonedRepoLocation string         `json:"-"`
}

/*
Config contains global configuration options for jobs
*/
type Config struct {
	Workdir        string
	Logger         *logrus.Logger
	GitHubAPIToken string
}

//Logger sets the (global) logger for the server package
func Logger(l *logrus.Logger) {
	logger = l
}

func (job *Job) addHostToRoutes(req *http.Request) {
	var host string

	if req.Host != "" {
		host = req.Host
	} else {
		host = req.URL.Host
	}

	var scheme string
	if req.TLS == nil {
		scheme = "http"
	} else {
		scheme = "https"
	}

	if strings.HasPrefix(job.LogRoute, "/") {
		job.LogRoute = scheme + "://" + host + job.LogRoute
	}

	if strings.HasPrefix(job.InfoRoute, "/") {
		job.InfoRoute = scheme + "://" + host + job.InfoRoute
	}
}

/*
NewJob creates a new job from the config as well as a job spec.  After creating
the job, calling job.Process() will actually perform the work.
*/
func NewJob(cfg *Config, spec *Spec, req *http.Request) *Job {
	var idUUID *gouuid.UUID
	var err error
	idUUID, err = gouuid.NewV4()
	if TestMode {
		idUUID, err = gouuid.NewV5(gouuid.NamespaceURL, []byte("0"))
	}

	if err != nil {
		cfg.Logger.WithField("error", err).Error("error creating uuid")
	}
	id := idUUID.String()

	bobfile := spec.Bobfile
	if bobfile == "" {
		bobfile = defaultBobfile
	}

	ret := &Job{
		Bobfile:        bobfile,
		ID:             id,
		Account:        spec.RepoOwner,
		GitHubAPIToken: spec.GitHubAPIToken,
		Ref:            spec.GitRef,
		Repo:           spec.RepoName,
		Workdir:        cfg.Workdir,
		InfoRoute:      "/jobs/" + id,
		LogRoute:       "/jobs/" + id + "/tail?n=" + defaultTail,
		logDir:         cfg.Workdir + "/" + id,
		Status:         "created",
		Created:        time.Now(),
	}
	ret.addHostToRoutes(req)

	out, file, err := newMultiWriter(ret.logDir)
	if err != nil {
		cfg.Logger.WithField("error", err).Error("error creating log dir")
		id = ""
	}

	ret.logFile = file
	ret.Logger = &logrus.Logger{
		Formatter: cfg.Logger.Formatter,
		Level:     cfg.Logger.Level,
		Out:       out,
	}

	if ret.GitHubAPIToken == "" {
		ret.GitHubAPIToken = cfg.GitHubAPIToken
	}

	if id != "" {
		jobs[id] = ret
	}

	return ret
}

func newMultiWriter(logDir string) (io.Writer, *os.File, error) {
	var out io.Writer

	if err := fileutils.MkdirP(logDir, 0755); err != nil {
		return nil, nil, err
	}

	file, err := os.Create(logDir + "/log.log")
	if err != nil {
		return nil, nil, err
	}

	if TestMode {
		out = file
	} else {
		out = io.MultiWriter(os.Stdout, file)
	}

	return out, file, nil
}

func (job *Job) clone() (string, error) {
	job.Logger.WithFields(logrus.Fields{
		"api_token_present":  job.GitHubAPIToken != "",
		"account":            job.Account,
		"ref":                job.Ref,
		"repo":               job.Repo,
		"clone_cache_option": kamino.No,
	}).Info("starting clone process")

	genome := &kamino.Genome{
		APIToken: job.GitHubAPIToken,
		Account:  job.Account,
		Ref:      job.Ref,
		Repo:     job.Repo,
		UseCache: kamino.No,
	}

	factory, err := kamino.NewCloneFactory(job.Workdir)
	if err != nil {
		job.Logger.WithFields(logrus.Fields{
			"api_token_present":  job.GitHubAPIToken != "",
			"account":            job.Account,
			"ref":                job.Ref,
			"repo":               job.Repo,
			"clone_cache_option": kamino.No,
			"error":              err,
		}).Error("issue creating clone factory")

		return "", err
	}

	job.Logger.Debug("attempting to clone")

	path, err := factory.Clone(genome)
	if err != nil {
		job.Logger.WithFields(logrus.Fields{
			"api_token_present":  job.GitHubAPIToken != "",
			"account":            job.Account,
			"ref":                job.Ref,
			"repo":               job.Repo,
			"clone_cache_option": kamino.No,
			"error":              err,
		}).Error("issue cloning")

		return "", err
	}

	job.Logger.WithFields(logrus.Fields{
		"api_token_present":  job.GitHubAPIToken != "",
		"account":            job.Account,
		"ref":                job.Ref,
		"repo":               job.Repo,
		"clone_cache_option": kamino.No,
	}).Info("cloning successful")

	return path, nil
}

func (job *Job) build() error {

	job.Logger.Debug("attempting to create a builder")
	unitConfig, err := unitconfig.ReadFromFile(job.clonedRepoLocation+"/"+job.Bobfile, unitconfig.TOML)
	if err != nil {
		job.Logger.WithField("error", err).Error("issue parsing Bobfile")
		return err
	}

	job.Logger.WithField("file", job.Bobfile).Info("building from file")
	// set skip-push

	if err := runner.RunBuild(unitConfig, job.clonedRepoLocation); err != nil {
		return err
	}
	return nil
}

/*
Process does the actual job processing work, including:

	1. clone the repo
	2. build from the Bobfile at the top level
	3. clean up the cloned repo
*/
func (job *Job) Process() error {
	if TestMode {
		return job.processTestMode()
	}

	defer func() {
		if job.logFile != nil {
			job.logFile.Close()
		}
	}()

	// step 1: clone
	job.Status = "cloning"
	path, err := job.clone()
	if err != nil {
		job.Logger.WithField("error", err).Error("unable to process job synchronously")
		job.Status = "errored"
		job.Error = err
		return err
	}
	job.clonedRepoLocation = path

	// step 2: build
	job.Status = "building"
	if err = job.build(); err != nil {
		job.Logger.WithField("error", err).Error("unable to process job synchronously")
		job.Status = "errored"
		job.Error = err
		return err
	}

	job.Status = "completed"
	job.Completed = time.Now()
	fileutils.RmRF(path)
	return nil
}

func (job *Job) processTestMode() error {
	// If this function is used correctly,
	// we should never see this warning message.
	job.Logger.Warn("processing job in test mode")

	// set status to validating in anticipation of performing validation step
	job.Status = "validating"

	// set clone path to fixtures dir
	job.clonedRepoLocation = specFixturesRepoDir

	// log something for test purposes
	levelBefore := job.Logger.Level
	job.Logger.Level = logrus.DebugLevel
	job.Logger.Debug("FOO")
	job.Logger.Level = levelBefore

	// mark job as completed
	job.Status = "completed"
	job.Completed = time.Now()

	return nil
}
<|endoftext|>


<commit_before>package main

import "testing"

func BenchmarkLuhn(b *testing.B) {
	for n := 0; n < b.N; n++ {
		Luhn("49927398716")
	}
}

func TestLunh(t *testing.T) {
	if !Luhn("001230147647009683210024") {
		t.Errorf("Checksum failed for valid unput")
	}

	if Luhn("1234567812345678") {
		t.Errorf("Checksum passed for invalid unput")
	}
}
<commit_msg>added parallel tests<commit_after>package main

import "testing"

func BenchmarkLuhn(b *testing.B) {
	for n := 0; n < b.N; n++ {
		Luhn("49927398716")
	}
}

func BenchmarkLuhnParallel(b *testing.B) {
	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			Luhn("49927398716")
		}
	})
}

func TestLunh(t *testing.T) {
	if !Luhn("001230147647009683210024") {
		t.Errorf("Checksum failed for valid unput")
	}

	if Luhn("1234567812345678") {
		t.Errorf("Checksum passed for invalid unput")
	}
}
<|endoftext|>