<commit_before>package flame

import (
	"time"

	"github.com/256dpi/fire/coal"

	"golang.org/x/crypto/bcrypt"
	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
)

// TokenData is used to carry token related information.
type TokenData struct {
	Scope           []string
	ExpiresAt       time.Time
	ClientID        bson.ObjectId
	ResourceOwnerID *bson.ObjectId
}

// Token is the interface that must be implemented by the tokens.
type Token interface {
	coal.Model

	// GetTokenData should collect and return the tokens data.
	GetTokenData() *TokenData

	// SetTokenData should set the specified token data.
	SetTokenData(*TokenData)
}

// AccessToken is the built-in model used to store access tokens.
type AccessToken struct {
	coal.Base     `json:"-" bson:",inline" valid:"required" coal:"access-tokens:access_tokens"`
	ExpiresAt     time.Time      `json:"expires-at" valid:"required" bson:"expires_at"`
	Scope         []string       `json:"scope" valid:"required" bson:"scope"`
	Client        bson.ObjectId  `json:"client-id" valid:"-" bson:"client_id"`
	ResourceOwner *bson.ObjectId `json:"resource-owner-id" valid:"-" bson:"resource_owner_id"`
}

// AddAccessTokenIndexes will add access token indexes to the specified indexer.
func AddAccessTokenIndexes(i *coal.Indexer, autoExpire bool) {
	i.Add(&AccessToken{}, false, false, "Client")
	i.Add(&AccessToken{}, false, false, "ResourceOwner")

	if autoExpire {
		i.AddRaw(coal.C(&AccessToken{}), mgo.Index{
			Key:         []string{coal.F(&AccessToken{}, "ExpiresAt")},
			ExpireAfter: time.Minute,
			Background:  true,
		})
	}
}

// GetTokenData implements the flame.Token interface.
func (t *AccessToken) GetTokenData() *TokenData {
	return &TokenData{
		Scope:           t.Scope,
		ExpiresAt:       t.ExpiresAt,
		ClientID:        t.Client,
		ResourceOwnerID: t.ResourceOwner,
	}
}

// SetTokenData implements the flame.Token interface.
func (t *AccessToken) SetTokenData(data *TokenData) {
	t.Scope = data.Scope
	t.ExpiresAt = data.ExpiresAt
	t.Client = data.ClientID
	t.ResourceOwner = data.ResourceOwnerID
}

// RefreshToken is the built-in model used to store refresh tokens.
type RefreshToken struct {
	coal.Base     `json:"-" bson:",inline" valid:"required" coal:"refresh-tokens:refresh_tokens"`
	ExpiresAt     time.Time      `json:"expires-at" valid:"required" bson:"expires_at"`
	Scope         []string       `json:"scope" valid:"required" bson:"scope"`
	Client        bson.ObjectId  `json:"client-id" valid:"-" bson:"client_id"`
	ResourceOwner *bson.ObjectId `json:"resource-owner-id" valid:"-" bson:"resource_owner_id"`
}

// AddRefreshTokenIndexes will add refresh token indexes to the specified indexer.
func AddRefreshTokenIndexes(i *coal.Indexer, autoExpire bool) {
	i.Add(&RefreshToken{}, false, false, "Client")
	i.Add(&RefreshToken{}, false, false, "ResourceOwner")

	if autoExpire {
		i.AddRaw(coal.C(&RefreshToken{}), mgo.Index{
			Key:         []string{coal.F(&RefreshToken{}, "ExpiresAt")},
			ExpireAfter: time.Minute,
			Background:  true,
		})
	}
}

// GetTokenData implements the flame.Token interface.
func (t *RefreshToken) GetTokenData() *TokenData {
	return &TokenData{
		Scope:           t.Scope,
		ExpiresAt:       t.ExpiresAt,
		ClientID:        t.Client,
		ResourceOwnerID: t.ResourceOwner,
	}
}

// SetTokenData implements the flame.Token interface.
func (t *RefreshToken) SetTokenData(data *TokenData) {
	t.Scope = data.Scope
	t.ExpiresAt = data.ExpiresAt
	t.Client = data.ClientID
	t.ResourceOwner = data.ResourceOwnerID
}

// A ClientDescription is returned by a Client model to specify details about
// its implementation.
type ClientDescription struct {
	IdentifierField string
}

// Client is the interface that must be implemented by clients.
type Client interface {
	coal.Model

	// DescribeClient should return a ClientDescription.
	DescribeClient() ClientDescription

	// ValidRedirectURL should return whether the specified redirect url can be
	// used by this client.
	//
	// Note: In order to increases security the callback should only allow
	// pre-registered redirect urls.
	ValidRedirectURL(string) bool

	// ValidSecret should determine whether the specified plain text secret
	// matches the stored hashed secret.
	ValidSecret(string) bool
}

// Application is the built-in model used to store clients.
type Application struct {
	coal.Base   `json:"-" bson:",inline" valid:"required" coal:"applications"`
	Name        string `json:"name" valid:"required"`
	Key         string `json:"key" valid:"required"`
	Secret      string `json:"secret,omitempty" bson:"-"`
	SecretHash  []byte `json:"-" valid:"required"`
	RedirectURL string `json:"redirect_url" valid:"required,url"`
}

// AddApplicationIndexes will add application indexes to the specified indexer.
func AddApplicationIndexes(i *coal.Indexer) {
	i.Add(&Application{}, true, false, "Key")
}

// DescribeClient implements the flame.Client interface.
func (a *Application) DescribeClient() ClientDescription {
	return ClientDescription{
		IdentifierField: "Key",
	}
}

// ValidRedirectURL implements the flame.Client interface.
func (a *Application) ValidRedirectURL(url string) bool {
	return url == a.RedirectURL
}

// ValidSecret implements the flame.Client interface.
func (a *Application) ValidSecret(secret string) bool {
	return bcrypt.CompareHashAndPassword(a.SecretHash, []byte(secret)) == nil
}

// Validate implements the coal.ValidatableModel interface.
func (a *Application) Validate() error {
	// hash password if available
	err := a.HashSecret()
	if err != nil {
		return err
	}

	return nil
}

// HashSecret will hash Secret and set SecretHash.
func (a *Application) HashSecret() error {
	if len(a.Secret) == 0 {
		return nil
	}

	// generate hash from password
	hash, err := bcrypt.GenerateFromPassword([]byte(a.Secret), bcrypt.DefaultCost)
	if err != nil {
		return err
	}

	// save hash
	a.SecretHash = hash

	// clear password
	a.Secret = ""

	return nil
}

// A ResourceOwnerDescription is returned by a ResourceOwner model to specify
// details about its implementation.
type ResourceOwnerDescription struct {
	IdentifierField string
}

// ResourceOwner is the interface that must be implemented resource owners.
type ResourceOwner interface {
	coal.Model

	// DescribeResourceOwner should return a ResourceOwnerDescription.
	DescribeResourceOwner() ResourceOwnerDescription

	// ValidSecret should determine whether the specified plain text password
	// matches the stored hashed password.
	ValidPassword(string) bool
}

// User is the built-in model used to store resource owners.
type User struct {
	coal.Base    `json:"-" bson:",inline" valid:"required" coal:"users"`
	Name         string `json:"name" valid:"required"`
	Email        string `json:"email" valid:"required,email"`
	Password     string `json:"password,omitempty" bson:"-"`
	PasswordHash []byte `json:"-" valid:"required"`
}

// AddUserIndexes will add user indexes to the specified indexer.
func AddUserIndexes(i *coal.Indexer) {
	i.Add(&User{}, true, false, "Email")
}

// DescribeResourceOwner implements the flame.ResourceOwner interface.
func (u *User) DescribeResourceOwner() ResourceOwnerDescription {
	return ResourceOwnerDescription{
		IdentifierField: "Email",
	}
}

// ValidPassword implements the flame.ResourceOwner interface.
func (u *User) ValidPassword(password string) bool {
	return bcrypt.CompareHashAndPassword(u.PasswordHash, []byte(password)) == nil
}

// Validate implements the coal.ValidatableModel interface.
func (u *User) Validate() error {
	// hash password if available
	err := u.HashPassword()
	if err != nil {
		return err
	}

	return nil
}

// HashPassword will hash Password and set PasswordHash.
func (u *User) HashPassword() error {
	if len(u.Password) == 0 {
		return nil
	}

	// generate hash from password
	hash, err := bcrypt.GenerateFromPassword([]byte(u.Password), bcrypt.DefaultCost)
	if err != nil {
		return err
	}

	// save hash
	u.PasswordHash = hash

	// clear password
	u.Password = ""

	return nil
}
<commit_msg>added docs<commit_after>package flame

import (
	"time"

	"github.com/256dpi/fire/coal"

	"golang.org/x/crypto/bcrypt"
	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
)

// TokenData is used to carry token related information.
type TokenData struct {
	Scope           []string
	ExpiresAt       time.Time
	ClientID        bson.ObjectId
	ResourceOwnerID *bson.ObjectId
}

// Token is the interface that must be implemented by the tokens.
type Token interface {
	coal.Model

	// GetTokenData should collect and return the tokens data.
	GetTokenData() *TokenData

	// SetTokenData should set the specified token data.
	SetTokenData(*TokenData)
}

// AccessToken is the built-in model used to store access tokens.
type AccessToken struct {
	coal.Base     `json:"-" bson:",inline" valid:"required" coal:"access-tokens:access_tokens"`
	ExpiresAt     time.Time      `json:"expires-at" valid:"required" bson:"expires_at"`
	Scope         []string       `json:"scope" valid:"required" bson:"scope"`
	Client        bson.ObjectId  `json:"client-id" valid:"-" bson:"client_id"`
	ResourceOwner *bson.ObjectId `json:"resource-owner-id" valid:"-" bson:"resource_owner_id"`
}

// AddAccessTokenIndexes will add access token indexes to the specified indexer.
func AddAccessTokenIndexes(i *coal.Indexer, autoExpire bool) {
	i.Add(&AccessToken{}, false, false, "Client")
	i.Add(&AccessToken{}, false, false, "ResourceOwner")

	if autoExpire {
		i.AddRaw(coal.C(&AccessToken{}), mgo.Index{
			Key:         []string{coal.F(&AccessToken{}, "ExpiresAt")},
			ExpireAfter: time.Minute,
			Background:  true,
		})
	}
}

// GetTokenData implements the flame.Token interface.
func (t *AccessToken) GetTokenData() *TokenData {
	return &TokenData{
		Scope:           t.Scope,
		ExpiresAt:       t.ExpiresAt,
		ClientID:        t.Client,
		ResourceOwnerID: t.ResourceOwner,
	}
}

// SetTokenData implements the flame.Token interface.
func (t *AccessToken) SetTokenData(data *TokenData) {
	t.Scope = data.Scope
	t.ExpiresAt = data.ExpiresAt
	t.Client = data.ClientID
	t.ResourceOwner = data.ResourceOwnerID
}

// RefreshToken is the built-in model used to store refresh tokens.
type RefreshToken struct {
	coal.Base     `json:"-" bson:",inline" valid:"required" coal:"refresh-tokens:refresh_tokens"`
	ExpiresAt     time.Time      `json:"expires-at" valid:"required" bson:"expires_at"`
	Scope         []string       `json:"scope" valid:"required" bson:"scope"`
	Client        bson.ObjectId  `json:"client-id" valid:"-" bson:"client_id"`
	ResourceOwner *bson.ObjectId `json:"resource-owner-id" valid:"-" bson:"resource_owner_id"`
}

// AddRefreshTokenIndexes will add refresh token indexes to the specified indexer.
func AddRefreshTokenIndexes(i *coal.Indexer, autoExpire bool) {
	i.Add(&RefreshToken{}, false, false, "Client")
	i.Add(&RefreshToken{}, false, false, "ResourceOwner")

	if autoExpire {
		i.AddRaw(coal.C(&RefreshToken{}), mgo.Index{
			Key:         []string{coal.F(&RefreshToken{}, "ExpiresAt")},
			ExpireAfter: time.Minute,
			Background:  true,
		})
	}
}

// GetTokenData implements the flame.Token interface.
func (t *RefreshToken) GetTokenData() *TokenData {
	return &TokenData{
		Scope:           t.Scope,
		ExpiresAt:       t.ExpiresAt,
		ClientID:        t.Client,
		ResourceOwnerID: t.ResourceOwner,
	}
}

// SetTokenData implements the flame.Token interface.
func (t *RefreshToken) SetTokenData(data *TokenData) {
	t.Scope = data.Scope
	t.ExpiresAt = data.ExpiresAt
	t.Client = data.ClientID
	t.ResourceOwner = data.ResourceOwnerID
}

// A ClientDescription is returned by a Client model to specify details about
// its implementation.
type ClientDescription struct {
	IdentifierField string
}

// Client is the interface that must be implemented by clients.
type Client interface {
	coal.Model

	// DescribeClient should return a ClientDescription.
	DescribeClient() ClientDescription

	// ValidRedirectURL should return whether the specified redirect url can be
	// used by this client.
	//
	// Note: In order to increases security the callback should only allow
	// pre-registered redirect urls.
	ValidRedirectURL(string) bool

	// ValidSecret should determine whether the specified plain text secret
	// matches the stored hashed secret.
	ValidSecret(string) bool
}

// Application is the built-in model used to store clients.
type Application struct {
	coal.Base   `json:"-" bson:",inline" valid:"required" coal:"applications"`
	Name        string `json:"name" valid:"required"`
	Key         string `json:"key" valid:"required"`
	Secret      string `json:"secret,omitempty" bson:"-"`
	SecretHash  []byte `json:"-" valid:"required"`
	RedirectURL string `json:"redirect_url" valid:"required,url"`
}

// AddApplicationIndexes will add application indexes to the specified indexer.
func AddApplicationIndexes(i *coal.Indexer) {
	i.Add(&Application{}, true, false, "Key")
}

// DescribeClient implements the flame.Client interface.
func (a *Application) DescribeClient() ClientDescription {
	return ClientDescription{
		IdentifierField: "Key",
	}
}

// ValidRedirectURL implements the flame.Client interface.
func (a *Application) ValidRedirectURL(url string) bool {
	return url == a.RedirectURL
}

// ValidSecret implements the flame.Client interface.
func (a *Application) ValidSecret(secret string) bool {
	return bcrypt.CompareHashAndPassword(a.SecretHash, []byte(secret)) == nil
}

// Validate implements the coal.ValidatableModel interface.
func (a *Application) Validate() error {
	// hash password if available
	err := a.HashSecret()
	if err != nil {
		return err
	}

	return nil
}

// HashSecret will hash Secret and set SecretHash.
func (a *Application) HashSecret() error {
	// check length
	if len(a.Secret) == 0 {
		return nil
	}

	// generate hash from password
	hash, err := bcrypt.GenerateFromPassword([]byte(a.Secret), bcrypt.DefaultCost)
	if err != nil {
		return err
	}

	// save hash
	a.SecretHash = hash

	// clear password
	a.Secret = ""

	return nil
}

// A ResourceOwnerDescription is returned by a ResourceOwner model to specify
// details about its implementation.
type ResourceOwnerDescription struct {
	IdentifierField string
}

// ResourceOwner is the interface that must be implemented resource owners.
type ResourceOwner interface {
	coal.Model

	// DescribeResourceOwner should return a ResourceOwnerDescription.
	DescribeResourceOwner() ResourceOwnerDescription

	// ValidSecret should determine whether the specified plain text password
	// matches the stored hashed password.
	ValidPassword(string) bool
}

// User is the built-in model used to store resource owners.
type User struct {
	coal.Base    `json:"-" bson:",inline" valid:"required" coal:"users"`
	Name         string `json:"name" valid:"required"`
	Email        string `json:"email" valid:"required,email"`
	Password     string `json:"password,omitempty" bson:"-"`
	PasswordHash []byte `json:"-" valid:"required"`
}

// AddUserIndexes will add user indexes to the specified indexer.
func AddUserIndexes(i *coal.Indexer) {
	i.Add(&User{}, true, false, "Email")
}

// DescribeResourceOwner implements the flame.ResourceOwner interface.
func (u *User) DescribeResourceOwner() ResourceOwnerDescription {
	return ResourceOwnerDescription{
		IdentifierField: "Email",
	}
}

// ValidPassword implements the flame.ResourceOwner interface.
func (u *User) ValidPassword(password string) bool {
	return bcrypt.CompareHashAndPassword(u.PasswordHash, []byte(password)) == nil
}

// Validate implements the coal.ValidatableModel interface.
func (u *User) Validate() error {
	// hash password if available
	err := u.HashPassword()
	if err != nil {
		return err
	}

	return nil
}

// HashPassword will hash Password and set PasswordHash.
func (u *User) HashPassword() error {
	// check length
	if len(u.Password) == 0 {
		return nil
	}

	// generate hash from password
	hash, err := bcrypt.GenerateFromPassword([]byte(u.Password), bcrypt.DefaultCost)
	if err != nil {
		return err
	}

	// save hash
	u.PasswordHash = hash

	// clear password
	u.Password = ""

	return nil
}
<|endoftext|>


<commit_before>package initialize

import (
	"fmt"
	"log"
	"path"

	"github.com/coreos/coreos-cloudinit/third_party/launchpad.net/goyaml"

	"github.com/coreos/coreos-cloudinit/system"
)

type CloudConfig struct {
	SSHAuthorizedKeys []string `yaml:"ssh_authorized_keys"`
	Coreos            struct {
		Etcd  EtcdEnvironment
		Units []system.Unit
		OEM   OEMRelease
	}
	WriteFiles []system.File `yaml:"write_files"`
	Hostname   string
	Users      []system.User
}

func NewCloudConfig(contents string) (*CloudConfig, error) {
	var cfg CloudConfig
	err := goyaml.Unmarshal([]byte(contents), &cfg)
	return &cfg, err
}

func (cc CloudConfig) String() string {
	bytes, err := goyaml.Marshal(cc)
	if err != nil {
		return ""
	}

	stringified := string(bytes)
	stringified = fmt.Sprintf("#cloud-config\n%s", stringified)

	return stringified
}

func Apply(cfg CloudConfig, env *Environment) error {
	if cfg.Hostname != "" {
		if err := system.SetHostname(cfg.Hostname); err != nil {
			return err
		}
		log.Printf("Set hostname to %s", cfg.Hostname)
	}

	if cfg.Coreos.OEM.ID != "" {
		if err := WriteOEMRelease(&cfg.Coreos.OEM, env.Root()); err != nil {
			return err
		}
		log.Printf("Wrote /etc/oem-release to filesystem")
	}

	if len(cfg.Users) > 0 {
		for _, user := range cfg.Users {
			if user.Name == "" {
				log.Printf("User object has no 'name' field, skipping")
				continue
			}

			if system.UserExists(&user) {
				log.Printf("User '%s' exists, ignoring creation-time fields", user.Name)
				if user.PasswordHash != "" {
					log.Printf("Setting '%s' user's password", user.Name)
					if err := system.SetUserPassword(user.Name, user.PasswordHash); err != nil {
						log.Printf("Failed setting '%s' user's password: %v", user.Name, err)
						return err
					}
				}
			} else {
				log.Printf("Creating user '%s'", user.Name)
				if err := system.CreateUser(&user); err != nil {
					log.Printf("Failed creating user '%s': %v", user.Name, err)
					return err
				}
			}

			if len(user.SSHAuthorizedKeys) > 0 {
				log.Printf("Authorizing %d SSH keys for user '%s'", len(user.SSHAuthorizedKeys), user.Name)
				if err := system.AuthorizeSSHKeys(user.Name, env.SSHKeyName(), user.SSHAuthorizedKeys); err != nil {
					return err
				}
			}
			if user.SSHImportGithubUser != "" {
				log.Printf("Authorizing github user %s SSH keys for CoreOS user '%s'", user.SSHImportGithubUser, user.Name)
				if err := SSHImportGithubUser(user.Name, user.SSHImportGithubUser); err != nil {
					return err
				}
			}
		}
	}

	if len(cfg.SSHAuthorizedKeys) > 0 {
		err := system.AuthorizeSSHKeys("core", env.SSHKeyName(), cfg.SSHAuthorizedKeys)
		if err == nil {
			log.Printf("Authorized SSH keys for core user")
		} else {
			return err
		}
	}

	if len(cfg.WriteFiles) > 0 {
		for _, file := range cfg.WriteFiles {
			file.Path = path.Join(env.Root(), file.Path)
			if err := system.WriteFile(&file); err != nil {
				return err
			}
			log.Printf("Wrote file %s to filesystem", file.Path)
		}
	}

	if len(cfg.Coreos.Etcd) > 0 {
		if err := WriteEtcdEnvironment(cfg.Coreos.Etcd, env.Root()); err != nil {
			log.Fatalf("Failed to write etcd config to filesystem: %v", err)
		}

		log.Printf("Wrote etcd config file to filesystem")
	}

	if len(cfg.Coreos.Units) > 0 {
		commands := make(map[string]string, 0)

		for _, unit := range cfg.Coreos.Units {
			if unit.Content != "" {
				log.Printf("Writing unit %s to filesystem", unit.Name)
				dst, err := system.PlaceUnit(&unit, env.Root())
				if err != nil {
					return err
				}
				log.Printf("Placed unit %s at %s", unit.Name, dst)

				if unit.Group() != "network" {
					log.Printf("Enabling unit file %s", dst)
					if err := system.EnableUnitFile(dst, unit.Runtime); err != nil {
						return err
					}
					log.Printf("Enabled unit %s", unit.Name)
				} else {
					log.Printf("Skipping enable for network-like unit %s", unit.Name)
				}
			}

			if unit.Group() == "network" {
				commands["systemd-networkd.service"] = "restart"
			} else {
				if unit.Command != "" {
				    commands[unit.Name] = unit.Command
				}
			}
		}

		if err := system.DaemonReload(); err != nil {
			log.Fatalf("Failed systemd daemon-reload: %v", err)
		}

		for unit, command := range commands {
			log.Printf("Calling unit command '%s %s'", command, unit)
			res, err := system.RunUnitCommand(command, unit)
			if err != nil {
				return err
			}
			log.Printf("Result of '%s %s': %s", command, unit, res)
		}
	}

	return nil
}
<commit_msg>fix(units): Drop automatic daemon-reload<commit_after>package initialize

import (
	"fmt"
	"log"
	"path"

	"github.com/coreos/coreos-cloudinit/third_party/launchpad.net/goyaml"

	"github.com/coreos/coreos-cloudinit/system"
)

type CloudConfig struct {
	SSHAuthorizedKeys []string `yaml:"ssh_authorized_keys"`
	Coreos            struct {
		Etcd  EtcdEnvironment
		Units []system.Unit
		OEM   OEMRelease
	}
	WriteFiles []system.File `yaml:"write_files"`
	Hostname   string
	Users      []system.User
}

func NewCloudConfig(contents string) (*CloudConfig, error) {
	var cfg CloudConfig
	err := goyaml.Unmarshal([]byte(contents), &cfg)
	return &cfg, err
}

func (cc CloudConfig) String() string {
	bytes, err := goyaml.Marshal(cc)
	if err != nil {
		return ""
	}

	stringified := string(bytes)
	stringified = fmt.Sprintf("#cloud-config\n%s", stringified)

	return stringified
}

func Apply(cfg CloudConfig, env *Environment) error {
	if cfg.Hostname != "" {
		if err := system.SetHostname(cfg.Hostname); err != nil {
			return err
		}
		log.Printf("Set hostname to %s", cfg.Hostname)
	}

	if cfg.Coreos.OEM.ID != "" {
		if err := WriteOEMRelease(&cfg.Coreos.OEM, env.Root()); err != nil {
			return err
		}
		log.Printf("Wrote /etc/oem-release to filesystem")
	}

	if len(cfg.Users) > 0 {
		for _, user := range cfg.Users {
			if user.Name == "" {
				log.Printf("User object has no 'name' field, skipping")
				continue
			}

			if system.UserExists(&user) {
				log.Printf("User '%s' exists, ignoring creation-time fields", user.Name)
				if user.PasswordHash != "" {
					log.Printf("Setting '%s' user's password", user.Name)
					if err := system.SetUserPassword(user.Name, user.PasswordHash); err != nil {
						log.Printf("Failed setting '%s' user's password: %v", user.Name, err)
						return err
					}
				}
			} else {
				log.Printf("Creating user '%s'", user.Name)
				if err := system.CreateUser(&user); err != nil {
					log.Printf("Failed creating user '%s': %v", user.Name, err)
					return err
				}
			}

			if len(user.SSHAuthorizedKeys) > 0 {
				log.Printf("Authorizing %d SSH keys for user '%s'", len(user.SSHAuthorizedKeys), user.Name)
				if err := system.AuthorizeSSHKeys(user.Name, env.SSHKeyName(), user.SSHAuthorizedKeys); err != nil {
					return err
				}
			}
			if user.SSHImportGithubUser != "" {
				log.Printf("Authorizing github user %s SSH keys for CoreOS user '%s'", user.SSHImportGithubUser, user.Name)
				if err := SSHImportGithubUser(user.Name, user.SSHImportGithubUser); err != nil {
					return err
				}
			}
		}
	}

	if len(cfg.SSHAuthorizedKeys) > 0 {
		err := system.AuthorizeSSHKeys("core", env.SSHKeyName(), cfg.SSHAuthorizedKeys)
		if err == nil {
			log.Printf("Authorized SSH keys for core user")
		} else {
			return err
		}
	}

	if len(cfg.WriteFiles) > 0 {
		for _, file := range cfg.WriteFiles {
			file.Path = path.Join(env.Root(), file.Path)
			if err := system.WriteFile(&file); err != nil {
				return err
			}
			log.Printf("Wrote file %s to filesystem", file.Path)
		}
	}

	if len(cfg.Coreos.Etcd) > 0 {
		if err := WriteEtcdEnvironment(cfg.Coreos.Etcd, env.Root()); err != nil {
			log.Fatalf("Failed to write etcd config to filesystem: %v", err)
		}

		log.Printf("Wrote etcd config file to filesystem")
	}

	if len(cfg.Coreos.Units) > 0 {
		commands := make(map[string]string, 0)

		for _, unit := range cfg.Coreos.Units {
			if unit.Content != "" {
				log.Printf("Writing unit %s to filesystem", unit.Name)
				dst, err := system.PlaceUnit(&unit, env.Root())
				if err != nil {
					return err
				}
				log.Printf("Placed unit %s at %s", unit.Name, dst)

				if unit.Group() != "network" {
					log.Printf("Enabling unit file %s", dst)
					if err := system.EnableUnitFile(dst, unit.Runtime); err != nil {
						return err
					}
					log.Printf("Enabled unit %s", unit.Name)
				} else {
					log.Printf("Skipping enable for network-like unit %s", unit.Name)
				}
			}

			if unit.Group() == "network" {
				commands["systemd-networkd.service"] = "restart"
			} else {
				if unit.Command != "" {
				    commands[unit.Name] = unit.Command
				}
			}
		}

		for unit, command := range commands {
			log.Printf("Calling unit command '%s %s'", command, unit)
			res, err := system.RunUnitCommand(command, unit)
			if err != nil {
				return err
			}
			log.Printf("Result of '%s %s': %s", command, unit, res)
		}
	}

	return nil
}
<|endoftext|>


<commit_before>// Copyright 2014 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.

// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows

package ipv4_test

import (
	"os"
	"syscall"
)

func protocolNotSupported(err error) bool {
	switch err := err.(type) {
	case syscall.Errno:
		if err == syscall.EPROTONOSUPPORT {
			return true
		}
	case *os.SyscallError:
		switch err := err.Err.(type) {
		case syscall.Errno:
			if err == syscall.EPROTONOSUPPORT {
				return true
			}
		}
	}
	return false
}
<commit_msg>go.net/ipv4: ignore ENOPROTOOPT in ancillary data socket option tests<commit_after>// Copyright 2014 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.

// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows

package ipv4_test

import (
	"os"
	"syscall"
)

func protocolNotSupported(err error) bool {
	switch err := err.(type) {
	case syscall.Errno:
		switch err {
		case syscall.EPROTONOSUPPORT, syscall.ENOPROTOOPT:
			return true
		}
	case *os.SyscallError:
		switch err := err.Err.(type) {
		case syscall.Errno:
			switch err {
			case syscall.EPROTONOSUPPORT, syscall.ENOPROTOOPT:
				return true
			}
		}
	}
	return false
}
<|endoftext|>


<commit_before>package install

import (
	"fmt"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"sort"
	"strings"

	"github.com/cockroachdb/roachprod/config"
	"github.com/cockroachdb/roachprod/ssh"
	"github.com/hashicorp/go-version"
)

var StartOpts struct {
	Sequential bool
}

type Cockroach struct{}

func cockroachNodeBinary(c *SyncedCluster, i int) string {
	if !c.IsLocal() || filepath.IsAbs(config.Binary) {
		return config.Binary
	}

	path := filepath.Join(fmt.Sprintf(os.ExpandEnv("${HOME}/local/%d"), i), config.Binary)
	if _, err := os.Stat(path); err == nil {
		return path
	}

	// For "local" clusters we have to find the binary to run and translate it to
	// an absolute path. First, look for the binary in PATH.
	path, err := exec.LookPath(config.Binary)
	if err != nil {
		if strings.HasPrefix(config.Binary, "/") {
			return config.Binary
		}
		// We're unable to find the binary in PATH and "binary" is a relative path:
		// look in the cockroach repo.
		gopath := os.Getenv("GOPATH")
		if gopath == "" {
			return config.Binary
		}
		path = gopath + "/src/github.com/cockroachdb/cockroach/" + config.Binary
		var err2 error
		path, err2 = exec.LookPath(path)
		if err2 != nil {
			return config.Binary
		}
	}
	path, err = filepath.Abs(path)
	if err != nil {
		return config.Binary
	}
	return path
}

func getCockroachVersion(c *SyncedCluster, i int, host, user string) (*version.Version, error) {
	session, err := ssh.NewSSHSession(user, host)
	if err != nil {
		return nil, err
	}
	defer session.Close()

	cmd := cockroachNodeBinary(c, i) + " version"
	out, err := session.CombinedOutput(cmd)
	if err != nil {
		return nil, err
	}

	matches := regexp.MustCompile(`(?m)^Build Tag:\s+(.*)$`).FindSubmatch(out)
	if len(matches) != 2 {
		return nil, fmt.Errorf("unable to parse cockroach version output:%s", out)
	}

	version, err := version.NewVersion(string(matches[1]))
	if err != nil {
		return nil, err
	}
	return version, nil
}

func GetAdminUIPort(connPort int) int {
	return connPort + 1
}

func (r Cockroach) Start(c *SyncedCluster, extraArgs []string) {
	display := fmt.Sprintf("%s: starting", c.Name)
	host1 := c.host(1)
	nodes := c.ServerNodes()

	p := 0
	if StartOpts.Sequential {
		p = 1
	}
	c.Parallel(display, len(nodes), p, func(i int) ([]byte, error) {
		host := c.host(nodes[i])
		user := c.user(nodes[i])

		vers, err := getCockroachVersion(c, nodes[i], host, user)
		if err != nil {
			return nil, err
		}

		session, err := ssh.NewSSHSession(user, host)
		if err != nil {
			return nil, err
		}
		defer session.Close()

		port := r.NodePort(c, nodes[i])

		var args []string
		if c.Secure {
			args = append(args, "--certs-dir=certs")
		} else {
			args = append(args, "--insecure")
		}
		dir := "/mnt/data1/cockroach"
		logDir := "${HOME}/logs"
		if c.IsLocal() {
			dir = fmt.Sprintf("${HOME}/local/%d/data", nodes[i])
			logDir = fmt.Sprintf("${HOME}/local/%d/data/logs", nodes[i])
		}
		args = append(args, "--store=path="+dir)
		args = append(args, "--log-dir="+logDir)
		args = append(args, "--background")
		if VersionSatifies(vers, ">=1.1") {
			cache := 25
			if c.IsLocal() {
				cache /= len(nodes)
				if cache == 0 {
					cache = 1
				}
			}
			args = append(args, fmt.Sprintf("--cache=%d%%", cache))
			args = append(args, fmt.Sprintf("--max-sql-memory=%d%%", cache))
		}
		args = append(args, fmt.Sprintf("--port=%d", port))
		args = append(args, fmt.Sprintf("--http-port=%d", GetAdminUIPort(port)))
		if locality := c.locality(nodes[i]); locality != "" {
			args = append(args, "--locality="+locality)
		}
		if nodes[i] != 1 {
			args = append(args, fmt.Sprintf("--join=%s:%d", host1, r.NodePort(c, 1)))
		}
		args = append(args, extraArgs...)

		binary := cockroachNodeBinary(c, nodes[i])
		cmd := "mkdir -p " + logDir + "; " +
			c.Env + " ROACHPROD=true " + binary + " start " + strings.Join(args, " ") +
			" >> " + logDir + "/cockroach.stdout 2>> " + logDir + "/cockroach.stderr"
		return session.CombinedOutput(cmd)
	})

	// Check to see if node 1 was started indicating the cluster was
	// bootstrapped.
	var bootstrapped bool
	for _, i := range nodes {
		if i == 1 {
			bootstrapped = true
			break
		}
	}

	if bootstrapped {
		var msg string
		display = fmt.Sprintf("%s: initializing cluster settings", c.Name)
		c.Parallel(display, 1, 0, func(i int) ([]byte, error) {
			session, err := ssh.NewSSHSession(c.user(1), c.host(1))
			if err != nil {
				return nil, err
			}
			defer session.Close()

			license := os.Getenv("COCKROACH_DEV_LICENSE")
			if license == "" {
				log.Printf("warning: COCKROACH_DEV_LICENSE unset: enterprise features will be unavailable")
			}

			binary := cockroachNodeBinary(c, 1)
			cmd := ssh.Escape([]string{
				binary, "sql", "--url", r.NodeURL(c, "localhost", r.NodePort(c, 1)), "-e",
				fmt.Sprintf(`
SET CLUSTER SETTING kv.allocator.stat_based_rebalancing.enabled = false;
SET CLUSTER SETTING server.remote_debugging.mode = 'any';
SET CLUSTER SETTING cluster.organization = 'Cockroach Labs - Production Testing';
SET CLUSTER SETTING enterprise.license = '%s';`, license),
			})
			out, err := session.CombinedOutput(cmd)
			if err != nil {
				msg = err.Error()
			} else {
				msg = strings.TrimSpace(string(out))
			}
			return nil, nil
		})

		fmt.Println(msg)
	}
}

func (Cockroach) NodeDir(c *SyncedCluster, index int) string {
	if c.IsLocal() {
		return os.ExpandEnv(fmt.Sprintf("${HOME}/local/%d/data", index))
	}
	return "/mnt/data1/cockroach"
}

func (Cockroach) NodeURL(c *SyncedCluster, host string, port int) string {
	url := fmt.Sprintf("'postgres://root@%s:%d", host, port)
	if c.Secure {
		url += "?sslcert=certs%2Fnode.crt&sslkey=certs%2Fnode.key&" +
			"sslrootcert=certs%2Fca.crt&sslmode=verify-full"
	} else {
		url += "?sslmode=disable"
	}
	url += "'"
	return url
}

func (Cockroach) NodePort(c *SyncedCluster, index int) int {
	const basePort = 26257
	port := basePort
	if c.IsLocal() {
		port += (index - 1) * 2
	}
	return port
}

func (Cockroach) SQL(c *SyncedCluster, args []string) error {
	url := Cockroach{}.NodeURL(c, "localhost", Cockroach{}.NodePort(c, 0))
	allArgs := []string{"./cockroach", "sql", "--url", url}
	allArgs = append(allArgs, args...)
	if len(args) == 0 {
		// If no arguments, we're going to get an interactive SQL shell. Require
		// exactly one target and ask SSH to provide a psuedoterminal.
		if len(c.Nodes) != 1 {
			return fmt.Errorf("invalid number of nodes for interactive sql: %d", len(c.Nodes))
		}
		return c.Ssh(append([]string{"-t"}, allArgs...))
	}

	// Otherwise, assume the user provided the "-e" flag, so we can reasonably
	// execute the query on all specified nodes.
	type result struct {
		node   int
		output string
	}
	resultChan := make(chan result, len(c.Nodes))

	display := fmt.Sprintf("%s: executing sql", c.Name)
	c.Parallel(display, len(c.Nodes), 0, func(i int) ([]byte, error) {
		session, err := ssh.NewSSHSession(c.user(c.Nodes[i]), c.host(c.Nodes[i]))
		if err != nil {
			return nil, err
		}
		defer session.Close()

		out, err := session.CombinedOutput(ssh.Escape(allArgs))
		if err != nil {
			resultChan <- result{node: c.Nodes[i], output: fmt.Sprintf("err=%s,out=%s", err, out)}
			return out, err
		}

		resultChan <- result{node: c.Nodes[i], output: string(out)}
		return nil, nil
	})

	results := make([]result, 0, len(c.Nodes))
	for _ = range c.Nodes {
		results = append(results, <-resultChan)
	}
	sort.Slice(results, func(i, j int) bool {
		return results[i].node < results[j].node
	})
	for _, r := range results {
		fmt.Printf("node %d:\n%s", r.node, r.output)
	}

	return nil
}
<commit_msg>roachprod: add a note about unhelpful behavior<commit_after>package install

import (
	"fmt"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"sort"
	"strings"

	"github.com/cockroachdb/roachprod/config"
	"github.com/cockroachdb/roachprod/ssh"
	"github.com/hashicorp/go-version"
)

var StartOpts struct {
	Sequential bool
}

type Cockroach struct{}

func cockroachNodeBinary(c *SyncedCluster, i int) string {
	if !c.IsLocal() || filepath.IsAbs(config.Binary) {
		return config.Binary
	}

	path := filepath.Join(fmt.Sprintf(os.ExpandEnv("${HOME}/local/%d"), i), config.Binary)
	if _, err := os.Stat(path); err == nil {
		return path
	}

	// For "local" clusters we have to find the binary to run and translate it to
	// an absolute path. First, look for the binary in PATH.
	path, err := exec.LookPath(config.Binary)
	if err != nil {
		if strings.HasPrefix(config.Binary, "/") {
			return config.Binary
		}
		// We're unable to find the binary in PATH and "binary" is a relative path:
		// look in the cockroach repo.
		gopath := os.Getenv("GOPATH")
		if gopath == "" {
			return config.Binary
		}
		path = gopath + "/src/github.com/cockroachdb/cockroach/" + config.Binary
		var err2 error
		path, err2 = exec.LookPath(path)
		if err2 != nil {
			return config.Binary
		}
	}
	path, err = filepath.Abs(path)
	if err != nil {
		return config.Binary
	}
	return path
}

func getCockroachVersion(c *SyncedCluster, i int, host, user string) (*version.Version, error) {
	session, err := ssh.NewSSHSession(user, host)
	if err != nil {
		return nil, err
	}
	defer session.Close()

	cmd := cockroachNodeBinary(c, i) + " version"
	out, err := session.CombinedOutput(cmd)
	if err != nil {
		return nil, err
	}

	matches := regexp.MustCompile(`(?m)^Build Tag:\s+(.*)$`).FindSubmatch(out)
	if len(matches) != 2 {
		return nil, fmt.Errorf("unable to parse cockroach version output:%s", out)
	}

	version, err := version.NewVersion(string(matches[1]))
	if err != nil {
		return nil, err
	}
	return version, nil
}

func GetAdminUIPort(connPort int) int {
	return connPort + 1
}

func (r Cockroach) Start(c *SyncedCluster, extraArgs []string) {
	display := fmt.Sprintf("%s: starting", c.Name)
	host1 := c.host(1)
	nodes := c.ServerNodes()

	p := 0
	if StartOpts.Sequential {
		p = 1
	}
	c.Parallel(display, len(nodes), p, func(i int) ([]byte, error) {
		host := c.host(nodes[i])
		user := c.user(nodes[i])

		vers, err := getCockroachVersion(c, nodes[i], host, user)
		if err != nil {
			return nil, err
		}

		session, err := ssh.NewSSHSession(user, host)
		if err != nil {
			return nil, err
		}
		defer session.Close()

		port := r.NodePort(c, nodes[i])

		var args []string
		if c.Secure {
			args = append(args, "--certs-dir=certs")
		} else {
			args = append(args, "--insecure")
		}
		dir := "/mnt/data1/cockroach"
		logDir := "${HOME}/logs"
		if c.IsLocal() {
			dir = fmt.Sprintf("${HOME}/local/%d/data", nodes[i])
			logDir = fmt.Sprintf("${HOME}/local/%d/data/logs", nodes[i])
		}
		args = append(args, "--store=path="+dir)
		args = append(args, "--log-dir="+logDir)
		args = append(args, "--background")
		if VersionSatifies(vers, ">=1.1") {
			cache := 25
			if c.IsLocal() {
				cache /= len(nodes)
				if cache == 0 {
					cache = 1
				}
			}
			args = append(args, fmt.Sprintf("--cache=%d%%", cache))
			args = append(args, fmt.Sprintf("--max-sql-memory=%d%%", cache))
		}
		args = append(args, fmt.Sprintf("--port=%d", port))
		args = append(args, fmt.Sprintf("--http-port=%d", GetAdminUIPort(port)))
		if locality := c.locality(nodes[i]); locality != "" {
			args = append(args, "--locality="+locality)
		}
		if nodes[i] != 1 {
			args = append(args, fmt.Sprintf("--join=%s:%d", host1, r.NodePort(c, 1)))
		}
		args = append(args, extraArgs...)

		binary := cockroachNodeBinary(c, nodes[i])
		// NB: this is awkward as when the process fails, the test runner will show an
		// unhelpful empty error (since everything has been redirected away). This is
		// unfortunately equally awkward to address.
		cmd := "mkdir -p " + logDir + "; " +
			c.Env + " ROACHPROD=true " + binary + " start " + strings.Join(args, " ") +
			" >> " + logDir + "/cockroach.stdout 2>> " + logDir + "/cockroach.stderr"
		return session.CombinedOutput(cmd)
	})

	// Check to see if node 1 was started indicating the cluster was
	// bootstrapped.
	var bootstrapped bool
	for _, i := range nodes {
		if i == 1 {
			bootstrapped = true
			break
		}
	}

	if bootstrapped {
		var msg string
		display = fmt.Sprintf("%s: initializing cluster settings", c.Name)
		c.Parallel(display, 1, 0, func(i int) ([]byte, error) {
			session, err := ssh.NewSSHSession(c.user(1), c.host(1))
			if err != nil {
				return nil, err
			}
			defer session.Close()

			license := os.Getenv("COCKROACH_DEV_LICENSE")
			if license == "" {
				log.Printf("warning: COCKROACH_DEV_LICENSE unset: enterprise features will be unavailable")
			}

			binary := cockroachNodeBinary(c, 1)
			cmd := ssh.Escape([]string{
				binary, "sql", "--url", r.NodeURL(c, "localhost", r.NodePort(c, 1)), "-e",
				fmt.Sprintf(`
SET CLUSTER SETTING kv.allocator.stat_based_rebalancing.enabled = false;
SET CLUSTER SETTING server.remote_debugging.mode = 'any';
SET CLUSTER SETTING cluster.organization = 'Cockroach Labs - Production Testing';
SET CLUSTER SETTING enterprise.license = '%s';`, license),
			})
			out, err := session.CombinedOutput(cmd)
			if err != nil {
				msg = err.Error()
			} else {
				msg = strings.TrimSpace(string(out))
			}
			return nil, nil
		})

		fmt.Println(msg)
	}
}

func (Cockroach) NodeDir(c *SyncedCluster, index int) string {
	if c.IsLocal() {
		return os.ExpandEnv(fmt.Sprintf("${HOME}/local/%d/data", index))
	}
	return "/mnt/data1/cockroach"
}

func (Cockroach) NodeURL(c *SyncedCluster, host string, port int) string {
	url := fmt.Sprintf("'postgres://root@%s:%d", host, port)
	if c.Secure {
		url += "?sslcert=certs%2Fnode.crt&sslkey=certs%2Fnode.key&" +
			"sslrootcert=certs%2Fca.crt&sslmode=verify-full"
	} else {
		url += "?sslmode=disable"
	}
	url += "'"
	return url
}

func (Cockroach) NodePort(c *SyncedCluster, index int) int {
	const basePort = 26257
	port := basePort
	if c.IsLocal() {
		port += (index - 1) * 2
	}
	return port
}

func (Cockroach) SQL(c *SyncedCluster, args []string) error {
	url := Cockroach{}.NodeURL(c, "localhost", Cockroach{}.NodePort(c, 0))
	allArgs := []string{"./cockroach", "sql", "--url", url}
	allArgs = append(allArgs, args...)
	if len(args) == 0 {
		// If no arguments, we're going to get an interactive SQL shell. Require
		// exactly one target and ask SSH to provide a psuedoterminal.
		if len(c.Nodes) != 1 {
			return fmt.Errorf("invalid number of nodes for interactive sql: %d", len(c.Nodes))
		}
		return c.Ssh(append([]string{"-t"}, allArgs...))
	}

	// Otherwise, assume the user provided the "-e" flag, so we can reasonably
	// execute the query on all specified nodes.
	type result struct {
		node   int
		output string
	}
	resultChan := make(chan result, len(c.Nodes))

	display := fmt.Sprintf("%s: executing sql", c.Name)
	c.Parallel(display, len(c.Nodes), 0, func(i int) ([]byte, error) {
		session, err := ssh.NewSSHSession(c.user(c.Nodes[i]), c.host(c.Nodes[i]))
		if err != nil {
			return nil, err
		}
		defer session.Close()

		out, err := session.CombinedOutput(ssh.Escape(allArgs))
		if err != nil {
			resultChan <- result{node: c.Nodes[i], output: fmt.Sprintf("err=%s,out=%s", err, out)}
			return out, err
		}

		resultChan <- result{node: c.Nodes[i], output: string(out)}
		return nil, nil
	})

	results := make([]result, 0, len(c.Nodes))
	for _ = range c.Nodes {
		results = append(results, <-resultChan)
	}
	sort.Slice(results, func(i, j int) bool {
		return results[i].node < results[j].node
	})
	for _, r := range results {
		fmt.Printf("node %d:\n%s", r.node, r.output)
	}

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/drone/drone/model"
	"github.com/urfave/cli"
)

var secretCreateCmd = cli.Command{
	Name:   "add",
	Usage:  "adds a secret",
	Action: secretCreate,
	Flags: []cli.Flag{
		cli.StringFlag{
			Name:  "repository",
			Usage: "repository name (e.g. octocat/hello-world)",
		},
		cli.StringFlag{
			Name:  "name",
			Usage: "secret name",
		},
		cli.StringFlag{
			Name:  "value",
			Usage: "secret value",
		},
		cli.StringSliceFlag{
			Name:  "event",
			Usage: "secret limited to these events",
		},
		cli.StringSliceFlag{
			Name:  "image",
			Usage: "secret limited to these images",
		},
	},
}

func secretCreate(c *cli.Context) error {
	reponame := c.String("repository")
	if reponame == "" {
		reponame = c.Args().First()
	}
	owner, name, err := parseRepo(reponame)
	if err != nil {
		return err
	}
	client, err := newClient(c)
	if err != nil {
		return err
	}
	secret := &model.Secret{
		Name:   c.String("name"),
		Value:  c.String("value"),
		Images: c.StringSlice("image"),
		Events: c.StringSlice("events"),
	}
	if len(secret.Events) == 0 {
		secret.Events = defaultSecretEvents
	}
	_, err = client.SecretUpdate(owner, name, secret)
	return err
}

var defaultSecretEvents = []string{
	model.EventPush,
	model.EventTag,
	model.EventDeploy,
}
<commit_msg>fix drone secret add<commit_after>package main

import (
	"github.com/drone/drone/model"
	"github.com/urfave/cli"
)

var secretCreateCmd = cli.Command{
	Name:   "add",
	Usage:  "adds a secret",
	Action: secretCreate,
	Flags: []cli.Flag{
		cli.StringFlag{
			Name:  "repository",
			Usage: "repository name (e.g. octocat/hello-world)",
		},
		cli.StringFlag{
			Name:  "name",
			Usage: "secret name",
		},
		cli.StringFlag{
			Name:  "value",
			Usage: "secret value",
		},
		cli.StringSliceFlag{
			Name:  "event",
			Usage: "secret limited to these events",
		},
		cli.StringSliceFlag{
			Name:  "image",
			Usage: "secret limited to these images",
		},
	},
}

func secretCreate(c *cli.Context) error {
	reponame := c.String("repository")
	if reponame == "" {
		reponame = c.Args().First()
	}
	owner, name, err := parseRepo(reponame)
	if err != nil {
		return err
	}
	client, err := newClient(c)
	if err != nil {
		return err
	}
	secret := &model.Secret{
		Name:   c.String("name"),
		Value:  c.String("value"),
		Images: c.StringSlice("image"),
		Events: c.StringSlice("events"),
	}
	if len(secret.Events) == 0 {
		secret.Events = defaultSecretEvents
	}
	_, err = client.SecretCreate(owner, name, secret)
	return err
}

var defaultSecretEvents = []string{
	model.EventPush,
	model.EventTag,
	model.EventDeploy,
}
<|endoftext|>


<commit_before>package fluxlog

import (
	"encoding/json"
	"testing"
	"time"
)

func configure()
	ChangeGlobalTags(map[string]string{"env": "test"})
	SaveMetadata(true)
	SetAddress("http://storage:8086")
}

func TestWrite(t *testing.T) {
	configure()              // setup influx connection
	defer DisconnectInflux() // teardown influx connection

	measure := "test_write_01"
	field := "id"
	count := getCount(t, measure, field)

	tags := map[string]string{"test": t.Name()}
	err := Write(measure, map[string]interface{}{field: 42}, tags)
	if err != nil {
		t.Fatal("Failed to write to influx due to error:", err)
	}

	if getCountWhere(t, measure, field, "\"file\" = 'fluxlog_test.go'") <= count {
		t.Fatal("Failed to Write point to influxdb")
	}
}

func TestWritef(t *testing.T) {
	configure()              // setup influx connection
	defer DisconnectInflux() // teardown influx connection

	measure := "failed to do thing with id %d"
	field := "d1"
	count := getCount(t, measure, field)

	err := Writef(measure)
	if err == nil {
		t.Fatal("Failed to generate writef error when insufficient values are given")
	}

	if getCountWhere(t, measure, field, "\"file\" = 'fluxlog_test.go'") != count {
		t.Fatal("Sometime was written using Writef to influxdb when it was expected not too")
	}

	err = Writef(measure, 42)
	if err != nil {
		t.Fatal("Failed to write to influx due to error:", err)
	}

	if getCountWhere(t, measure, field, "\"file\" = 'fluxlog_test.go'") <= count {
		t.Fatal("Failed to Writef point to influxdb")
	}
}

func TestWhitelist(t *testing.T) {
	configure()              // setup influx connection
	defer DisconnectInflux() // teardown influx connection

	measureDeny := "test_write_02"
	measureAllow := "test_write_03"
	AddMeasurementToWhitelist(measureAllow)
	AddMeasurementToWhitelist(measureAllow + "1")
	defer ChangeMeasurementsWhitelist([]string{})
	field := "id"
	count := getCount(t, measureDeny, field)

	err := Write(measureDeny, map[string]interface{}{field: 42}, map[string]string{})
	if err == nil {
		t.Fatal("Failed to write to influx due to error:", err)
	}

	if getCountWhere(t, measureDeny, field, "\"file\" = 'fluxlog_test.go'") != count {
		t.Fatal("Something was written to influx when the measurement was not whitelisted")
	}

	err = Write(measureAllow, map[string]interface{}{field: 42}, map[string]string{})
	if err != nil {
		t.Fatal("Failed to write whitelisted measure to influx due to error:", err)
	}

	if getCountWhere(t, measureAllow, field, "\"file\" = 'fluxlog_test.go'") <= count {
		t.Fatal("Failed to write whitelisted measure to influx")
	}
}

func BenchmarkWrite(b *testing.B) {
	configure()              // setup influx connection
	defer DisconnectInflux() // teardown influx connection

	var err error
	fields := map[string]interface{}{"id": 42}
	tags := map[string]string{"test": b.Name()}
	// run the Fib function b.N times
	for n := 0; n < b.N; n++ {
		err = Write("test_write_03", fields, tags)
	}
	if err != nil {
		b.Fatal("Final write in benchmark failed with error:", err)
	}
}

func BenchmarkWritef(b *testing.B) {
	configure()              // setup influx connection
	defer DisconnectInflux() // teardown influx connection

	var err error
	for n := 0; n < b.N; n++ {
		err = Writef("benchmarking thing with id %d", n)
	}
	if err != nil {
		b.Fatal("Final writef in benchmark failed with error:", err)
	}
}

func BenchmarkWritefSlow(b *testing.B) {
	if testing.Short() {
		b.Skipf("Skipping %s in short mode", b.Name())
	}
	configure()              // setup influx connection
	defer DisconnectInflux() // teardown influx connection

	var err error
	for n := 0; n < b.N; n++ {
		err = Writef("benchmarking thing with id %d", n)
		time.Sleep(500 * time.Millisecond)
	}
	if err != nil {
		b.Fatal("Final writef in benchmark failed with error:", err)
	}
}

func getCountWhere(t *testing.T, measurement string, field string, where string) int64 {
	t.Helper()
	res, err := queryInflux("SELECT count(" + field + ") FROM \"" + measurement + "\" WHERE " + where)
	if err != nil || res[0].Series == nil {
		return 0
	}
	val, err := res[0].Series[0].Values[0][1].(json.Number).Int64()
	if err != nil {
		return 0
	}
	return val
}

func getCount(t *testing.T, measurement string, field string) int64 {
	t.Helper()
	res, err := queryInflux("SELECT count(" + field + ") FROM \"" + measurement + "\" WHERE \"env\" ='test'")
	if err != nil || res[0].Series == nil {
		return 0
	}
	val, err := res[0].Series[0].Values[0][1].(json.Number).Int64()
	if err != nil {
		return 0
	}
	return val
}
<commit_msg>Increase error detection in tests and add benhmark that reconnects each time<commit_after>package fluxlog

import (
	"encoding/json"
	"testing"
	"time"
)

func configure() {
	ChangeGlobalTags(map[string]string{"env": "test"})
	SaveMetadata(true)
	SetAddress("http://storage:8086")
}

func TestWrite(t *testing.T) {
	configure()              // setup influx connection
	defer DisconnectInflux() // teardown influx connection

	measure := "test_write_01"
	field := "id"
	count := getCount(t, measure, field)

	tags := map[string]string{"test": t.Name()}
	err := Write(measure, map[string]interface{}{field: 42}, tags)
	if err != nil {
		t.Fatal("Failed to write to influx due to error:", err)
	}

	if getCountWhere(t, measure, field, "\"file\" = 'fluxlog_test.go'") <= count {
		t.Fatal("Failed to Write point to influxdb")
	}
}

func TestWritef(t *testing.T) {
	configure()              // setup influx connection
	defer DisconnectInflux() // teardown influx connection

	measure := "failed to do thing with id %d"
	field := "d1"
	count := getCount(t, measure, field)

	err := Writef(measure)
	if err == nil {
		t.Fatal("Failed to generate writef error when insufficient values are given")
	}

	if getCountWhere(t, measure, field, "\"file\" = 'fluxlog_test.go'") != count {
		t.Fatal("Sometime was written using Writef to influxdb when it was expected not too")
	}

	err = Writef(measure, 42)
	if err != nil {
		t.Fatal("Failed to write to influx due to error:", err)
	}

	if getCountWhere(t, measure, field, "\"file\" = 'fluxlog_test.go'") <= count {
		t.Fatal("Failed to Writef point to influxdb")
	}
}

func TestWhitelist(t *testing.T) {
	configure()              // setup influx connection
	defer DisconnectInflux() // teardown influx connection

	measureDeny := "test_write_02"
	measureAllow := "test_write_03"
	AddMeasurementToWhitelist(measureAllow)
	AddMeasurementToWhitelist(measureAllow + "1")
	defer ChangeMeasurementsWhitelist([]string{})
	field := "id"
	count := getCount(t, measureDeny, field)

	err := Write(measureDeny, map[string]interface{}{field: 42}, map[string]string{})
	if err == nil {
		t.Fatal("Failed to write to influx due to error:", err)
	}

	if getCountWhere(t, measureDeny, field, "\"file\" = 'fluxlog_test.go'") != count {
		t.Fatal("Something was written to influx when the measurement was not whitelisted")
	}

	err = Write(measureAllow, map[string]interface{}{field: 42}, map[string]string{})
	if err != nil {
		t.Fatal("Failed to write whitelisted measure to influx due to error:", err)
	}

	if getCountWhere(t, measureAllow, field, "\"file\" = 'fluxlog_test.go'") <= count {
		t.Fatal("Failed to write whitelisted measure to influx")
	}
}

func BenchmarkWrite(b *testing.B) {
	configure()              // setup influx connection
	defer DisconnectInflux() // teardown influx connection

	var err error
	fields := map[string]interface{}{"id": 42}
	tags := map[string]string{"test": b.Name()}
	// run the Fib function b.N times
	for n := 0; n < b.N; n++ {
		err = Write("test_write_03", fields, tags)
		if err != nil {
			b.Fatal("Write in benchmark failed with error:", err)
		}
	}
}

func BenchmarkWriteReconnect(b *testing.B) {
	configure()              // setup influx connection
	defer DisconnectInflux() // teardown influx connection

	var err error
	fields := map[string]interface{}{"id": 42}
	tags := map[string]string{"test": b.Name()}
	// run the Fib function b.N times
	for n := 0; n < b.N; n++ {
		err = Write("test_write_04", fields, tags)
		if err != nil {
			b.Fatal("Write in benchmark failed with error:", err)
		}
		DisconnectInflux()
	}
}

func BenchmarkWritef(b *testing.B) {
	configure()              // setup influx connection
	defer DisconnectInflux() // teardown influx connection

	var err error
	for n := 0; n < b.N; n++ {
		err = Writef("benchmarking thing with id %d", n)
		if err != nil {
			b.Fatal("Writef in benchmark failed with error:", err)
		}
	}
}

func BenchmarkWritefSlow(b *testing.B) {
	if testing.Short() {
		b.Skipf("Skipping %s in short mode", b.Name())
	}
	configure()              // setup influx connection
	defer DisconnectInflux() // teardown influx connection

	var err error
	for n := 0; n < b.N; n++ {
		err = Writef("benchmarking slow thing with id %d", n)
		if err != nil {
			b.Fatal("Writef in benchmark failed with error:", err)
		}
		time.Sleep(500 * time.Millisecond)
	}
}

func getCountWhere(t *testing.T, measurement string, field string, where string) int64 {
	t.Helper()
	res, err := queryInflux("SELECT count(" + field + ") FROM \"" + measurement + "\" WHERE " + where)
	if err != nil || res[0].Series == nil {
		return 0
	}
	val, err := res[0].Series[0].Values[0][1].(json.Number).Int64()
	if err != nil {
		return 0
	}
	return val
}

func getCount(t *testing.T, measurement string, field string) int64 {
	t.Helper()
	res, err := queryInflux("SELECT count(" + field + ") FROM \"" + measurement + "\" WHERE \"env\" ='test'")
	if err != nil || res[0].Series == nil {
		return 0
	}
	val, err := res[0].Series[0].Values[0][1].(json.Number).Int64()
	if err != nil {
		return 0
	}
	return val
}
<|endoftext|>


<commit_before>package internal

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"path"
	"sort"
	"strconv"
	"strings"

	"github.com/peterh/liner"
)

type Arguments = map[string]string

type Scope int

const (
	InvalidScope Scope = iota
	LocalScope
	ParentScope
	GlobalScope
)

func (s Scope) String() string {
	switch s {
	case LocalScope:
		return "local"
	case ParentScope:
		return "parent"
	case GlobalScope:
		return "global"
	default:
		return "invalid scope"
	}
}

type Context struct {
	line    *liner.State // interactive line reader
	scanner BasicScanner // file based line reader

	historyFile string
	scopes      []Arguments
}

func NewContext() *Context {
	return &Context{}
}

func (ctx *Context) StartLiner(history string) {
	ctx.line = liner.NewLiner()
	ctx.readHistoryFile(history)
	ctx.ScanLiner()
}

func (ctx *Context) StopLiner() {
	if ctx.line != nil {
		ctx.writeHistoryFile()
		ctx.line.Close()
	}
}

func (ctx *Context) UpdateHistory(line string) {
	if ctx.line != nil {
		ctx.line.AppendHistory(line)
	}
}

func (ctx *Context) SetWordCompleter(completer func(line string, pos int) (head string, completions []string, tail string)) {
	if ctx.line != nil {
		ctx.line.SetWordCompleter(completer)
	}
}

func (ctx *Context) readHistoryFile(history string) {
	if len(history) == 0 {
		// no history file
		return
	}

	filepath := history // start with current directory
	if f, err := os.Open(filepath); err == nil {
		ctx.line.ReadHistory(f)
		f.Close()

		ctx.historyFile = filepath
		return
	}

	filepath = path.Join(os.Getenv("HOME"), filepath) // then check home directory
	if f, err := os.Open(filepath); err == nil {
		ctx.line.ReadHistory(f)
		f.Close()

		ctx.historyFile = filepath
		return
	}

	if f, err := os.Create(filepath); err == nil { // if we can create the history file, set the path
		// create history file
		f.Close()

		ctx.historyFile = filepath
	}
}

func (ctx *Context) writeHistoryFile() {
	if len(ctx.historyFile) == 0 {
		// no history file
		return
	}

	if f, err := os.Create(ctx.historyFile); err == nil {
		ctx.line.WriteHistory(f)
		f.Close()
	}
}

//
// PushScope pushes a new scope for variables, with the associated dvalues
//
func (ctx *Context) PushScope(vars map[string]string, args []string) {
	scope := make(Arguments)

	for k, v := range vars {
		scope[k] = v
	}

	for i, v := range args {
		k := strconv.Itoa(i)
		scope[k] = v
	}

	if args != nil {
		scope["*"] = strings.Join(args[1:], " ") // all args
		scope["#"] = strconv.Itoa(len(args[1:])) // args[0] is the function name
	}

	ctx.scopes = append(ctx.scopes, scope)
}

//
// PopScope removes the current scope, restoring the previous one
//
func (ctx *Context) PopScope() {
	l := len(ctx.scopes)
	if l == 0 {
		panic("no scopes")
	}

	ctx.scopes = ctx.scopes[:l-1]
}

//
// GetScope returns the variable sets for the specified scope
//
func (ctx *Context) GetScope(scope Scope) Arguments {
	i := len(ctx.scopes) - 1 // index of local scope
	if i < 0 {
		panic("no scopes")
	}

	switch scope {
	case GlobalScope:
		i = 0 // index of global scope

	case ParentScope:
		if i > 0 {
			i -= 1 // index of parent scope
		}
	}

	return ctx.scopes[i]
}

//
// SetVar sets a variable in the current, parent or global scope
//
func (ctx *Context) SetVar(k string, v interface{}, scope Scope) {
	i := len(ctx.scopes) - 1 // index of local scope
	if i < 0 {
		panic("no scopes")
	}

	switch scope {
	case GlobalScope:
		i = 0 // index of global scope

	case ParentScope:
		if i > 0 {
			i -= 1 // index of parent scope
		}
	}

	ctx.scopes[i][k] = fmt.Sprintf("%v", v)
}

//
// UnsetVar removes a variable from the current, parent or global scope
//
func (ctx *Context) UnsetVar(k string, scope Scope) {
	i := len(ctx.scopes) - 1 // index of local scope
	if i < 0 {
		panic("no scopes")
	}

	switch scope {
	case GlobalScope:
		i = 0 // index of global scope

	case ParentScope:
		if i > 0 {
			i -= 1 // index of parent scope
		}
	}

	if _, ok := ctx.scopes[i][k]; ok {
		delete(ctx.scopes[i], k)
	}
}

//
// GetVar return the value of the specified variable from the closest scope
//
func (ctx *Context) GetVar(k string) (string, bool) {
	for i := len(ctx.scopes) - 1; i >= 0; i-- {
		if v, ok := ctx.scopes[i][k]; ok {
			return v, true
		}
	}

	return "", false
}

//
// GetAllVars return a copy of all variables available at the current scope
//
func (ctx *Context) GetAllVars() (all Arguments) {
	all = Arguments{}

	for _, scope := range ctx.scopes {
		for k, v := range scope {
			all[k] = v
		}
	}

	return
}

//
// GetAllVars return a copy of all variables available at the current scope
//
func (ctx *Context) GetVarNames() (names []string) {
	for name, _ := range ctx.GetAllVars() {
		names = append(names, name)
	}

	sort.Strings(names)
	return
}

//
// A basic scanner interface
//
type BasicScanner interface {
	Scan(prompt string) bool
	Text() string
	Err() error
}

//
// An implementation of basicScanner that works on a list of lines
//
type ScanLines struct {
	lines []string
}

func (s *ScanLines) Scan(prompt string) bool {
	return len(s.lines) > 0
}

func (s *ScanLines) Text() (text string) {
	if len(s.lines) == 0 {
		return
	}

	text, s.lines = s.lines[0], s.lines[1:]
	return
}

func (s *ScanLines) Err() (err error) {
	return
}

//
// An implementation of basicScanner that works with "liner"
//
type ScanLiner struct {
	line *liner.State
	text string
	err  error
}

func (s *ScanLiner) Scan(prompt string) bool {
	s.text, s.err = s.line.Prompt(prompt)
	return s.err == nil
}

func (s *ScanLiner) Text() string {
	return s.text
}

func (s *ScanLiner) Err() error {
	return s.err
}

//
// An implementation of basicScanner that works with an io.Reader (wrapped in a bufio.Scanner)
//
type ScanReader struct {
	sr *bufio.Scanner
}

func (s *ScanReader) Scan(prompt string) bool {
	return s.sr.Scan()
}

func (s *ScanReader) Text() string {
	return s.sr.Text()
}

func (s *ScanReader) Err() error {
	return s.sr.Err()
}

//
// SetScanner sets the current scanner and return the previos one
//
func (ctx *Context) SetScanner(curr BasicScanner) (prev BasicScanner) {
	prev, ctx.scanner = ctx.scanner, curr
	return
}

//
// ScanLiner sets the current scanner to a "liner" scanner
//
func (ctx *Context) ScanLiner() BasicScanner {
	return ctx.SetScanner(&ScanLiner{line: ctx.line})
}

//
// ScanBlock sets the current scanner to a block scanner
//
func (ctx *Context) ScanBlock(block []string) BasicScanner {
	return ctx.SetScanner(&ScanLines{lines: block})
}

//
// ScanReader sets the current scanner to an io.Reader scanner
//
func (ctx *Context) ScanReader(r io.Reader) BasicScanner {
	return ctx.SetScanner(&ScanReader{sr: bufio.NewScanner(r)})
}

func (ctx *Context) readOneLine(prompt string) (line string, err error) {
	if ctx.scanner.Scan(prompt) {
		line = ctx.scanner.Text()
	} else if ctx.scanner.Err() != nil {
		err = ctx.scanner.Err()
	} else {
		err = io.EOF
	}

	// fmt.Printf("readOneLine:%v %q %v\n", prompt, line, err)
	return
}

func (ctx *Context) ReadLine(prompt, cont string) (line string, err error) {
	line, err = ctx.readOneLine(prompt)
	if err != nil {
		return
	}

	line = strings.TrimSpace(line)

	//
	// merge lines ending with '\' into one single line
	//
	for strings.HasSuffix(line, "\\") { // continuation
		line = strings.TrimRight(line, "\\")
		line = strings.TrimSpace(line)

		l, err := ctx.readOneLine(cont)
		if err != nil {
			fmt.Fprintln(os.Stderr, "continuation", err)
			break
		}

		line += " " + strings.TrimSpace(l)
	}

	return
}

func (ctx *Context) ReadBlock(body, next, cont string) ([]string, []string, error) {
	if !strings.HasSuffix(body, "{") { // one line body
		body := strings.Replace(body, "\\$", "$", -1) // for one-liners variables should be escaped
		return []string{body}, nil, nil
	}

	if body != "{" { // we can't do inline command + body
		return nil, nil, fmt.Errorf("unexpected body and block")
	}

	opened := 1
	var block1, block2 []string
	var line string
	var err error

	for {

		line, err = ctx.ReadLine(cont, cont)
		if err != nil {
			return nil, nil, err
		}

		line = strings.TrimSpace(line)
		if strings.HasPrefix(line, "#") || line == "" {
			block1 = append(block1, line)
			continue
		}

		if strings.HasPrefix(line, "}") {
			opened -= 1
			if opened <= 0 { // close first block
				break
			}
		}
		if strings.HasSuffix(line, "{") {
			opened += 1
		}

		block1 = append(block1, line)
	}

	line = strings.TrimPrefix(line, "}")
	line = strings.TrimSpace(line)

	if strings.HasPrefix(line, "#") || line == "" {
		return block1, nil, nil
	}

	if next != "" && !strings.HasPrefix(line, next) {
		return nil, nil, fmt.Errorf("expected %q, got %q", next, line)
	}

	line = line[len(next):]
	line = strings.TrimSpace(line)

	if line != "{" {
		return nil, nil, fmt.Errorf("expected }, got %q", line)
	}

	opened = 1

	for {

		line, err = ctx.ReadLine(cont, cont)
		if err != nil {
			return nil, nil, err
		}

		line = strings.TrimSpace(line)
		if strings.HasPrefix(line, "#") || line == "" {
			block2 = append(block2, line)
			continue
		}

		if strings.HasPrefix(line, "}") {
			opened -= 1
			if opened <= 0 { // close second block
				break
			}
		}
		if strings.HasSuffix(line, "{") {
			opened += 1
		}

		block2 = append(block2, line)
	}

	return block1, block2, nil
}

func (ctx *Context) ResetTerminal() {
	if ctx.line != nil {
		ctx.line.Close()
	}
}

func (ctx *Context) TerminalMode() (liner.ModeApplier, error) {
	return liner.TerminalMode()
}

func (ctx *Context) RestoreMode(m liner.ModeApplier) {
	if m != nil {
		m.ApplyMode()
	}
}
<commit_msg>don't write history file if there are no changes<commit_after>package internal

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"path"
	"sort"
	"strconv"
	"strings"

	"github.com/peterh/liner"
)

type Arguments = map[string]string

type Scope int

const (
	InvalidScope Scope = iota
	LocalScope
	ParentScope
	GlobalScope
)

func (s Scope) String() string {
	switch s {
	case LocalScope:
		return "local"
	case ParentScope:
		return "parent"
	case GlobalScope:
		return "global"
	default:
		return "invalid scope"
	}
}

type Context struct {
	line    *liner.State // interactive line reader
	scanner BasicScanner // file based line reader

	historyFile string
	hasHistory  bool
	scopes      []Arguments
}

func NewContext() *Context {
	return &Context{}
}

func (ctx *Context) StartLiner(history string) {
	ctx.line = liner.NewLiner()
	ctx.readHistoryFile(history)
	ctx.ScanLiner()
}

func (ctx *Context) StopLiner() {
	if ctx.line != nil {
		ctx.writeHistoryFile()
		ctx.line.Close()
	}
}

func (ctx *Context) UpdateHistory(line string) {
	if ctx.line != nil {
		ctx.line.AppendHistory(line)
		ctx.hasHistory = true
	}
}

func (ctx *Context) SetWordCompleter(completer func(line string, pos int) (head string, completions []string, tail string)) {
	if ctx.line != nil {
		ctx.line.SetWordCompleter(completer)
	}
}

func (ctx *Context) readHistoryFile(history string) {
	if len(history) == 0 {
		// no history file
		return
	}

	filepath := history // start with current directory
	if f, err := os.Open(filepath); err == nil {
		ctx.line.ReadHistory(f)
		f.Close()

		ctx.historyFile = filepath
		return
	}

	filepath = path.Join(os.Getenv("HOME"), filepath) // then check home directory
	if f, err := os.Open(filepath); err == nil {
		ctx.line.ReadHistory(f)
		f.Close()

		ctx.historyFile = filepath
		return
	}

	if f, err := os.Create(filepath); err == nil { // if we can create the history file, set the path
		// create history file
		f.Close()

		ctx.historyFile = filepath
	}
}

func (ctx *Context) writeHistoryFile() {
	if len(ctx.historyFile) == 0 || !ctx.hasHistory {
		// no history file or no changes
		return
	}

	if f, err := os.Create(ctx.historyFile); err == nil {
		ctx.line.WriteHistory(f)
		f.Close()
	}
}

//
// PushScope pushes a new scope for variables, with the associated dvalues
//
func (ctx *Context) PushScope(vars map[string]string, args []string) {
	scope := make(Arguments)

	for k, v := range vars {
		scope[k] = v
	}

	for i, v := range args {
		k := strconv.Itoa(i)
		scope[k] = v
	}

	if args != nil {
		scope["*"] = strings.Join(args[1:], " ") // all args
		scope["#"] = strconv.Itoa(len(args[1:])) // args[0] is the function name
	}

	ctx.scopes = append(ctx.scopes, scope)
}

//
// PopScope removes the current scope, restoring the previous one
//
func (ctx *Context) PopScope() {
	l := len(ctx.scopes)
	if l == 0 {
		panic("no scopes")
	}

	ctx.scopes = ctx.scopes[:l-1]
}

//
// GetScope returns the variable sets for the specified scope
//
func (ctx *Context) GetScope(scope Scope) Arguments {
	i := len(ctx.scopes) - 1 // index of local scope
	if i < 0 {
		panic("no scopes")
	}

	switch scope {
	case GlobalScope:
		i = 0 // index of global scope

	case ParentScope:
		if i > 0 {
			i -= 1 // index of parent scope
		}
	}

	return ctx.scopes[i]
}

//
// SetVar sets a variable in the current, parent or global scope
//
func (ctx *Context) SetVar(k string, v interface{}, scope Scope) {
	i := len(ctx.scopes) - 1 // index of local scope
	if i < 0 {
		panic("no scopes")
	}

	switch scope {
	case GlobalScope:
		i = 0 // index of global scope

	case ParentScope:
		if i > 0 {
			i -= 1 // index of parent scope
		}
	}

	ctx.scopes[i][k] = fmt.Sprintf("%v", v)
}

//
// UnsetVar removes a variable from the current, parent or global scope
//
func (ctx *Context) UnsetVar(k string, scope Scope) {
	i := len(ctx.scopes) - 1 // index of local scope
	if i < 0 {
		panic("no scopes")
	}

	switch scope {
	case GlobalScope:
		i = 0 // index of global scope

	case ParentScope:
		if i > 0 {
			i -= 1 // index of parent scope
		}
	}

	if _, ok := ctx.scopes[i][k]; ok {
		delete(ctx.scopes[i], k)
	}
}

//
// GetVar return the value of the specified variable from the closest scope
//
func (ctx *Context) GetVar(k string) (string, bool) {
	for i := len(ctx.scopes) - 1; i >= 0; i-- {
		if v, ok := ctx.scopes[i][k]; ok {
			return v, true
		}
	}

	return "", false
}

//
// GetAllVars return a copy of all variables available at the current scope
//
func (ctx *Context) GetAllVars() (all Arguments) {
	all = Arguments{}

	for _, scope := range ctx.scopes {
		for k, v := range scope {
			all[k] = v
		}
	}

	return
}

//
// GetAllVars return a copy of all variables available at the current scope
//
func (ctx *Context) GetVarNames() (names []string) {
	for name, _ := range ctx.GetAllVars() {
		names = append(names, name)
	}

	sort.Strings(names)
	return
}

//
// A basic scanner interface
//
type BasicScanner interface {
	Scan(prompt string) bool
	Text() string
	Err() error
}

//
// An implementation of basicScanner that works on a list of lines
//
type ScanLines struct {
	lines []string
}

func (s *ScanLines) Scan(prompt string) bool {
	return len(s.lines) > 0
}

func (s *ScanLines) Text() (text string) {
	if len(s.lines) == 0 {
		return
	}

	text, s.lines = s.lines[0], s.lines[1:]
	return
}

func (s *ScanLines) Err() (err error) {
	return
}

//
// An implementation of basicScanner that works with "liner"
//
type ScanLiner struct {
	line *liner.State
	text string
	err  error
}

func (s *ScanLiner) Scan(prompt string) bool {
	s.text, s.err = s.line.Prompt(prompt)
	return s.err == nil
}

func (s *ScanLiner) Text() string {
	return s.text
}

func (s *ScanLiner) Err() error {
	return s.err
}

//
// An implementation of basicScanner that works with an io.Reader (wrapped in a bufio.Scanner)
//
type ScanReader struct {
	sr *bufio.Scanner
}

func (s *ScanReader) Scan(prompt string) bool {
	return s.sr.Scan()
}

func (s *ScanReader) Text() string {
	return s.sr.Text()
}

func (s *ScanReader) Err() error {
	return s.sr.Err()
}

//
// SetScanner sets the current scanner and return the previos one
//
func (ctx *Context) SetScanner(curr BasicScanner) (prev BasicScanner) {
	prev, ctx.scanner = ctx.scanner, curr
	return
}

//
// ScanLiner sets the current scanner to a "liner" scanner
//
func (ctx *Context) ScanLiner() BasicScanner {
	return ctx.SetScanner(&ScanLiner{line: ctx.line})
}

//
// ScanBlock sets the current scanner to a block scanner
//
func (ctx *Context) ScanBlock(block []string) BasicScanner {
	return ctx.SetScanner(&ScanLines{lines: block})
}

//
// ScanReader sets the current scanner to an io.Reader scanner
//
func (ctx *Context) ScanReader(r io.Reader) BasicScanner {
	return ctx.SetScanner(&ScanReader{sr: bufio.NewScanner(r)})
}

func (ctx *Context) readOneLine(prompt string) (line string, err error) {
	if ctx.scanner.Scan(prompt) {
		line = ctx.scanner.Text()
	} else if ctx.scanner.Err() != nil {
		err = ctx.scanner.Err()
	} else {
		err = io.EOF
	}

	// fmt.Printf("readOneLine:%v %q %v\n", prompt, line, err)
	return
}

func (ctx *Context) ReadLine(prompt, cont string) (line string, err error) {
	line, err = ctx.readOneLine(prompt)
	if err != nil {
		return
	}

	line = strings.TrimSpace(line)

	//
	// merge lines ending with '\' into one single line
	//
	for strings.HasSuffix(line, "\\") { // continuation
		line = strings.TrimRight(line, "\\")
		line = strings.TrimSpace(line)

		l, err := ctx.readOneLine(cont)
		if err != nil {
			fmt.Fprintln(os.Stderr, "continuation", err)
			break
		}

		line += " " + strings.TrimSpace(l)
	}

	return
}

func (ctx *Context) ReadBlock(body, next, cont string) ([]string, []string, error) {
	if !strings.HasSuffix(body, "{") { // one line body
		body := strings.Replace(body, "\\$", "$", -1) // for one-liners variables should be escaped
		return []string{body}, nil, nil
	}

	if body != "{" { // we can't do inline command + body
		return nil, nil, fmt.Errorf("unexpected body and block")
	}

	opened := 1
	var block1, block2 []string
	var line string
	var err error

	for {

		line, err = ctx.ReadLine(cont, cont)
		if err != nil {
			return nil, nil, err
		}

		line = strings.TrimSpace(line)
		if strings.HasPrefix(line, "#") || line == "" {
			block1 = append(block1, line)
			continue
		}

		if strings.HasPrefix(line, "}") {
			opened -= 1
			if opened <= 0 { // close first block
				break
			}
		}
		if strings.HasSuffix(line, "{") {
			opened += 1
		}

		block1 = append(block1, line)
	}

	line = strings.TrimPrefix(line, "}")
	line = strings.TrimSpace(line)

	if strings.HasPrefix(line, "#") || line == "" {
		return block1, nil, nil
	}

	if next != "" && !strings.HasPrefix(line, next) {
		return nil, nil, fmt.Errorf("expected %q, got %q", next, line)
	}

	line = line[len(next):]
	line = strings.TrimSpace(line)

	if line != "{" {
		return nil, nil, fmt.Errorf("expected }, got %q", line)
	}

	opened = 1

	for {

		line, err = ctx.ReadLine(cont, cont)
		if err != nil {
			return nil, nil, err
		}

		line = strings.TrimSpace(line)
		if strings.HasPrefix(line, "#") || line == "" {
			block2 = append(block2, line)
			continue
		}

		if strings.HasPrefix(line, "}") {
			opened -= 1
			if opened <= 0 { // close second block
				break
			}
		}
		if strings.HasSuffix(line, "{") {
			opened += 1
		}

		block2 = append(block2, line)
	}

	return block1, block2, nil
}

func (ctx *Context) ResetTerminal() {
	if ctx.line != nil {
		ctx.line.Close()
	}
}

func (ctx *Context) TerminalMode() (liner.ModeApplier, error) {
	return liner.TerminalMode()
}

func (ctx *Context) RestoreMode(m liner.ModeApplier) {
	if m != nil {
		m.ApplyMode()
	}
}
<|endoftext|>


<commit_before>package oss_test

import (
	"bytes"
	"io"
	"io/ioutil"
	"math/rand"
	"net/http"
	"os"
	"strconv"
	"sync"
	//"net/http"
	"testing"
	"time"

	"github.com/denverdino/aliyungo/oss"
)

var (
	client     *oss.Client //= oss.NewOSSClient(TestRegion, false, TestAccessKeyId, TestAccessKeySecret, false)
	TestBucket = strconv.FormatInt(time.Now().Unix(), 10)
)

func init() {
	AccessKeyId := os.Getenv("AccessKeyId")
	AccessKeySecret := os.Getenv("AccessKeySecret")
	if len(AccessKeyId) != 0 && len(AccessKeySecret) != 0 {
		client = oss.NewOSSClient(TestRegion, false, AccessKeyId, AccessKeySecret, false)
	} else {
		client = oss.NewOSSClient(TestRegion, false, TestAccessKeyId, TestAccessKeySecret, false)
	}

}

func TestCreateBucket(t *testing.T) {
	b := client.Bucket(TestBucket)
	err := b.PutBucket(oss.Private)
	if err != nil {
		t.Errorf("Failed for PutBucket: %v", err)
	}
	t.Log("Wait a while for bucket creation ...")
	time.Sleep(10 * time.Second)
}

func TestHead(t *testing.T) {

	b := client.Bucket(TestBucket)
	_, err := b.Head("name", nil)

	if err == nil {
		t.Errorf("Failed for Head: %v", err)
	}
}

func TestPutObject(t *testing.T) {
	const DISPOSITION = "attachment; filename=\"0x1a2b3c.jpg\""

	b := client.Bucket(TestBucket)
	err := b.Put("name", []byte("content"), "content-type", oss.Private, oss.Options{ContentDisposition: DISPOSITION})
	if err != nil {
		t.Errorf("Failed for Put: %v", err)
	}
}

func TestGet(t *testing.T) {

	b := client.Bucket(TestBucket)
	data, err := b.Get("name")

	if err != nil || string(data) != "content" {
		t.Errorf("Failed for Get: %v", err)
	}
}

func TestURL(t *testing.T) {

	b := client.Bucket(TestBucket)
	url := b.URL("name")

	t.Log("URL: ", url)
	//	/c.Assert(req.URL.Path, check.Equals, "/denverdino_test/name")
}

func TestGetReader(t *testing.T) {

	b := client.Bucket(TestBucket)
	rc, err := b.GetReader("name")
	if err != nil {
		t.Fatalf("Failed for GetReader: %v", err)
	}
	data, err := ioutil.ReadAll(rc)
	rc.Close()
	if err != nil || string(data) != "content" {
		t.Errorf("Failed for ReadAll: %v", err)
	}
}

func aTestGetNotFound(t *testing.T) {

	b := client.Bucket("non-existent-bucket")
	_, err := b.Get("non-existent")
	if err == nil {
		t.Fatalf("Failed for TestGetNotFound: %v", err)
	}
	ossErr, _ := err.(*oss.Error)
	if ossErr.StatusCode != 404 || ossErr.BucketName != "non-existent-bucket" {
		t.Errorf("Failed for TestGetNotFound: %v", err)
	}

}

func TestPutCopy(t *testing.T) {
	b := client.Bucket(TestBucket)
	t.Log("Source: ", b.Path("name"))
	res, err := b.PutCopy("newname", oss.Private, oss.CopyOptions{},
		b.Path("name"))
	if err == nil {
		t.Logf("Copy result: %v", res)
	} else {
		t.Errorf("Failed for PutCopy: %v", err)
	}
}

func TestList(t *testing.T) {

	b := client.Bucket(TestBucket)

	data, err := b.List("n", "", "", 0)
	if err != nil || len(data.Contents) != 2 {
		t.Errorf("Failed for List: %v", err)
	} else {
		t.Logf("Contents = %++v", data)
	}
}

func TestListWithDelimiter(t *testing.T) {

	b := client.Bucket(TestBucket)

	data, err := b.List("photos/2006/", "/", "some-marker", 1000)
	if err != nil || len(data.Contents) != 0 {
		t.Errorf("Failed for List: %v", err)
	} else {
		t.Logf("Contents = %++v", data)
	}

}

func TestPutReader(t *testing.T) {

	b := client.Bucket(TestBucket)
	buf := bytes.NewBufferString("content")
	err := b.PutReader("name", buf, int64(buf.Len()), "application/octet-stream", oss.Private, oss.Options{})
	if err != nil {
		t.Errorf("Failed for PutReader: %v", err)
	}
	TestGetReader(t)
}

var _fileSize int64 = 25 * 1024 * 1024
var _offset int64 = 10 * 1024 * 1024

func TestPutLargeFile(t *testing.T) {

	reader := newRandReader(_fileSize)

	b := client.Bucket(TestBucket)
	err := b.PutReader("largefile", reader, _fileSize, "application/octet-stream", oss.Private, oss.Options{})
	if err != nil {
		t.Errorf("Failed for PutReader: %v", err)
	}
}

func TestGetLargeFile(t *testing.T) {
	b := client.Bucket(TestBucket)
	headers := http.Header{}
	resp, err := b.GetResponseWithHeaders("largefile", headers)
	if err != nil {
		t.Fatalf("Failed for GetResponseWithHeaders: %v", err)
	}
	if resp.ContentLength != _fileSize {
		t.Errorf("Read file with incorrect ContentLength: %d", resp.ContentLength)

	}
	t.Logf("Large file response headers: %++v", resp.Header)

	data, err := ioutil.ReadAll(resp.Body)

	if err != nil {
		t.Errorf("Failed for Read file: %v", err)
	}

	if len(data) != int(_fileSize) {
		t.Errorf("Incorrect length for Read with offset: %v", len(data))
	}
	resp.Body.Close()
}

func TestGetLargeFileWithOffset(t *testing.T) {
	b := client.Bucket(TestBucket)
	headers := http.Header{}
	headers.Add("Range", "bytes="+strconv.FormatInt(_offset, 10)+"-")
	resp, err := b.GetResponseWithHeaders("largefile", headers)
	if err != nil {
		t.Fatalf("Failed for GetResponseWithHeaders: %v", err)
	}
	t.Logf("Large file response headers: %++v", resp.Header)

	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		t.Errorf("Failed for Read with offset: %v", err)
	}
	if len(data) != int(_fileSize-_offset) {
		t.Errorf("Incorrect length for Read with offset: %v", len(data))
	}
	resp.Body.Close()
}

func TestSignedURL(t *testing.T) {
	b := client.Bucket(TestBucket)
	expires := time.Now().Add(20 * time.Minute)
	url := b.SignedURL("largefile", expires)
	resp, err := http.Get(url)
	t.Logf("Large file response headers: %++v", resp.Header)

	if err != nil {
		t.Fatalf("Failed for GetResponseWithHeaders: %v", err)
	}
	data, err := ioutil.ReadAll(resp.Body)

	if err != nil {
		t.Errorf("Failed for Read file: %v", err)
	}

	if len(data) != int(_fileSize) {
		t.Errorf("Incorrect length for Read with offset: %v", len(data))
	}
	resp.Body.Close()
}

func TestCopyLargeFile(t *testing.T) {
	b := client.Bucket(TestBucket)
	err := b.CopyLargeFile("largefile", "largefile2", "application/octet-stream", oss.Private, oss.Options{})
	if err != nil {
		t.Errorf("Failed for copy large file: %v", err)
	}
	t.Log("Large file copy successfully.")
	len1, err := b.GetContentLength("largefile")

	if err != nil {
		t.Fatalf("Failed for Head file: %v", err)
	}
	len2, err := b.GetContentLength("largefile2")

	if err != nil {
		t.Fatalf("Failed for Head file: %v", err)
	}

	if len1 != len2 || len1 != _fileSize {
		t.Fatalf("Content-Length should be equal %d != %d", len1, len2)
	}

	bytes1, err := b.Get("largefile")
	if err != nil {
		t.Fatalf("Failed for Get file: %v", err)
	}
	bytes2, err := b.Get("largefile2")
	if err != nil {
		t.Fatalf("Failed for Get file: %v", err)
	}

	if bytes.Compare(bytes1, bytes2) != 0 {
		t.Fatal("The result should be equal")
	}
}

func TestDelLargeObject(t *testing.T) {

	b := client.Bucket(TestBucket)
	err := b.Del("largefile")
	if err != nil {
		t.Errorf("Failed for Del largefile: %v", err)
	}
	err = b.Del("largefile2")
	if err != nil {
		t.Errorf("Failed for Del largefile2: %v", err)
	}
}

func TestExists(t *testing.T) {

	b := client.Bucket(TestBucket)
	result, err := b.Exists("name")
	if err != nil || result != true {
		t.Errorf("Failed for Exists: %v", err)
	}
}

func TestLocation(t *testing.T) {
	b := client.Bucket(TestBucket)
	result, err := b.Location()

	if err != nil || result != string(TestRegion) {
		t.Errorf("Failed for Location: %v %s", err, result)
	}
}

func TestACL(t *testing.T) {
	b := client.Bucket(TestBucket)
	result, err := b.ACL()

	if err != nil {
		t.Errorf("Failed for ACL: %v", err)
	} else {
		t.Logf("AccessControlPolicy: %++v", result)
	}
}

func TestDelObject(t *testing.T) {

	b := client.Bucket(TestBucket)
	err := b.Del("name")
	if err != nil {
		t.Errorf("Failed for Del: %v", err)
	}
}

func TestDelMultiObjects(t *testing.T) {

	b := client.Bucket(TestBucket)
	objects := []oss.Object{oss.Object{Key: "newname"}}
	err := b.DelMulti(oss.Delete{
		Quiet:   false,
		Objects: objects,
	})
	if err != nil {
		t.Errorf("Failed for DelMulti: %v", err)
	}
}

func TestGetService(t *testing.T) {
	bucketList, err := client.GetService()
	if err != nil {
		t.Errorf("Unable to get service: %v", err)
	} else {
		t.Logf("GetService: %++v", bucketList)
	}
}

func TestGetBucketInfo(t *testing.T) {
	b := client.Bucket(TestBucket)
	resp, err := b.Info()
	if err != nil {
		t.Errorf("Failed for Info: %v", err)
	} else {
		t.Logf("Bucket Info: %v", resp)
	}
}

func TestDelBucket(t *testing.T) {

	b := client.Bucket(TestBucket)
	err := b.DelBucket()
	if err != nil {
		t.Errorf("Failed for DelBucket: %v", err)
	}
}

type randReader struct {
	r int64
	m sync.Mutex
}

func (rr *randReader) Read(p []byte) (n int, err error) {
	rr.m.Lock()
	defer rr.m.Unlock()
	for i := 0; i < len(p) && rr.r > 0; i++ {
		p[i] = byte(rand.Intn(255))
		n++
		rr.r--
	}
	if rr.r == 0 {
		err = io.EOF
	}
	return
}

func newRandReader(n int64) *randReader {
	return &randReader{r: n}
}
<commit_msg>removed commented code<commit_after>package oss_test

import (
	"bytes"
	"io"
	"io/ioutil"
	"math/rand"
	"net/http"
	"os"
	"strconv"
	"sync"
	//"net/http"
	"testing"
	"time"

	"github.com/denverdino/aliyungo/oss"
)

var (
	client     *oss.Client
	TestBucket = strconv.FormatInt(time.Now().Unix(), 10)
)

func init() {
	AccessKeyId := os.Getenv("AccessKeyId")
	AccessKeySecret := os.Getenv("AccessKeySecret")
	if len(AccessKeyId) != 0 && len(AccessKeySecret) != 0 {
		client = oss.NewOSSClient(TestRegion, false, AccessKeyId, AccessKeySecret, false)
	} else {
		client = oss.NewOSSClient(TestRegion, false, TestAccessKeyId, TestAccessKeySecret, false)
	}

}

func TestCreateBucket(t *testing.T) {
	b := client.Bucket(TestBucket)
	err := b.PutBucket(oss.Private)
	if err != nil {
		t.Errorf("Failed for PutBucket: %v", err)
	}
	t.Log("Wait a while for bucket creation ...")
	time.Sleep(10 * time.Second)
}

func TestHead(t *testing.T) {

	b := client.Bucket(TestBucket)
	_, err := b.Head("name", nil)

	if err == nil {
		t.Errorf("Failed for Head: %v", err)
	}
}

func TestPutObject(t *testing.T) {
	const DISPOSITION = "attachment; filename=\"0x1a2b3c.jpg\""

	b := client.Bucket(TestBucket)
	err := b.Put("name", []byte("content"), "content-type", oss.Private, oss.Options{ContentDisposition: DISPOSITION})
	if err != nil {
		t.Errorf("Failed for Put: %v", err)
	}
}

func TestGet(t *testing.T) {

	b := client.Bucket(TestBucket)
	data, err := b.Get("name")

	if err != nil || string(data) != "content" {
		t.Errorf("Failed for Get: %v", err)
	}
}

func TestURL(t *testing.T) {

	b := client.Bucket(TestBucket)
	url := b.URL("name")

	t.Log("URL: ", url)
	//	/c.Assert(req.URL.Path, check.Equals, "/denverdino_test/name")
}

func TestGetReader(t *testing.T) {

	b := client.Bucket(TestBucket)
	rc, err := b.GetReader("name")
	if err != nil {
		t.Fatalf("Failed for GetReader: %v", err)
	}
	data, err := ioutil.ReadAll(rc)
	rc.Close()
	if err != nil || string(data) != "content" {
		t.Errorf("Failed for ReadAll: %v", err)
	}
}

func aTestGetNotFound(t *testing.T) {

	b := client.Bucket("non-existent-bucket")
	_, err := b.Get("non-existent")
	if err == nil {
		t.Fatalf("Failed for TestGetNotFound: %v", err)
	}
	ossErr, _ := err.(*oss.Error)
	if ossErr.StatusCode != 404 || ossErr.BucketName != "non-existent-bucket" {
		t.Errorf("Failed for TestGetNotFound: %v", err)
	}

}

func TestPutCopy(t *testing.T) {
	b := client.Bucket(TestBucket)
	t.Log("Source: ", b.Path("name"))
	res, err := b.PutCopy("newname", oss.Private, oss.CopyOptions{},
		b.Path("name"))
	if err == nil {
		t.Logf("Copy result: %v", res)
	} else {
		t.Errorf("Failed for PutCopy: %v", err)
	}
}

func TestList(t *testing.T) {

	b := client.Bucket(TestBucket)

	data, err := b.List("n", "", "", 0)
	if err != nil || len(data.Contents) != 2 {
		t.Errorf("Failed for List: %v", err)
	} else {
		t.Logf("Contents = %++v", data)
	}
}

func TestListWithDelimiter(t *testing.T) {

	b := client.Bucket(TestBucket)

	data, err := b.List("photos/2006/", "/", "some-marker", 1000)
	if err != nil || len(data.Contents) != 0 {
		t.Errorf("Failed for List: %v", err)
	} else {
		t.Logf("Contents = %++v", data)
	}

}

func TestPutReader(t *testing.T) {

	b := client.Bucket(TestBucket)
	buf := bytes.NewBufferString("content")
	err := b.PutReader("name", buf, int64(buf.Len()), "application/octet-stream", oss.Private, oss.Options{})
	if err != nil {
		t.Errorf("Failed for PutReader: %v", err)
	}
	TestGetReader(t)
}

var _fileSize int64 = 25 * 1024 * 1024
var _offset int64 = 10 * 1024 * 1024

func TestPutLargeFile(t *testing.T) {

	reader := newRandReader(_fileSize)

	b := client.Bucket(TestBucket)
	err := b.PutReader("largefile", reader, _fileSize, "application/octet-stream", oss.Private, oss.Options{})
	if err != nil {
		t.Errorf("Failed for PutReader: %v", err)
	}
}

func TestGetLargeFile(t *testing.T) {
	b := client.Bucket(TestBucket)
	headers := http.Header{}
	resp, err := b.GetResponseWithHeaders("largefile", headers)
	if err != nil {
		t.Fatalf("Failed for GetResponseWithHeaders: %v", err)
	}
	if resp.ContentLength != _fileSize {
		t.Errorf("Read file with incorrect ContentLength: %d", resp.ContentLength)

	}
	t.Logf("Large file response headers: %++v", resp.Header)

	data, err := ioutil.ReadAll(resp.Body)

	if err != nil {
		t.Errorf("Failed for Read file: %v", err)
	}

	if len(data) != int(_fileSize) {
		t.Errorf("Incorrect length for Read with offset: %v", len(data))
	}
	resp.Body.Close()
}

func TestGetLargeFileWithOffset(t *testing.T) {
	b := client.Bucket(TestBucket)
	headers := http.Header{}
	headers.Add("Range", "bytes="+strconv.FormatInt(_offset, 10)+"-")
	resp, err := b.GetResponseWithHeaders("largefile", headers)
	if err != nil {
		t.Fatalf("Failed for GetResponseWithHeaders: %v", err)
	}
	t.Logf("Large file response headers: %++v", resp.Header)

	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		t.Errorf("Failed for Read with offset: %v", err)
	}
	if len(data) != int(_fileSize-_offset) {
		t.Errorf("Incorrect length for Read with offset: %v", len(data))
	}
	resp.Body.Close()
}

func TestSignedURL(t *testing.T) {
	b := client.Bucket(TestBucket)
	expires := time.Now().Add(20 * time.Minute)
	url := b.SignedURL("largefile", expires)
	resp, err := http.Get(url)
	t.Logf("Large file response headers: %++v", resp.Header)

	if err != nil {
		t.Fatalf("Failed for GetResponseWithHeaders: %v", err)
	}
	data, err := ioutil.ReadAll(resp.Body)

	if err != nil {
		t.Errorf("Failed for Read file: %v", err)
	}

	if len(data) != int(_fileSize) {
		t.Errorf("Incorrect length for Read with offset: %v", len(data))
	}
	resp.Body.Close()
}

func TestCopyLargeFile(t *testing.T) {
	b := client.Bucket(TestBucket)
	err := b.CopyLargeFile("largefile", "largefile2", "application/octet-stream", oss.Private, oss.Options{})
	if err != nil {
		t.Errorf("Failed for copy large file: %v", err)
	}
	t.Log("Large file copy successfully.")
	len1, err := b.GetContentLength("largefile")

	if err != nil {
		t.Fatalf("Failed for Head file: %v", err)
	}
	len2, err := b.GetContentLength("largefile2")

	if err != nil {
		t.Fatalf("Failed for Head file: %v", err)
	}

	if len1 != len2 || len1 != _fileSize {
		t.Fatalf("Content-Length should be equal %d != %d", len1, len2)
	}

	bytes1, err := b.Get("largefile")
	if err != nil {
		t.Fatalf("Failed for Get file: %v", err)
	}
	bytes2, err := b.Get("largefile2")
	if err != nil {
		t.Fatalf("Failed for Get file: %v", err)
	}

	if bytes.Compare(bytes1, bytes2) != 0 {
		t.Fatal("The result should be equal")
	}
}

func TestDelLargeObject(t *testing.T) {

	b := client.Bucket(TestBucket)
	err := b.Del("largefile")
	if err != nil {
		t.Errorf("Failed for Del largefile: %v", err)
	}
	err = b.Del("largefile2")
	if err != nil {
		t.Errorf("Failed for Del largefile2: %v", err)
	}
}

func TestExists(t *testing.T) {

	b := client.Bucket(TestBucket)
	result, err := b.Exists("name")
	if err != nil || result != true {
		t.Errorf("Failed for Exists: %v", err)
	}
}

func TestLocation(t *testing.T) {
	b := client.Bucket(TestBucket)
	result, err := b.Location()

	if err != nil || result != string(TestRegion) {
		t.Errorf("Failed for Location: %v %s", err, result)
	}
}

func TestACL(t *testing.T) {
	b := client.Bucket(TestBucket)
	result, err := b.ACL()

	if err != nil {
		t.Errorf("Failed for ACL: %v", err)
	} else {
		t.Logf("AccessControlPolicy: %++v", result)
	}
}

func TestDelObject(t *testing.T) {

	b := client.Bucket(TestBucket)
	err := b.Del("name")
	if err != nil {
		t.Errorf("Failed for Del: %v", err)
	}
}

func TestDelMultiObjects(t *testing.T) {

	b := client.Bucket(TestBucket)
	objects := []oss.Object{oss.Object{Key: "newname"}}
	err := b.DelMulti(oss.Delete{
		Quiet:   false,
		Objects: objects,
	})
	if err != nil {
		t.Errorf("Failed for DelMulti: %v", err)
	}
}

func TestGetService(t *testing.T) {
	bucketList, err := client.GetService()
	if err != nil {
		t.Errorf("Unable to get service: %v", err)
	} else {
		t.Logf("GetService: %++v", bucketList)
	}
}

func TestGetBucketInfo(t *testing.T) {
	b := client.Bucket(TestBucket)
	resp, err := b.Info()
	if err != nil {
		t.Errorf("Failed for Info: %v", err)
	} else {
		t.Logf("Bucket Info: %v", resp)
	}
}

func TestDelBucket(t *testing.T) {

	b := client.Bucket(TestBucket)
	err := b.DelBucket()
	if err != nil {
		t.Errorf("Failed for DelBucket: %v", err)
	}
}

type randReader struct {
	r int64
	m sync.Mutex
}

func (rr *randReader) Read(p []byte) (n int, err error) {
	rr.m.Lock()
	defer rr.m.Unlock()
	for i := 0; i < len(p) && rr.r > 0; i++ {
		p[i] = byte(rand.Intn(255))
		n++
		rr.r--
	}
	if rr.r == 0 {
		err = io.EOF
	}
	return
}

func newRandReader(n int64) *randReader {
	return &randReader{r: n}
}
<|endoftext|>


<commit_before>package xmlinput

import (
	"fmt"
	"testing"
)

var xmldata = []byte(`<?xml version="1.0" encoding="UTF-8"?>
<InputData>
	<CPU>
		<Config>true</Config>
 		<Min>1</Min>
		<Max>16</Max>
	    <DefaultValue>1</DefaultValue>
  	</CPU>
	<RAM>
		<Config>true</Config>
  		<Min>2500</Min>
      	<Max>0</Max>
		<DefaultValue>2500</DefaultValue>
  	</RAM>
	<Networks>
		<Config>true</Config>
		<!-- Maximal amount of networks to configure -->
		<Max>10</Max>
		<Default>
			<Network>
				<Name>Management</Name>
			</Network>
			<Network>
				<Name>Data1</Name>
			</Network>
			<Network>
				<Name>Data2</Name>
			</Network>
		</Default>
  	</Networks>
  	<NICs>
	 	<!-- Allowed vendors and models -->
		<Allow>
		    <Vendor>Intel</Vendor>
			<Model></Model>
			<Mode>passthrough</Mode>
		</Allow>
		<Allow>
			<Vendor>Broadcom</Vendor>
			<Model></Model>
			<Mode>direct</Mode>
		</Allow>
		<!-- Denied vendors and models -->
		<Deny>
			 <Vendor>Broadcom</Vendor>
			 <Model></Model>
		</Deny>
	</NICs>
</InputData>`)

func TestParse(t *testing.T) {
	d, err := Parse(xmldata)
	if err != nil {
		t.Fatal(err)
	}

	fmt.Printf("%v\n", d)

	for _, nic := range d.Allowed {
		fmt.Printf("\nNIC Vendor =>%s\nNIC Model => %s\nNIC Mode => %s\n",
			nic.Vendor, nic.Model, nic.Mode)
	}
}
<commit_msg>Update xml_input_data_test.go<commit_after>package xmlinput

import (
	"fmt"
	"testing"
)

var xmldata = []byte(`<?xml version="1.0" encoding="UTF-8"?>
<InputData>
  <CPU>
    	<Config>true</Config>
 	<Min>1</Min>
	<Max>16</Max>
	<DefaultValue>1</DefaultValue>
  </CPU>
  <RAM>
	<Config>true</Config>
  	<Min>2500</Min>
      	<Max>0</Max>
	<DefaultValue>2500</DefaultValue>
  </RAM>
  <Networks>
	<Config>true</Config>
	<!-- Maximal amount of networks to configure -->
	<Max>10</Max>
	<Default>
		<Network>
			<Name>Management</Name>
		</Network>
		<Network>
			<Name>Data1</Name>
		</Network>
		<Network>
			<Name>Data2</Name>
		</Network>
	</Default>
  </Networks>
  <NICs>
	<!-- Allowed vendors and models -->
	<Allow>
		<Vendor>Intel</Vendor>
		<Model></Model>
		<Mode>passthrough</Mode>
	</Allow>
	<Allow>
		<Vendor>Broadcom</Vendor>
		<Model></Model>
		<Mode>direct</Mode>
	</Allow>
	<!-- Denied vendors and models -->
	<Deny>
		<Vendor>Broadcom</Vendor>
		<Model></Model>
	</Deny>
   </NICs>
</InputData>`)

func TestParse(t *testing.T) {
	d, err := Parse(xmldata)
	if err != nil {
		t.Fatal(err)
	}

	fmt.Printf("%v\n", d)

	for _, nic := range d.Allowed {
		fmt.Printf("\nNIC Vendor =>%s\nNIC Model => %s\nNIC Mode => %s\n",
			nic.Vendor, nic.Model, nic.Mode)
	}
}
<|endoftext|>