<commit_before>package cqrs

import (
	"errors"
	"fmt"
)

const MESSAGE_TYPE_MASK = 0x80000000
// http://crc32-checksum.waraxe.us/

func C(version uint32, commandId uint32) uint32 {
	return MESSAGE_TYPE_MASK | (version << 16) | (commandId & 0xFF)
}

func E(version uint32, commandId uint32) uint32 {
	return (MESSAGE_TYPE_MASK-1) | (version << 16) | (commandId & 0xFF)
}

type AggregateLoader interface {
	Load(events []Event)
}

type Aggregate interface {
	GetDomain() uint32
	GetId() uint64
	GetVersion() int32
	MatchById(domain uint32, id uint64) bool
}

type AggregateMemento struct {
	Domain uint32 `json:"__domain"`		// Aggregate Domain
	Id uint64 `json:"__id"`				// Aggregate Id
	Version int32 `json:"__version"`	// Aggregate Version
}

func NewAggregate(domain uint32, id uint64, version int32) AggregateMemento {
	return AggregateMemento {
		Domain: domain,
		Id: id,
		Version: version,
	}
}

func (aggregate AggregateMemento) GetDomain() uint32 {
	return aggregate.Domain
}

func (aggregate AggregateMemento) GetId() uint64 {
	return aggregate.Id
}

func (aggregate AggregateMemento) GetVersion() int32 {
	return aggregate.Version
}

func (aggregate AggregateMemento) String() string {
	return fmt.Sprintf("DM[%d] ID[%d] V[%d]", aggregate.Domain, aggregate.Id, aggregate.Version)
}

type Command interface {
	GetCommandType() uint32
}

type CommandMemento struct {
	AggregateMemento					// Aggregate
	CommandType uint32 `json:"__ctype"`	// Command Type
}

func NewCommand(domain uint32, commandType uint32, id uint64, version int32) CommandMemento {
	return CommandMemento {
		AggregateMemento: NewAggregate(domain, id, version),
		CommandType: commandType,
	}
}

func (command CommandMemento) GetCommandType() uint32 {
	return command.CommandType
}

func (command CommandMemento) String() string {
	return fmt.Sprintf(" <C [ %s -> C[%d] ] C\\> ", command.AggregateMemento.String(), command.CommandType)
}

type Event interface {
	GetEventType() uint32
}

type EventMemento struct {
	AggregateMemento					// Aggregate
	EventType uint32 `json:"__etype"`	// Event Type
}

func NewEvent(domain uint32, eventType uint32, id uint64, version int32) EventMemento {
	return EventMemento {
		AggregateMemento: NewAggregate(domain, id, version),
		EventType: eventType,
	}
}

func (event EventMemento) GetEventType() uint32 {
	return event.EventType
}

func (event EventMemento) String() string {
	return fmt.Sprintf(" <E [ %s -> E[%d] ] E\\> ", event.AggregateMemento.String(), event.EventType)
}

type EventStorer interface {
	PersistEvent(event Event)
	ReadAllEvents() (int, []Event, error)
//	ReadAllEventsFrom(index int) (int, []Event, error)
	ReadAggregateEvents(aggregate Aggregate) ([]Event, error)
	ReadAggregateEventsFromSnapshot(aggregate Aggregate) ([]Event, error)
}

type MemoryEventStore struct {
	Snapshot []Aggregate
	EventsChan chan Event
	Data []Event
}

func (eventstore *MemoryEventStore) PersistEvent(event Event) {
	eventstore.Data = append(eventstore.Data, event)
}

func (eventstore *MemoryEventStore) ReadAllEvents() (int, []Event, error) {
	return len(eventstore.Data), eventstore.Data, nil
}

func (eventstore *MemoryEventStore) ReadAllEventsFrom(index int) (int, []Event, error) {
	if index < len(eventstore.Data) {
		events := make([]Event, 0)
		for i := index; i < len(eventstore.Data); i++ {
			events = append(events, eventstore.Data[i])
		}
		return len(eventstore.Data), events, nil
	} else {
		return 0, nil, errors.New("Index position out of range")
	}
}

func (eventstore *MemoryEventStore) ReadAggregateEvents(aggregate Aggregate) ([]Event, error) {
	matching := make([]Event, 0)
	for _, item := range eventstore.Data {
		switch event := item.(type) {
			case Aggregate: {
				if (event.GetDomain() != aggregate.GetDomain() || event.GetId() != aggregate.GetId())) {
					break
				}
				matching = append(matching, item.(Event))
			}
			default: {
				return nil, errors.New(fmt.Sprintf("Item in MemoryEventStore isn't an event [ %s ]\n", item))
			}
		}
	}
	return matching, nil
}

func (eventstore *MemoryEventStore) ReadAggregateEventsFromSnapshot(aggregate Aggregate) ([]Event, error) {
	matching := make([]Event, 0)
	for _, item := range eventstore.Data {
		switch event := item.(type) {
			case Aggregate: {
				if (event.GetDomain() != aggregate.GetDomain() || event.GetId() != aggregate.GetId() || event.GetVersion() < aggregate.GetVersion()) {
					break
				}
				matching = append(matching, item.(Event))
			}
			default: {
				return nil, errors.New(fmt.Sprintf("Item in MemoryEventStore isn't an event [ %s ]\n", item))
			}
		}
	}
	return matching, nil
}

func (eventstore *cqrs.MemoryEventStore) PersistenceLayer(eventBus chan cqrs.Event) {
	for {
		select {
		case event := <- eventstore.EventsChan:
			eventstore.StoreEvent(event)
			eventBus <- event
		}
	}
}

<commit_msg>Removed token EventStore persistence layer<commit_after>package cqrs

import (
	"errors"
	"fmt"
)

const MESSAGE_TYPE_MASK = 0x80000000
// http://crc32-checksum.waraxe.us/

func C(version uint32, commandId uint32) uint32 {
	return MESSAGE_TYPE_MASK | (version << 16) | (commandId & 0xFF)
}

func E(version uint32, commandId uint32) uint32 {
	return (MESSAGE_TYPE_MASK-1) | (version << 16) | (commandId & 0xFF)
}

type AggregateLoader interface {
	Load(events []Event)
}

type Aggregate interface {
	GetDomain() uint32
	GetId() uint64
	GetVersion() int32
	MatchById(domain uint32, id uint64) bool
}

type AggregateMemento struct {
	Domain uint32 `json:"__domain"`		// Aggregate Domain
	Id uint64 `json:"__id"`				// Aggregate Id
	Version int32 `json:"__version"`	// Aggregate Version
}

func NewAggregate(domain uint32, id uint64, version int32) AggregateMemento {
	return AggregateMemento {
		Domain: domain,
		Id: id,
		Version: version,
	}
}

func (aggregate AggregateMemento) GetDomain() uint32 {
	return aggregate.Domain
}

func (aggregate AggregateMemento) GetId() uint64 {
	return aggregate.Id
}

func (aggregate AggregateMemento) GetVersion() int32 {
	return aggregate.Version
}

func (aggregate AggregateMemento) String() string {
	return fmt.Sprintf("DM[%d] ID[%d] V[%d]", aggregate.Domain, aggregate.Id, aggregate.Version)
}

type Command interface {
	GetCommandType() uint32
}

type CommandMemento struct {
	AggregateMemento					// Aggregate
	CommandType uint32 `json:"__ctype"`	// Command Type
}

func NewCommand(domain uint32, commandType uint32, id uint64, version int32) CommandMemento {
	return CommandMemento {
		AggregateMemento: NewAggregate(domain, id, version),
		CommandType: commandType,
	}
}

func (command CommandMemento) GetCommandType() uint32 {
	return command.CommandType
}

func (command CommandMemento) String() string {
	return fmt.Sprintf(" <C [ %s -> C[%d] ] C\\> ", command.AggregateMemento.String(), command.CommandType)
}

type Event interface {
	GetEventType() uint32
}

type EventMemento struct {
	AggregateMemento					// Aggregate
	EventType uint32 `json:"__etype"`	// Event Type
}

func NewEvent(domain uint32, eventType uint32, id uint64, version int32) EventMemento {
	return EventMemento {
		AggregateMemento: NewAggregate(domain, id, version),
		EventType: eventType,
	}
}

func (event EventMemento) GetEventType() uint32 {
	return event.EventType
}

func (event EventMemento) String() string {
	return fmt.Sprintf(" <E [ %s -> E[%d] ] E\\> ", event.AggregateMemento.String(), event.EventType)
}

type EventStorer interface {
	PersistEvent(event Event)
	ReadAllEvents() (int, []Event, error)
//	ReadAllEventsFrom(index int) (int, []Event, error)
	ReadAggregateEvents(aggregate Aggregate) ([]Event, error)
	ReadAggregateEventsFromSnapshot(aggregate Aggregate) ([]Event, error)
}

type MemoryEventStore struct {
	Snapshots []Aggregate
	Data []Event
}

func NewMemoryEventStore() MemoryEventStore {
	return MemoryEventStore {
		Snapshots: make([]Aggregate, 0),
		Data: make([]Event, 0),
	}
}

func (eventstore *MemoryEventStore) PersistEvent(event Event) {
	eventstore.Data = append(eventstore.Data, event)
}

func (eventstore *MemoryEventStore) ReadAllEvents() (int, []Event, error) {
	return len(eventstore.Data), eventstore.Data, nil
}

func (eventstore *MemoryEventStore) ReadAllEventsFrom(index int) (int, []Event, error) {
	if index < len(eventstore.Data) {
		events := make([]Event, 0)
		for i := index; i < len(eventstore.Data); i++ {
			events = append(events, eventstore.Data[i])
		}
		return len(eventstore.Data), events, nil
	} else {
		return 0, nil, errors.New("Index position out of range")
	}
}

func (eventstore *MemoryEventStore) ReadAggregateEvents(aggregate Aggregate) ([]Event, error) {
	matching := make([]Event, 0)
	for _, item := range eventstore.Data {
		switch event := item.(type) {
			case Aggregate: {
				if (event.GetDomain() != aggregate.GetDomain() || event.GetId() != aggregate.GetId())) {
					break
				}
				matching = append(matching, item.(Event))
			}
			default: {
				return nil, errors.New(fmt.Sprintf("Item in MemoryEventStore isn't an event [ %s ]\n", item))
			}
		}
	}
	return matching, nil
}

func (eventstore *MemoryEventStore) ReadAggregateEventsFromSnapshot(aggregate Aggregate) ([]Event, error) {
	matching := make([]Event, 0)
	for _, item := range eventstore.Data {
		switch event := item.(type) {
			case Aggregate: {
				if (event.GetDomain() != aggregate.GetDomain() || event.GetId() != aggregate.GetId() || event.GetVersion() < aggregate.GetVersion()) {
					break
				}
				matching = append(matching, item.(Event))
			}
			default: {
				return nil, errors.New(fmt.Sprintf("Item in MemoryEventStore isn't an event [ %s ]\n", item))
			}
		}
	}
	return matching, nil
}

<|endoftext|>


<commit_before>package main

import (
	"encoding/pem"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"

	"crypto/rsa"
	"crypto/x509"

	"code.google.com/p/go.crypto/ssh"

	"code.google.com/p/gopass"
	"github.com/codegangsta/cli"
)

func decryptPEM(pemblock *pem.Block) ([]byte, error) {
	passwd, _ := gopass.GetPass("Enter passphrase for ~/.ssh/id_rsa: ")
	decrypted_bytes, err := x509.DecryptPEMBlock(pemblock, []byte(passwd))
	panic_the_err(err)
	pem_bytes := pem.Block{
		Type:  "RSA PRIVATE KEY",
		Bytes: decrypted_bytes,
	}
	decrypted_pem := pem.EncodeToMemory(&pem_bytes)
	return decrypted_pem, nil
}

func main() {
	app := cli.NewApp()
	app.Name = "Credulous"
	app.Usage = "Use it!"
	app.Version = "0.1.2"

	app.Commands = []cli.Command{
		{
			Name:  "save",
			Usage: "Save AWS credentials for a file.",
			Flags: []cli.Flag{
				cli.StringFlag{"key, k", "", "SSH public key"},
			},
			Action: func(c *cli.Context) {
				var pubkey_file string
				if c.String("key") == "" {
					pubkey_file = filepath.Join(os.Getenv("HOME"), "/.ssh/id_rsa.pub")
				} else {
					pubkey_file = c.String("key")
				}

				aws_access_key_id := os.Getenv("AWS_ACCESS_KEY_ID")
				aws_secret_access_key := os.Getenv("AWS_SECRET_ACCESS_KEY")
				username, _ := getAWSUsername(aws_access_key_id, aws_secret_access_key)
				alias, _ := getAWSAccountAlias(aws_access_key_id, aws_secret_access_key)
				fmt.Printf("saving credentials for %s@%s\n", username, alias)
				pubkey_str, err := ioutil.ReadFile(pubkey_file)
				panic_the_err(err)
				pubkey, _, _, _, err := ssh.ParseAuthorizedKey([]byte(pubkey_str))
				SaveCredentials(username, alias, aws_access_key_id, aws_secret_access_key, pubkey)
			},
		},
		{
			Name:  "source",
			Usage: "Source AWS credentials from a file.",
			Flags: []cli.Flag{
				cli.StringFlag{"account, a", "", "AWS Account alias or id"},
				cli.StringFlag{"username, u", "", "IAM User"},
			},
			Action: func(c *cli.Context) {

				home := os.Getenv("HOME")
				tmp, err := ioutil.ReadFile(home + "/.ssh/id_rsa")
				panic_the_err(err)
				pemblock, _ := pem.Decode([]byte(tmp))
				if x509.IsEncryptedPEMBlock(pemblock) {
					tmp, err = decryptPEM(pemblock)
					panic_the_err(err)
				} else {
					log.Print("WARNING: Your private SSH key has no passphrase!")
				}
				key, err := ssh.ParseRawPrivateKey(tmp)
				panic_the_err(err)
				privkey := key.(*rsa.PrivateKey)
				cred := RetrieveCredentials(c.String("account"), c.String("username"), privkey)
				cred.Display(os.Stdout)
			},
		},
		{
			Name:  "display",
			Usage: "Display loaded AWS credentials",
			Action: func(c *cli.Context) {
				aws_access_key_id := os.Getenv("AWS_ACCESS_KEY_ID")
				aws_secret_access_key := os.Getenv("AWS_SECRET_ACCESS_KEY")
				fmt.Printf("AWS_ACCESS_KEY_ID: %s\n", aws_access_key_id)
				fmt.Printf("AWS_SECRET_ACCESS_KEY: %s\n", aws_secret_access_key)
			},
		},
	}

	app.Run(os.Args)
}
<commit_msg>Allow choosing an SSH private key on the command-line<commit_after>package main

import (
	"encoding/pem"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"

	"crypto/rsa"
	"crypto/x509"

	"code.google.com/p/go.crypto/ssh"

	"code.google.com/p/gopass"
	"github.com/codegangsta/cli"
)

func decryptPEM(pemblock *pem.Block) ([]byte, error) {
	passwd, _ := gopass.GetPass("Enter passphrase for ~/.ssh/id_rsa: ")
	decrypted_bytes, err := x509.DecryptPEMBlock(pemblock, []byte(passwd))
	panic_the_err(err)
	pem_bytes := pem.Block{
		Type:  "RSA PRIVATE KEY",
		Bytes: decrypted_bytes,
	}
	decrypted_pem := pem.EncodeToMemory(&pem_bytes)
	return decrypted_pem, nil
}

func main() {
	app := cli.NewApp()
	app.Name = "Credulous"
	app.Usage = "Use it!"
	app.Version = "0.1.2"

	app.Commands = []cli.Command{
		{
			Name:  "save",
			Usage: "Save AWS credentials for a file.",
			Flags: []cli.Flag{
				cli.StringFlag{"key, k", "", "SSH public key"},
			},
			Action: func(c *cli.Context) {
				var pubkey_file string
				if c.String("key") == "" {
					pubkey_file = filepath.Join(os.Getenv("HOME"), "/.ssh/id_rsa.pub")
				} else {
					pubkey_file = c.String("key")
				}

				aws_access_key_id := os.Getenv("AWS_ACCESS_KEY_ID")
				aws_secret_access_key := os.Getenv("AWS_SECRET_ACCESS_KEY")
				username, _ := getAWSUsername(aws_access_key_id, aws_secret_access_key)
				alias, _ := getAWSAccountAlias(aws_access_key_id, aws_secret_access_key)
				fmt.Printf("saving credentials for %s@%s\n", username, alias)
				pubkey_str, err := ioutil.ReadFile(pubkey_file)
				panic_the_err(err)
				pubkey, _, _, _, err := ssh.ParseAuthorizedKey([]byte(pubkey_str))
				SaveCredentials(username, alias, aws_access_key_id, aws_secret_access_key, pubkey)
			},
		},
		{
			Name:  "source",
			Usage: "Source AWS credentials from a file.",
			Flags: []cli.Flag{
				cli.StringFlag{"account, a", "", "AWS Account alias or id"},
				cli.StringFlag{"key, k", "", "SSH private key"},
				cli.StringFlag{"username, u", "", "IAM User"},
			},
			Action: func(c *cli.Context) {
				var privateKey string
				if c.String("key") == "" {
					privateKey = filepath.Join(os.Getenv("HOME"), "/.ssh/id_rsa")
				} else {
					privateKey = c.String("key")
				}
				tmp, err := ioutil.ReadFile(privateKey)
				panic_the_err(err)
				pemblock, _ := pem.Decode([]byte(tmp))
				if x509.IsEncryptedPEMBlock(pemblock) {
					tmp, err = decryptPEM(pemblock)
					panic_the_err(err)
				} else {
					log.Print("WARNING: Your private SSH key has no passphrase!")
				}
				key, err := ssh.ParseRawPrivateKey(tmp)
				panic_the_err(err)
				privkey := key.(*rsa.PrivateKey)
				cred := RetrieveCredentials(c.String("account"), c.String("username"), privkey)
				cred.Display(os.Stdout)
			},
		},
		{
			Name:  "display",
			Usage: "Display loaded AWS credentials",
			Action: func(c *cli.Context) {
				aws_access_key_id := os.Getenv("AWS_ACCESS_KEY_ID")
				aws_secret_access_key := os.Getenv("AWS_SECRET_ACCESS_KEY")
				fmt.Printf("AWS_ACCESS_KEY_ID: %s\n", aws_access_key_id)
				fmt.Printf("AWS_SECRET_ACCESS_KEY: %s\n", aws_secret_access_key)
			},
		},
	}

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


<commit_before>// Copyright (c) 2017 Tigera, Inc. All rights reserved.

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

package clientv2

import (
	"context"
	"encoding/hex"
	"fmt"

	"github.com/satori/go.uuid"
	log "github.com/sirupsen/logrus"

	"github.com/projectcalico/libcalico-go/lib/apiconfig"
	"github.com/projectcalico/libcalico-go/lib/backend"
	bapi "github.com/projectcalico/libcalico-go/lib/backend/api"
	"github.com/projectcalico/libcalico-go/lib/backend/model"
	"github.com/projectcalico/libcalico-go/lib/errors"
	"github.com/projectcalico/libcalico-go/lib/ipam"
	"github.com/projectcalico/libcalico-go/lib/net"
	"github.com/projectcalico/libcalico-go/lib/options"
)

// client implements the client.Interface.
type client struct {
	// The backend client is currently public to allow access to datastore
	// specific functions that are used by calico/node.  This is a temporary
	// measure and users of the client API should not assume that the backend
	// will be available in the future.
	Backend bapi.Client

	// The resources client used internally.
	resources resourceInterface
}

// New returns a connected client. The ClientConfig can either be created explicitly,
// or can be loaded from a config file or environment variables using the LoadClientConfig() function.
func New(config apiconfig.CalicoAPIConfig) (Interface, error) {
	var err error
	cc := client{}
	if cc.Backend, err = backend.NewClient(config); err != nil {
		return nil, err
	}
	cc.resources = &resources{backend: cc.Backend}
	return cc, err
}

// NewFromEnv loads the config from ENV variables and returns a connected client.
func NewFromEnv() (Interface, error) {

	config, err := apiconfig.LoadClientConfigFromEnvironment()
	if err != nil {
		return nil, err
	}

	return New(*config)
}

// Nodes returns an interface for managing node resources.
func (c client) Nodes() NodeInterface {
	return nodes{client: c}
}

// Policies returns an interface for managing policy resources.
func (c client) NetworkPolicies() NetworkPolicyInterface {
	return networkPolicies{client: c}
}

// Policies returns an interface for managing policy resources.
func (c client) GlobalNetworkPolicies() GlobalNetworkPolicyInterface {
	return globalnetworkpolicies{client: c}
}

// IPPools returns an interface for managing IP pool resources.
func (c client) IPPools() IPPoolInterface {
	return ipPools{client: c}
}

// Profiles returns an interface for managing profile resources.
func (c client) Profiles() ProfileInterface {
	return profiles{client: c}
}

// HostEndpoints returns an interface for managing host endpoint resources.
func (c client) HostEndpoints() HostEndpointInterface {
	return hostEndpoints{client: c}
}

// WorkloadEndpoints returns an interface for managing workload endpoint resources.
func (c client) WorkloadEndpoints() WorkloadEndpointInterface {
	return workloadEndpoints{client: c}
}

// BGPPeers returns an interface for managing BGP peer resources.
func (c client) BGPPeers() BGPPeerInterface {
	return bgpPeers{client: c}
}

// IPAM returns an interface for managing IP address assignment and releasing.
func (c client) IPAM() ipam.Interface {
	return ipam.NewIPAMClient(c.Backend, poolAccessor{client: &c})
}

// BGPConfigurations returns an interface for managing the BGP configuration resources.
func (c client) BGPConfigurations() BGPConfigurationInterface {
	return bgpConfigurations{client: c}
}

// FelixConfigurations returns an interface for managing the Felix configuration resources.
func (c client) FelixConfigurations() FelixConfigurationInterface {
	return felixConfigurations{client: c}
}

// ClusterInformation returns an interface for managing the cluster information resource.
func (c client) ClusterInformation() ClusterInformationInterface {
	return clusterInformation{client: c}
}

type poolAccessor struct {
	client *client
}

func (p poolAccessor) GetEnabledPools(ipVersion int) ([]net.IPNet, error) {
	pools, err := p.client.IPPools().List(context.Background(), options.ListOptions{})
	if err != nil {
		return nil, err
	}
	log.Debugf("Got list of all IPPools: %v", pools)
	enabled := []net.IPNet{}
	for _, pool := range pools.Items {
		if pool.Spec.Disabled {
			continue
		} else if _, cidr, err := net.ParseCIDR(pool.Spec.CIDR); err == nil && cidr.Version() == ipVersion {
			log.Debugf("Adding pool (%s) to the enabled IPPool list", cidr.String())
			enabled = append(enabled, *cidr)
		} else if err != nil {
			log.Warnf("Failed to parse the IPPool: %s. Ignoring that IPPool", pool.Spec.CIDR)
		} else {
			log.Debugf("Ignoring IPPool: %s. IP version is different.", pool.Spec.CIDR)
		}
	}
	return enabled, nil
}

// EnsureInitialized is used to ensure the backend datastore is correctly
// initialized for use by Calico.  This method may be called multiple times, and
// will have no effect if the datastore is already correctly initialized.
//
// Most Calico deployment scenarios will automatically implicitly invoke this
// method and so a general consumer of this API can assume that the datastore
// is already initialized.
func (c client) EnsureInitialized() error {
	// Perform datastore specific initialization first.
	if err := c.Backend.EnsureInitialized(); err != nil {
		return err
	}

	// Ensure a cluster GUID is set for the deployment.  We do this
	// irrespective of how Calico is deployed.
	kv := &model.KVPair{
		Key:   model.GlobalConfigKey{Name: "ClusterGUID"},
		Value: fmt.Sprintf("%v", hex.EncodeToString(uuid.NewV4().Bytes())),
	}
	if _, err := c.Backend.Create(context.Background(), kv); err == nil {
		log.WithField("ClusterGUID", kv.Value).Info("Assigned cluster GUID")
	} else {
		if _, ok := err.(errors.ErrorResourceAlreadyExists); !ok {
			log.WithError(err).WithField("ClusterGUID", kv.Value).Warn("Failed to assign cluster GUID")
			return err
		}
		log.Infof("Using previously configured cluster GUID")
	}

	return nil
}
<commit_msg>Expose Backend interface on main client and remove old GUID init<commit_after>// Copyright (c) 2017 Tigera, Inc. All rights reserved.

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

package clientv2

import (
	"context"

	log "github.com/sirupsen/logrus"

	"github.com/projectcalico/libcalico-go/lib/apiconfig"
	"github.com/projectcalico/libcalico-go/lib/backend"
	bapi "github.com/projectcalico/libcalico-go/lib/backend/api"
	"github.com/projectcalico/libcalico-go/lib/ipam"
	"github.com/projectcalico/libcalico-go/lib/net"
	"github.com/projectcalico/libcalico-go/lib/options"
)

// client implements the client.Interface.
type client struct {
	// The backend client.
	backend bapi.Client

	// The resources client used internally.
	resources resourceInterface
}

// New returns a connected client. The ClientConfig can either be created explicitly,
// or can be loaded from a config file or environment variables using the LoadClientConfig() function.
func New(config apiconfig.CalicoAPIConfig) (Interface, error) {
	be, err := backend.NewClient(config)
	if err != nil {
		return nil, err
	}
	return client{
		backend: be,
		resources: &resources{backend: be},
	}, nil
}

// NewFromEnv loads the config from ENV variables and returns a connected client.
func NewFromEnv() (Interface, error) {

	config, err := apiconfig.LoadClientConfigFromEnvironment()
	if err != nil {
		return nil, err
	}

	return New(*config)
}

// Nodes returns an interface for managing node resources.
func (c client) Nodes() NodeInterface {
	return nodes{client: c}
}

// Policies returns an interface for managing policy resources.
func (c client) NetworkPolicies() NetworkPolicyInterface {
	return networkPolicies{client: c}
}

// Policies returns an interface for managing policy resources.
func (c client) GlobalNetworkPolicies() GlobalNetworkPolicyInterface {
	return globalnetworkpolicies{client: c}
}

// IPPools returns an interface for managing IP pool resources.
func (c client) IPPools() IPPoolInterface {
	return ipPools{client: c}
}

// Profiles returns an interface for managing profile resources.
func (c client) Profiles() ProfileInterface {
	return profiles{client: c}
}

// HostEndpoints returns an interface for managing host endpoint resources.
func (c client) HostEndpoints() HostEndpointInterface {
	return hostEndpoints{client: c}
}

// WorkloadEndpoints returns an interface for managing workload endpoint resources.
func (c client) WorkloadEndpoints() WorkloadEndpointInterface {
	return workloadEndpoints{client: c}
}

// BGPPeers returns an interface for managing BGP peer resources.
func (c client) BGPPeers() BGPPeerInterface {
	return bgpPeers{client: c}
}

// IPAM returns an interface for managing IP address assignment and releasing.
func (c client) IPAM() ipam.Interface {
	return ipam.NewIPAMClient(c.backend, poolAccessor{client: &c})
}

// BGPConfigurations returns an interface for managing the BGP configuration resources.
func (c client) BGPConfigurations() BGPConfigurationInterface {
	return bgpConfigurations{client: c}
}

// FelixConfigurations returns an interface for managing the Felix configuration resources.
func (c client) FelixConfigurations() FelixConfigurationInterface {
	return felixConfigurations{client: c}
}

// ClusterInformation returns an interface for managing the cluster information resource.
func (c client) ClusterInformation() ClusterInformationInterface {
	return clusterInformation{client: c}
}

type poolAccessor struct {
	client *client
}

func (p poolAccessor) GetEnabledPools(ipVersion int) ([]net.IPNet, error) {
	pools, err := p.client.IPPools().List(context.Background(), options.ListOptions{})
	if err != nil {
		return nil, err
	}
	log.Debugf("Got list of all IPPools: %v", pools)
	enabled := []net.IPNet{}
	for _, pool := range pools.Items {
		if pool.Spec.Disabled {
			continue
		} else if _, cidr, err := net.ParseCIDR(pool.Spec.CIDR); err == nil && cidr.Version() == ipVersion {
			log.Debugf("Adding pool (%s) to the enabled IPPool list", cidr.String())
			enabled = append(enabled, *cidr)
		} else if err != nil {
			log.Warnf("Failed to parse the IPPool: %s. Ignoring that IPPool", pool.Spec.CIDR)
		} else {
			log.Debugf("Ignoring IPPool: %s. IP version is different.", pool.Spec.CIDR)
		}
	}
	return enabled, nil
}

// EnsureInitialized is used to ensure the backend datastore is correctly
// initialized for use by Calico.  This method may be called multiple times, and
// will have no effect if the datastore is already correctly initialized.
//
// Most Calico deployment scenarios will automatically implicitly invoke this
// method and so a general consumer of this API can assume that the datastore
// is already initialized.
func (c client) EnsureInitialized() error {
	// Perform datastore specific initialization first.
	if err := c.backend.EnsureInitialized(); err != nil {
		return err
	}

	return nil
}

// Backend returns the backend client used by the v2 client.  Not exposed on the main
// client API, but available publicly for consumers that require access to the backend
// client (e.g. for syncer support).
func (c client) Backend() bapi.Client {
	return c.backend
}
<|endoftext|>


<commit_before>// Copyright 2017 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

package ddl_test

import (
	. "github.com/pingcap/check"
	"github.com/pingcap/tidb/ddl"
	"github.com/pingcap/tidb/model"
	"github.com/pingcap/tidb/session"
	"github.com/pingcap/tidb/store/mockstore"
	"github.com/pingcap/tidb/store/tikv"
	"github.com/pingcap/tidb/tablecodec"
	"golang.org/x/net/context"
)

type testDDLTableSplitSuite struct{}

var _ = Suite(&testDDLTableSplitSuite{})

func (s *testDDLTableSplitSuite) TestTableSplit(c *C) {
	store, err := mockstore.NewMockTikvStore()
	c.Assert(err, IsNil)
	defer store.Close()
	session.SetSchemaLease(0)
	session.SetStatsLease(0)
	ddl.EnableSplitTableRegion = true
	dom, err := session.BootstrapSession(store)
	c.Assert(err, IsNil)
	defer dom.Close()
	ddl.EnableSplitTableRegion = false
	infoSchema := dom.InfoSchema()
	c.Assert(infoSchema, NotNil)
	t, err := infoSchema.TableByName(model.NewCIStr("mysql"), model.NewCIStr("tidb"))
	c.Assert(err, IsNil)
	regionStartKey := tablecodec.EncodeTablePrefix(t.Meta().ID)

	type kvStore interface {
		GetRegionCache() *tikv.RegionCache
	}
	cache := store.(kvStore).GetRegionCache()
	loc, err := cache.LocateKey(tikv.NewBackoffer(context.Background(), 5000), regionStartKey)
	c.Assert(err, IsNil)
	c.Assert(loc.StartKey, BytesEquals, []byte(regionStartKey))
}
<commit_msg>ddl: make TestTableSplit stable (#7487)<commit_after>// Copyright 2017 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

package ddl_test

import (
	"bytes"
	"time"

	. "github.com/pingcap/check"
	"github.com/pingcap/tidb/ddl"
	"github.com/pingcap/tidb/model"
	"github.com/pingcap/tidb/session"
	"github.com/pingcap/tidb/store/mockstore"
	"github.com/pingcap/tidb/store/tikv"
	"github.com/pingcap/tidb/tablecodec"
	"golang.org/x/net/context"
)

type testDDLTableSplitSuite struct{}

var _ = Suite(&testDDLTableSplitSuite{})

func (s *testDDLTableSplitSuite) TestTableSplit(c *C) {
	store, err := mockstore.NewMockTikvStore()
	c.Assert(err, IsNil)
	defer store.Close()
	session.SetSchemaLease(0)
	session.SetStatsLease(0)
	ddl.EnableSplitTableRegion = true
	dom, err := session.BootstrapSession(store)
	c.Assert(err, IsNil)
	defer dom.Close()
	ddl.EnableSplitTableRegion = false
	infoSchema := dom.InfoSchema()
	c.Assert(infoSchema, NotNil)
	t, err := infoSchema.TableByName(model.NewCIStr("mysql"), model.NewCIStr("tidb"))
	c.Assert(err, IsNil)
	regionStartKey := tablecodec.EncodeTablePrefix(t.Meta().ID)

	type kvStore interface {
		GetRegionCache() *tikv.RegionCache
	}
	var loc *tikv.KeyLocation
	for i := 0; i < 10; i++ {
		cache := store.(kvStore).GetRegionCache()
		loc, err = cache.LocateKey(tikv.NewBackoffer(context.Background(), 5000), regionStartKey)
		c.Assert(err, IsNil)

		// Region cache may be out of date, so we need to drop this expired region and load it again.
		cache.DropRegion(loc.Region)
		if bytes.Compare(loc.StartKey, []byte(regionStartKey)) == 0 {
			return
		}
		time.Sleep(3 * time.Millisecond)
	}
	c.Assert(loc.StartKey, BytesEquals, []byte(regionStartKey))
}
<|endoftext|>


<commit_before>package jsonptrerror_test

import (
	"fmt"
	"strings"

	"github.com/dolmen-go/jsonptrerror"
)

func ExampleDecoder() {
	decoder := jsonptrerror.NewDecoder(strings.NewReader(
		`{"key": "x", "value": 5}`,
	))
	var out struct {
		Key   string `json:"key"`
		Value bool   `json:"value"`
	}
	err := decoder.Decode(&out)
	fmt.Println(err)
	if err, ok := err.(*jsonptrerror.UnmarshalTypeError); ok {
		fmt.Println("Original error:", err.UnmarshalTypeError.Error())
		fmt.Println("Error location:", err.Pointer)
	}

	// Output:
	// /value: cannot unmarshal number into Go value of type bool
	// Original error: json: cannot unmarshal number into Go struct field .value of type bool
	// Error location: /value
}
<commit_msg>Disable ExampleDecoder testing on go < 1.8<commit_after>// The original error message returned by stdlib changed with go1.8.
// We only test the latest release.
//
//+build go1.8 forcego1.8

package jsonptrerror_test

import (
	"fmt"
	"strings"

	"github.com/dolmen-go/jsonptrerror"
)

func ExampleDecoder() {
	decoder := jsonptrerror.NewDecoder(strings.NewReader(
		`{"key": "x", "value": 5}`,
	))
	var out struct {
		Key   string `json:"key"`
		Value bool   `json:"value"`
	}
	err := decoder.Decode(&out)
	fmt.Println(err)
	if err, ok := err.(*jsonptrerror.UnmarshalTypeError); ok {
		fmt.Println("Original error:", err.UnmarshalTypeError.Error())
		fmt.Println("Error location:", err.Pointer)
	}

	// Output:
	// /value: cannot unmarshal number into Go value of type bool
	// Original error: json: cannot unmarshal number into Go struct field .value of type bool
	// Error location: /value
}
<|endoftext|>


<commit_before>package buffalo

import (
	"net/http/httptest"
	"net/url"
	"testing"

	"github.com/Sirupsen/logrus"
	"github.com/markbates/buffalo/render"
	"github.com/markbates/willie"
	"github.com/pkg/errors"
	"github.com/stretchr/testify/require"
)

func Test_DefaultContext_Param(t *testing.T) {
	r := require.New(t)
	c := DefaultContext{
		params: url.Values{
			"name": []string{"Mark"},
		},
	}

	r.Equal("Mark", c.Param("name"))
}

func Test_DefaultContext_ParamInt(t *testing.T) {
	r := require.New(t)
	c := DefaultContext{
		params: url.Values{
			"name": []string{"Mark"},
			"id":   []string{"1"},
		},
	}

	id, err := c.ParamInt("id")
	r.NoError(err)
	r.Equal(1, id)

	_, err = c.ParamInt("badkey")
	r.Error(err)

	_, err = c.ParamInt("name")
	r.Error(err)
}

func Test_DefaultContext_GetSet(t *testing.T) {
	r := require.New(t)
	c := DefaultContext{data: map[string]interface{}{}}
	r.Nil(c.Get("name"))

	c.Set("name", "Mark")
	r.NotNil(c.Get("name"))
	r.Equal("Mark", c.Get("name").(string))
}

func Test_DefaultContext_Render(t *testing.T) {
	r := require.New(t)

	res := httptest.NewRecorder()
	c := DefaultContext{
		response: res,
		params:   url.Values{"name": []string{"Mark"}},
		data:     map[string]interface{}{"greet": "Hello"},
		logger:   logrus.New(),
	}

	err := c.Render(123, render.String("{{.greet}} {{.params.name}}!"))
	r.NoError(err)

	r.Equal(123, res.Code)
	r.Equal("Hello Mark!", res.Body.String())
}

func Test_DefaultContext_Bind_Default(t *testing.T) {
	r := require.New(t)

	user := struct {
		FirstName string `schema:"first_name"`
	}{}

	a := New(Options{})
	a.POST("/", func(c Context) error {
		err := c.Bind(&user)
		if err != nil {
			return errors.WithStack(err)
		}
		return c.NoContent(201)
	})

	w := willie.New(a)
	uv := url.Values{"first_name": []string{"Mark"}}
	res := w.Request("/").Post(uv)
	r.Equal(201, res.Code)

	r.Equal("Mark", user.FirstName)
}

func Test_DefaultContext_Bind_JSON(t *testing.T) {
	r := require.New(t)

	user := struct {
		FirstName string `json:"first_name"`
	}{}

	a := New(Options{})
	a.POST("/", func(c Context) error {
		err := c.Bind(&user)
		if err != nil {
			return errors.WithStack(err)
		}
		return c.NoContent(201)
	})

	w := willie.New(a)
	res := w.JSON("/").Post(map[string]string{
		"first_name": "Mark",
	})
	r.Equal(201, res.Code)

	r.Equal("Mark", user.FirstName)
}

// func Test_DefaultContext_Bind_XML(t *testing.T) {
// 	r := require.New(t)
//
// 	user := struct {
// 		FirstName string `json:"first_name"`
// 	}{}
//
// 	a := New(Options{})
// 	a.POST("/", func(c Context) error {
// 		err := c.Bind(&user)
// 		if err != nil {
// 			return errors.WithStack(err)
// 		}
// 		return c.NoContent(201)
// 	})
//
// 	w := willie.New(a)
// 	req := w.Request("/")
// 	req.Headers["Content-Type"] = "application/xml"
// 	b, err := xml.Marshal(map[string]string{
// 		"first_name": "Mark",
// 	})
// 	r.NoError(err)
// 	res := req.Post(bytes.NewReader(b))
// 	r.Equal(201, res.Code)
//
// 	r.Equal("Mark", user.FirstName)
// }
<commit_msg>added xml binder<commit_after>package buffalo

import (
	"net/http/httptest"
	"net/url"
	"testing"

	"github.com/Sirupsen/logrus"
	"github.com/markbates/buffalo/render"
	"github.com/markbates/willie"
	"github.com/pkg/errors"
	"github.com/stretchr/testify/require"
)

func Test_DefaultContext_Param(t *testing.T) {
	r := require.New(t)
	c := DefaultContext{
		params: url.Values{
			"name": []string{"Mark"},
		},
	}

	r.Equal("Mark", c.Param("name"))
}

func Test_DefaultContext_ParamInt(t *testing.T) {
	r := require.New(t)
	c := DefaultContext{
		params: url.Values{
			"name": []string{"Mark"},
			"id":   []string{"1"},
		},
	}

	id, err := c.ParamInt("id")
	r.NoError(err)
	r.Equal(1, id)

	_, err = c.ParamInt("badkey")
	r.Error(err)

	_, err = c.ParamInt("name")
	r.Error(err)
}

func Test_DefaultContext_GetSet(t *testing.T) {
	r := require.New(t)
	c := DefaultContext{data: map[string]interface{}{}}
	r.Nil(c.Get("name"))

	c.Set("name", "Mark")
	r.NotNil(c.Get("name"))
	r.Equal("Mark", c.Get("name").(string))
}

func Test_DefaultContext_Render(t *testing.T) {
	r := require.New(t)

	res := httptest.NewRecorder()
	c := DefaultContext{
		response: res,
		params:   url.Values{"name": []string{"Mark"}},
		data:     map[string]interface{}{"greet": "Hello"},
		logger:   logrus.New(),
	}

	err := c.Render(123, render.String("{{.greet}} {{.params.name}}!"))
	r.NoError(err)

	r.Equal(123, res.Code)
	r.Equal("Hello Mark!", res.Body.String())
}

func Test_DefaultContext_Bind_Default(t *testing.T) {
	r := require.New(t)

	user := struct {
		FirstName string `schema:"first_name"`
	}{}

	a := New(Options{})
	a.POST("/", func(c Context) error {
		err := c.Bind(&user)
		if err != nil {
			return errors.WithStack(err)
		}
		return c.NoContent(201)
	})

	w := willie.New(a)
	uv := url.Values{"first_name": []string{"Mark"}}
	res := w.Request("/").Post(uv)
	r.Equal(201, res.Code)

	r.Equal("Mark", user.FirstName)
}

func Test_DefaultContext_Bind_JSON(t *testing.T) {
	r := require.New(t)

	user := struct {
		FirstName string `json:"first_name"`
	}{}

	a := New(Options{})
	a.POST("/", func(c Context) error {
		err := c.Bind(&user)
		if err != nil {
			return errors.WithStack(err)
		}
		return c.NoContent(201)
	})

	w := willie.New(a)
	res := w.JSON("/").Post(map[string]string{
		"first_name": "Mark",
	})
	r.Equal(201, res.Code)

	r.Equal("Mark", user.FirstName)
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"github.com/gorilla/sessions"
	"net/http"
	"sync"
	"time"
)

var roomIds = []string{
	"kougi201",
	"kougi202",
	"kougi203",
	"kougi204",

	"kougi301",
	"kougi302",
	"kougi303",
	"kougi304",
}

const (
	SESSION_NAME = "temvote_myvote"
)

type SessionFunc func(func(r *http.Request, w *http.ResponseWriter, s *sessions.CookieStore))

type RoomStatus struct {
	RoomID     string  `json:"id"`
	Templature float32 `json:"templature"`
	Hot        uint    `json:"hot"`
	Cold       uint    `json:"cold"`
	lock       sync.RWMutex
}

type MyVote struct {
	Vote      string `json:"vote"`
	Timestamp int64  `json:"timestamp"`
}

type RoomStatusManager struct {
	statMap map[string]*RoomStatus
}

func NewRoomStatusManager() *RoomStatusManager {
	rs := &RoomStatusManager{}
	rs.statMap = make(map[string]*RoomStatus)
	for _, id := range roomIds {
		rs.statMap[id] = &RoomStatus{
			RoomID:     id,
			Templature: 30.0,
			Hot:        0,
			Cold:       0,
			lock:       sync.RWMutex{},
		}
	}
	return rs
}

func getSessionName(id string) string {
	return SESSION_NAME + "/" + id
}

func (rs *RoomStatusManager) GetMyVote(sf SessionFunc, id string) (*MyVote, error) {
	var err error
	var vote *MyVote

	sf(func(r *http.Request, w *http.ResponseWriter, store *sessions.CookieStore) {
		s, err := store.Get(r, getSessionName(id))
		if err != nil {
			return
		}

		vote = &MyVote{
			Vote:      s.Values["vote"].(string),
			Timestamp: s.Values["timestamp"].(int64),
		}
	})
	return vote, err
}

func (rs *RoomStatusManager) GetStatus(id string) (*RoomStatus, error) {
	stat := rs.statMap[id]
	if stat == nil {
		return nil, errors.New(fmt.Sprintf(`invalid id: "%s"`, id))
	}

	var newStat = *stat
	return &newStat, nil
}

func (rs *RoomStatusManager) setter(id string, callback func(*RoomStatus) error) error {
	stat := rs.statMap[id]
	if stat == nil {
		return nil
	}
	stat.lock.Lock()
	defer stat.lock.Unlock()
	return callback(stat)
}

func (rs *RoomStatusManager) Vote(sf SessionFunc, id string, hot, cold int) error {
	var err error
	if !(hot == 1 || cold == 1) {
		return errors.New("Invalid args")
	}

	sf(func(r *http.Request, w *http.ResponseWriter, store *sessions.CookieStore) {
		var s *sessions.Session
		s, err = store.Get(r, getSessionName(id))
		if err != nil {
			err = nil
			s = sessions.NewSession(store, getSessionName(id))
			s.Options = &sessions.Options{
				Path:     "/",
				HttpOnly: true,
			}
		}

		// 以前の投票を取り消す
		if s.Values["vote"] != nil {
			switch s.Values["vote"].(string) {
			case "hot":
				hot -= 1
			case "cold":
				cold -= 1
			}
		}

		// 投票結果をCookieに保存
		if hot != 0 {
			s.Values["vote"] = "hot"
		} else if cold != 0 {
			s.Values["vote"] = "cold"
		}
		s.Values["timestamp"] = time.Now().Unix()

		err = s.Save(r, *w)
	})

	if err != nil {
		return err
	}

	return rs.setter(id, func(status *RoomStatus) error {
		status.Hot = uint(int(status.Hot) + hot)
		status.Cold = uint(int(status.Cold) + cold)
		return nil
	})
}
<commit_msg>fix cookie name<commit_after>package main

import (
	"errors"
	"fmt"
	"github.com/gorilla/sessions"
	"net/http"
	"sync"
	"time"
)

var roomIds = []string{
	"kougi201",
	"kougi202",
	"kougi203",
	"kougi204",

	"kougi301",
	"kougi302",
	"kougi303",
	"kougi304",
}

const (
	SESSION_NAME = "temvote_myvote"
)

type SessionFunc func(func(r *http.Request, w *http.ResponseWriter, s *sessions.CookieStore))

type RoomStatus struct {
	RoomID     string  `json:"id"`
	Templature float32 `json:"templature"`
	Hot        uint    `json:"hot"`
	Cold       uint    `json:"cold"`
	lock       sync.RWMutex
}

type MyVote struct {
	Vote      string `json:"vote"`
	Timestamp int64  `json:"timestamp"`
}

type RoomStatusManager struct {
	statMap map[string]*RoomStatus
}

func NewRoomStatusManager() *RoomStatusManager {
	rs := &RoomStatusManager{}
	rs.statMap = make(map[string]*RoomStatus)
	for _, id := range roomIds {
		rs.statMap[id] = &RoomStatus{
			RoomID:     id,
			Templature: 30.0,
			Hot:        0,
			Cold:       0,
			lock:       sync.RWMutex{},
		}
	}
	return rs
}

func getSessionName(id string) string {
	return SESSION_NAME + "___" + id
}

func (rs *RoomStatusManager) GetMyVote(sf SessionFunc, id string) (*MyVote, error) {
	var err error
	var vote *MyVote

	sf(func(r *http.Request, w *http.ResponseWriter, store *sessions.CookieStore) {
		s, err := store.Get(r, getSessionName(id))
		if err != nil {
			return
		}

		vote = &MyVote{
			Vote:      s.Values["vote"].(string),
			Timestamp: s.Values["timestamp"].(int64),
		}
	})
	return vote, err
}

func (rs *RoomStatusManager) GetStatus(id string) (*RoomStatus, error) {
	stat := rs.statMap[id]
	if stat == nil {
		return nil, errors.New(fmt.Sprintf(`invalid id: "%s"`, id))
	}

	var newStat = *stat
	return &newStat, nil
}

func (rs *RoomStatusManager) setter(id string, callback func(*RoomStatus) error) error {
	stat := rs.statMap[id]
	if stat == nil {
		return nil
	}
	stat.lock.Lock()
	defer stat.lock.Unlock()
	return callback(stat)
}

func (rs *RoomStatusManager) Vote(sf SessionFunc, id string, hot, cold int) error {
	var err error
	if !(hot == 1 || cold == 1) {
		return errors.New("Invalid args")
	}

	sf(func(r *http.Request, w *http.ResponseWriter, store *sessions.CookieStore) {
		var s *sessions.Session
		s, err = store.Get(r, getSessionName(id))
		if err != nil {
			err = nil
			s = sessions.NewSession(store, getSessionName(id))
			s.Options = &sessions.Options{
				Path:     "/",
				HttpOnly: true,
			}
		}

		// 以前の投票を取り消す
		if s.Values["vote"] != nil {
			switch s.Values["vote"].(string) {
			case "hot":
				hot -= 1
			case "cold":
				cold -= 1
			}
		}

		// 投票結果をCookieに保存
		if hot != 0 {
			s.Values["vote"] = "hot"
		} else if cold != 0 {
			s.Values["vote"] = "cold"
		}
		s.Values["timestamp"] = time.Now().Unix()

		err = s.Save(r, *w)
	})

	if err != nil {
		return err
	}

	return rs.setter(id, func(status *RoomStatus) error {
		status.Hot = uint(int(status.Hot) + hot)
		status.Cold = uint(int(status.Cold) + cold)
		return nil
	})
}
<|endoftext|>


<commit_before>package isolated

import (
	"code.cloudfoundry.org/cli/integration/helpers"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	. "github.com/onsi/gomega/gbytes"
	. "github.com/onsi/gomega/gexec"
)

var _ = Describe("spaces command", func() {
	var orgName string

	BeforeEach(func() {
		orgName = helpers.NewOrgName()
	})

	Describe("help", func() {
		When("--help flag is set", func() {
			It("displays command usage to output", func() {
				session := helpers.CF("spaces", "--help")
				Eventually(session).Should(Say("NAME:"))
				Eventually(session).Should(Say(`\s+spaces - List all spaces in an org`))
				Eventually(session).Should(Say("USAGE:"))
				Eventually(session).Should(Say(`\s+cf spaces`))
				Eventually(session).Should(Say("OPTIONS:"))
				Eventually(session).Should(Say("--labels"))
				Eventually(session).Should(Say("SEE ALSO:"))
				Eventually(session).Should(Say(`\s+target`))
				Eventually(session).Should(Exit(0))
			})
		})
	})

	When("the environment is setup correctly", func() {
		var username, spaceName1, spaceName2, spaceName3, spaceName4, spaceName5, spaceName6 string

		BeforeEach(func() {
			username = helpers.LoginCF()
			helpers.CreateOrg(orgName)
			helpers.TargetOrg(orgName)

			spaceName1 = helpers.PrefixedRandomName("INTEGRATION-SPACE-DEF")
			spaceName2 = helpers.PrefixedRandomName("INTEGRATION-SPACE-XYZ")
			spaceName3 = helpers.PrefixedRandomName("INTEGRATION-SPACE-jop")
			spaceName4 = helpers.PrefixedRandomName("INTEGRATION-SPACE-ABC")
			spaceName5 = helpers.PrefixedRandomName("INTEGRATION-SPACE-543")
			spaceName6 = helpers.PrefixedRandomName("INTEGRATION-SPACE-125")
			helpers.CreateSpace(spaceName1)
			helpers.CreateSpace(spaceName2)
			helpers.CreateSpace(spaceName3)
			helpers.CreateSpace(spaceName4)
			helpers.CreateSpace(spaceName5)
			helpers.CreateSpace(spaceName6)
		})

		When("the --labels flag is given", func() {

			BeforeEach(func() {
				Eventually(helpers.CF("set-label", "space", spaceName1, "environment=production", "tier=backend")).Should(Exit(0))
				Eventually(helpers.CF("set-label", "space", spaceName2, "environment=staging", "tier=frontend")).Should(Exit(0))
			})

			It("displays spaces with provided labels", func() {
				session := helpers.CF("spaces", "--labels", "environment in (production,staging),tier in (backend)")
				Eventually(session).Should(Say(`Getting spaces in org %s as %s\.\.\.`, orgName, username))
				Eventually(session).Should(Exit(0))
				Expect(session).Should(Say(spaceName1))
				Expect(session).ShouldNot(Say(spaceName2))
				Expect(session).ShouldNot(Say(spaceName3))
				Expect(session).ShouldNot(Say(spaceName4))
				Expect(session).ShouldNot(Say(spaceName5))
				Expect(session).ShouldNot(Say(spaceName6))
			})

			It("displays no spaces when no labels match", func() {
				session := helpers.CF("spaces", "--labels", "environment in (production,staging),environment notin (production,staging)")
				Eventually(session).Should(Exit(0))
				Expect(session).Should(Say("No spaces found"))
			})
		})
	})
})
<commit_msg>Commented out labels test<commit_after>package isolated

import (
	"code.cloudfoundry.org/cli/integration/helpers"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	. "github.com/onsi/gomega/gbytes"
	. "github.com/onsi/gomega/gexec"
)

var _ = Describe("spaces command", func() {
	var orgName string

	BeforeEach(func() {
		orgName = helpers.NewOrgName()
	})

	Describe("help", func() {
		When("--help flag is set", func() {
			It("displays command usage to output", func() {
				session := helpers.CF("spaces", "--help")
				Eventually(session).Should(Say("NAME:"))
				Eventually(session).Should(Say(`\s+spaces - List all spaces in an org`))
				Eventually(session).Should(Say("USAGE:"))
				Eventually(session).Should(Say(`\s+cf spaces`))
				Eventually(session).Should(Say("OPTIONS:"))
				Eventually(session).Should(Say("--labels"))
				Eventually(session).Should(Say("SEE ALSO:"))
				Eventually(session).Should(Say(`\s+target`))
				Eventually(session).Should(Exit(0))
			})
		})
	})

	When("the environment is setup correctly", func() {
		var username, spaceName1, spaceName2, spaceName3, spaceName4, spaceName5, spaceName6 string

		BeforeEach(func() {
			username = helpers.LoginCF()
			helpers.CreateOrg(orgName)
			helpers.TargetOrg(orgName)

			spaceName1 = helpers.PrefixedRandomName("INTEGRATION-SPACE-DEF")
			spaceName2 = helpers.PrefixedRandomName("INTEGRATION-SPACE-XYZ")
			spaceName3 = helpers.PrefixedRandomName("INTEGRATION-SPACE-jop")
			spaceName4 = helpers.PrefixedRandomName("INTEGRATION-SPACE-ABC")
			spaceName5 = helpers.PrefixedRandomName("INTEGRATION-SPACE-543")
			spaceName6 = helpers.PrefixedRandomName("INTEGRATION-SPACE-125")
			helpers.CreateSpace(spaceName1)
			helpers.CreateSpace(spaceName2)
			helpers.CreateSpace(spaceName3)
			helpers.CreateSpace(spaceName4)
			helpers.CreateSpace(spaceName5)
			helpers.CreateSpace(spaceName6)
		})

		XWhen("the --labels flag is given", func() {

			BeforeEach(func() {
				Eventually(helpers.CF("set-label", "space", spaceName1, "environment=production", "tier=backend")).Should(Exit(0))
				Eventually(helpers.CF("set-label", "space", spaceName2, "environment=staging", "tier=frontend")).Should(Exit(0))
			})

			It("displays spaces with provided labels", func() {
				session := helpers.CF("spaces", "--labels", "environment in (production,staging),tier in (backend)")
				Eventually(session).Should(Say(`Getting spaces in org %s as %s\.\.\.`, orgName, username))
				Eventually(session).Should(Exit(0))
				Expect(session).Should(Say(spaceName1))
				Expect(session).ShouldNot(Say(spaceName2))
				Expect(session).ShouldNot(Say(spaceName3))
				Expect(session).ShouldNot(Say(spaceName4))
				Expect(session).ShouldNot(Say(spaceName5))
				Expect(session).ShouldNot(Say(spaceName6))
			})

			It("displays no spaces when no labels match", func() {
				session := helpers.CF("spaces", "--labels", "environment in (production,staging),environment notin (production,staging)")
				Eventually(session).Should(Exit(0))
				Expect(session).Should(Say("No spaces found"))
			})
		})
	})
})
<|endoftext|>


<commit_before>package main

import (
	"crypto/sha256"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"os/exec"
	"strconv"
	//"github.com/uli-go/xz/lzma"
	"bytes"

	"github.com/gorilla/mux"
	"github.com/lxc/lxd/shared"
	"gopkg.in/yaml.v2"
)

const (
	COMPRESSION_TAR = iota
	COMPRESSION_GZIP
	COMPRESSION_BZ2
	COMPRESSION_LZMA
	COMPRESSION_XY
)

const (
	ARCH_UNKNOWN                     = 0
	ARCH_32BIT_INTEL_X86             = 1
	ARCH_64BIT_INTEL_X86             = 2
	ARCH_ARMV7_LITTLE_ENDIAN         = 3
	ARCH_64BIT_ARMV8_LITTLE_ENDIAN   = 4
	ARCH_32BIT_POWERPC_BIG_ENDIAN    = 5
	ARCH_64BIT_POWERPC_BIG_ENDIAN    = 6
	ARCH_64BIT_POWERPC_LITTLE_ENDIAN = 7
)

var architectures = map[string]int{
	"i686":    ARCH_32BIT_INTEL_X86,
	"x86_64":  ARCH_64BIT_INTEL_X86,
	"armv7l":  ARCH_ARMV7_LITTLE_ENDIAN,
	"aarch64": ARCH_64BIT_ARMV8_LITTLE_ENDIAN,
	"ppc":     ARCH_32BIT_POWERPC_BIG_ENDIAN,
	"ppc64":   ARCH_64BIT_POWERPC_BIG_ENDIAN,
	"ppc64le": ARCH_64BIT_POWERPC_LITTLE_ENDIAN,
}

func getSize(f *os.File) (int64, error) {
	fi, err := f.Stat()
	if err != nil {
		return 0, err
	}
	return fi.Size(), nil
}

func detectCompression(fname string) (int, error) {

	f, err := os.Open(fname)
	if err != nil {
		return -1, err
	}
	defer f.Close()

	// read header parts to detect compression method
	// bz2 - 2 bytes, 'BZ' signature/magic number
	// gz - 2 bytes, 0x1f 0x8b
	// lzma - 6 bytes, { [0x000, 0xE0], '7', 'z', 'X', 'Z', 0x00 } -
	// xy - 6 bytes,  header format { 0xFD, '7', 'z', 'X', 'Z', 0x00 }
	// tar - 263 bytes, trying to get ustar from 257 - 262
	header := make([]byte, 263)
	_, err = f.Read(header)

	switch {
	case bytes.Equal(header[0:2], []byte{'B', 'Z'}):
		return COMPRESSION_BZ2, nil
	case bytes.Equal(header[0:2], []byte{0x1f, 0x8b}):
		return COMPRESSION_GZIP, nil
	case (bytes.Equal(header[1:5], []byte{'7', 'z', 'X', 'Z'}) && header[0] == 0xFD):
		return COMPRESSION_XY, nil
	case (bytes.Equal(header[1:5], []byte{'7', 'z', 'X', 'Z'}) && header[0] != 0xFD):
		return COMPRESSION_LZMA, nil
	case bytes.Equal(header[257:262], []byte{'u', 's', 't', 'a', 'r'}):
		return COMPRESSION_TAR, nil
	default:
		return -1, fmt.Errorf("Unsupported compression.")
	}

}

type imageMetadata struct {
	Architecture  string
	Creation_date float64
	Properties    map[string]interface{}
}

func imagesPost(d *Daemon, r *http.Request) Response {

	cleanup := func(err error, fname string) Response {
		// show both errors, if remove fails
		if remErr := os.Remove(fname); remErr != nil {
			return InternalError(fmt.Errorf("Could not process image: %s; Error deleting temporary file: %s", err, remErr))
		}
		return InternalError(err)
	}

	shared.Debugf("responding to images:post")

	public, err := strconv.Atoi(r.Header.Get("X-LXD-public"))
	tarname := r.Header.Get("X-LXD-filename")

	dirname := shared.VarPath("images")
	err = os.MkdirAll(dirname, 0700)
	if err != nil {
		return InternalError(err)
	}

	f, err := ioutil.TempFile(dirname, "image_")
	defer f.Close()

	if err != nil {
		return InternalError(err)
	}

	fname := f.Name()

	sha256 := sha256.New()
	size, err := io.Copy(io.MultiWriter(f, sha256), r.Body)

	if err != nil {
		return cleanup(err, fname)
	}

	uuid := fmt.Sprintf("%x", sha256.Sum(nil))
	uuidfname := shared.VarPath("images", uuid)

	if shared.PathExists(uuidfname) {
		return InternalError(fmt.Errorf("Image exists"))
	}

	err = os.Rename(fname, uuidfname)
	if err != nil {
		return cleanup(err, fname)
	}

	imageMeta, err := getImageMetadata(uuidfname)
	if err != nil {
		return cleanup(err, uuidfname)
	}

	arch := ARCH_UNKNOWN
	_, exists := architectures[imageMeta.Architecture]
	if exists {
		arch = architectures[imageMeta.Architecture]
	}

	tx, err := d.db.Begin()
	if err != nil {
		return cleanup(err, uuidfname)
	}

	stmt, err := tx.Prepare(`INSERT INTO images (fingerprint, filename, size, public, architecture, upload_date) VALUES (?, ?, ?, ?, ?, strftime("%s"))`)
	if err != nil {
		tx.Rollback()
		return cleanup(err, uuidfname)
	}
	defer stmt.Close()

	_, err = stmt.Exec(uuid, tarname, size, public, arch)
	if err != nil {
		tx.Rollback()
		return cleanup(err, uuidfname)
	}

	if err := tx.Commit(); err != nil {
		return cleanup(err, uuidfname)
	}

	/*
	 * TODO - take X-LXD-properties from headers and add those to
	 * containers_properties table
	 */

	metadata := make(map[string]string)
	metadata["fingerprint"] = uuid
	metadata["size"] = strconv.FormatInt(size, 10)

	return SyncResponse(true, metadata)
}

func xzReader(r io.Reader) io.ReadCloser {
	rpipe, wpipe := io.Pipe()

	cmd := exec.Command("xz", "--decompress", "--stdout")
	cmd.Stdin = r
	cmd.Stdout = wpipe

	go func() {
		err := cmd.Run()
		wpipe.CloseWithError(err)
	}()

	return rpipe
}

func getImageMetadata(fname string) (*imageMetadata, error) {

	compression, err := detectCompression(fname)

	if err != nil {
		return nil, err
	}

	args := []string{"-O"}
	switch compression {
	case COMPRESSION_TAR:
		args = append(args, "-xf")
	case COMPRESSION_GZIP:
		args = append(args, "-zxf")
	case COMPRESSION_BZ2:
		args = append(args, "--jxf")
	case COMPRESSION_LZMA:
		args = append(args, "--lzma", "-xf")
	default:
		args = append(args, "-Jxf")
	}
	args = append(args, fname, "metadata.yaml")

	// read the metadata.yaml
	output, err := exec.Command("tar", args...).Output()

	if err != nil {
		return nil, fmt.Errorf("Could not get image metadata: %v", err)
	}

	metadata := new(imageMetadata)
	err = yaml.Unmarshal(output, &metadata)

	if err != nil {
		return nil, fmt.Errorf("Could not get image metadata: %v", err)
	}

	return metadata, nil

}

func imagesGet(d *Daemon, r *http.Request) Response {
	shared.Debugf("responding to images:get")

	rows, err := d.db.Query("SELECT fingerprint FROM images")
	if err != nil {
		return BadRequest(err)
	}
	defer rows.Close()
	result := make([]string, 0)
	for rows.Next() {
		var name string
		rows.Scan(&name)
		url := fmt.Sprintf("/%s/images/%s", shared.APIVersion, name)
		result = append(result, url)
	}

	return SyncResponse(true, result)
}

var imagesCmd = Command{name: "images", post: imagesPost, get: imagesGet}

func imageDelete(d *Daemon, r *http.Request) Response {
	shared.Debugf("responding to image:delete")

	uuid := mux.Vars(r)["name"]
	uuidfname := shared.VarPath("images", uuid)
	err := os.Remove(uuidfname)
	if err != nil {
		shared.Debugf("Error deleting image file %s: %s\n", uuidfname, err)
	}

	_, _ = d.db.Exec("DELETE FROM images_aliases WHERE image_id=(SELECT id FROM images WHERE fingerprint=?);", uuid)
	_, _ = d.db.Exec("DELETE FROM images WHERE fingerprint=?", uuid)

	return EmptySyncResponse
}

var imageCmd = Command{name: "images/{name}", delete: imageDelete}

type aliasPostReq struct {
	Name        string `json:"name"`
	Description string `json:"descriptoin"`
	Target      string `json:"target"`
}

func aliasesPost(d *Daemon, r *http.Request) Response {
	shared.Debugf("responding to images/aliases:put")

	req := aliasPostReq{}
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		return BadRequest(err)
	}

	if req.Name == "" || req.Target == "" {
		return BadRequest(fmt.Errorf("name and target are required"))
	}
	if req.Description == "" {
		req.Description = req.Name
	}

	_, _, err := dbAliasGet(d, req.Name)
	if err == nil {
		return BadRequest(fmt.Errorf("alias exists"))
	}

	iId, err := dbImageGet(d, req.Target)
	if err != nil {
		return BadRequest(err)
	}

	err = dbAddAlias(d, req.Name, iId, req.Description)
	if err != nil {
		return BadRequest(err)
	}

	return EmptySyncResponse
}

func aliasesGet(d *Daemon, r *http.Request) Response {
	shared.Debugf("responding to images/aliases:get")

	rows, err := d.db.Query("SELECT name FROM images_aliases")
	if err != nil {
		return BadRequest(err)
	}
	defer rows.Close()
	result := make([]string, 0)
	for rows.Next() {
		var name string
		rows.Scan(&name)
		url := fmt.Sprintf("/%s/images/aliases/%s", shared.APIVersion, name)
		result = append(result, url)
	}

	return SyncResponse(true, result)
}

func aliasGet(d *Daemon, r *http.Request) Response {
	name := mux.Vars(r)["name"]
	rows, err := d.db.Query(`SELECT images.fingerprint, images_aliases.description
	                         FROM images_aliases
	                         INNER JOIN images
				 ON images_aliases.image_id=images.id
				 WHERE images_aliases.name=?`, name)
	if err != nil {
		return InternalError(err)
	}
	defer rows.Close()

	for rows.Next() {
		var fingerprint, description string
		if err := rows.Scan(&fingerprint, &description); err != nil {
			return InternalError(err)
		}

		return SyncResponse(true, shared.Jmap{"target": fingerprint, "description": description})
	}

	return NotFound
}

func aliasDelete(d *Daemon, r *http.Request) Response {
	shared.Debugf("responding to images/aliases:delete")

	name := mux.Vars(r)["name"]
	_, _ = d.db.Exec("DELETE FROM images_aliases WHERE name=?", name)

	return EmptySyncResponse
}

var aliasesCmd = Command{name: "images/aliases", post: aliasesPost, get: aliasesGet}

var aliasCmd = Command{name: "images/aliases/{name:.*}", get: aliasGet, delete: aliasDelete}
<commit_msg>removing temp files, if image exists<commit_after>package main

import (
	"crypto/sha256"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"os/exec"
	"strconv"
	//"github.com/uli-go/xz/lzma"
	"bytes"

	"github.com/gorilla/mux"
	"github.com/lxc/lxd/shared"
	"gopkg.in/yaml.v2"
)

const (
	COMPRESSION_TAR = iota
	COMPRESSION_GZIP
	COMPRESSION_BZ2
	COMPRESSION_LZMA
	COMPRESSION_XY
)

const (
	ARCH_UNKNOWN                     = 0
	ARCH_32BIT_INTEL_X86             = 1
	ARCH_64BIT_INTEL_X86             = 2
	ARCH_ARMV7_LITTLE_ENDIAN         = 3
	ARCH_64BIT_ARMV8_LITTLE_ENDIAN   = 4
	ARCH_32BIT_POWERPC_BIG_ENDIAN    = 5
	ARCH_64BIT_POWERPC_BIG_ENDIAN    = 6
	ARCH_64BIT_POWERPC_LITTLE_ENDIAN = 7
)

var architectures = map[string]int{
	"i686":    ARCH_32BIT_INTEL_X86,
	"x86_64":  ARCH_64BIT_INTEL_X86,
	"armv7l":  ARCH_ARMV7_LITTLE_ENDIAN,
	"aarch64": ARCH_64BIT_ARMV8_LITTLE_ENDIAN,
	"ppc":     ARCH_32BIT_POWERPC_BIG_ENDIAN,
	"ppc64":   ARCH_64BIT_POWERPC_BIG_ENDIAN,
	"ppc64le": ARCH_64BIT_POWERPC_LITTLE_ENDIAN,
}

func getSize(f *os.File) (int64, error) {
	fi, err := f.Stat()
	if err != nil {
		return 0, err
	}
	return fi.Size(), nil
}

func detectCompression(fname string) (int, error) {

	f, err := os.Open(fname)
	if err != nil {
		return -1, err
	}
	defer f.Close()

	// read header parts to detect compression method
	// bz2 - 2 bytes, 'BZ' signature/magic number
	// gz - 2 bytes, 0x1f 0x8b
	// lzma - 6 bytes, { [0x000, 0xE0], '7', 'z', 'X', 'Z', 0x00 } -
	// xy - 6 bytes,  header format { 0xFD, '7', 'z', 'X', 'Z', 0x00 }
	// tar - 263 bytes, trying to get ustar from 257 - 262
	header := make([]byte, 263)
	_, err = f.Read(header)

	switch {
	case bytes.Equal(header[0:2], []byte{'B', 'Z'}):
		return COMPRESSION_BZ2, nil
	case bytes.Equal(header[0:2], []byte{0x1f, 0x8b}):
		return COMPRESSION_GZIP, nil
	case (bytes.Equal(header[1:5], []byte{'7', 'z', 'X', 'Z'}) && header[0] == 0xFD):
		return COMPRESSION_XY, nil
	case (bytes.Equal(header[1:5], []byte{'7', 'z', 'X', 'Z'}) && header[0] != 0xFD):
		return COMPRESSION_LZMA, nil
	case bytes.Equal(header[257:262], []byte{'u', 's', 't', 'a', 'r'}):
		return COMPRESSION_TAR, nil
	default:
		return -1, fmt.Errorf("Unsupported compression.")
	}

}

type imageMetadata struct {
	Architecture  string
	Creation_date float64
	Properties    map[string]interface{}
}

func imagesPost(d *Daemon, r *http.Request) Response {

	cleanup := func(err error, fname string) Response {
		// show both errors, if remove fails
		if remErr := os.Remove(fname); remErr != nil {
			return InternalError(fmt.Errorf("Could not process image: %s; Error deleting temporary file: %s", err, remErr))
		}
		return InternalError(err)
	}

	shared.Debugf("responding to images:post")

	public, err := strconv.Atoi(r.Header.Get("X-LXD-public"))
	tarname := r.Header.Get("X-LXD-filename")

	dirname := shared.VarPath("images")
	err = os.MkdirAll(dirname, 0700)
	if err != nil {
		return InternalError(err)
	}

	f, err := ioutil.TempFile(dirname, "image_")
	defer f.Close()

	if err != nil {
		return InternalError(err)
	}

	fname := f.Name()

	sha256 := sha256.New()
	size, err := io.Copy(io.MultiWriter(f, sha256), r.Body)

	if err != nil {
		return cleanup(err, fname)
	}

	uuid := fmt.Sprintf("%x", sha256.Sum(nil))
	uuidfname := shared.VarPath("images", uuid)

	if shared.PathExists(uuidfname) {
		return cleanup(fmt.Errorf("Image exists already."), fname)
	}

	err = os.Rename(fname, uuidfname)
	if err != nil {
		return cleanup(err, fname)
	}

	imageMeta, err := getImageMetadata(uuidfname)
	if err != nil {
		return cleanup(err, uuidfname)
	}

	arch := ARCH_UNKNOWN
	_, exists := architectures[imageMeta.Architecture]
	if exists {
		arch = architectures[imageMeta.Architecture]
	}

	tx, err := d.db.Begin()
	if err != nil {
		return cleanup(err, uuidfname)
	}

	stmt, err := tx.Prepare(`INSERT INTO images (fingerprint, filename, size, public, architecture, upload_date) VALUES (?, ?, ?, ?, ?, strftime("%s"))`)
	if err != nil {
		tx.Rollback()
		return cleanup(err, uuidfname)
	}
	defer stmt.Close()

	_, err = stmt.Exec(uuid, tarname, size, public, arch)
	if err != nil {
		tx.Rollback()
		return cleanup(err, uuidfname)
	}

	if err := tx.Commit(); err != nil {
		return cleanup(err, uuidfname)
	}

	/*
	 * TODO - take X-LXD-properties from headers and add those to
	 * containers_properties table
	 */

	metadata := make(map[string]string)
	metadata["fingerprint"] = uuid
	metadata["size"] = strconv.FormatInt(size, 10)

	return SyncResponse(true, metadata)
}

func xzReader(r io.Reader) io.ReadCloser {
	rpipe, wpipe := io.Pipe()

	cmd := exec.Command("xz", "--decompress", "--stdout")
	cmd.Stdin = r
	cmd.Stdout = wpipe

	go func() {
		err := cmd.Run()
		wpipe.CloseWithError(err)
	}()

	return rpipe
}

func getImageMetadata(fname string) (*imageMetadata, error) {

	compression, err := detectCompression(fname)

	if err != nil {
		return nil, err
	}

	args := []string{"-O"}
	switch compression {
	case COMPRESSION_TAR:
		args = append(args, "-xf")
	case COMPRESSION_GZIP:
		args = append(args, "-zxf")
	case COMPRESSION_BZ2:
		args = append(args, "--jxf")
	case COMPRESSION_LZMA:
		args = append(args, "--lzma", "-xf")
	default:
		args = append(args, "-Jxf")
	}
	args = append(args, fname, "metadata.yaml")

	// read the metadata.yaml
	output, err := exec.Command("tar", args...).Output()

	if err != nil {
		return nil, fmt.Errorf("Could not get image metadata: %v", err)
	}

	metadata := new(imageMetadata)
	err = yaml.Unmarshal(output, &metadata)

	if err != nil {
		return nil, fmt.Errorf("Could not get image metadata: %v", err)
	}

	return metadata, nil

}

func imagesGet(d *Daemon, r *http.Request) Response {
	shared.Debugf("responding to images:get")

	rows, err := d.db.Query("SELECT fingerprint FROM images")
	if err != nil {
		return BadRequest(err)
	}
	defer rows.Close()
	result := make([]string, 0)
	for rows.Next() {
		var name string
		rows.Scan(&name)
		url := fmt.Sprintf("/%s/images/%s", shared.APIVersion, name)
		result = append(result, url)
	}

	return SyncResponse(true, result)
}

var imagesCmd = Command{name: "images", post: imagesPost, get: imagesGet}

func imageDelete(d *Daemon, r *http.Request) Response {
	shared.Debugf("responding to image:delete")

	uuid := mux.Vars(r)["name"]
	uuidfname := shared.VarPath("images", uuid)
	err := os.Remove(uuidfname)
	if err != nil {
		shared.Debugf("Error deleting image file %s: %s\n", uuidfname, err)
	}

	_, _ = d.db.Exec("DELETE FROM images_aliases WHERE image_id=(SELECT id FROM images WHERE fingerprint=?);", uuid)
	_, _ = d.db.Exec("DELETE FROM images WHERE fingerprint=?", uuid)

	return EmptySyncResponse
}

var imageCmd = Command{name: "images/{name}", delete: imageDelete}

type aliasPostReq struct {
	Name        string `json:"name"`
	Description string `json:"descriptoin"`
	Target      string `json:"target"`
}

func aliasesPost(d *Daemon, r *http.Request) Response {
	shared.Debugf("responding to images/aliases:put")

	req := aliasPostReq{}
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		return BadRequest(err)
	}

	if req.Name == "" || req.Target == "" {
		return BadRequest(fmt.Errorf("name and target are required"))
	}
	if req.Description == "" {
		req.Description = req.Name
	}

	_, _, err := dbAliasGet(d, req.Name)
	if err == nil {
		return BadRequest(fmt.Errorf("alias exists"))
	}

	iId, err := dbImageGet(d, req.Target)
	if err != nil {
		return BadRequest(err)
	}

	err = dbAddAlias(d, req.Name, iId, req.Description)
	if err != nil {
		return BadRequest(err)
	}

	return EmptySyncResponse
}

func aliasesGet(d *Daemon, r *http.Request) Response {
	shared.Debugf("responding to images/aliases:get")

	rows, err := d.db.Query("SELECT name FROM images_aliases")
	if err != nil {
		return BadRequest(err)
	}
	defer rows.Close()
	result := make([]string, 0)
	for rows.Next() {
		var name string
		rows.Scan(&name)
		url := fmt.Sprintf("/%s/images/aliases/%s", shared.APIVersion, name)
		result = append(result, url)
	}

	return SyncResponse(true, result)
}

func aliasGet(d *Daemon, r *http.Request) Response {
	name := mux.Vars(r)["name"]
	rows, err := d.db.Query(`SELECT images.fingerprint, images_aliases.description
	                         FROM images_aliases
	                         INNER JOIN images
				 ON images_aliases.image_id=images.id
				 WHERE images_aliases.name=?`, name)
	if err != nil {
		return InternalError(err)
	}
	defer rows.Close()

	for rows.Next() {
		var fingerprint, description string
		if err := rows.Scan(&fingerprint, &description); err != nil {
			return InternalError(err)
		}

		return SyncResponse(true, shared.Jmap{"target": fingerprint, "description": description})
	}

	return NotFound
}

func aliasDelete(d *Daemon, r *http.Request) Response {
	shared.Debugf("responding to images/aliases:delete")

	name := mux.Vars(r)["name"]
	_, _ = d.db.Exec("DELETE FROM images_aliases WHERE name=?", name)

	return EmptySyncResponse
}

var aliasesCmd = Command{name: "images/aliases", post: aliasesPost, get: aliasesGet}

var aliasCmd = Command{name: "images/aliases/{name:.*}", get: aliasGet, delete: aliasDelete}
<|endoftext|>


<commit_before>// +build linux,cgo,!agent

package sys

import (
	"path/filepath"
	"sync"

	log "github.com/lxc/lxd/shared/log15"

	"github.com/lxc/lxd/lxd/cgroup"
	"github.com/lxc/lxd/lxd/util"
	"github.com/lxc/lxd/shared"
	"github.com/lxc/lxd/shared/idmap"
	"github.com/lxc/lxd/shared/logger"
)

// InotifyTargetInfo records the inotify information associated with a given
// inotify target
type InotifyTargetInfo struct {
	Mask uint32
	Wd   int
	Path string
}

// InotifyInfo records the inotify information associated with a given
// inotify instance
type InotifyInfo struct {
	Fd int
	sync.RWMutex
	Targets map[string]*InotifyTargetInfo
}

// OS is a high-level facade for accessing all operating-system
// level functionality that LXD uses.
type OS struct {
	// Directories
	CacheDir string // Cache directory (e.g. /var/cache/lxd/).
	LogDir   string // Log directory (e.g. /var/log/lxd).
	VarDir   string // Data directory (e.g. /var/lib/lxd/).

	// Daemon environment
	Architectures   []int           // Cache of detected system architectures
	BackingFS       string          // Backing filesystem of $LXD_DIR/containers
	ExecPath        string          // Absolute path to the LXD executable
	IdmapSet        *idmap.IdmapSet // Information about user/group ID mapping
	InotifyWatch    InotifyInfo
	LxcPath         string // Path to the $LXD_DIR/containers directory
	MockMode        bool   // If true some APIs will be mocked (for testing)
	Nodev           bool
	RunningInUserNS bool

	// Privilege dropping
	UnprivUser  string
	UnprivUID   uint32
	UnprivGroup string
	UnprivGID   uint32

	// Apparmor features
	AppArmorAdmin     bool
	AppArmorAvailable bool
	AppArmorConfined  bool
	AppArmorStacked   bool
	AppArmorStacking  bool

	// Cgroup features
	CGInfo cgroup.Info

	// Kernel features
	CloseRange              bool
	NativeTerminals         bool
	NetnsGetifaddrs         bool
	PidFds                  bool
	PidFdSetns              bool
	SeccompListener         bool
	SeccompListenerAddfd    bool
	SeccompListenerContinue bool
	Shiftfs                 bool
	UeventInjection         bool
	VFS3Fscaps              bool

	// LXC features
	LXCFeatures map[string]bool
}

// DefaultOS returns a fresh uninitialized OS instance with default values.
func DefaultOS() *OS {
	newOS := &OS{
		VarDir:   shared.VarPath(),
		CacheDir: shared.CachePath(),
		LogDir:   shared.LogPath(),
	}
	newOS.InotifyWatch.Fd = -1
	newOS.InotifyWatch.Targets = make(map[string]*InotifyTargetInfo)
	return newOS
}

// Init our internal data structures.
func (s *OS) Init() error {
	err := s.initDirs()
	if err != nil {
		return err
	}

	s.Architectures, err = util.GetArchitectures()
	if err != nil {
		return err
	}

	s.LxcPath = filepath.Join(s.VarDir, "containers")

	s.BackingFS, err = util.FilesystemDetect(s.LxcPath)
	if err != nil {
		logger.Error("Error detecting backing fs", log.Ctx{"err": err})
	}

	// Detect if it is possible to run daemons as an unprivileged user and group.
	for _, user := range []string{"lxd", "nobody"} {
		uid, err := shared.UserId(user)
		if err != nil {
			continue
		}

		s.UnprivUser = user
		s.UnprivUID = uint32(uid)
		break
	}

	for _, group := range []string{"lxd", "nogroup"} {
		gid, err := shared.GroupId(group)
		if err != nil {
			continue
		}

		s.UnprivGroup = group
		s.UnprivGID = uint32(gid)
		break
	}

	s.IdmapSet = util.GetIdmapSet()
	s.ExecPath = util.GetExecPath()
	s.RunningInUserNS = shared.RunningInUserNS()

	s.initAppArmor()
	s.CGInfo = cgroup.GetInfo()

	return nil
}
<commit_msg>lxd/sys/os: Adds InitStorage<commit_after>// +build linux,cgo,!agent

package sys

import (
	"path/filepath"
	"sync"

	log "github.com/lxc/lxd/shared/log15"

	"github.com/lxc/lxd/lxd/cgroup"
	"github.com/lxc/lxd/lxd/util"
	"github.com/lxc/lxd/shared"
	"github.com/lxc/lxd/shared/idmap"
	"github.com/lxc/lxd/shared/logger"
)

// InotifyTargetInfo records the inotify information associated with a given
// inotify target
type InotifyTargetInfo struct {
	Mask uint32
	Wd   int
	Path string
}

// InotifyInfo records the inotify information associated with a given
// inotify instance
type InotifyInfo struct {
	Fd int
	sync.RWMutex
	Targets map[string]*InotifyTargetInfo
}

// OS is a high-level facade for accessing all operating-system
// level functionality that LXD uses.
type OS struct {
	// Directories
	CacheDir string // Cache directory (e.g. /var/cache/lxd/).
	LogDir   string // Log directory (e.g. /var/log/lxd).
	VarDir   string // Data directory (e.g. /var/lib/lxd/).

	// Daemon environment
	Architectures   []int           // Cache of detected system architectures
	BackingFS       string          // Backing filesystem of $LXD_DIR/containers
	ExecPath        string          // Absolute path to the LXD executable
	IdmapSet        *idmap.IdmapSet // Information about user/group ID mapping
	InotifyWatch    InotifyInfo
	LxcPath         string // Path to the $LXD_DIR/containers directory
	MockMode        bool   // If true some APIs will be mocked (for testing)
	Nodev           bool
	RunningInUserNS bool

	// Privilege dropping
	UnprivUser  string
	UnprivUID   uint32
	UnprivGroup string
	UnprivGID   uint32

	// Apparmor features
	AppArmorAdmin     bool
	AppArmorAvailable bool
	AppArmorConfined  bool
	AppArmorStacked   bool
	AppArmorStacking  bool

	// Cgroup features
	CGInfo cgroup.Info

	// Kernel features
	CloseRange              bool
	NativeTerminals         bool
	NetnsGetifaddrs         bool
	PidFds                  bool
	PidFdSetns              bool
	SeccompListener         bool
	SeccompListenerAddfd    bool
	SeccompListenerContinue bool
	Shiftfs                 bool
	UeventInjection         bool
	VFS3Fscaps              bool

	// LXC features
	LXCFeatures map[string]bool
}

// DefaultOS returns a fresh uninitialized OS instance with default values.
func DefaultOS() *OS {
	newOS := &OS{
		VarDir:   shared.VarPath(),
		CacheDir: shared.CachePath(),
		LogDir:   shared.LogPath(),
	}
	newOS.InotifyWatch.Fd = -1
	newOS.InotifyWatch.Targets = make(map[string]*InotifyTargetInfo)
	return newOS
}

// Init our internal data structures.
func (s *OS) Init() error {
	err := s.initDirs()
	if err != nil {
		return err
	}

	s.Architectures, err = util.GetArchitectures()
	if err != nil {
		return err
	}

	s.LxcPath = filepath.Join(s.VarDir, "containers")

	s.BackingFS, err = util.FilesystemDetect(s.LxcPath)
	if err != nil {
		logger.Error("Error detecting backing fs", log.Ctx{"err": err})
	}

	// Detect if it is possible to run daemons as an unprivileged user and group.
	for _, user := range []string{"lxd", "nobody"} {
		uid, err := shared.UserId(user)
		if err != nil {
			continue
		}

		s.UnprivUser = user
		s.UnprivUID = uint32(uid)
		break
	}

	for _, group := range []string{"lxd", "nogroup"} {
		gid, err := shared.GroupId(group)
		if err != nil {
			continue
		}

		s.UnprivGroup = group
		s.UnprivGID = uint32(gid)
		break
	}

	s.IdmapSet = util.GetIdmapSet()
	s.ExecPath = util.GetExecPath()
	s.RunningInUserNS = shared.RunningInUserNS()

	s.initAppArmor()
	s.CGInfo = cgroup.GetInfo()

	return nil
}

// InitStorage initialises the storage layer after it has been mounted.
func (s *OS) InitStorage() error {
	return s.initStorageDirs()
}
<|endoftext|>


<commit_before>package rpc

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"

	rpcJSON "github.com/gorilla/rpc/json"
)

type (
	// Client is a simple JSON-RPC over HTTP client used by the agent.
	Client struct {
		URL string
	}
)

// NewClient create a new client.  This only communicates with 127.0.0.1
func NewClient(port uint, path string) (*Client, error) {
	if path == "" {
		path = RPCPath
	}
	c := &Client{
		//XXX: this seems wrong
		URL: fmt.Sprintf("http://127.0.0.1:%d%s", port, path),
	}
	return c, nil
}

// Do calls an RPC method
func (c *Client) Do(method string, request interface{}, response interface{}) error {
	data, err := rpcJSON.EncodeClientRequest(method, request)
	if err != nil {
		return err
	}
	resp, err := http.Post(c.URL, "application/json", bytes.NewReader(data))
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	err = rpcJSON.DecodeClientResponse(resp.Body, &response)
	if err != nil {
		return err
	}
	return nil
}

// DoRaw calls a service and proxies the response
func (c *Client) DoRaw(request interface{}, rw http.ResponseWriter) {
	data, err := json.Marshal(request)
	if err != nil {
		http.Error(rw, err.Error(), 500)
		return
	}
	resp, err := http.Post(c.URL, "application/json", bytes.NewReader(data))
	if err != nil {
		http.Error(rw, err.Error(), 500)
		return
	}
	defer resp.Body.Close()

	if resp.StatusCode != 200 {
		buf := new(bytes.Buffer)
		if _, err := buf.ReadFrom(resp.Body); err != nil {
			http.Error(rw, err.Error(), 500)
			return
		}
		http.Error(rw, buf.String(), resp.StatusCode)
		return
	}
	rw.Header().Set("Content-Type", "application/octet-stream")
	_, err = io.Copy(rw, resp.Body)
	if err != nil {
		http.Error(rw, err.Error(), 500)
	}
	return
}
<commit_msg>MIST-286 Handle error responses in the RPC Client.Do method<commit_after>package rpc

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net/http"

	rpcJSON "github.com/gorilla/rpc/json"
)

type (
	// Client is a simple JSON-RPC over HTTP client used by the agent.
	Client struct {
		URL string
	}
)

// NewClient create a new client.  This only communicates with 127.0.0.1
func NewClient(port uint, path string) (*Client, error) {
	if path == "" {
		path = RPCPath
	}
	c := &Client{
		//XXX: this seems wrong
		URL: fmt.Sprintf("http://127.0.0.1:%d%s", port, path),
	}
	return c, nil
}

// Do calls an RPC method
func (c *Client) Do(method string, request interface{}, response interface{}) error {
	data, err := rpcJSON.EncodeClientRequest(method, request)
	if err != nil {
		return err
	}
	resp, err := http.Post(c.URL, "application/json", bytes.NewReader(data))
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		buf := new(bytes.Buffer)
		if _, err := buf.ReadFrom(resp.Body); err != nil {
			return err
		}
		return errors.New(buf.String())
	}

	err = rpcJSON.DecodeClientResponse(resp.Body, &response)
	if err != nil {
		return err
	}
	return nil
}

// DoRaw calls a service and proxies the response
func (c *Client) DoRaw(request interface{}, rw http.ResponseWriter) {
	data, err := json.Marshal(request)
	if err != nil {
		http.Error(rw, err.Error(), 500)
		return
	}
	resp, err := http.Post(c.URL, "application/json", bytes.NewReader(data))
	if err != nil {
		http.Error(rw, err.Error(), 500)
		return
	}
	defer resp.Body.Close()

	if resp.StatusCode != 200 {
		buf := new(bytes.Buffer)
		if _, err := buf.ReadFrom(resp.Body); err != nil {
			http.Error(rw, err.Error(), 500)
			return
		}
		http.Error(rw, buf.String(), resp.StatusCode)
		return
	}
	rw.Header().Set("Content-Type", "application/octet-stream")
	_, err = io.Copy(rw, resp.Body)
	if err != nil {
		http.Error(rw, err.Error(), 500)
	}
	return
}
<|endoftext|>


<commit_before>/*
Package css is a CSS3 tokenizer and parser written in Go. Both are implemented using the specifications at http://www.w3.org/TR/css-syntax-3/
Tokenizer using example:
	package main
	import (
		"fmt"
		"io"
		"os"
		"github.com/tdewolff/css"
	)
	// Tokenize CSS3 from stdin.
	func main() {
		z := css.NewTokenizer(os.Stdin)
		for {
			tt, data := z.Next()
			switch tt {
			case css.ErrorToken:
				if z.Err() != io.EOF {
					fmt.Println("Error on line", z.Line(), ":", z.Err())
				}
				return
			case css.IdentToken:
				fmt.Println("Identifier", data)
			case css.NumberToken:
				fmt.Println("Number", data)
			// ...
			}
		}
	}
Parser using example:
	package main
	import (
		"fmt"
		"os"
		"github.com/tdewolff/css"
	)
	// Parse CSS3 from stdin.
	func main() {
		stylesheet, err := css.Parse(os.Stdin)
		if err != nil {
			fmt.Println("Error:", err)
			return
		}
		for _, node := range stylesheet.Nodes {
			switch m := node.(type) {
			case *css.TokenNode:
				fmt.Println("Token", string(m.Data))
			case *css.DeclarationNode:
				fmt.Println("Declaration for property", string(m.Prop.Data))
			case *css.RulesetNode:
				fmt.Println("Ruleset with", len(m.Decls), "declarations")
			case *css.AtRuleNode:
				fmt.Println("AtRule", string(m.At.Data))
			}
		}
	}
*/
package css // import "github.com/tdewolff/parse/css"

import (
	"errors"
	"io"
	"strconv"

	"github.com/tdewolff/parse"
)

var wsBytes = []byte(" ")
var emptyBytes = []byte("")

////////////////////////////////////////////////////////////////

// GrammarType determines the type of grammar.
type GrammarType uint32

// GrammarType values.
const (
	ErrorGrammar GrammarType = iota // extra token when errors occur
	AtRuleGrammar
	BeginAtRuleGrammar
	EndAtRuleGrammar
	BeginRulesetGrammar
	EndRulesetGrammar
	DeclarationGrammar
	TokenGrammar
)

// String returns the string representation of a GrammarType.
func (tt GrammarType) String() string {
	switch tt {
	case ErrorGrammar:
		return "Error"
	case AtRuleGrammar:
		return "AtRule"
	case BeginAtRuleGrammar:
		return "BeginAtRule"
	case EndAtRuleGrammar:
		return "EndAtRule"
	case BeginRulesetGrammar:
		return "BeginRuleset"
	case EndRulesetGrammar:
		return "EndRuleset"
	case DeclarationGrammar:
		return "Declaration"
	case TokenGrammar:
		return "Token"
	}
	return "Invalid(" + strconv.Itoa(int(tt)) + ")"
}

////////////////////////////////////////////////////////////////

type State func() GrammarType

type Token struct {
	TokenType
	Data []byte
}

func String(ts []Token) string {
	var data []byte
	for _, t := range ts {
		data = append(data, t.Data...)
	}
	return string(data)
}

type Parser struct {
	z     *Tokenizer
	state []State
	err   error

	buf []Token

	tt     TokenType
	data   []byte
	prevWS bool
}

func NewParser(r io.Reader, isStylesheet bool) *Parser {
	z := NewTokenizer(r)
	p := &Parser{
		z: z,
	}
	if isStylesheet {
		p.state = []State{p.parseStylesheet}
	} else {
		p.state = []State{p.parseDeclarationList}
	}
	return p
}

func (p *Parser) Err() error {
	if p.err != nil {
		return p.err
	}
	return p.z.Err()
}

func (p *Parser) Next() (GrammarType, TokenType, []byte) {
	p.tt, p.data = p.popToken()
	gt := p.state[len(p.state)-1]()
	return gt, p.tt, p.data
}

func (p *Parser) Values() []Token {
	return p.buf
}

func (p *Parser) popToken() (TokenType, []byte) {
	p.prevWS = false
	tt, data := p.z.Next()
	for tt == WhitespaceToken || tt == CommentToken {
		if tt == WhitespaceToken {
			p.prevWS = true
		}
		tt, data = p.z.Next()
	}
	return tt, data
}

func (p *Parser) initBuf() {
	if !p.z.IsEOF() {
		p.data = parse.Copy(p.data)
	}
	p.buf = p.buf[:0]
}

func (p *Parser) pushBuf(tt TokenType, data []byte) {
	if p.z.IsEOF() {
		p.buf = append(p.buf, Token{tt, data})
	} else {
		p.buf = append(p.buf, Token{tt, parse.Copy(data)})
	}
}

////////////////////////////////////////////////////////////////

func (p *Parser) parseStylesheet() GrammarType {
	if p.tt == CDOToken || p.tt == CDCToken {
		return TokenGrammar
	} else if p.tt == AtKeywordToken {
		return p.parseAtRule()
	} else if p.tt == ErrorToken {
		return ErrorGrammar
	} else {
		return p.parseQualifiedRule()
	}
}

func (p *Parser) parseRuleList() GrammarType {
	if p.tt == AtKeywordToken {
		return p.parseAtRule()
	} else if p.tt == ErrorToken {
		return ErrorGrammar
	} else {
		return p.parseQualifiedRule()
	}
}

func (p *Parser) parseDeclarationList() GrammarType {
	for p.tt == SemicolonToken {
		p.tt, p.data = p.popToken()
	}
	if p.tt == ErrorToken {
		return ErrorGrammar
	} else if p.tt == AtKeywordToken {
		return p.parseAtRule()
	} else if p.tt == IdentToken {
		return p.parseDeclaration()
	} else if p.tt == DelimToken && p.data[0] == '*' { // CSS hack
		p.tt, p.data = p.popToken()
		if p.tt == IdentToken {
			p.data = append([]byte("*"), p.data...)
			return p.parseDeclaration()
		}
		return p.state[len(p.state)-1]()
	}
	// parse error
	for p.tt != SemicolonToken && p.tt != ErrorToken {
		p.tt, p.data = p.popToken()
	}
	return p.state[len(p.state)-1]()
}

////////////////////////////////////////////////////////////////

func (p *Parser) parseAtRule() GrammarType {
	p.initBuf()
	parse.ToLower(p.data)
	atRule := ToHash(p.data[1:])
	first := true
	level := 0
	skipWS := false
	for {
		tt, data := p.popToken()
		if tt == LeftBraceToken && level == 0 {
			if atRule == Font_Face || atRule == Page {
				p.state = append(p.state, p.parseAtRuleDeclarationList)
			} else if atRule == Document || atRule == Keyframes || atRule == Media || atRule == Supports {
				p.state = append(p.state, p.parseAtRuleRuleList)
			} else {
				p.err = errors.New("unknown at-rule '" + string(p.data) + "' with block")
				return ErrorGrammar
			}
			return BeginAtRuleGrammar
		} else if tt == SemicolonToken && level == 0 || tt == ErrorToken {
			return AtRuleGrammar
		} else if tt == LeftParenthesisToken || tt == LeftBraceToken || tt == LeftBracketToken || tt == FunctionToken {
			level++
		} else if tt == RightParenthesisToken || tt == RightBraceToken || tt == RightBracketToken {
			level--
		}
		if first {
			if tt == LeftParenthesisToken || tt == LeftBracketToken {
				p.prevWS = false
			}
			first = false
		}
		if len(data) == 1 && (data[0] == ',' || data[0] == ':') {
			skipWS = true
		} else if p.prevWS && !skipWS && tt != RightParenthesisToken {
			p.pushBuf(WhitespaceToken, wsBytes)
		} else {
			skipWS = false
		}
		if tt == LeftParenthesisToken {
			skipWS = true
		}
		p.pushBuf(tt, data)
	}
}

func (p *Parser) parseAtRuleRuleList() GrammarType {
	if p.tt == RightBraceToken || p.tt == ErrorToken {
		p.state = p.state[:len(p.state)-1]
		return EndAtRuleGrammar
	}
	return p.parseRuleList()
}

func (p *Parser) parseAtRuleDeclarationList() GrammarType {
	for p.tt == SemicolonToken {
		p.tt, p.data = p.popToken()
	}
	if p.tt == RightBraceToken || p.tt == ErrorToken {
		p.state = p.state[:len(p.state)-1]
		return EndAtRuleGrammar
	}
	return p.parseDeclarationList()
}

func (p *Parser) parseQualifiedRule() GrammarType {
	p.initBuf()
	first := true
	inAttrSel := false
	level := 0
	skipWS := true
	var tt TokenType
	var data []byte
	for {
		if first {
			tt, data = p.tt, p.data
			p.tt = WhitespaceToken
			p.data = emptyBytes
			first = false
		} else {
			tt, data = p.popToken()
		}
		if tt == LeftBraceToken && level == 0 {
			p.state = append(p.state, p.parseQualifiedRuleDeclarationList)
			return BeginRulesetGrammar
		} else if tt == ErrorToken {
			p.err = errors.New("unexpected error in qualified rule '" + String(p.buf) + "' before encountering '{'")
			return ErrorGrammar
		} else if tt == LeftParenthesisToken || tt == LeftBraceToken || tt == LeftBracketToken || tt == FunctionToken {
			level++
		} else if tt == RightParenthesisToken || tt == RightBraceToken || tt == RightBracketToken {
			level--
		}
		if len(data) == 1 && (data[0] == ',' || data[0] == '>' || data[0] == '+' || data[0] == '~') {
			skipWS = true
		} else if p.prevWS && !skipWS && !inAttrSel {
			p.pushBuf(WhitespaceToken, wsBytes)
		} else {
			skipWS = false
		}
		if tt == LeftBracketToken {
			inAttrSel = true
		} else if tt == RightBracketToken {
			inAttrSel = false
		}
		p.pushBuf(tt, data)
	}
}

func (p *Parser) parseQualifiedRuleDeclarationList() GrammarType {
	for p.tt == SemicolonToken {
		p.tt, p.data = p.popToken()
	}
	if p.tt == RightBraceToken || p.tt == ErrorToken {
		p.state = p.state[:len(p.state)-1]
		return EndRulesetGrammar
	}
	return p.parseDeclarationList()
}

func (p *Parser) parseDeclaration() GrammarType {
	p.initBuf()
	parse.ToLower(p.data)
	if tt, _ := p.popToken(); tt != ColonToken {
		p.err = errors.New("unexpected token for declaration colon: " + p.tt.String())
		return ErrorGrammar
	}
	level := 0
	skipWS := true
	for {
		tt, data := p.popToken()
		if (tt == SemicolonToken || tt == RightBraceToken) && level == 0 {
			return DeclarationGrammar
		} else if tt == ErrorToken {
			return DeclarationGrammar
		} else if tt == LeftParenthesisToken || tt == LeftBraceToken || tt == LeftBracketToken || tt == FunctionToken {
			level++
		} else if tt == RightParenthesisToken || tt == RightBraceToken || tt == RightBracketToken {
			level--
		}
		if len(data) == 1 && (data[0] == ',' || data[0] == '/' || data[0] == ':' || data[0] == '!' || data[0] == '=') {
			skipWS = true
		} else if p.prevWS && !skipWS {
			p.pushBuf(WhitespaceToken, wsBytes)
		} else {
			skipWS = false
		}
		p.pushBuf(tt, data)
	}
}
<commit_msg>Handle unknown at rules and vendor specific at rules<commit_after>/*
Package css is a CSS3 tokenizer and parser written in Go. Both are implemented using the specifications at http://www.w3.org/TR/css-syntax-3/
Tokenizer using example:
	package main
	import (
		"fmt"
		"io"
		"os"
		"github.com/tdewolff/css"
	)
	// Tokenize CSS3 from stdin.
	func main() {
		z := css.NewTokenizer(os.Stdin)
		for {
			tt, data := z.Next()
			switch tt {
			case css.ErrorToken:
				if z.Err() != io.EOF {
					fmt.Println("Error on line", z.Line(), ":", z.Err())
				}
				return
			case css.IdentToken:
				fmt.Println("Identifier", data)
			case css.NumberToken:
				fmt.Println("Number", data)
			// ...
			}
		}
	}
Parser using example:
	package main
	import (
		"fmt"
		"os"
		"github.com/tdewolff/css"
	)
	// Parse CSS3 from stdin.
	func main() {
		stylesheet, err := css.Parse(os.Stdin)
		if err != nil {
			fmt.Println("Error:", err)
			return
		}
		for _, node := range stylesheet.Nodes {
			switch m := node.(type) {
			case *css.TokenNode:
				fmt.Println("Token", string(m.Data))
			case *css.DeclarationNode:
				fmt.Println("Declaration for property", string(m.Prop.Data))
			case *css.RulesetNode:
				fmt.Println("Ruleset with", len(m.Decls), "declarations")
			case *css.AtRuleNode:
				fmt.Println("AtRule", string(m.At.Data))
			}
		}
	}
*/
package css // import "github.com/tdewolff/parse/css"

import (
	"bytes"
	"errors"
	"io"
	"strconv"

	"github.com/tdewolff/parse"
)

var wsBytes = []byte(" ")
var emptyBytes = []byte("")

////////////////////////////////////////////////////////////////

// GrammarType determines the type of grammar.
type GrammarType uint32

// GrammarType values.
const (
	ErrorGrammar GrammarType = iota // extra token when errors occur
	AtRuleGrammar
	BeginAtRuleGrammar
	EndAtRuleGrammar
	BeginRulesetGrammar
	EndRulesetGrammar
	DeclarationGrammar
	TokenGrammar
)

// String returns the string representation of a GrammarType.
func (tt GrammarType) String() string {
	switch tt {
	case ErrorGrammar:
		return "Error"
	case AtRuleGrammar:
		return "AtRule"
	case BeginAtRuleGrammar:
		return "BeginAtRule"
	case EndAtRuleGrammar:
		return "EndAtRule"
	case BeginRulesetGrammar:
		return "BeginRuleset"
	case EndRulesetGrammar:
		return "EndRuleset"
	case DeclarationGrammar:
		return "Declaration"
	case TokenGrammar:
		return "Token"
	}
	return "Invalid(" + strconv.Itoa(int(tt)) + ")"
}

////////////////////////////////////////////////////////////////

type State func() GrammarType

type Token struct {
	TokenType
	Data []byte
}

func String(ts []Token) string {
	var data []byte
	for _, t := range ts {
		data = append(data, t.Data...)
	}
	return string(data)
}

type Parser struct {
	z     *Tokenizer
	state []State
	err   error

	buf []Token

	tt     TokenType
	data   []byte
	prevWS bool
	level  int
}

func NewParser(r io.Reader, isStylesheet bool) *Parser {
	z := NewTokenizer(r)
	p := &Parser{
		z: z,
	}
	if isStylesheet {
		p.state = []State{p.parseStylesheet}
	} else {
		p.state = []State{p.parseDeclarationList}
	}
	return p
}

func (p *Parser) Err() error {
	if p.err != nil {
		return p.err
	}
	return p.z.Err()
}

func (p *Parser) Next() (GrammarType, TokenType, []byte) {
	p.tt, p.data = p.popToken()
	gt := p.state[len(p.state)-1]()
	return gt, p.tt, p.data
}

func (p *Parser) Values() []Token {
	return p.buf
}

func (p *Parser) popToken() (TokenType, []byte) {
	p.prevWS = false
	tt, data := p.z.Next()
	for tt == WhitespaceToken || tt == CommentToken {
		if tt == WhitespaceToken {
			p.prevWS = true
		}
		tt, data = p.z.Next()
	}
	return tt, data
}

func (p *Parser) initBuf() {
	if !p.z.IsEOF() {
		p.data = parse.Copy(p.data)
	}
	p.buf = p.buf[:0]
}

func (p *Parser) pushBuf(tt TokenType, data []byte) {
	if p.z.IsEOF() {
		p.buf = append(p.buf, Token{tt, data})
	} else {
		p.buf = append(p.buf, Token{tt, parse.Copy(data)})
	}
}

////////////////////////////////////////////////////////////////

func (p *Parser) parseStylesheet() GrammarType {
	if p.tt == CDOToken || p.tt == CDCToken {
		return TokenGrammar
	} else if p.tt == AtKeywordToken {
		return p.parseAtRule()
	} else if p.tt == ErrorToken {
		return ErrorGrammar
	} else {
		return p.parseQualifiedRule()
	}
}

func (p *Parser) parseRuleList() GrammarType {
	if p.tt == AtKeywordToken {
		return p.parseAtRule()
	} else if p.tt == ErrorToken {
		return ErrorGrammar
	} else {
		return p.parseQualifiedRule()
	}
}

func (p *Parser) parseDeclarationList() GrammarType {
	for p.tt == SemicolonToken {
		p.tt, p.data = p.popToken()
	}
	if p.tt == ErrorToken {
		return ErrorGrammar
	} else if p.tt == AtKeywordToken {
		return p.parseAtRule()
	} else if p.tt == IdentToken {
		return p.parseDeclaration()
	} else if p.tt == DelimToken && p.data[0] == '*' { // CSS hack
		p.tt, p.data = p.popToken()
		if p.tt == IdentToken {
			p.data = append([]byte("*"), p.data...)
			return p.parseDeclaration()
		}
		return p.state[len(p.state)-1]()
	}
	// parse error
	for p.tt != SemicolonToken && p.tt != ErrorToken {
		p.tt, p.data = p.popToken()
	}
	return p.state[len(p.state)-1]()
}

////////////////////////////////////////////////////////////////

func (p *Parser) parseAtRule() GrammarType {
	p.initBuf()
	parse.ToLower(p.data)
	if len(p.data) > 0 && p.data[1] == '-' {
		if i := bytes.IndexByte(p.data[2:], '-'); i != -1 {
			p.data = p.data[i+3:] // skip vendor specific prefix
		}
	}
	atRule := ToHash(p.data[1:])
	first := true
	skipWS := false
	for {
		tt, data := p.popToken()
		if tt == LeftBraceToken && p.level == 0 {
			if atRule == Font_Face || atRule == Page {
				p.state = append(p.state, p.parseAtRuleDeclarationList)
			} else if atRule == Document || atRule == Keyframes || atRule == Media || atRule == Supports {
				p.state = append(p.state, p.parseAtRuleRuleList)
			} else {
				p.state = append(p.state, p.parseAtRuleUnknown)
			}
			return BeginAtRuleGrammar
		} else if tt == SemicolonToken && p.level == 0 || tt == ErrorToken {
			return AtRuleGrammar
		} else if tt == LeftParenthesisToken || tt == LeftBraceToken || tt == LeftBracketToken || tt == FunctionToken {
			p.level++
		} else if tt == RightParenthesisToken || tt == RightBraceToken || tt == RightBracketToken {
			p.level--
		}
		if first {
			if tt == LeftParenthesisToken || tt == LeftBracketToken {
				p.prevWS = false
			}
			first = false
		}
		if len(data) == 1 && (data[0] == ',' || data[0] == ':') {
			skipWS = true
		} else if p.prevWS && !skipWS && tt != RightParenthesisToken {
			p.pushBuf(WhitespaceToken, wsBytes)
		} else {
			skipWS = false
		}
		if tt == LeftParenthesisToken {
			skipWS = true
		}
		p.pushBuf(tt, data)
	}
}

func (p *Parser) parseAtRuleRuleList() GrammarType {
	if p.tt == RightBraceToken || p.tt == ErrorToken {
		p.state = p.state[:len(p.state)-1]
		return EndAtRuleGrammar
	}
	return p.parseRuleList()
}

func (p *Parser) parseAtRuleDeclarationList() GrammarType {
	for p.tt == SemicolonToken {
		p.tt, p.data = p.popToken()
	}
	if p.tt == RightBraceToken || p.tt == ErrorToken {
		p.state = p.state[:len(p.state)-1]
		return EndAtRuleGrammar
	}
	return p.parseDeclarationList()
}

func (p *Parser) parseAtRuleUnknown() GrammarType {
	if p.level == 0 && p.tt == RightBraceToken || p.tt == ErrorToken {
		p.state = p.state[:len(p.state)-1]
		return EndAtRuleGrammar
	}
	if p.tt == LeftParenthesisToken || p.tt == LeftBraceToken || p.tt == LeftBracketToken || p.tt == FunctionToken {
		p.level++
	} else if p.tt == RightParenthesisToken || p.tt == RightBraceToken || p.tt == RightBracketToken {
		p.level--
	}
	return TokenGrammar
}

func (p *Parser) parseQualifiedRule() GrammarType {
	p.initBuf()
	first := true
	inAttrSel := false
	skipWS := true
	var tt TokenType
	var data []byte
	for {
		if first {
			tt, data = p.tt, p.data
			p.tt = WhitespaceToken
			p.data = emptyBytes
			first = false
		} else {
			tt, data = p.popToken()
		}
		if tt == LeftBraceToken && p.level == 0 {
			p.state = append(p.state, p.parseQualifiedRuleDeclarationList)
			return BeginRulesetGrammar
		} else if tt == ErrorToken {
			p.err = errors.New("unexpected error in qualified rule '" + String(p.buf) + "' before encountering '{'")
			return ErrorGrammar
		} else if tt == LeftParenthesisToken || tt == LeftBraceToken || tt == LeftBracketToken || tt == FunctionToken {
			p.level++
		} else if tt == RightParenthesisToken || tt == RightBraceToken || tt == RightBracketToken {
			p.level--
		}
		if len(data) == 1 && (data[0] == ',' || data[0] == '>' || data[0] == '+' || data[0] == '~') {
			skipWS = true
		} else if p.prevWS && !skipWS && !inAttrSel {
			p.pushBuf(WhitespaceToken, wsBytes)
		} else {
			skipWS = false
		}
		if tt == LeftBracketToken {
			inAttrSel = true
		} else if tt == RightBracketToken {
			inAttrSel = false
		}
		p.pushBuf(tt, data)
	}
}

func (p *Parser) parseQualifiedRuleDeclarationList() GrammarType {
	for p.tt == SemicolonToken {
		p.tt, p.data = p.popToken()
	}
	if p.tt == RightBraceToken || p.tt == ErrorToken {
		p.state = p.state[:len(p.state)-1]
		return EndRulesetGrammar
	}
	return p.parseDeclarationList()
}

func (p *Parser) parseDeclaration() GrammarType {
	p.initBuf()
	parse.ToLower(p.data)
	if tt, _ := p.popToken(); tt != ColonToken {
		p.err = errors.New("unexpected token for declaration colon: " + p.tt.String())
		return ErrorGrammar
	}
	skipWS := true
	for {
		tt, data := p.popToken()
		if (tt == SemicolonToken || tt == RightBraceToken) && p.level == 0 {
			return DeclarationGrammar
		} else if tt == ErrorToken {
			return DeclarationGrammar
		} else if tt == LeftParenthesisToken || tt == LeftBraceToken || tt == LeftBracketToken || tt == FunctionToken {
			p.level++
		} else if tt == RightParenthesisToken || tt == RightBraceToken || tt == RightBracketToken {
			p.level--
		}
		if len(data) == 1 && (data[0] == ',' || data[0] == '/' || data[0] == ':' || data[0] == '!' || data[0] == '=') {
			skipWS = true
		} else if p.prevWS && !skipWS {
			p.pushBuf(WhitespaceToken, wsBytes)
		} else {
			skipWS = false
		}
		p.pushBuf(tt, data)
	}
}
<|endoftext|>