<commit_before>package core

import (
	"database/sql"
	"errors"
	"log"
	"math"
	"sort"
	"strconv"
	"sync"

	"github.com/wawandco/transporter/Godeps/_workspace/src/github.com/apaganobeleno/pq"
	"github.com/wawandco/transporter/Godeps/_workspace/src/github.com/go-sql-driver/mysql"

	"github.com/wawandco/transporter/Godeps/_workspace/src/gopkg.in/yaml.v1"
	"github.com/wawandco/transporter/managers"
)

var mu sync.Mutex

func init() {
	mu.Lock()
	defer mu.Unlock()

	if !driverRegistered("postgres") {
		sql.Register("postgres", &pq.Driver{})
	}

	if !driverRegistered("mysql") {
		sql.Register("mysql", &mysql.MySQLDriver{})
	}
}

var migrations []Migration
var manager managers.DatabaseManager
var databaseManagers = map[string]managers.DatabaseManager{
	"postgres": &managers.PostgreSQLManager{},
	"mysql":    &managers.MySQLManager{},
}

const (
	// MigrationsTable is the Db table where we will store migrations
	MigrationsTable = "transporter_migrations"
)

// Add function adds a migration to the migrations array
// So Transporter verifies if the migration is already completed or runs
// the desired migration as needed.
//
// Register checks if migration attempted to be registered id is unique.
func Add(m Migration) {
	migrations = append(migrations, m)
}

// MigrationsTableExists returns true if the table for the migrations already exists.
func MigrationsTableExists(db *sql.DB) bool {
	query := manager.AllMigrationsQuery(MigrationsTable)
	_, err := db.Query(query)
	return err == nil
}

//RunAllMigrationsUp runs pending migrations and stores migration on the migrations table.
func RunAllMigrationsUp(db *sql.DB) {

	//1. Migrations table exists? -> Create if needed
	if !MigrationsTableExists(db) {
		CreateMigrationsTable(db)
	}

	sort.Sort(ByIdentifier(migrations))

	version := DatabaseVersion(db)
	if len(migrations) > 0 && version == migrations[len(migrations)-1].GetID() {
		log.Println("| No migrations to run, DB is on latest version. (" + version + ")")
		return
	}

	var err error
	for _, migration := range migrations {
		// Check if migration is on the database already
		if migration.Pending(db) {
			err = RunMigrationUp(db, &migration)

			if err != nil {
				log.Println("| Could not complete your migration (" + migration.GetID() + "), please check your SQL.")
				log.Println("| " + err.Error())
				break
			}
		}
	}

	version = DatabaseVersion(db)
	if err == nil && version != "" {
		log.Println("| Done, new database version is " + version)
	}
}

// RunMigrationUp runs a single migration up and if success it saves the
// Migration identifier on the migrations table.
func RunMigrationUp(db *sql.DB, m *Migration) error {
	tx, err := dbTransaction(db)
	if err != nil {
		return errors.New("Could not open a db transaction.")
	}

	if m.Up != nil {
		m.Up(tx)
		migerr := tx.err
		err = tx.Commit()

		if err != nil || migerr != nil {
			return migerr
		}

		query := manager.AddMigrationQuery(MigrationsTable, m.GetID())
		_, err = db.Exec(query)
		return nil
	}

	return errors.New("Migration doesnt have Up function defined.")
}

// RunMigrationDown Runs one migration down and if successful it removes the migration from
// the migrations table.
func RunMigrationDown(db *sql.DB, m *Migration) error {
	tx, err := dbTransaction(db)
	if err != nil {
		return errors.New("Could not begin a transaction.")
	}

	if m.Down != nil {
		m.Down(tx)
		migerr := tx.err
		err = tx.Commit()

		if err != nil || migerr != nil {
			return migerr
		}
		query := manager.DeleteMigrationQuery(MigrationsTable, m.GetID())
		_, err = db.Exec(query)
		return nil
	}

	return errors.New("Migration (" + m.GetID() + ") doesn't have Down function defined.")
}

//RunOneMigrationDown Run down last migration that have completed.
func RunOneMigrationDown(db *sql.DB) {
	if !MigrationsTableExists(db) {
		CreateMigrationsTable(db)
	}

	sort.Sort(ByIdentifier(migrations))
	identifier := DatabaseVersion(db)
	id, err := strconv.Atoi(identifier)

	if err != nil {
		log.Println("Sorry, there is no migration to run back")
	}

	for _, mig := range migrations {
		if mig.Identifier-int64(id) == 0 {
			log.Println("| Running " + mig.GetID() + " back")
			err := RunMigrationDown(db, &mig)
			if err == nil {
				version := DatabaseVersion(db)
				if version != "" {
					log.Println("| Done, new database version is " + version)
				} else {
					log.Println("| Done, All existing migrations down.")
				}
			} else {
				log.Println("| Could not rollback your migration (" + mig.GetID() + "), please check your SQL.")
				log.Println("| " + err.Error())
			}
			break
		}
	}

}

//DatabaseVersion returns the latest database version.
func DatabaseVersion(db *sql.DB) string {
	query := manager.LastMigrationQuery(MigrationsTable)
	rows, err := db.Query(query)
	if err != nil {
		return strconv.FormatInt(math.MaxInt64, 10)
	}

	var identifier string
	for rows.Next() {
		rows.Scan(&identifier)
		break
	}

	return identifier
}

//SetManager allows external entities like testing to set the driver as needed.
func SetManager(man managers.DatabaseManager) {
	manager = man
}

//DBConnection Returns a DB connection from the yml config file
func DBConnection(ymlFile []byte, environment string) (*sql.DB, error) {
	var connData map[string]map[string]string
	err := yaml.Unmarshal([]byte(ymlFile), &connData)

	if err != nil {
		return nil, err
	}

	if connData[environment] == nil {
		err = errors.New("Environment [" + environment + "] does not exist in your config.yml")
		return nil, err
	}

	manager = databaseManagers[connData[environment]["driver"]]
	return sql.Open(connData[environment]["driver"], connData[environment]["url"])
}

func dbTransaction(db *sql.DB) (*Tx, error) {
	sqlTx, err := db.Begin()
	if err != nil {
		log.Println("| Error, could not initialize transaction")
	}

	tx := &Tx{
		Tx:      sqlTx,
		Manager: manager,
		err:     nil,
	}

	return tx, err
}
<commit_msg>[cleaning] logging database version error<commit_after>package core

import (
	"database/sql"
	"errors"
	"log"
	"math"
	"sort"
	"strconv"
	"sync"

	"github.com/wawandco/transporter/Godeps/_workspace/src/github.com/apaganobeleno/pq"
	"github.com/wawandco/transporter/Godeps/_workspace/src/github.com/go-sql-driver/mysql"

	"github.com/wawandco/transporter/Godeps/_workspace/src/gopkg.in/yaml.v1"
	"github.com/wawandco/transporter/managers"
)

var mu sync.Mutex

func init() {
	mu.Lock()
	defer mu.Unlock()

	if !driverRegistered("postgres") {
		sql.Register("postgres", &pq.Driver{})
	}

	if !driverRegistered("mysql") {
		sql.Register("mysql", &mysql.MySQLDriver{})
	}
}

var migrations []Migration
var manager managers.DatabaseManager
var databaseManagers = map[string]managers.DatabaseManager{
	"postgres": &managers.PostgreSQLManager{},
	"mysql":    &managers.MySQLManager{},
}

const (
	// MigrationsTable is the Db table where we will store migrations
	MigrationsTable = "transporter_migrations"
)

// Add function adds a migration to the migrations array
// So Transporter verifies if the migration is already completed or runs
// the desired migration as needed.
//
// Register checks if migration attempted to be registered id is unique.
func Add(m Migration) {
	migrations = append(migrations, m)
}

// MigrationsTableExists returns true if the table for the migrations already exists.
func MigrationsTableExists(db *sql.DB) bool {
	query := manager.AllMigrationsQuery(MigrationsTable)
	_, err := db.Query(query)
	return err == nil
}

//RunAllMigrationsUp runs pending migrations and stores migration on the migrations table.
func RunAllMigrationsUp(db *sql.DB) {

	//1. Migrations table exists? -> Create if needed
	if !MigrationsTableExists(db) {
		CreateMigrationsTable(db)
	}

	sort.Sort(ByIdentifier(migrations))

	version := DatabaseVersion(db)
	if len(migrations) > 0 && version == migrations[len(migrations)-1].GetID() {
		log.Println("| No migrations to run, DB is on latest version. (" + version + ")")
		return
	}

	var err error
	for _, migration := range migrations {
		// Check if migration is on the database already
		if migration.Pending(db) {
			err = RunMigrationUp(db, &migration)

			if err != nil {
				log.Println("| Could not complete your migration (" + migration.GetID() + "), please check your SQL.")
				log.Println("| " + err.Error())
				break
			}
		}
	}

	version = DatabaseVersion(db)
	if err == nil && version != "" {
		log.Println("| Done, new database version is " + version)
	}
}

// RunMigrationUp runs a single migration up and if success it saves the
// Migration identifier on the migrations table.
func RunMigrationUp(db *sql.DB, m *Migration) error {
	tx, err := dbTransaction(db)
	if err != nil {
		return errors.New("Could not open a db transaction.")
	}

	if m.Up != nil {
		m.Up(tx)
		migerr := tx.err
		err = tx.Commit()

		if err != nil || migerr != nil {
			return migerr
		}

		query := manager.AddMigrationQuery(MigrationsTable, m.GetID())
		_, err = db.Exec(query)
		return nil
	}

	return errors.New("Migration doesnt have Up function defined.")
}

// RunMigrationDown Runs one migration down and if successful it removes the migration from
// the migrations table.
func RunMigrationDown(db *sql.DB, m *Migration) error {
	tx, err := dbTransaction(db)
	if err != nil {
		return errors.New("Could not begin a transaction.")
	}

	if m.Down != nil {
		m.Down(tx)
		migerr := tx.err
		err = tx.Commit()

		if err != nil || migerr != nil {
			return migerr
		}
		query := manager.DeleteMigrationQuery(MigrationsTable, m.GetID())
		_, err = db.Exec(query)
		return nil
	}

	return errors.New("Migration (" + m.GetID() + ") doesn't have Down function defined.")
}

//RunOneMigrationDown Run down last migration that have completed.
func RunOneMigrationDown(db *sql.DB) {
	if !MigrationsTableExists(db) {
		CreateMigrationsTable(db)
	}

	sort.Sort(ByIdentifier(migrations))
	identifier := DatabaseVersion(db)
	id, err := strconv.Atoi(identifier)

	if err != nil {
		log.Println("Sorry, there is no migration to run back")
	}

	for _, mig := range migrations {
		if mig.Identifier-int64(id) == 0 {
			log.Println("| Running " + mig.GetID() + " back")
			err := RunMigrationDown(db, &mig)
			if err == nil {
				version := DatabaseVersion(db)
				if version != "" {
					log.Println("| Done, new database version is " + version)
				} else {
					log.Println("| Done, All existing migrations down.")
				}
			} else {
				log.Println("| Could not rollback your migration (" + mig.GetID() + "), please check your SQL.")
				log.Println("| " + err.Error())
			}
			break
		}
	}

}

//DatabaseVersion returns the latest database version.
func DatabaseVersion(db *sql.DB) string {
	query := manager.LastMigrationQuery(MigrationsTable)
	rows, err := db.Query(query)
	if err != nil {
		log.Println(err)
		return strconv.FormatInt(math.MaxInt64, 10)
	}

	var identifier string
	for rows.Next() {
		rows.Scan(&identifier)
		break
	}

	return identifier
}

//SetManager allows external entities like testing to set the driver as needed.
func SetManager(man managers.DatabaseManager) {
	manager = man
}

//DBConnection Returns a DB connection from the yml config file
func DBConnection(ymlFile []byte, environment string) (*sql.DB, error) {
	var connData map[string]map[string]string
	err := yaml.Unmarshal([]byte(ymlFile), &connData)

	if err != nil {
		return nil, err
	}

	if connData[environment] == nil {
		err = errors.New("Environment [" + environment + "] does not exist in your config.yml")
		return nil, err
	}

	manager = databaseManagers[connData[environment]["driver"]]
	return sql.Open(connData[environment]["driver"], connData[environment]["url"])
}

func dbTransaction(db *sql.DB) (*Tx, error) {
	sqlTx, err := db.Begin()
	if err != nil {
		log.Println("| Error, could not initialize transaction")
	}

	tx := &Tx{
		Tx:      sqlTx,
		Manager: manager,
		err:     nil,
	}

	return tx, err
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"strings"

	"github.com/zeebe-io/zeebe/clients/go/entities"
	"github.com/zeebe-io/zeebe/clients/go/worker"
	"github.com/zeebe-io/zeebe/clients/go/zbc"
)

const (
	zeebeBrokerAddr = "0.0.0.0:26500"
	port            = "8100"
)

var (
	client zbc.ZBClient
)

func main() {
	startHTTPServer()
}

func startHTTPServer() {
	// setup REST endpoint (yay - this is not really REST - I know - but sufficient for this example)
	http.HandleFunc("/payment", handleHTTPRequest)
	log.Fatal(http.ListenAndServe(":"+port, nil))
}

func handleHTTPRequest(w http.ResponseWriter, r *http.Request) {
	bodyBytes, _ := ioutil.ReadAll(r.Body)
	jsonStr := string(bodyBytes)
	fmt.Println("Retrieving payment request" + jsonStr)

	err := chargeCreditCard(jsonStr)
	if err != nil {
		w.WriteHeader(500)
	} else {
		w.WriteHeader(202)
	}
}

func init() {
	// connect to Zeebe Broker
	newClient, err := zbc.NewZBClient(&zbc.ZBClientConfig{
		GatewayAddress:         zeebeBrokerAddr,
		UsePlaintextConnection: true})
	if err != nil {
		log.Fatal(err)
	}
	client = newClient

	// register job handler for 'charge-credit-card' and subscribe
	// jobWorker :=
	client.NewJobWorker().JobType("charge-credit-card").Handler(handleChargeCreditCardJob).Open()
	//defer jobWorker.Close()
	//jobWorker.AwaitClose()

	// deploy workflow model
	deployment, err := client.NewDeployWorkflowCommand().AddResourceFile("payment.bpmn").Send()
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("deployed workflow model: ", deployment)
}

func chargeCreditCard(someDataAsJSON string) error {
	payload := make(map[string]interface{})
	json.Unmarshal([]byte(someDataAsJSON), &payload)
	request, err := client.NewCreateInstanceCommand().BPMNProcessId("paymentV3b").LatestVersion().VariablesFromMap(payload)
	if err != nil {
		fmt.Println("Error: " + err.Error())
	}
	workflowInstance, err := request.Send()
	if err != nil {
		fmt.Println("Error: " + err.Error())
		return err
	}

	fmt.Println("Started: " + workflowInstance.String())
	return nil
}

func handleChargeCreditCardJob(client worker.JobClient, job entities.Job) {
	variables, err := job.GetVariablesAsMap()
	if err != nil {
		// failed to handle job as we require the variables
		failJob(client, job, err)
		return
	}
	jsonPayload, err := json.Marshal(variables)
	if err != nil {
		log.Fatal(err)
		failJob(client, job, err)
		return
	}

	_, err = doHTTPCall(string(jsonPayload))
	if err != nil {
		// couldn't do http call, fail job to trigger retry
		failJob(client, job, err)
	} else {
		// complete job after processing
		completeJob(client, job, true)
	}
}

func completeJob(client worker.JobClient, job entities.Job, success bool) {
	variables := make(map[string]interface{})
	variables["chargeSuccess"] = success

	request, err := client.NewCompleteJobCommand().JobKey(job.GetKey()).VariablesFromMap(variables)
	if err != nil {
		failJob(client, job, err)
		return
	}
	log.Println("Complete job", job, success)
	request.Send()
}

func failJob(client worker.JobClient, job entities.Job, err error) {
	log.Println("Failed to complete job", job.GetKey(), err)
	if job.Retries > 1 {
		client.NewFailJobCommand().JobKey(job.GetKey()).Retries(job.Retries - 1).Send()
	} else {
		// if no more retries left, complete the task but mark it for being failed
		completeJob(client, job, false)
	}
}

func doHTTPCall(someDataAsJSON string) (resp *http.Response, err error) {
	fmt.Println("Doing http call", someDataAsJSON)
	return http.Post("http://localhost:8099/charge", "application/json", strings.NewReader(someDataAsJSON))
}
<commit_msg>removed some comments for cleanup<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"strings"

	"github.com/zeebe-io/zeebe/clients/go/entities"
	"github.com/zeebe-io/zeebe/clients/go/worker"
	"github.com/zeebe-io/zeebe/clients/go/zbc"
)

const (
	zeebeBrokerAddr = "0.0.0.0:26500"
	port            = "8100"
)

var (
	client zbc.ZBClient
)

func main() {
	startHTTPServer()
}

func startHTTPServer() {
	// setup REST endpoint (yay - this is not really REST - I know - but sufficient for this example)
	http.HandleFunc("/payment", handleHTTPRequest)
	log.Fatal(http.ListenAndServe(":"+port, nil))
}

func handleHTTPRequest(w http.ResponseWriter, r *http.Request) {
	bodyBytes, _ := ioutil.ReadAll(r.Body)
	jsonStr := string(bodyBytes)
	fmt.Println("Retrieving payment request" + jsonStr)

	err := chargeCreditCard(jsonStr)
	if err != nil {
		w.WriteHeader(500)
	} else {
		w.WriteHeader(202)
	}
}

func init() {
	// connect to Zeebe Broker
	newClient, err := zbc.NewZBClient(&zbc.ZBClientConfig{
		GatewayAddress:         zeebeBrokerAddr,
		UsePlaintextConnection: true})
	if err != nil {
		log.Fatal(err)
	}
	client = newClient

	// register job handler for 'charge-credit-card' and subscribe
	client.NewJobWorker().JobType("charge-credit-card").Handler(handleChargeCreditCardJob).Open()

	// deploy workflow model
	deployment, err := client.NewDeployWorkflowCommand().AddResourceFile("payment.bpmn").Send()
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("deployed workflow model: ", deployment)
}

func chargeCreditCard(someDataAsJSON string) error {
	payload := make(map[string]interface{})
	json.Unmarshal([]byte(someDataAsJSON), &payload)
	request, err := client.NewCreateInstanceCommand().BPMNProcessId("paymentV3b").LatestVersion().VariablesFromMap(payload)
	if err != nil {
		fmt.Println("Error: " + err.Error())
	}
	workflowInstance, err := request.Send()
	if err != nil {
		fmt.Println("Error: " + err.Error())
		return err
	}

	fmt.Println("Started: " + workflowInstance.String())
	return nil
}

func handleChargeCreditCardJob(client worker.JobClient, job entities.Job) {
	variables, err := job.GetVariablesAsMap()
	if err != nil {
		// failed to handle job as we require the variables
		failJob(client, job, err)
		return
	}
	jsonPayload, err := json.Marshal(variables)
	if err != nil {
		log.Fatal(err)
		failJob(client, job, err)
		return
	}

	_, err = doHTTPCall(string(jsonPayload))
	if err != nil {
		// couldn't do http call, fail job to trigger retry
		failJob(client, job, err)
	} else {
		// complete job after processing
		completeJob(client, job, true)
	}
}

func completeJob(client worker.JobClient, job entities.Job, success bool) {
	variables := make(map[string]interface{})
	variables["chargeSuccess"] = success

	request, err := client.NewCompleteJobCommand().JobKey(job.GetKey()).VariablesFromMap(variables)
	if err != nil {
		failJob(client, job, err)
		return
	}
	log.Println("Complete job", job, success)
	request.Send()
}

func failJob(client worker.JobClient, job entities.Job, err error) {
	log.Println("Failed to complete job", job.GetKey(), err)
	if job.Retries > 1 {
		client.NewFailJobCommand().JobKey(job.GetKey()).Retries(job.Retries - 1).Send()
	} else {
		// if no more retries left, complete the task but mark it for being failed
		completeJob(client, job, false)
	}
}

func doHTTPCall(someDataAsJSON string) (resp *http.Response, err error) {
	fmt.Println("Doing http call", someDataAsJSON)
	return http.Post("http://localhost:8099/charge", "application/json", strings.NewReader(someDataAsJSON))
}
<|endoftext|>


<commit_before>package config

import (
	"fmt"
	"github.com/mypurecloud/platform-client-sdk-cli/build/gc/models"
	"os"

	"github.com/spf13/viper"
)

type Configuration interface {
	ProfileName() string
	Environment() string
	ClientID() string
	ClientSecret() string
	OAuthTokenData() string
	fmt.Stringer
}

type configuration struct {
	profileName  string
	environment  string
	clientID     string
	clientSecret string
	oAuthTokenData   string
}

//ProfileName is the name of the profile being used to run the CLI
func (c *configuration) ProfileName() string {
	return c.profileName
}

//ClientID is the OAuth client id used by the OAuth Client
func (c *configuration) ClientID() string {
	return viper.GetString(fmt.Sprintf("%s.client_credentials", c.profileName))
}

//ClientSecret is the OAuth client secret used by the OAuth Client
func (c *configuration) ClientSecret() string {
	return viper.GetString(fmt.Sprintf("%s.client_secret", c.profileName))
}

//OAuthTokenData is the raw OAuth token data returned from the login API call combined with the access token expiry timestamp
func (c *configuration) OAuthTokenData() string {
	return viper.GetString(fmt.Sprintf("%s.oauth_token_data", c.profileName))
}

//Environment is the Genesys Cloud Environment the CLI will talk to
func (c *configuration) Environment() string {
	return viper.GetString(fmt.Sprintf("%s.environment", c.profileName))
}

func (c *configuration) String() string {
	return fmt.Sprintf(`{"profileName": "%s", "environment": "%s", "clientName": "%s", "clientSecret": "%s"}`, c.ProfileName(), c.Environment(), c.ClientID(), c.ClientSecret())
}

//GetConfig retrieves the config for the current profile
func GetConfig(profileName string) (Configuration, error) {
	if err := viper.ReadInConfig(); err != nil {
		return nil, fmt.Errorf("Error reading config file, %s", err)
	}

	profile := viper.GetViper().Get(profileName)

	if profile == nil {
		return nil, fmt.Errorf("The profile named %s passed can not be located in the config file.", profileName)
	}

	return &configuration{profileName: profileName,
		clientID:         viper.GetString(fmt.Sprintf("%s.client_credentials", profileName)),
		clientSecret:     viper.GetString(fmt.Sprintf("%s.client_secret", profileName)),
		environment:      viper.GetString(fmt.Sprintf("%s.environment", profileName)),
		oAuthTokenData:   viper.GetString(fmt.Sprintf("%s.oauth_token_data", profileName)),
	}, nil
}

func ListConfigs() ([]configuration, error) {
	if err := viper.ReadInConfig(); err != nil {
		return nil, fmt.Errorf("Error reading config file, %s", err)
	}

	settings := viper.GetViper().AllSettings()
	if settings == nil || len(settings) == 0 {
		return nil, fmt.Errorf("No profiles have been found.")
	}

	configurations := make([]configuration, 0)
	for profileName, _ := range settings {
		configurations = append(configurations, configuration{
			profileName:      profileName,
			clientID:         viper.GetString(fmt.Sprintf("%s.client_credentials", profileName)),
			clientSecret:     viper.GetString(fmt.Sprintf("%s.client_secret", profileName)),
			environment:      viper.GetString(fmt.Sprintf("%s.environment", profileName)),
			oAuthTokenData:   viper.GetString(fmt.Sprintf("%s.oauth_token_data", profileName)),
		})
	}

	return configurations, nil
}

func SaveConfig(config Configuration) error {
	return writeConfig(config, nil)
}

func UpdateOAuthToken(config Configuration, data *models.OAuthTokenData) error {
	return writeConfig(config, data)
}

func writeConfig(config Configuration, data *models.OAuthTokenData) error {
	viper.Set(fmt.Sprintf("%s.client_credentials", config.ProfileName()), config.ClientID())
	viper.Set(fmt.Sprintf("%s.client_secret", config.ProfileName()), config.ClientSecret())
	viper.Set(fmt.Sprintf("%s.environment", config.ProfileName()), config.Environment())
	if data != nil {
		viper.Set(fmt.Sprintf("%s.oauth_token_data", config.ProfileName()), data.String())
	}
	//Checking to see if the file does not exist.  It it doesnt we write out the config as default config.toml
	if err := viper.ReadInConfig(); err != nil {
		if _, ok := err.(viper.ConfigFileNotFoundError); ok {
			homeDir, _ := os.UserHomeDir()
			gcDir := fmt.Sprintf("%s/.gc", homeDir)
			if _, err := os.Stat(gcDir); os.IsNotExist(err) {
				err = os.Mkdir(gcDir, 0755)
				if err != nil {
					return err
				}
			}
			return viper.WriteConfigAs(fmt.Sprintf("%s/config.toml", gcDir))
		}
	}

	return viper.WriteConfig()
}
<commit_msg>Add trace message when no config file is found<commit_after>package config

import (
	"fmt"
	"os"

	"github.com/mypurecloud/platform-client-sdk-cli/build/gc/models"

	"github.com/spf13/viper"
)

type Configuration interface {
	ProfileName() string
	Environment() string
	ClientID() string
	ClientSecret() string
	OAuthTokenData() string
	fmt.Stringer
}

type configuration struct {
	profileName    string
	environment    string
	clientID       string
	clientSecret   string
	oAuthTokenData string
}

//ProfileName is the name of the profile being used to run the CLI
func (c *configuration) ProfileName() string {
	return c.profileName
}

//ClientID is the OAuth client id used by the OAuth Client
func (c *configuration) ClientID() string {
	return viper.GetString(fmt.Sprintf("%s.client_credentials", c.profileName))
}

//ClientSecret is the OAuth client secret used by the OAuth Client
func (c *configuration) ClientSecret() string {
	return viper.GetString(fmt.Sprintf("%s.client_secret", c.profileName))
}

//OAuthTokenData is the raw OAuth token data returned from the login API call combined with the access token expiry timestamp
func (c *configuration) OAuthTokenData() string {
	return viper.GetString(fmt.Sprintf("%s.oauth_token_data", c.profileName))
}

//Environment is the Genesys Cloud Environment the CLI will talk to
func (c *configuration) Environment() string {
	return viper.GetString(fmt.Sprintf("%s.environment", c.profileName))
}

func (c *configuration) String() string {
	return fmt.Sprintf(`{"profileName": "%s", "environment": "%s", "clientName": "%s", "clientSecret": "%s"}`, c.ProfileName(), c.Environment(), c.ClientID(), c.ClientSecret())
}

//GetConfig retrieves the config for the current profile
func GetConfig(profileName string) (Configuration, error) {
	if err := viper.ReadInConfig(); err != nil {
		if _, ok := err.(viper.ConfigFileNotFoundError); ok {
			homeDir, _ := os.UserHomeDir()
			configDir := fmt.Sprintf("%s/.gc/config.toml", homeDir)
			return nil, fmt.Errorf(`Failed to load config file in "%s". Please use "gc profiles" command to configure the CLI profiles`, configDir)
		} else {
			return nil, fmt.Errorf("Error reading config file, %s", err)
		}
	}

	profile := viper.GetViper().Get(profileName)

	if profile == nil {
		return nil, fmt.Errorf("The profile named %s passed can not be located in the config file.", profileName)
	}

	return &configuration{profileName: profileName,
		clientID:       viper.GetString(fmt.Sprintf("%s.client_credentials", profileName)),
		clientSecret:   viper.GetString(fmt.Sprintf("%s.client_secret", profileName)),
		environment:    viper.GetString(fmt.Sprintf("%s.environment", profileName)),
		oAuthTokenData: viper.GetString(fmt.Sprintf("%s.oauth_token_data", profileName)),
	}, nil
}

func ListConfigs() ([]configuration, error) {
	if err := viper.ReadInConfig(); err != nil {
		if _, ok := err.(viper.ConfigFileNotFoundError); ok {
			homeDir, _ := os.UserHomeDir()
			configDir := fmt.Sprintf("%s/.gc/config.toml", homeDir)
			return nil, fmt.Errorf(`Failed to load config file in "%s". Please use "gc profiles" command to configure the CLI profiles`, configDir)
		} else {
			return nil, fmt.Errorf("Error reading config file, %s", err)
		}
	}

	settings := viper.GetViper().AllSettings()
	if settings == nil || len(settings) == 0 {
		return nil, fmt.Errorf("No profiles have been found.")
	}

	configurations := make([]configuration, 0)
	for profileName, _ := range settings {
		configurations = append(configurations, configuration{
			profileName:    profileName,
			clientID:       viper.GetString(fmt.Sprintf("%s.client_credentials", profileName)),
			clientSecret:   viper.GetString(fmt.Sprintf("%s.client_secret", profileName)),
			environment:    viper.GetString(fmt.Sprintf("%s.environment", profileName)),
			oAuthTokenData: viper.GetString(fmt.Sprintf("%s.oauth_token_data", profileName)),
		})
	}

	return configurations, nil
}

func SaveConfig(config Configuration) error {
	return writeConfig(config, nil)
}

func UpdateOAuthToken(config Configuration, data *models.OAuthTokenData) error {
	return writeConfig(config, data)
}

func writeConfig(config Configuration, data *models.OAuthTokenData) error {
	viper.Set(fmt.Sprintf("%s.client_credentials", config.ProfileName()), config.ClientID())
	viper.Set(fmt.Sprintf("%s.client_secret", config.ProfileName()), config.ClientSecret())
	viper.Set(fmt.Sprintf("%s.environment", config.ProfileName()), config.Environment())
	if data != nil {
		viper.Set(fmt.Sprintf("%s.oauth_token_data", config.ProfileName()), data.String())
	}
	//Checking to see if the file does not exist.  It it doesnt we write out the config as default config.toml
	if err := viper.ReadInConfig(); err != nil {
		if _, ok := err.(viper.ConfigFileNotFoundError); ok {
			homeDir, _ := os.UserHomeDir()
			gcDir := fmt.Sprintf("%s/.gc", homeDir)
			if _, err := os.Stat(gcDir); os.IsNotExist(err) {
				err = os.Mkdir(gcDir, 0755)
				if err != nil {
					return err
				}
			}
			return viper.WriteConfigAs(fmt.Sprintf("%s/config.toml", gcDir))
		}
	}

	return viper.WriteConfig()
}
<|endoftext|>


<commit_before>// Copyright 2016 The Prometheus 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.

package discovery

import (
	"context"
	"fmt"

	"github.com/go-kit/kit/log"
	"github.com/go-kit/kit/log/level"

	"github.com/prometheus/prometheus/config"
	sd_config "github.com/prometheus/prometheus/discovery/config"
	"github.com/prometheus/prometheus/discovery/targetgroup"

	"github.com/prometheus/prometheus/discovery/azure"
	"github.com/prometheus/prometheus/discovery/consul"
	"github.com/prometheus/prometheus/discovery/dns"
	"github.com/prometheus/prometheus/discovery/ec2"
	"github.com/prometheus/prometheus/discovery/file"
	"github.com/prometheus/prometheus/discovery/gce"
	"github.com/prometheus/prometheus/discovery/kubernetes"
	"github.com/prometheus/prometheus/discovery/marathon"
	"github.com/prometheus/prometheus/discovery/openstack"
	"github.com/prometheus/prometheus/discovery/triton"
	"github.com/prometheus/prometheus/discovery/zookeeper"
)

// Discoverer provides information about target groups. It maintains a set
// of sources from which TargetGroups can originate. Whenever a discovery provider
// detects a potential change, it sends the TargetGroup through its channel.
//
// Discoverer does not know if an actual change happened.
// It does guarantee that it sends the new TargetGroup whenever a change happens.
//
// Discoverers should initially send a full set of all discoverable TargetGroups.
type Discoverer interface {
	// Run hands a channel to the discovery provider(consul,dns etc) through which it can send
	// updated target groups.
	// Must returns if the context gets canceled. It should not close the update
	// channel on returning.
	Run(ctx context.Context, up chan<- []*targetgroup.Group)
}

type poolKey struct {
	setName  string
	provider string
}

// NewManager is the Discovery Manager constructor
func NewManager(logger log.Logger) *Manager {
	return &Manager{
		logger:         logger,
		actionCh:       make(chan func(context.Context)),
		syncCh:         make(chan map[string][]*targetgroup.Group),
		targets:        make(map[poolKey]map[string]*targetgroup.Group),
		discoverCancel: []context.CancelFunc{},
	}
}

// Manager maintains a set of discovery providers and sends each update to a channel used by other packages.
type Manager struct {
	logger         log.Logger
	actionCh       chan func(context.Context)
	discoverCancel []context.CancelFunc
	// Some Discoverers(eg. k8s) send only the updates for a given target group
	// so we use map[tg.Source]*targetgroup.Group to know which group to update.
	targets map[poolKey]map[string]*targetgroup.Group
	// The sync channels sends the updates in map[targetSetName] where targetSetName is the job value from the scrape config.
	syncCh chan map[string][]*targetgroup.Group
}

// Run starts the background processing
func (m *Manager) Run(ctx context.Context) error {
	for {
		select {
		case f := <-m.actionCh:
			f(ctx)
		case <-ctx.Done():
			m.cancelDiscoverers()
			return ctx.Err()
		}
	}
}

// SyncCh returns a read only channel used by all Discoverers to send target updates.
func (m *Manager) SyncCh() <-chan map[string][]*targetgroup.Group {
	return m.syncCh
}

// ApplyConfig removes all running discovery providers and starts new ones using the provided config.
func (m *Manager) ApplyConfig(cfg *config.Config) error {
	err := make(chan error)
	m.actionCh <- func(ctx context.Context) {
		m.cancelDiscoverers()
		for _, scfg := range cfg.ScrapeConfigs {
			for provName, prov := range m.providersFromConfig(scfg.ServiceDiscoveryConfig) {
				m.startProvider(ctx, poolKey{setName: scfg.JobName, provider: provName}, prov)
			}
		}
		close(err)
	}

	return <-err
}

func (m *Manager) startProvider(ctx context.Context, poolKey poolKey, worker Discoverer) {
	ctx, cancel := context.WithCancel(ctx)
	updates := make(chan []*targetgroup.Group)

	m.discoverCancel = append(m.discoverCancel, cancel)

	go worker.Run(ctx, updates)
	go m.runProvider(ctx, poolKey, updates)
}

func (m *Manager) runProvider(ctx context.Context, poolKey poolKey, updates chan []*targetgroup.Group) {
	for {
		select {
		case <-ctx.Done():
			return
		case tgs, ok := <-updates:
			// Handle the case that a target provider exits and closes the channel
			// before the context is done.
			if !ok {
				return
			}
			m.updateGroup(poolKey, tgs)
			m.syncCh <- m.allGroups()
		}
	}
}

func (m *Manager) cancelDiscoverers() {
	for _, c := range m.discoverCancel {
		c()
	}
	m.targets = make(map[poolKey]map[string]*targetgroup.Group)
	m.discoverCancel = nil
}

func (m *Manager) updateGroup(poolKey poolKey, tgs []*targetgroup.Group) {
	done := make(chan struct{})

	m.actionCh <- func(ctx context.Context) {
		if tgs == nil {
			close(done)
			return
		}

		for _, tg := range tgs {
			if tg != nil { // Some Discoverers send nil targetgroup so need to check for it to avoid panics.
				if _, ok := m.targets[poolKey]; !ok {
					m.targets[poolKey] = make(map[string]*targetgroup.Group)
				}
				m.targets[poolKey][tg.Source] = tg
			}
		}
		close(done)

	}
	<-done
}

func (m *Manager) allGroups() map[string][]*targetgroup.Group {
	tSets := make(chan map[string][]*targetgroup.Group)

	m.actionCh <- func(ctx context.Context) {
		tSetsAll := map[string][]*targetgroup.Group{}
		for pkey, tsets := range m.targets {
			del := true
			for _, tg := range tsets {
				if len(tg.Targets) != 0 {
					tSetsAll[pkey.setName] = append(tSetsAll[pkey.setName], tg)
					del = false
				}
			}
			// Delete the empty map for this target set to avoid memory leaks.
			if del {
				delete(m.targets, pkey)
			}
		}
		tSets <- tSetsAll
	}
	return <-tSets

}

func (m *Manager) providersFromConfig(cfg sd_config.ServiceDiscoveryConfig) map[string]Discoverer {
	providers := map[string]Discoverer{}

	app := func(mech string, i int, tp Discoverer) {
		providers[fmt.Sprintf("%s/%d", mech, i)] = tp
	}

	for i, c := range cfg.DNSSDConfigs {
		app("dns", i, dns.NewDiscovery(*c, log.With(m.logger, "discovery", "dns")))
	}
	for i, c := range cfg.FileSDConfigs {
		app("file", i, file.NewDiscovery(c, log.With(m.logger, "discovery", "file")))
	}
	for i, c := range cfg.ConsulSDConfigs {
		k, err := consul.NewDiscovery(c, log.With(m.logger, "discovery", "consul"))
		if err != nil {
			level.Error(m.logger).Log("msg", "Cannot create Consul discovery", "err", err)
			continue
		}
		app("consul", i, k)
	}
	for i, c := range cfg.MarathonSDConfigs {
		t, err := marathon.NewDiscovery(*c, log.With(m.logger, "discovery", "marathon"))
		if err != nil {
			level.Error(m.logger).Log("msg", "Cannot create Marathon discovery", "err", err)
			continue
		}
		app("marathon", i, t)
	}
	for i, c := range cfg.KubernetesSDConfigs {
		k, err := kubernetes.New(log.With(m.logger, "discovery", "k8s"), c)
		if err != nil {
			level.Error(m.logger).Log("msg", "Cannot create Kubernetes discovery", "err", err)
			continue
		}
		app("kubernetes", i, k)
	}
	for i, c := range cfg.ServersetSDConfigs {
		app("serverset", i, zookeeper.NewServersetDiscovery(c, log.With(m.logger, "discovery", "zookeeper")))
	}
	for i, c := range cfg.NerveSDConfigs {
		app("nerve", i, zookeeper.NewNerveDiscovery(c, log.With(m.logger, "discovery", "nerve")))
	}
	for i, c := range cfg.EC2SDConfigs {
		app("ec2", i, ec2.NewDiscovery(c, log.With(m.logger, "discovery", "ec2")))
	}
	for i, c := range cfg.OpenstackSDConfigs {
		openstackd, err := openstack.NewDiscovery(c, log.With(m.logger, "discovery", "openstack"))
		if err != nil {
			level.Error(m.logger).Log("msg", "Cannot initialize OpenStack discovery", "err", err)
			continue
		}
		app("openstack", i, openstackd)
	}

	for i, c := range cfg.GCESDConfigs {
		gced, err := gce.NewDiscovery(*c, log.With(m.logger, "discovery", "gce"))
		if err != nil {
			level.Error(m.logger).Log("msg", "Cannot initialize GCE discovery", "err", err)
			continue
		}
		app("gce", i, gced)
	}
	for i, c := range cfg.AzureSDConfigs {
		app("azure", i, azure.NewDiscovery(c, log.With(m.logger, "discovery", "azure")))
	}
	for i, c := range cfg.TritonSDConfigs {
		t, err := triton.New(log.With(m.logger, "discovery", "trition"), c)
		if err != nil {
			level.Error(m.logger).Log("msg", "Cannot create Triton discovery", "err", err)
			continue
		}
		app("triton", i, t)
	}
	if len(cfg.StaticConfigs) > 0 {
		app("static", 0, NewStaticProvider(cfg.StaticConfigs))
	}

	return providers
}

// StaticProvider holds a list of target groups that never change.
type StaticProvider struct {
	TargetGroups []*targetgroup.Group
}

// NewStaticProvider returns a StaticProvider configured with the given
// target groups.
func NewStaticProvider(groups []*targetgroup.Group) *StaticProvider {
	for i, tg := range groups {
		tg.Source = fmt.Sprintf("%d", i)
	}
	return &StaticProvider{groups}
}

// Run implements the Worker interface.
func (sd *StaticProvider) Run(ctx context.Context, ch chan<- []*targetgroup.Group) {
	// We still have to consider that the consumer exits right away in which case
	// the context will be canceled.
	select {
	case ch <- sd.TargetGroups:
	case <-ctx.Done():
	}
	close(ch)
}
<commit_msg>few mote usefull comments<commit_after>// Copyright 2016 The Prometheus 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.

package discovery

import (
	"context"
	"fmt"

	"github.com/go-kit/kit/log"
	"github.com/go-kit/kit/log/level"

	"github.com/prometheus/prometheus/config"
	sd_config "github.com/prometheus/prometheus/discovery/config"
	"github.com/prometheus/prometheus/discovery/targetgroup"

	"github.com/prometheus/prometheus/discovery/azure"
	"github.com/prometheus/prometheus/discovery/consul"
	"github.com/prometheus/prometheus/discovery/dns"
	"github.com/prometheus/prometheus/discovery/ec2"
	"github.com/prometheus/prometheus/discovery/file"
	"github.com/prometheus/prometheus/discovery/gce"
	"github.com/prometheus/prometheus/discovery/kubernetes"
	"github.com/prometheus/prometheus/discovery/marathon"
	"github.com/prometheus/prometheus/discovery/openstack"
	"github.com/prometheus/prometheus/discovery/triton"
	"github.com/prometheus/prometheus/discovery/zookeeper"
)

// Discoverer provides information about target groups. It maintains a set
// of sources from which TargetGroups can originate. Whenever a discovery provider
// detects a potential change, it sends the TargetGroup through its channel.
//
// Discoverer does not know if an actual change happened.
// It does guarantee that it sends the new TargetGroup whenever a change happens.
//
// Discoverers should initially send a full set of all discoverable TargetGroups.
type Discoverer interface {
	// Run hands a channel to the discovery provider(consul,dns etc) through which it can send
	// updated target groups.
	// Must returns if the context gets canceled. It should not close the update
	// channel on returning.
	Run(ctx context.Context, up chan<- []*targetgroup.Group)
}

type poolKey struct {
	setName  string
	provider string
}

// NewManager is the Discovery Manager constructor
func NewManager(logger log.Logger) *Manager {
	return &Manager{
		logger:         logger,
		actionCh:       make(chan func(context.Context)),
		syncCh:         make(chan map[string][]*targetgroup.Group),
		targets:        make(map[poolKey]map[string]*targetgroup.Group),
		discoverCancel: []context.CancelFunc{},
	}
}

// Manager maintains a set of discovery providers and sends each update to a channel used by other packages.
// Targets are grouped by target set names.
// When a given target set doesn't include any targets the manager doesn't send any updates for this target set.
type Manager struct {
	logger         log.Logger
	actionCh       chan func(context.Context)
	discoverCancel []context.CancelFunc
	// Some Discoverers(eg. k8s) send only the updates for a given target group
	// so we use map[tg.Source]*targetgroup.Group to know which group to update.
	targets map[poolKey]map[string]*targetgroup.Group
	// The sync channels sends the updates in map[targetSetName] where targetSetName is the job value from the scrape config.
	syncCh chan map[string][]*targetgroup.Group
}

// Run starts the background processing
func (m *Manager) Run(ctx context.Context) error {
	for {
		select {
		case f := <-m.actionCh:
			f(ctx)
		case <-ctx.Done():
			m.cancelDiscoverers()
			return ctx.Err()
		}
	}
}

// SyncCh returns a read only channel used by all Discoverers to send target updates.
func (m *Manager) SyncCh() <-chan map[string][]*targetgroup.Group {
	return m.syncCh
}

// ApplyConfig removes all running discovery providers and starts new ones using the provided config.
func (m *Manager) ApplyConfig(cfg *config.Config) error {
	err := make(chan error)
	m.actionCh <- func(ctx context.Context) {
		m.cancelDiscoverers()
		for _, scfg := range cfg.ScrapeConfigs {
			for provName, prov := range m.providersFromConfig(scfg.ServiceDiscoveryConfig) {
				m.startProvider(ctx, poolKey{setName: scfg.JobName, provider: provName}, prov)
			}
		}
		close(err)
	}

	return <-err
}

func (m *Manager) startProvider(ctx context.Context, poolKey poolKey, worker Discoverer) {
	ctx, cancel := context.WithCancel(ctx)
	updates := make(chan []*targetgroup.Group)

	m.discoverCancel = append(m.discoverCancel, cancel)

	go worker.Run(ctx, updates)
	go m.runProvider(ctx, poolKey, updates)
}

func (m *Manager) runProvider(ctx context.Context, poolKey poolKey, updates chan []*targetgroup.Group) {
	for {
		select {
		case <-ctx.Done():
			return
		case tgs, ok := <-updates:
			// Handle the case that a target provider exits and closes the channel
			// before the context is done.
			if !ok {
				return
			}
			m.updateGroup(poolKey, tgs)
			m.syncCh <- m.allGroups()
		}
	}
}

func (m *Manager) cancelDiscoverers() {
	for _, c := range m.discoverCancel {
		c()
	}
	m.targets = make(map[poolKey]map[string]*targetgroup.Group)
	m.discoverCancel = nil
}

func (m *Manager) updateGroup(poolKey poolKey, tgs []*targetgroup.Group) {
	done := make(chan struct{})

	m.actionCh <- func(ctx context.Context) {
		if tgs == nil {
			close(done)
			return
		}

		for _, tg := range tgs {
			if tg != nil { // Some Discoverers send nil target group so need to check for it to avoid panics.
				if _, ok := m.targets[poolKey]; !ok {
					m.targets[poolKey] = make(map[string]*targetgroup.Group)
				}
				m.targets[poolKey][tg.Source] = tg
			}
		}
		close(done)

	}
	<-done
}

func (m *Manager) allGroups() map[string][]*targetgroup.Group {
	tSets := make(chan map[string][]*targetgroup.Group)

	m.actionCh <- func(ctx context.Context) {
		tSetsAll := map[string][]*targetgroup.Group{}
		for pkey, tsets := range m.targets {
			del := true
			for _, tg := range tsets {
				// Don't add a target set if the target group has no targets.
				// This happens when a Discoverer sends an empty targets array for a group to indicate that these targets have been removed.
				if len(tg.Targets) != 0 {
					tSetsAll[pkey.setName] = append(tSetsAll[pkey.setName], tg)
					del = false
				}
			}
			// Delete the empty map for this target set to avoid memory leaks.
			if del {
				delete(m.targets, pkey)
			}
		}
		tSets <- tSetsAll
	}
	return <-tSets

}

func (m *Manager) providersFromConfig(cfg sd_config.ServiceDiscoveryConfig) map[string]Discoverer {
	providers := map[string]Discoverer{}

	app := func(mech string, i int, tp Discoverer) {
		providers[fmt.Sprintf("%s/%d", mech, i)] = tp
	}

	for i, c := range cfg.DNSSDConfigs {
		app("dns", i, dns.NewDiscovery(*c, log.With(m.logger, "discovery", "dns")))
	}
	for i, c := range cfg.FileSDConfigs {
		app("file", i, file.NewDiscovery(c, log.With(m.logger, "discovery", "file")))
	}
	for i, c := range cfg.ConsulSDConfigs {
		k, err := consul.NewDiscovery(c, log.With(m.logger, "discovery", "consul"))
		if err != nil {
			level.Error(m.logger).Log("msg", "Cannot create Consul discovery", "err", err)
			continue
		}
		app("consul", i, k)
	}
	for i, c := range cfg.MarathonSDConfigs {
		t, err := marathon.NewDiscovery(*c, log.With(m.logger, "discovery", "marathon"))
		if err != nil {
			level.Error(m.logger).Log("msg", "Cannot create Marathon discovery", "err", err)
			continue
		}
		app("marathon", i, t)
	}
	for i, c := range cfg.KubernetesSDConfigs {
		k, err := kubernetes.New(log.With(m.logger, "discovery", "k8s"), c)
		if err != nil {
			level.Error(m.logger).Log("msg", "Cannot create Kubernetes discovery", "err", err)
			continue
		}
		app("kubernetes", i, k)
	}
	for i, c := range cfg.ServersetSDConfigs {
		app("serverset", i, zookeeper.NewServersetDiscovery(c, log.With(m.logger, "discovery", "zookeeper")))
	}
	for i, c := range cfg.NerveSDConfigs {
		app("nerve", i, zookeeper.NewNerveDiscovery(c, log.With(m.logger, "discovery", "nerve")))
	}
	for i, c := range cfg.EC2SDConfigs {
		app("ec2", i, ec2.NewDiscovery(c, log.With(m.logger, "discovery", "ec2")))
	}
	for i, c := range cfg.OpenstackSDConfigs {
		openstackd, err := openstack.NewDiscovery(c, log.With(m.logger, "discovery", "openstack"))
		if err != nil {
			level.Error(m.logger).Log("msg", "Cannot initialize OpenStack discovery", "err", err)
			continue
		}
		app("openstack", i, openstackd)
	}

	for i, c := range cfg.GCESDConfigs {
		gced, err := gce.NewDiscovery(*c, log.With(m.logger, "discovery", "gce"))
		if err != nil {
			level.Error(m.logger).Log("msg", "Cannot initialize GCE discovery", "err", err)
			continue
		}
		app("gce", i, gced)
	}
	for i, c := range cfg.AzureSDConfigs {
		app("azure", i, azure.NewDiscovery(c, log.With(m.logger, "discovery", "azure")))
	}
	for i, c := range cfg.TritonSDConfigs {
		t, err := triton.New(log.With(m.logger, "discovery", "trition"), c)
		if err != nil {
			level.Error(m.logger).Log("msg", "Cannot create Triton discovery", "err", err)
			continue
		}
		app("triton", i, t)
	}
	if len(cfg.StaticConfigs) > 0 {
		app("static", 0, NewStaticProvider(cfg.StaticConfigs))
	}

	return providers
}

// StaticProvider holds a list of target groups that never change.
type StaticProvider struct {
	TargetGroups []*targetgroup.Group
}

// NewStaticProvider returns a StaticProvider configured with the given
// target groups.
func NewStaticProvider(groups []*targetgroup.Group) *StaticProvider {
	for i, tg := range groups {
		tg.Source = fmt.Sprintf("%d", i)
	}
	return &StaticProvider{groups}
}

// Run implements the Worker interface.
func (sd *StaticProvider) Run(ctx context.Context, ch chan<- []*targetgroup.Group) {
	// We still have to consider that the consumer exits right away in which case
	// the context will be canceled.
	select {
	case ch <- sd.TargetGroups:
	case <-ctx.Done():
	}
	close(ch)
}
<|endoftext|>


<commit_before>package mgo

import (
	"errors"
	"gopkg.in/mgo.v2/bson"
)

// 在指定集合进行条件查询
type Find struct {
	Database   string                 // 数据库
	Collection string                 // 集合
	Query      map[string]interface{} // 查询语句
	Sort       []string               // 排序，用法如Sort("firstname", "-lastname")，优先按firstname正序排列，其次按lastname倒序排列
	Skip       int                    // 跳过前n个文档
	Limit      int                    // 返回最多n个文档
	Select     interface{}            // 只查询、返回指定字段，如{"name":1}
	// Result     struct {
	// 	Docs  []interface{}
	// 	Total int
	// }
}

func (self *Find) Exec() (interface{}, error) {
	s, c, err := Open(self.Database, self.Collection)
	defer Close(s)
	if err != nil {
		return nil, err
	}

	if id, ok := self.Query["_id"]; ok {
		if idStr, ok2 := id.(string); !ok2 {
			return nil, errors.New("参数 _id 必须为 string 类型！")
		} else {
			self.Query["_id"] = bson.ObjectIdHex(idStr)
		}
	}

	var result = make(map[string]interface{})

	q := c.Find(self.Query)

	result["total"], _ = q.Count()

	if len(self.Sort) > 0 {
		q.Sort(self.Sort...)
	}

	if self.Skip > 0 {
		q.Skip(self.Skip)
	}

	if self.Limit > 0 {
		q.Limit(self.Limit)
	}

	if self.Select != nil {
		q.Select(self.Select)
	}

	err = q.All(result["docs"])
	return result, err
}
<commit_msg>修复mgo find操作<commit_after>package mgo

import (
	"errors"
	"gopkg.in/mgo.v2/bson"
)

// 在指定集合进行条件查询
type Find struct {
	Database   string                 // 数据库
	Collection string                 // 集合
	Query      map[string]interface{} // 查询语句
	Sort       []string               // 排序，用法如Sort("firstname", "-lastname")，优先按firstname正序排列，其次按lastname倒序排列
	Skip       int                    // 跳过前n个文档
	Limit      int                    // 返回最多n个文档
	Select     interface{}            // 只查询、返回指定字段，如{"name":1}
	// Result     struct {
	// 	Docs  []interface{}
	// 	Total int
	// }
}

func (self *Find) Exec() (interface{}, error) {
	s, c, err := Open(self.Database, self.Collection)
	defer Close(s)
	if err != nil {
		return nil, err
	}

	if id, ok := self.Query["_id"]; ok {
		if idStr, ok2 := id.(string); !ok2 {
			return nil, errors.New("参数 _id 必须为 string 类型！")
		} else {
			self.Query["_id"] = bson.ObjectIdHex(idStr)
		}
	}

	var result = make(map[string]interface{})

	q := c.Find(self.Query)

	result["Total"], _ = q.Count()

	if len(self.Sort) > 0 {
		q.Sort(self.Sort...)
	}

	if self.Skip > 0 {
		q.Skip(self.Skip)
	}

	if self.Limit > 0 {
		q.Limit(self.Limit)
	}

	if self.Select != nil {
		q.Select(self.Select)
	}
	r := []interface{}{}
	err = q.All(&r)
	result["Docs"] = r
	return result, err
}
<|endoftext|>


<commit_before>// asmcheck

// Copyright 2021 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 main

func a(n string) bool {
	// arm64:"CBZ"
	if len(n) > 0 {
		return true
	}
	return false
}

func a2(n []int) bool {
	// arm64:"CBZ"
	if len(n) > 0 {
		return true
	}
	return false
}

func a3(n []int) bool {
	// amd64:"TESTQ"
	if len(n) < 1 {
		return true
	}
	return false
}
<commit_msg>test/codegen: fix package name for test case<commit_after>// asmcheck

// Copyright 2021 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 codegen

func a(n string) bool {
	// arm64:"CBZ"
	if len(n) > 0 {
		return true
	}
	return false
}

func a2(n []int) bool {
	// arm64:"CBZ"
	if len(n) > 0 {
		return true
	}
	return false
}

func a3(n []int) bool {
	// amd64:"TESTQ"
	if len(n) < 1 {
		return true
	}
	return false
}
<|endoftext|>


<commit_before>package nv

import (
	"bytes"
	"encoding/binary"
	"errors"
	"fmt"
	"io"
	"reflect"
	"runtime"
	"time"

	xdr "github.com/davecgh/go-xdr/xdr2"
)

// Decode
// Note: care should be taken when decoding into a `map[string]interface{}` as
// bytes/uint8s (and their array forms) can not be distinguished and will be
// treated as uint8/[]uint8.
func Decode(data []byte, target interface{}) (err error) {
	// Catch any panics from reflection
	defer func() {
		if r := recover(); r != nil {
			if _, ok := r.(runtime.Error); ok {
				panic(r)
			}
			if rs, ok := r.(string); ok {
				err = errors.New(rs)
			} else {
				err = r.(error)
			}
		}
	}()

	b := bytes.NewReader(data)

	// Validate data encoding
	enc := encoding{}
	if err := binary.Read(b, binary.BigEndian, &enc); err != nil {
		return err
	}
	if enc.Encoding > 1 {
		return fmt.Errorf("invalid encoding: %v", enc.Encoding)
	}
	if enc.Endianess > 1 {
		return fmt.Errorf("invalid endianess: %v", enc.Endianess)
	}
	if enc.Reserved1 != 0 {
		return fmt.Errorf("unexpected reserved1 value: %v", enc.Reserved1)
	}
	if enc.Reserved2 != 0 {
		return fmt.Errorf("unexpected reserved2 value: %v", enc.Reserved2)
	}

	// Validate target
	targetV := reflect.ValueOf(target)
	if targetV.Kind() != reflect.Ptr {
		return fmt.Errorf("cannot decode into non-pointer: %v", reflect.TypeOf(targetV).String())
	}
	if targetV.IsNil() {
		return fmt.Errorf("cannot decode into nil")
	}

	return decodeListStruct(b, reflect.Indirect(targetV))
}

func decodeListStruct(r io.ReadSeeker, target reflect.Value) error {
	// Validate data header
	var h header
	if err := binary.Read(r, binary.BigEndian, &h); err != nil {
		return err
	}
	if h.Version != 0 {
		return fmt.Errorf("unexpected version: %v", h.Version)
	}
	if h.Flag < _UNIQUE_NAME || h.Flag > _UNIQUE_NAME_TYPE {
		return fmt.Errorf("unexpected Flag: %v", h.Flag)
	}

	// Make sure the target is not a pointer. If it is, initilize and
	// dereference.
	if target.Kind() == reflect.Ptr {
		target.Set(reflect.New(target.Type().Elem()))
		target = reflect.Indirect(target)
	}

	// Maps and structs have slightly different handling
	// Interface types will be handled as maps
	isMap := (target.Kind() == reflect.Map || target.Kind() == reflect.Interface)

	if isMap {
		// Initialize the map. Can't add keys without this.
		if target.Kind() == reflect.Interface {
			target.Set(reflect.MakeMap(reflect.TypeOf(map[string]interface{}{})))
			target = target.Elem()
		} else {
			target.Set(reflect.MakeMap(target.Type()))
		}
	}

	// Special map alias that collects values and nvlist types
	isList := target.Type().String() == "nv.list"

	// For structs, create the lookup table for field name/tag -> field index
	var targetFieldIndexMap map[string]int
	if !isMap {
		targetFieldIndexMap = fieldIndexMap(target)
	}

	// Start decoding data
	for {
		// Done when there's no more data or an error has occured
		if end, err := isEnd(r); end || err != nil {
			return err
		}

		// Get next encoded data pair
		// Note: This just gets the data pair metadata. The actual value data
		// is left on the reader, to be pulled off by the decoder.
		dataPair := pair{}
		if _, err := xdr.Unmarshal(r, &dataPair); err != nil {
			return err
		}

		// If not dealing with a map, look up the corresponding struct field
		var targetField reflect.Value
		if !isMap {
			targetFieldIndex, ok := targetFieldIndexMap[dataPair.Name]
			// If there's no corresponding struct field, skip the data and move
			// on to the next data pair
			if !ok {
				r.Seek(int64(dataPair.EncodedSize-uint32(dataPair.headerSize())), 1)
				continue
			} else {
				targetField = target.Field(targetFieldIndex)
			}
		}

		// val used to set if target is a map
		var val reflect.Value
		// fieldSetFunc used to set if target is a struct field
		var fieldSetFunc func()

		var err error
		var v interface{}
		dec := newDecoder(r)
		switch dataPair.Type {
		case _BOOLEAN:
			v := Boolean(true)
			val = reflect.ValueOf(v)
			fieldSetFunc = func() {
				targetField.Set(val)
			}
		case _BOOLEAN_VALUE:
			v, err = dec.DecodeBool()
			val = reflect.ValueOf(v)
			fieldSetFunc = func() {
				targetField.SetBool(v.(bool))
			}
		case _BYTE:
			v, err = dec.DecodeByte()
			val = reflect.ValueOf(v)
			fieldSetFunc = func() {
				targetField.SetUint(uint64(v.(uint8)))
			}
		case _INT8:
			v, err = dec.DecodeInt8()
			val = reflect.ValueOf(v)
			fieldSetFunc = func() {
				targetField.SetInt(int64(v.(int8)))
			}
		case _INT16:
			v, err = dec.DecodeInt16()
			val = reflect.ValueOf(v)
			fieldSetFunc = func() {
				targetField.SetInt(int64(v.(int16)))
			}
		case _INT32:
			v, err = dec.DecodeInt32()
			val = reflect.ValueOf(v)
			fieldSetFunc = func() {
				targetField.SetInt(int64(v.(int32)))
			}
		case _INT64:
			v, err = dec.DecodeInt64()
			val = reflect.ValueOf(v)
			fieldSetFunc = func() {
				targetField.SetInt(v.(int64))
			}
		case _UINT8:
			v, err = dec.DecodeUint8()
			val = reflect.ValueOf(v)
			fieldSetFunc = func() {
				targetField.SetUint(uint64(v.(uint8)))
			}
		case _UINT16:
			v, err = dec.DecodeUint16()
			val = reflect.ValueOf(v)
			fieldSetFunc = func() {
				targetField.SetUint(uint64(v.(uint16)))
			}
		case _UINT32:
			v, err = dec.DecodeUint32()
			val = reflect.ValueOf(v)
			fieldSetFunc = func() {
				targetField.SetUint(uint64(v.(uint32)))
			}
		case _UINT64:
			v, err = dec.DecodeUint64()
			val = reflect.ValueOf(v)
			fieldSetFunc = func() {
				targetField.SetUint(uint64(v.(uint64)))
			}
		case _HRTIME:
			v, err = dec.DecodeHRTime()
			val = reflect.ValueOf(v)
			fieldSetFunc = func() {
				targetField.SetInt(int64(v.(time.Duration)))
			}
		case _DOUBLE:
			v, err = dec.DecodeFloat64()
			val = reflect.ValueOf(v)
			fieldSetFunc = func() {
				targetField.SetFloat(v.(float64))
			}
		case _BOOLEAN_ARRAY:
			v, err = dec.DecodeBoolArray()
			val = reflect.ValueOf(v)
			fieldSetFunc = func() {
				targetField.Set(val)
			}
		case _BYTE_ARRAY:
			if _, err = r.Seek(-4, 1); err == nil {
				v, err = dec.DecodeByteArray()
				val = reflect.ValueOf(v)
				fieldSetFunc = func() {
					targetField.SetBytes(v.([]byte))
				}
			}
		case _INT8_ARRAY:
			v, err = dec.DecodeInt8Array()
			val = reflect.ValueOf(v)
			fieldSetFunc = func() {
				targetField.Set(val)
			}
		case _INT16_ARRAY:
			v, err = dec.DecodeInt16Array()
			val = reflect.ValueOf(v)
			fieldSetFunc = func() {
				targetField.Set(val)
			}
		case _INT32_ARRAY:
			v, err = dec.DecodeInt32Array()
			val = reflect.ValueOf(v)
			fieldSetFunc = func() {
				targetField.Set(val)
			}
		case _INT64_ARRAY:
			v, err = dec.DecodeInt64Array()
			val = reflect.ValueOf(v)
			fieldSetFunc = func() {
				targetField.Set(val)
			}
		case _UINT8_ARRAY:
			v, err = dec.DecodeUint8Array()
			val = reflect.ValueOf(v)
			fieldSetFunc = func() {
				targetField.Set(val)
			}
		case _UINT16_ARRAY:
			v, err = dec.DecodeUint16Array()
			val = reflect.ValueOf(v)
			fieldSetFunc = func() {
				targetField.Set(val)
			}
		case _UINT32_ARRAY:
			v, err = dec.DecodeUint32Array()
			val = reflect.ValueOf(v)
			fieldSetFunc = func() {
				targetField.Set(val)
			}
		case _UINT64_ARRAY:
			v, err = dec.DecodeUint64Array()
			val = reflect.ValueOf(v)
			fieldSetFunc = func() {
				targetField.Set(val)
			}
		case _STRING:
			v, err = dec.DecodeString()
			val = reflect.ValueOf(v)
			fieldSetFunc = func() {
				targetField.SetString(v.(string))
			}
		case _STRING_ARRAY:
			if _, err = r.Seek(-4, 1); err == nil {
				v, err = dec.DecodeStringArray()
				val = reflect.ValueOf(v)
				fieldSetFunc = func() {
					targetField.Set(val)
				}
			}
		case _NVLIST:
			if isList {
				val = reflect.Indirect(reflect.New(target.Type()))
			} else if isMap {
				val = reflect.Indirect(reflect.New(target.Type().Elem()))
			} else {
				val = reflect.Indirect(reflect.New(targetField.Type()))
			}
			err = decodeListStruct(r, val)
			fieldSetFunc = func() {
				targetField.Set(val)
			}
		case _NVLIST_ARRAY:
			var sliceType reflect.Type
			if isList {
				sliceType = target.Type()
			} else if isMap {
				sliceType = target.Type().Elem()
			} else {
				sliceType = targetField.Type()
			}

			if sliceType.Kind() == reflect.Interface {
				sliceType = reflect.TypeOf([]map[string]interface{}{})
			}

			val = reflect.MakeSlice(sliceType, 0, int(dataPair.NElements))
			for i := uint32(0); i < dataPair.NElements; i++ {
				elem := reflect.Indirect(reflect.New(sliceType.Elem()))
				err = decodeListStruct(r, elem)
				if err != nil {
					break
				}
				val = reflect.Append(val, elem)
			}
			fieldSetFunc = func() {
				targetField.Set(val)
			}
		default:
			return fmt.Errorf("unknown type: %v", dataPair.Type)
		}

		if err != nil {
			return err
		}

		// Set the value appropriately
		if isMap {
			name := reflect.ValueOf(dataPair.Name)
			if isList {
				val = reflect.ValueOf(map[string]interface{}{
					"type":  dataPair.Type.String(),
					"value": val.Interface(),
				})
			}
			target.SetMapIndex(name, val)
		} else {
			fieldSetFunc()
		}
	}
	return nil
}

// fieldIndexMap creates a map of field names, with tag name overrides,
// to their index
func fieldIndexMap(v reflect.Value) map[string]int {
	vFieldIndexMap := make(map[string]int)
	forEachField(v, func(i int, field reflect.Value) {
		// Skip fields that can't be set (e.g. unexported)
		if !field.CanSet() {
			return
		}
		name := v.Type().Field(i).Name
		if tags := getTags(i, v); len(tags) > 0 && tags[0] != "" {
			name = tags[0]
		}
		vFieldIndexMap[name] = i
	})
	return vFieldIndexMap
}

func isEnd(r io.ReadSeeker) (bool, error) {
	var end uint64
	err := binary.Read(r, binary.BigEndian, &end)
	if err != nil {
		return false, err
	}
	if end == 0 {
		return true, nil
	}
	_, err = r.Seek(-8, 1)
	return false, err
}
<commit_msg>rename decodeListStruct -> decodeList<commit_after>package nv

import (
	"bytes"
	"encoding/binary"
	"errors"
	"fmt"
	"io"
	"reflect"
	"runtime"
	"time"

	xdr "github.com/davecgh/go-xdr/xdr2"
)

// Decode
// Note: care should be taken when decoding into a `map[string]interface{}` as
// bytes/uint8s (and their array forms) can not be distinguished and will be
// treated as uint8/[]uint8.
func Decode(data []byte, target interface{}) (err error) {
	// Catch any panics from reflection
	defer func() {
		if r := recover(); r != nil {
			if _, ok := r.(runtime.Error); ok {
				panic(r)
			}
			if rs, ok := r.(string); ok {
				err = errors.New(rs)
			} else {
				err = r.(error)
			}
		}
	}()

	b := bytes.NewReader(data)

	// Validate data encoding
	enc := encoding{}
	if err := binary.Read(b, binary.BigEndian, &enc); err != nil {
		return err
	}
	if enc.Encoding > 1 {
		return fmt.Errorf("invalid encoding: %v", enc.Encoding)
	}
	if enc.Endianess > 1 {
		return fmt.Errorf("invalid endianess: %v", enc.Endianess)
	}
	if enc.Reserved1 != 0 {
		return fmt.Errorf("unexpected reserved1 value: %v", enc.Reserved1)
	}
	if enc.Reserved2 != 0 {
		return fmt.Errorf("unexpected reserved2 value: %v", enc.Reserved2)
	}

	// Validate target
	targetV := reflect.ValueOf(target)
	if targetV.Kind() != reflect.Ptr {
		return fmt.Errorf("cannot decode into non-pointer: %v", reflect.TypeOf(targetV).String())
	}
	if targetV.IsNil() {
		return fmt.Errorf("cannot decode into nil")
	}

	return decodeList(b, reflect.Indirect(targetV))
}

func decodeList(r io.ReadSeeker, target reflect.Value) error {
	// Validate data header
	var h header
	if err := binary.Read(r, binary.BigEndian, &h); err != nil {
		return err
	}
	if h.Version != 0 {
		return fmt.Errorf("unexpected version: %v", h.Version)
	}
	if h.Flag < _UNIQUE_NAME || h.Flag > _UNIQUE_NAME_TYPE {
		return fmt.Errorf("unexpected Flag: %v", h.Flag)
	}

	// Make sure the target is not a pointer. If it is, initilize and
	// dereference.
	if target.Kind() == reflect.Ptr {
		target.Set(reflect.New(target.Type().Elem()))
		target = reflect.Indirect(target)
	}

	// Maps and structs have slightly different handling
	// Interface types will be handled as maps
	isMap := (target.Kind() == reflect.Map || target.Kind() == reflect.Interface)

	if isMap {
		// Initialize the map. Can't add keys without this.
		if target.Kind() == reflect.Interface {
			target.Set(reflect.MakeMap(reflect.TypeOf(map[string]interface{}{})))
			target = target.Elem()
		} else {
			target.Set(reflect.MakeMap(target.Type()))
		}
	}

	// Special map alias that collects values and nvlist types
	isList := target.Type().String() == "nv.list"

	// For structs, create the lookup table for field name/tag -> field index
	var targetFieldIndexMap map[string]int
	if !isMap {
		targetFieldIndexMap = fieldIndexMap(target)
	}

	// Start decoding data
	for {
		// Done when there's no more data or an error has occured
		if end, err := isEnd(r); end || err != nil {
			return err
		}

		// Get next encoded data pair
		// Note: This just gets the data pair metadata. The actual value data
		// is left on the reader, to be pulled off by the decoder.
		dataPair := pair{}
		if _, err := xdr.Unmarshal(r, &dataPair); err != nil {
			return err
		}

		// If not dealing with a map, look up the corresponding struct field
		var targetField reflect.Value
		if !isMap {
			targetFieldIndex, ok := targetFieldIndexMap[dataPair.Name]
			// If there's no corresponding struct field, skip the data and move
			// on to the next data pair
			if !ok {
				r.Seek(int64(dataPair.EncodedSize-uint32(dataPair.headerSize())), 1)
				continue
			} else {
				targetField = target.Field(targetFieldIndex)
			}
		}

		// val used to set if target is a map
		var val reflect.Value
		// fieldSetFunc used to set if target is a struct field
		var fieldSetFunc func()

		var err error
		var v interface{}
		dec := newDecoder(r)
		switch dataPair.Type {
		case _BOOLEAN:
			v := Boolean(true)
			val = reflect.ValueOf(v)
			fieldSetFunc = func() {
				targetField.Set(val)
			}
		case _BOOLEAN_VALUE:
			v, err = dec.DecodeBool()
			val = reflect.ValueOf(v)
			fieldSetFunc = func() {
				targetField.SetBool(v.(bool))
			}
		case _BYTE:
			v, err = dec.DecodeByte()
			val = reflect.ValueOf(v)
			fieldSetFunc = func() {
				targetField.SetUint(uint64(v.(uint8)))
			}
		case _INT8:
			v, err = dec.DecodeInt8()
			val = reflect.ValueOf(v)
			fieldSetFunc = func() {
				targetField.SetInt(int64(v.(int8)))
			}
		case _INT16:
			v, err = dec.DecodeInt16()
			val = reflect.ValueOf(v)
			fieldSetFunc = func() {
				targetField.SetInt(int64(v.(int16)))
			}
		case _INT32:
			v, err = dec.DecodeInt32()
			val = reflect.ValueOf(v)
			fieldSetFunc = func() {
				targetField.SetInt(int64(v.(int32)))
			}
		case _INT64:
			v, err = dec.DecodeInt64()
			val = reflect.ValueOf(v)
			fieldSetFunc = func() {
				targetField.SetInt(v.(int64))
			}
		case _UINT8:
			v, err = dec.DecodeUint8()
			val = reflect.ValueOf(v)
			fieldSetFunc = func() {
				targetField.SetUint(uint64(v.(uint8)))
			}
		case _UINT16:
			v, err = dec.DecodeUint16()
			val = reflect.ValueOf(v)
			fieldSetFunc = func() {
				targetField.SetUint(uint64(v.(uint16)))
			}
		case _UINT32:
			v, err = dec.DecodeUint32()
			val = reflect.ValueOf(v)
			fieldSetFunc = func() {
				targetField.SetUint(uint64(v.(uint32)))
			}
		case _UINT64:
			v, err = dec.DecodeUint64()
			val = reflect.ValueOf(v)
			fieldSetFunc = func() {
				targetField.SetUint(uint64(v.(uint64)))
			}
		case _HRTIME:
			v, err = dec.DecodeHRTime()
			val = reflect.ValueOf(v)
			fieldSetFunc = func() {
				targetField.SetInt(int64(v.(time.Duration)))
			}
		case _DOUBLE:
			v, err = dec.DecodeFloat64()
			val = reflect.ValueOf(v)
			fieldSetFunc = func() {
				targetField.SetFloat(v.(float64))
			}
		case _BOOLEAN_ARRAY:
			v, err = dec.DecodeBoolArray()
			val = reflect.ValueOf(v)
			fieldSetFunc = func() {
				targetField.Set(val)
			}
		case _BYTE_ARRAY:
			if _, err = r.Seek(-4, 1); err == nil {
				v, err = dec.DecodeByteArray()
				val = reflect.ValueOf(v)
				fieldSetFunc = func() {
					targetField.SetBytes(v.([]byte))
				}
			}
		case _INT8_ARRAY:
			v, err = dec.DecodeInt8Array()
			val = reflect.ValueOf(v)
			fieldSetFunc = func() {
				targetField.Set(val)
			}
		case _INT16_ARRAY:
			v, err = dec.DecodeInt16Array()
			val = reflect.ValueOf(v)
			fieldSetFunc = func() {
				targetField.Set(val)
			}
		case _INT32_ARRAY:
			v, err = dec.DecodeInt32Array()
			val = reflect.ValueOf(v)
			fieldSetFunc = func() {
				targetField.Set(val)
			}
		case _INT64_ARRAY:
			v, err = dec.DecodeInt64Array()
			val = reflect.ValueOf(v)
			fieldSetFunc = func() {
				targetField.Set(val)
			}
		case _UINT8_ARRAY:
			v, err = dec.DecodeUint8Array()
			val = reflect.ValueOf(v)
			fieldSetFunc = func() {
				targetField.Set(val)
			}
		case _UINT16_ARRAY:
			v, err = dec.DecodeUint16Array()
			val = reflect.ValueOf(v)
			fieldSetFunc = func() {
				targetField.Set(val)
			}
		case _UINT32_ARRAY:
			v, err = dec.DecodeUint32Array()
			val = reflect.ValueOf(v)
			fieldSetFunc = func() {
				targetField.Set(val)
			}
		case _UINT64_ARRAY:
			v, err = dec.DecodeUint64Array()
			val = reflect.ValueOf(v)
			fieldSetFunc = func() {
				targetField.Set(val)
			}
		case _STRING:
			v, err = dec.DecodeString()
			val = reflect.ValueOf(v)
			fieldSetFunc = func() {
				targetField.SetString(v.(string))
			}
		case _STRING_ARRAY:
			if _, err = r.Seek(-4, 1); err == nil {
				v, err = dec.DecodeStringArray()
				val = reflect.ValueOf(v)
				fieldSetFunc = func() {
					targetField.Set(val)
				}
			}
		case _NVLIST:
			if isList {
				val = reflect.Indirect(reflect.New(target.Type()))
			} else if isMap {
				val = reflect.Indirect(reflect.New(target.Type().Elem()))
			} else {
				val = reflect.Indirect(reflect.New(targetField.Type()))
			}
			err = decodeList(r, val)
			fieldSetFunc = func() {
				targetField.Set(val)
			}
		case _NVLIST_ARRAY:
			var sliceType reflect.Type
			if isList {
				sliceType = target.Type()
			} else if isMap {
				sliceType = target.Type().Elem()
			} else {
				sliceType = targetField.Type()
			}

			if sliceType.Kind() == reflect.Interface {
				sliceType = reflect.TypeOf([]map[string]interface{}{})
			}

			val = reflect.MakeSlice(sliceType, 0, int(dataPair.NElements))
			for i := uint32(0); i < dataPair.NElements; i++ {
				elem := reflect.Indirect(reflect.New(sliceType.Elem()))
				err = decodeList(r, elem)
				if err != nil {
					break
				}
				val = reflect.Append(val, elem)
			}
			fieldSetFunc = func() {
				targetField.Set(val)
			}
		default:
			return fmt.Errorf("unknown type: %v", dataPair.Type)
		}

		if err != nil {
			return err
		}

		// Set the value appropriately
		if isMap {
			name := reflect.ValueOf(dataPair.Name)
			if isList {
				val = reflect.ValueOf(map[string]interface{}{
					"type":  dataPair.Type.String(),
					"value": val.Interface(),
				})
			}
			target.SetMapIndex(name, val)
		} else {
			fieldSetFunc()
		}
	}
	return nil
}

// fieldIndexMap creates a map of field names, with tag name overrides,
// to their index
func fieldIndexMap(v reflect.Value) map[string]int {
	vFieldIndexMap := make(map[string]int)
	forEachField(v, func(i int, field reflect.Value) {
		// Skip fields that can't be set (e.g. unexported)
		if !field.CanSet() {
			return
		}
		name := v.Type().Field(i).Name
		if tags := getTags(i, v); len(tags) > 0 && tags[0] != "" {
			name = tags[0]
		}
		vFieldIndexMap[name] = i
	})
	return vFieldIndexMap
}

func isEnd(r io.ReadSeeker) (bool, error) {
	var end uint64
	err := binary.Read(r, binary.BigEndian, &end)
	if err != nil {
		return false, err
	}
	if end == 0 {
		return true, nil
	}
	_, err = r.Seek(-8, 1)
	return false, err
}
<|endoftext|>


<commit_before>package handlers

import (
	"io"
	"log"
	"net/http"
	"strconv"
	"strings"
	"time"

	"github.com/openfaas/faas/gateway/metrics"
	"github.com/openfaas/faas/gateway/types"
	"github.com/prometheus/client_golang/prometheus"
)

// MakeForwardingProxyHandler create a handler which forwards HTTP requests
func MakeForwardingProxyHandler(proxy *types.HTTPClientReverseProxy, metrics *metrics.MetricOptions) http.HandlerFunc {
	baseURL := proxy.BaseURL.String()
	if strings.HasSuffix(baseURL, "/") {
		baseURL = baseURL[0 : len(baseURL)-1]
	}

	return func(w http.ResponseWriter, r *http.Request) {

		requestURL := r.URL.String()

		log.Printf("> Forwarding [%s] to %s", r.Method, requestURL)
		start := time.Now()

		upstreamReq, _ := http.NewRequest(r.Method, baseURL+requestURL, nil)

		upstreamReq.Header["X-Forwarded-For"] = []string{r.RequestURI}

		if r.Body != nil {
			defer r.Body.Close()
			upstreamReq.Body = r.Body

		}

		res, resErr := proxy.Client.Do(upstreamReq)
		if resErr != nil {
			log.Printf("upstream client error: %s\n", resErr)
			return
		}

		if res.Body != nil {
			defer res.Body.Close()
		}

		for k, v := range res.Header {
			w.Header()[k] = v
		}

		io.CopyBuffer(w, res.Body, nil)

		seconds := time.Since(start).Seconds()
		log.Printf("< [%s] - %d took %f seconds\n", r.URL.String(),
			res.StatusCode, seconds)

		forward := "/function/"
		if startsWith(requestURL, forward) {
			// log.Printf("function=%s", uri[len(forward):])

			service := requestURL[len(forward):]

			metrics.GatewayFunctionsHistogram.
				WithLabelValues(service).
				Observe(seconds)

			code := strconv.Itoa(res.StatusCode)

			metrics.GatewayFunctionInvocation.
				With(prometheus.Labels{"function_name": service, "code": code}).
				Inc()
		}

	}
}

func startsWith(value, token string) bool {
	return len(value) > len(token) && strings.Index(value, token) == 0
}
<commit_msg>Pass along status code<commit_after>package handlers

import (
	"io"
	"log"
	"net/http"
	"strconv"
	"strings"
	"time"

	"github.com/openfaas/faas/gateway/metrics"
	"github.com/openfaas/faas/gateway/types"
	"github.com/prometheus/client_golang/prometheus"
)

// MakeForwardingProxyHandler create a handler which forwards HTTP requests
func MakeForwardingProxyHandler(proxy *types.HTTPClientReverseProxy, metrics *metrics.MetricOptions) http.HandlerFunc {
	baseURL := proxy.BaseURL.String()
	if strings.HasSuffix(baseURL, "/") {
		baseURL = baseURL[0 : len(baseURL)-1]
	}

	return func(w http.ResponseWriter, r *http.Request) {

		requestURL := r.URL.String()

		log.Printf("> Forwarding [%s] to %s", r.Method, requestURL)
		start := time.Now()

		upstreamReq, _ := http.NewRequest(r.Method, baseURL+requestURL, nil)

		upstreamReq.Header["X-Forwarded-For"] = []string{r.RequestURI}

		if r.Body != nil {
			defer r.Body.Close()
			upstreamReq.Body = r.Body

		}

		res, resErr := proxy.Client.Do(upstreamReq)
		if resErr != nil {
			log.Printf("upstream client error: %s\n", resErr)
			return
		}

		if res.Body != nil {
			defer res.Body.Close()
		}

		// Populate any headers received
		for k, v := range res.Header {
			w.Header()[k] = v
		}

		// Write status code
		w.WriteHeader(res.StatusCode)

		// Copy the body over
		io.CopyBuffer(w, res.Body, nil)

		seconds := time.Since(start).Seconds()
		log.Printf("< [%s] - %d took %f seconds\n", r.URL.String(),
			res.StatusCode, seconds)

		forward := "/function/"
		if startsWith(requestURL, forward) {
			// log.Printf("function=%s", uri[len(forward):])

			service := requestURL[len(forward):]

			metrics.GatewayFunctionsHistogram.
				WithLabelValues(service).
				Observe(seconds)

			code := strconv.Itoa(res.StatusCode)

			metrics.GatewayFunctionInvocation.
				With(prometheus.Labels{"function_name": service, "code": code}).
				Inc()
		}

	}
}

func startsWith(value, token string) bool {
	return len(value) > len(token) && strings.Index(value, token) == 0
}
<|endoftext|>


<commit_before>package dht

import (
	"context"
	"time"

	process "github.com/jbenet/goprocess"
	processctx "github.com/jbenet/goprocess/context"
	"github.com/libp2p/go-libp2p-core/routing"
	"github.com/multiformats/go-multiaddr"
	_ "github.com/multiformats/go-multiaddr-dns"
)

var DefaultBootstrapPeers []multiaddr.Multiaddr

var minRTRefreshThreshold = 4

func init() {
	for _, s := range []string{
		"/dnsaddr/bootstrap.libp2p.io/ipfs/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN",
		"/dnsaddr/bootstrap.libp2p.io/ipfs/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa",
		"/dnsaddr/bootstrap.libp2p.io/ipfs/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb",
		"/dnsaddr/bootstrap.libp2p.io/ipfs/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt",
		"/ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ",            // mars.i.ipfs.io
		"/ip4/104.236.179.241/tcp/4001/ipfs/QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM",           // pluto.i.ipfs.io
		"/ip4/128.199.219.111/tcp/4001/ipfs/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu",           // saturn.i.ipfs.io
		"/ip4/104.236.76.40/tcp/4001/ipfs/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64",             // venus.i.ipfs.io
		"/ip4/178.62.158.247/tcp/4001/ipfs/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd",            // earth.i.ipfs.io
		"/ip6/2604:a880:1:20::203:d001/tcp/4001/ipfs/QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM",  // pluto.i.ipfs.io
		"/ip6/2400:6180:0:d0::151:6001/tcp/4001/ipfs/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu",  // saturn.i.ipfs.io
		"/ip6/2604:a880:800:10::4a:5001/tcp/4001/ipfs/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64", // venus.i.ipfs.io
		"/ip6/2a03:b0c0:0:1010::23:1001/tcp/4001/ipfs/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd", // earth.i.ipfs.io
	} {
		ma, err := multiaddr.NewMultiaddr(s)
		if err != nil {
			panic(err)
		}
		DefaultBootstrapPeers = append(DefaultBootstrapPeers, ma)
	}
}

// Start the refresh worker.
func (dht *IpfsDHT) startRefreshing() error {
	// scan the RT table periodically & do a random walk on k-buckets that haven't been queried since the given bucket period
	dht.proc.Go(func(proc process.Process) {
		ctx := processctx.OnClosingContext(proc)

		refreshTicker := time.NewTicker(dht.rtRefreshPeriod)
		defer refreshTicker.Stop()

		// refresh if option is set
		if dht.autoRefresh {
			dht.doRefresh(ctx)
		} else {
			// disable the "auto-refresh" ticker so that no more ticks are sent to this channel
			refreshTicker.Stop()
		}

		for {
			select {
			case <-refreshTicker.C:
			case <-dht.triggerRtRefresh:
				logger.Infof("triggering a refresh: RT has %d peers", dht.routingTable.Size())
			case <-ctx.Done():
				return
			}
			dht.doRefresh(ctx)
		}
	})

	return nil
}

func (dht *IpfsDHT) doRefresh(ctx context.Context) {
	dht.selfWalk(ctx)
	dht.refreshBuckets(ctx)
}

// refreshBuckets scans the routing table, and does a random walk on k-buckets that haven't been queried since the given bucket period
func (dht *IpfsDHT) refreshBuckets(ctx context.Context) {
	doQuery := func(bucketId int, target string, f func(context.Context) error) error {
		logger.Infof("starting refreshing bucket %d to %s (routing table size was %d)",
			bucketId, target, dht.routingTable.Size())
		defer func() {
			logger.Infof("finished refreshing bucket %d to %s (routing table size is now %d)",
				bucketId, target, dht.routingTable.Size())
		}()
		queryCtx, cancel := context.WithTimeout(ctx, dht.rtRefreshQueryTimeout)
		defer cancel()
		err := f(queryCtx)
		if err == context.DeadlineExceeded && queryCtx.Err() == context.DeadlineExceeded && ctx.Err() == nil {
			return nil
		}
		return err
	}

	buckets := dht.routingTable.GetAllBuckets()
	if len(buckets) > 16 {
		// Don't bother bootstrapping more than 16 buckets.
		// GenRandPeerID can't generate target peer IDs with more than
		// 16 bits specified anyways.
		buckets = buckets[:16]
	}
	for bucketID, bucket := range buckets {
		if time.Since(bucket.RefreshedAt()) <= dht.rtRefreshPeriod {
			continue
		}
		// gen rand peer in the bucket
		randPeerInBucket := dht.routingTable.GenRandPeerID(bucketID)

		// walk to the generated peer
		walkFnc := func(c context.Context) error {
			_, err := dht.FindPeer(c, randPeerInBucket)
			if err == routing.ErrNotFound {
				return nil
			}
			return err
		}

		if err := doQuery(bucketID, randPeerInBucket.String(), walkFnc); err != nil {
			logger.Warningf("failed to do a random walk on bucket %d: %s", bucketID, err)
		}
	}
}

// Traverse the DHT toward the self ID
func (dht *IpfsDHT) selfWalk(ctx context.Context) {
	queryCtx, cancel := context.WithTimeout(ctx, dht.rtRefreshQueryTimeout)
	defer cancel()
	_, err := dht.FindPeer(queryCtx, dht.self)
	if err == routing.ErrNotFound {
		return
	}
	logger.Warningf("failed to query self during routing table refresh: %s", err)
}

// Bootstrap tells the DHT to get into a bootstrapped state satisfying the
// IpfsRouter interface.
//
// This just calls `RefreshRoutingTable`.
func (dht *IpfsDHT) Bootstrap(_ context.Context) error {
	dht.RefreshRoutingTable()
	return nil
}

// RefreshRoutingTable tells the DHT to refresh it's routing tables.
func (dht *IpfsDHT) RefreshRoutingTable() {
	select {
	case dht.triggerRtRefresh <- struct{}{}:
	default:
	}
}
<commit_msg>doc(bootstrap): document minRTRefreshThreshold<commit_after>package dht

import (
	"context"
	"time"

	process "github.com/jbenet/goprocess"
	processctx "github.com/jbenet/goprocess/context"
	"github.com/libp2p/go-libp2p-core/routing"
	"github.com/multiformats/go-multiaddr"
	_ "github.com/multiformats/go-multiaddr-dns"
)

var DefaultBootstrapPeers []multiaddr.Multiaddr

// Minimum number of peers in the routing table. If we drop below this and we
// see a new peer, we trigger a bootstrap round.
var minRTRefreshThreshold = 4

func init() {
	for _, s := range []string{
		"/dnsaddr/bootstrap.libp2p.io/ipfs/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN",
		"/dnsaddr/bootstrap.libp2p.io/ipfs/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa",
		"/dnsaddr/bootstrap.libp2p.io/ipfs/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb",
		"/dnsaddr/bootstrap.libp2p.io/ipfs/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt",
		"/ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ",            // mars.i.ipfs.io
		"/ip4/104.236.179.241/tcp/4001/ipfs/QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM",           // pluto.i.ipfs.io
		"/ip4/128.199.219.111/tcp/4001/ipfs/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu",           // saturn.i.ipfs.io
		"/ip4/104.236.76.40/tcp/4001/ipfs/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64",             // venus.i.ipfs.io
		"/ip4/178.62.158.247/tcp/4001/ipfs/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd",            // earth.i.ipfs.io
		"/ip6/2604:a880:1:20::203:d001/tcp/4001/ipfs/QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM",  // pluto.i.ipfs.io
		"/ip6/2400:6180:0:d0::151:6001/tcp/4001/ipfs/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu",  // saturn.i.ipfs.io
		"/ip6/2604:a880:800:10::4a:5001/tcp/4001/ipfs/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64", // venus.i.ipfs.io
		"/ip6/2a03:b0c0:0:1010::23:1001/tcp/4001/ipfs/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd", // earth.i.ipfs.io
	} {
		ma, err := multiaddr.NewMultiaddr(s)
		if err != nil {
			panic(err)
		}
		DefaultBootstrapPeers = append(DefaultBootstrapPeers, ma)
	}
}

// Start the refresh worker.
func (dht *IpfsDHT) startRefreshing() error {
	// scan the RT table periodically & do a random walk on k-buckets that haven't been queried since the given bucket period
	dht.proc.Go(func(proc process.Process) {
		ctx := processctx.OnClosingContext(proc)

		refreshTicker := time.NewTicker(dht.rtRefreshPeriod)
		defer refreshTicker.Stop()

		// refresh if option is set
		if dht.autoRefresh {
			dht.doRefresh(ctx)
		} else {
			// disable the "auto-refresh" ticker so that no more ticks are sent to this channel
			refreshTicker.Stop()
		}

		for {
			select {
			case <-refreshTicker.C:
			case <-dht.triggerRtRefresh:
				logger.Infof("triggering a refresh: RT has %d peers", dht.routingTable.Size())
			case <-ctx.Done():
				return
			}
			dht.doRefresh(ctx)
		}
	})

	return nil
}

func (dht *IpfsDHT) doRefresh(ctx context.Context) {
	dht.selfWalk(ctx)
	dht.refreshBuckets(ctx)
}

// refreshBuckets scans the routing table, and does a random walk on k-buckets that haven't been queried since the given bucket period
func (dht *IpfsDHT) refreshBuckets(ctx context.Context) {
	doQuery := func(bucketId int, target string, f func(context.Context) error) error {
		logger.Infof("starting refreshing bucket %d to %s (routing table size was %d)",
			bucketId, target, dht.routingTable.Size())
		defer func() {
			logger.Infof("finished refreshing bucket %d to %s (routing table size is now %d)",
				bucketId, target, dht.routingTable.Size())
		}()
		queryCtx, cancel := context.WithTimeout(ctx, dht.rtRefreshQueryTimeout)
		defer cancel()
		err := f(queryCtx)
		if err == context.DeadlineExceeded && queryCtx.Err() == context.DeadlineExceeded && ctx.Err() == nil {
			return nil
		}
		return err
	}

	buckets := dht.routingTable.GetAllBuckets()
	if len(buckets) > 16 {
		// Don't bother bootstrapping more than 16 buckets.
		// GenRandPeerID can't generate target peer IDs with more than
		// 16 bits specified anyways.
		buckets = buckets[:16]
	}
	for bucketID, bucket := range buckets {
		if time.Since(bucket.RefreshedAt()) <= dht.rtRefreshPeriod {
			continue
		}
		// gen rand peer in the bucket
		randPeerInBucket := dht.routingTable.GenRandPeerID(bucketID)

		// walk to the generated peer
		walkFnc := func(c context.Context) error {
			_, err := dht.FindPeer(c, randPeerInBucket)
			if err == routing.ErrNotFound {
				return nil
			}
			return err
		}

		if err := doQuery(bucketID, randPeerInBucket.String(), walkFnc); err != nil {
			logger.Warningf("failed to do a random walk on bucket %d: %s", bucketID, err)
		}
	}
}

// Traverse the DHT toward the self ID
func (dht *IpfsDHT) selfWalk(ctx context.Context) {
	queryCtx, cancel := context.WithTimeout(ctx, dht.rtRefreshQueryTimeout)
	defer cancel()
	_, err := dht.FindPeer(queryCtx, dht.self)
	if err == routing.ErrNotFound {
		return
	}
	logger.Warningf("failed to query self during routing table refresh: %s", err)
}

// Bootstrap tells the DHT to get into a bootstrapped state satisfying the
// IpfsRouter interface.
//
// This just calls `RefreshRoutingTable`.
func (dht *IpfsDHT) Bootstrap(_ context.Context) error {
	dht.RefreshRoutingTable()
	return nil
}

// RefreshRoutingTable tells the DHT to refresh it's routing tables.
func (dht *IpfsDHT) RefreshRoutingTable() {
	select {
	case dht.triggerRtRefresh <- struct{}{}:
	default:
	}
}
<|endoftext|>