<commit_before>//go:build linux
// +build linux

package macvlan

import (
	"fmt"

	"github.com/docker/docker/libnetwork/driverapi"
	"github.com/docker/docker/libnetwork/netlabel"
	"github.com/docker/docker/libnetwork/ns"
	"github.com/docker/docker/libnetwork/options"
	"github.com/docker/docker/libnetwork/osl"
	"github.com/docker/docker/libnetwork/types"
	"github.com/docker/docker/pkg/stringid"
	"github.com/sirupsen/logrus"
)

// CreateNetwork the network for the specified driver type
func (d *driver) CreateNetwork(nid string, option map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error {
	defer osl.InitOSContext()()

	// reject a null v4 network
	if len(ipV4Data) == 0 || ipV4Data[0].Pool.String() == "0.0.0.0/0" {
		return fmt.Errorf("ipv4 pool is empty")
	}
	// parse and validate the config and bind to networkConfiguration
	config, err := parseNetworkOptions(nid, option)
	if err != nil {
		return err
	}
	config.ID = nid
	err = config.processIPAM(nid, ipV4Data, ipV6Data)
	if err != nil {
		return err
	}
	// verify the macvlan mode from -o macvlan_mode option
	switch config.MacvlanMode {
	case "", modeBridge:
		// default to macvlan bridge mode if -o macvlan_mode is empty
		config.MacvlanMode = modeBridge
	case modePrivate:
		config.MacvlanMode = modePrivate
	case modePassthru:
		config.MacvlanMode = modePassthru
	case modeVepa:
		config.MacvlanMode = modeVepa
	default:
		return fmt.Errorf("requested macvlan mode '%s' is not valid, 'bridge' mode is the macvlan driver default", config.MacvlanMode)
	}
	// loopback is not a valid parent link
	if config.Parent == "lo" {
		return fmt.Errorf("loopback interface is not a valid %s parent link", macvlanType)
	}
	// if parent interface not specified, create a dummy type link to use named dummy+net_id
	if config.Parent == "" {
		config.Parent = getDummyName(stringid.TruncateID(config.ID))
	}
	foundExisting, err := d.createNetwork(config)
	if err != nil {
		return err
	}

	if foundExisting {
		return types.InternalMaskableErrorf("restoring existing network %s", config.ID)
	}

	// update persistent db, rollback on fail
	err = d.storeUpdate(config)
	if err != nil {
		d.deleteNetwork(config.ID)
		logrus.Debugf("encountered an error rolling back a network create for %s : %v", config.ID, err)
		return err
	}

	return nil
}

// createNetwork is used by new network callbacks and persistent network cache
func (d *driver) createNetwork(config *configuration) (bool, error) {
	foundExisting := false
	networkList := d.getNetworks()
	for _, nw := range networkList {
		if config.Parent == nw.config.Parent {
			if config.ID != nw.config.ID {
				return false, fmt.Errorf("network %s is already using parent interface %s",
					getDummyName(stringid.TruncateID(nw.config.ID)), config.Parent)
			}
			logrus.Debugf("Create Network for the same ID %s\n", config.ID)
			foundExisting = true
			break
		}
	}
	if !parentExists(config.Parent) {
		// Create a dummy link if a dummy name is set for parent
		if dummyName := getDummyName(stringid.TruncateID(config.ID)); dummyName == config.Parent {
			err := createDummyLink(config.Parent, dummyName)
			if err != nil {
				return false, err
			}
			config.CreatedSlaveLink = true
			// notify the user in logs that they have limited communications
			logrus.Debugf("Empty -o parent= limit communications to other containers inside of network: %s",
				config.Parent)
		} else {
			// if the subinterface parent_iface.vlan_id checks do not pass, return err.
			//  a valid example is 'eth0.10' for a parent iface 'eth0' with a vlan id '10'
			err := createVlanLink(config.Parent)
			if err != nil {
				return false, err
			}
			// if driver created the networks slave link, record it for future deletion
			config.CreatedSlaveLink = true
		}
	}
	if !foundExisting {
		n := &network{
			id:        config.ID,
			driver:    d,
			endpoints: endpointTable{},
			config:    config,
		}
		// add the network
		d.addNetwork(n)
	}

	return foundExisting, nil
}

// DeleteNetwork deletes the network for the specified driver type
func (d *driver) DeleteNetwork(nid string) error {
	defer osl.InitOSContext()()
	n := d.network(nid)
	if n == nil {
		return fmt.Errorf("network id %s not found", nid)
	}
	// if the driver created the slave interface, delete it, otherwise leave it
	if ok := n.config.CreatedSlaveLink; ok {
		// if the interface exists, only delete if it matches iface.vlan or dummy.net_id naming
		if ok := parentExists(n.config.Parent); ok {
			// only delete the link if it is named the net_id
			if n.config.Parent == getDummyName(stringid.TruncateID(nid)) {
				err := delDummyLink(n.config.Parent)
				if err != nil {
					logrus.Debugf("link %s was not deleted, continuing the delete network operation: %v",
						n.config.Parent, err)
				}
			} else {
				// only delete the link if it matches iface.vlan naming
				err := delVlanLink(n.config.Parent)
				if err != nil {
					logrus.Debugf("link %s was not deleted, continuing the delete network operation: %v",
						n.config.Parent, err)
				}
			}
		}
	}
	for _, ep := range n.endpoints {
		if link, err := ns.NlHandle().LinkByName(ep.srcName); err == nil {
			if err := ns.NlHandle().LinkDel(link); err != nil {
				logrus.WithError(err).Warnf("Failed to delete interface (%s)'s link on endpoint (%s) delete", ep.srcName, ep.id)
			}
		}

		if err := d.storeDelete(ep); err != nil {
			logrus.Warnf("Failed to remove macvlan endpoint %.7s from store: %v", ep.id, err)
		}
	}
	// delete the *network
	d.deleteNetwork(nid)
	// delete the network record from persistent cache
	err := d.storeDelete(n.config)
	if err != nil {
		return fmt.Errorf("error deleting deleting id %s from datastore: %v", nid, err)
	}
	return nil
}

// parseNetworkOptions parses docker network options
func parseNetworkOptions(id string, option options.Generic) (*configuration, error) {
	var (
		err    error
		config = &configuration{}
	)
	// parse generic labels first
	if genData, ok := option[netlabel.GenericData]; ok && genData != nil {
		if config, err = parseNetworkGenericOptions(genData); err != nil {
			return nil, err
		}
	}
	if val, ok := option[netlabel.Internal]; ok {
		if internal, ok := val.(bool); ok && internal {
			config.Internal = true
		}
	}

	return config, nil
}

// parseNetworkGenericOptions parses generic driver docker network options
func parseNetworkGenericOptions(data interface{}) (*configuration, error) {
	var (
		err    error
		config *configuration
	)
	switch opt := data.(type) {
	case *configuration:
		config = opt
	case map[string]string:
		config = &configuration{}
		err = config.fromOptions(opt)
	case options.Generic:
		var opaqueConfig interface{}
		if opaqueConfig, err = options.GenerateFromModel(opt, config); err == nil {
			config = opaqueConfig.(*configuration)
		}
	default:
		err = types.BadRequestErrorf("unrecognized network configuration format: %v", opt)
	}

	return config, err
}

// fromOptions binds the generic options to networkConfiguration to cache
func (config *configuration) fromOptions(labels map[string]string) error {
	for label, value := range labels {
		switch label {
		case parentOpt:
			// parse driver option '-o parent'
			config.Parent = value
		case driverModeOpt:
			// parse driver option '-o macvlan_mode'
			config.MacvlanMode = value
		}
	}

	return nil
}

// processIPAM parses v4 and v6 IP information and binds it to the network configuration
func (config *configuration) processIPAM(id string, ipamV4Data, ipamV6Data []driverapi.IPAMData) error {
	if len(ipamV4Data) > 0 {
		for _, ipd := range ipamV4Data {
			s := &ipSubnet{
				SubnetIP: ipd.Pool.String(),
				GwIP:     ipd.Gateway.String(),
			}
			config.Ipv4Subnets = append(config.Ipv4Subnets, s)
		}
	}
	if len(ipamV6Data) > 0 {
		for _, ipd := range ipamV6Data {
			s := &ipSubnet{
				SubnetIP: ipd.Pool.String(),
				GwIP:     ipd.Gateway.String(),
			}
			config.Ipv6Subnets = append(config.Ipv6Subnets, s)
		}
	}

	return nil
}
<commit_msg>libnetwork: macvlan: set network ID as part of parseNetworkOptions<commit_after>//go:build linux
// +build linux

package macvlan

import (
	"fmt"

	"github.com/docker/docker/libnetwork/driverapi"
	"github.com/docker/docker/libnetwork/netlabel"
	"github.com/docker/docker/libnetwork/ns"
	"github.com/docker/docker/libnetwork/options"
	"github.com/docker/docker/libnetwork/osl"
	"github.com/docker/docker/libnetwork/types"
	"github.com/docker/docker/pkg/stringid"
	"github.com/sirupsen/logrus"
)

// CreateNetwork the network for the specified driver type
func (d *driver) CreateNetwork(nid string, option map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error {
	defer osl.InitOSContext()()

	// reject a null v4 network
	if len(ipV4Data) == 0 || ipV4Data[0].Pool.String() == "0.0.0.0/0" {
		return fmt.Errorf("ipv4 pool is empty")
	}
	// parse and validate the config and bind to networkConfiguration
	config, err := parseNetworkOptions(nid, option)
	if err != nil {
		return err
	}
	err = config.processIPAM(nid, ipV4Data, ipV6Data)
	if err != nil {
		return err
	}
	// verify the macvlan mode from -o macvlan_mode option
	switch config.MacvlanMode {
	case "", modeBridge:
		// default to macvlan bridge mode if -o macvlan_mode is empty
		config.MacvlanMode = modeBridge
	case modePrivate:
		config.MacvlanMode = modePrivate
	case modePassthru:
		config.MacvlanMode = modePassthru
	case modeVepa:
		config.MacvlanMode = modeVepa
	default:
		return fmt.Errorf("requested macvlan mode '%s' is not valid, 'bridge' mode is the macvlan driver default", config.MacvlanMode)
	}
	// loopback is not a valid parent link
	if config.Parent == "lo" {
		return fmt.Errorf("loopback interface is not a valid %s parent link", macvlanType)
	}
	// if parent interface not specified, create a dummy type link to use named dummy+net_id
	if config.Parent == "" {
		config.Parent = getDummyName(stringid.TruncateID(config.ID))
	}
	foundExisting, err := d.createNetwork(config)
	if err != nil {
		return err
	}

	if foundExisting {
		return types.InternalMaskableErrorf("restoring existing network %s", config.ID)
	}

	// update persistent db, rollback on fail
	err = d.storeUpdate(config)
	if err != nil {
		d.deleteNetwork(config.ID)
		logrus.Debugf("encountered an error rolling back a network create for %s : %v", config.ID, err)
		return err
	}

	return nil
}

// createNetwork is used by new network callbacks and persistent network cache
func (d *driver) createNetwork(config *configuration) (bool, error) {
	foundExisting := false
	networkList := d.getNetworks()
	for _, nw := range networkList {
		if config.Parent == nw.config.Parent {
			if config.ID != nw.config.ID {
				return false, fmt.Errorf("network %s is already using parent interface %s",
					getDummyName(stringid.TruncateID(nw.config.ID)), config.Parent)
			}
			logrus.Debugf("Create Network for the same ID %s\n", config.ID)
			foundExisting = true
			break
		}
	}
	if !parentExists(config.Parent) {
		// Create a dummy link if a dummy name is set for parent
		if dummyName := getDummyName(stringid.TruncateID(config.ID)); dummyName == config.Parent {
			err := createDummyLink(config.Parent, dummyName)
			if err != nil {
				return false, err
			}
			config.CreatedSlaveLink = true
			// notify the user in logs that they have limited communications
			logrus.Debugf("Empty -o parent= limit communications to other containers inside of network: %s",
				config.Parent)
		} else {
			// if the subinterface parent_iface.vlan_id checks do not pass, return err.
			//  a valid example is 'eth0.10' for a parent iface 'eth0' with a vlan id '10'
			err := createVlanLink(config.Parent)
			if err != nil {
				return false, err
			}
			// if driver created the networks slave link, record it for future deletion
			config.CreatedSlaveLink = true
		}
	}
	if !foundExisting {
		n := &network{
			id:        config.ID,
			driver:    d,
			endpoints: endpointTable{},
			config:    config,
		}
		// add the network
		d.addNetwork(n)
	}

	return foundExisting, nil
}

// DeleteNetwork deletes the network for the specified driver type
func (d *driver) DeleteNetwork(nid string) error {
	defer osl.InitOSContext()()
	n := d.network(nid)
	if n == nil {
		return fmt.Errorf("network id %s not found", nid)
	}
	// if the driver created the slave interface, delete it, otherwise leave it
	if ok := n.config.CreatedSlaveLink; ok {
		// if the interface exists, only delete if it matches iface.vlan or dummy.net_id naming
		if ok := parentExists(n.config.Parent); ok {
			// only delete the link if it is named the net_id
			if n.config.Parent == getDummyName(stringid.TruncateID(nid)) {
				err := delDummyLink(n.config.Parent)
				if err != nil {
					logrus.Debugf("link %s was not deleted, continuing the delete network operation: %v",
						n.config.Parent, err)
				}
			} else {
				// only delete the link if it matches iface.vlan naming
				err := delVlanLink(n.config.Parent)
				if err != nil {
					logrus.Debugf("link %s was not deleted, continuing the delete network operation: %v",
						n.config.Parent, err)
				}
			}
		}
	}
	for _, ep := range n.endpoints {
		if link, err := ns.NlHandle().LinkByName(ep.srcName); err == nil {
			if err := ns.NlHandle().LinkDel(link); err != nil {
				logrus.WithError(err).Warnf("Failed to delete interface (%s)'s link on endpoint (%s) delete", ep.srcName, ep.id)
			}
		}

		if err := d.storeDelete(ep); err != nil {
			logrus.Warnf("Failed to remove macvlan endpoint %.7s from store: %v", ep.id, err)
		}
	}
	// delete the *network
	d.deleteNetwork(nid)
	// delete the network record from persistent cache
	err := d.storeDelete(n.config)
	if err != nil {
		return fmt.Errorf("error deleting deleting id %s from datastore: %v", nid, err)
	}
	return nil
}

// parseNetworkOptions parses docker network options
func parseNetworkOptions(id string, option options.Generic) (*configuration, error) {
	var (
		err    error
		config = &configuration{}
	)
	// parse generic labels first
	if genData, ok := option[netlabel.GenericData]; ok && genData != nil {
		if config, err = parseNetworkGenericOptions(genData); err != nil {
			return nil, err
		}
	}
	if val, ok := option[netlabel.Internal]; ok {
		if internal, ok := val.(bool); ok && internal {
			config.Internal = true
		}
	}
	config.ID = id
	return config, nil
}

// parseNetworkGenericOptions parses generic driver docker network options
func parseNetworkGenericOptions(data interface{}) (*configuration, error) {
	var (
		err    error
		config *configuration
	)
	switch opt := data.(type) {
	case *configuration:
		config = opt
	case map[string]string:
		config = &configuration{}
		err = config.fromOptions(opt)
	case options.Generic:
		var opaqueConfig interface{}
		if opaqueConfig, err = options.GenerateFromModel(opt, config); err == nil {
			config = opaqueConfig.(*configuration)
		}
	default:
		err = types.BadRequestErrorf("unrecognized network configuration format: %v", opt)
	}

	return config, err
}

// fromOptions binds the generic options to networkConfiguration to cache
func (config *configuration) fromOptions(labels map[string]string) error {
	for label, value := range labels {
		switch label {
		case parentOpt:
			// parse driver option '-o parent'
			config.Parent = value
		case driverModeOpt:
			// parse driver option '-o macvlan_mode'
			config.MacvlanMode = value
		}
	}

	return nil
}

// processIPAM parses v4 and v6 IP information and binds it to the network configuration
func (config *configuration) processIPAM(id string, ipamV4Data, ipamV6Data []driverapi.IPAMData) error {
	if len(ipamV4Data) > 0 {
		for _, ipd := range ipamV4Data {
			s := &ipSubnet{
				SubnetIP: ipd.Pool.String(),
				GwIP:     ipd.Gateway.String(),
			}
			config.Ipv4Subnets = append(config.Ipv4Subnets, s)
		}
	}
	if len(ipamV6Data) > 0 {
		for _, ipd := range ipamV6Data {
			s := &ipSubnet{
				SubnetIP: ipd.Pool.String(),
				GwIP:     ipd.Gateway.String(),
			}
			config.Ipv6Subnets = append(config.Ipv6Subnets, s)
		}
	}

	return nil
}
<|endoftext|>


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

package storage

import (
	"fmt"
	"testing"

	"github.com/cockroachdb/cockroach/client"
	"github.com/cockroachdb/cockroach/roachpb"
	"github.com/cockroachdb/cockroach/util"
	"github.com/cockroachdb/cockroach/util/leaktest"
	"github.com/coreos/etcd/raft"
	"github.com/coreos/etcd/raft/raftpb"
)

func TestGetQuorumMatchedIndex(t *testing.T) {
	defer leaktest.AfterTest(t)()

	testCases := []struct {
		commit   uint64
		progress []uint64
		padding  uint64
		expected uint64
	}{
		// Basic cases.
		{1, []uint64{1}, 0, 1},
		{1, []uint64{1, 2}, 0, 1},
		{2, []uint64{1, 2, 3}, 0, 2},
		{2, []uint64{1, 2, 3, 4}, 0, 2},
		{3, []uint64{1, 2, 3, 4, 5}, 0, 3},
		// Sorting.
		{3, []uint64{5, 4, 3, 2, 1}, 0, 3},
		// Padding.
		{3, []uint64{1, 3, 3}, 1, 2},
		{3, []uint64{1, 3, 3}, 2, 1},
		{3, []uint64{1, 3, 3}, 3, 1},
		// Minimum progress value limits padding.
		{3, []uint64{2, 3, 3}, 3, 2},
	}
	for i, c := range testCases {
		status := &raft.Status{
			HardState: raftpb.HardState{
				Commit: c.commit,
			},
			Progress: make(map[uint64]raft.Progress),
		}
		for j, v := range c.progress {
			status.Progress[uint64(j)] = raft.Progress{Match: v}
		}
		quorumMatchedIndex := getQuorumMatchedIndex(status, c.padding)
		if c.expected != quorumMatchedIndex {
			t.Fatalf("%d: expected %d, but got %d", i, c.expected, quorumMatchedIndex)
		}
	}
}

// TestGetTruncatableIndexes verifies that the correctly returns when there are
// indexes to be truncated.
func TestGetTruncatableIndexes(t *testing.T) {
	defer leaktest.AfterTest(t)()
	store, _, stopper := createTestStore(t)
	defer stopper.Stop()
	if _, err := store.GetReplica(0); err == nil {
		t.Error("expected GetRange to fail on missing range")
	}

	store.DisableRaftLogQueue(true)

	// Test on a new range which should not have a raft group yet.
	rngNew := createRange(store, 100, roachpb.RKey("a"), roachpb.RKey("c"))
	truncatableIndexes, oldestIndex, err := getTruncatableIndexes(rngNew)
	if err != nil {
		t.Errorf("expected no error, got %s", err)
	}
	if truncatableIndexes != 0 {
		t.Errorf("expected 0 for truncatable index, got %d", truncatableIndexes)
	}
	if oldestIndex != 0 {
		t.Errorf("expected 0 for oldest index, got %d", oldestIndex)
	}

	r, err := store.GetReplica(1)
	if err != nil {
		t.Error(err)
	}

	r.mu.Lock()
	firstIndex, err := r.FirstIndex()
	r.mu.Unlock()
	if err != nil {
		t.Error(err)
	}

	// Write a few keys to the range.
	for i := 0; i < 10; i++ {
		key := roachpb.Key(fmt.Sprintf("key%02d", i))
		args := putArgs(key, []byte(fmt.Sprintf("value%02d", i)))
		if _, err := client.SendWrapped(store.testSender(), nil, &args); err != nil {
			t.Fatal(err)
		}
	}

	truncatableIndexes, oldestIndex, err = getTruncatableIndexes(r)
	if err != nil {
		t.Errorf("expected no error, got %s", err)
	}
	if truncatableIndexes == 0 {
		t.Errorf("expected a value for truncatable index, got 0")
	}
	if oldestIndex < firstIndex {
		t.Errorf("expected oldest index (%d) to be greater than or equal to first index (%d)", oldestIndex,
			firstIndex)
	}

	// Enable the raft log scanner and and force a truncation.
	store.DisableRaftLogQueue(false)
	store.ForceRaftLogScanAndProcess()
	// Wait for tasks to finish, in case the processLoop grabbed the event
	// before ForceRaftLogScanAndProcess but is still working on it.
	stopper.Quiesce()

	r.mu.Lock()
	newFirstIndex, err := r.FirstIndex()
	r.mu.Unlock()
	if err != nil {
		t.Fatal(err)
	}

	if newFirstIndex <= firstIndex {
		t.Errorf("log was not correctly truncated, older first index:%d, current first index:%d", firstIndex,
			newFirstIndex)
	}

	// Once truncated, we should have no truncatable indexes. If this turns out
	// to be flaky, we can remove it as the same functionality is tested in
	// client_raft_log_queue_test.
	util.SucceedsSoon(t, func() error {
		store.ForceRaftLogScanAndProcess()
		truncatableIndexes, oldestIndex, err := getTruncatableIndexes(rngNew)
		if err != nil {
			return util.Errorf("expected no error, got %s", err)
		}
		if truncatableIndexes != 0 {
			return util.Errorf("expected 0 for truncatable index, got %d", truncatableIndexes)
		}
		if oldestIndex != 0 {
			return util.Errorf("expected 0 for oldest index, got %d", oldestIndex)
		}
		return nil
	})
}
<commit_msg>storage: skip flaky test<commit_after>// Copyright 2016 The Cockroach Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License.
//
// Author: Bram Gruneir (bram+code@cockroachlabs.com)

package storage

import (
	"fmt"
	"testing"

	"github.com/cockroachdb/cockroach/client"
	"github.com/cockroachdb/cockroach/roachpb"
	"github.com/cockroachdb/cockroach/util"
	"github.com/cockroachdb/cockroach/util/leaktest"
	"github.com/coreos/etcd/raft"
	"github.com/coreos/etcd/raft/raftpb"
)

func TestGetQuorumMatchedIndex(t *testing.T) {
	defer leaktest.AfterTest(t)()

	testCases := []struct {
		commit   uint64
		progress []uint64
		padding  uint64
		expected uint64
	}{
		// Basic cases.
		{1, []uint64{1}, 0, 1},
		{1, []uint64{1, 2}, 0, 1},
		{2, []uint64{1, 2, 3}, 0, 2},
		{2, []uint64{1, 2, 3, 4}, 0, 2},
		{3, []uint64{1, 2, 3, 4, 5}, 0, 3},
		// Sorting.
		{3, []uint64{5, 4, 3, 2, 1}, 0, 3},
		// Padding.
		{3, []uint64{1, 3, 3}, 1, 2},
		{3, []uint64{1, 3, 3}, 2, 1},
		{3, []uint64{1, 3, 3}, 3, 1},
		// Minimum progress value limits padding.
		{3, []uint64{2, 3, 3}, 3, 2},
	}
	for i, c := range testCases {
		status := &raft.Status{
			HardState: raftpb.HardState{
				Commit: c.commit,
			},
			Progress: make(map[uint64]raft.Progress),
		}
		for j, v := range c.progress {
			status.Progress[uint64(j)] = raft.Progress{Match: v}
		}
		quorumMatchedIndex := getQuorumMatchedIndex(status, c.padding)
		if c.expected != quorumMatchedIndex {
			t.Fatalf("%d: expected %d, but got %d", i, c.expected, quorumMatchedIndex)
		}
	}
}

// TestGetTruncatableIndexes verifies that the correctly returns when there are
// indexes to be truncated.
func TestGetTruncatableIndexes(t *testing.T) {
	defer leaktest.AfterTest(t)()
	t.Skip("TODO(bram): #7056")
	store, _, stopper := createTestStore(t)
	defer stopper.Stop()
	if _, err := store.GetReplica(0); err == nil {
		t.Error("expected GetRange to fail on missing range")
	}

	store.DisableRaftLogQueue(true)

	// Test on a new range which should not have a raft group yet.
	rngNew := createRange(store, 100, roachpb.RKey("a"), roachpb.RKey("c"))
	truncatableIndexes, oldestIndex, err := getTruncatableIndexes(rngNew)
	if err != nil {
		t.Errorf("expected no error, got %s", err)
	}
	if truncatableIndexes != 0 {
		t.Errorf("expected 0 for truncatable index, got %d", truncatableIndexes)
	}
	if oldestIndex != 0 {
		t.Errorf("expected 0 for oldest index, got %d", oldestIndex)
	}

	r, err := store.GetReplica(1)
	if err != nil {
		t.Error(err)
	}

	r.mu.Lock()
	firstIndex, err := r.FirstIndex()
	r.mu.Unlock()
	if err != nil {
		t.Error(err)
	}

	// Write a few keys to the range.
	for i := 0; i < 10; i++ {
		key := roachpb.Key(fmt.Sprintf("key%02d", i))
		args := putArgs(key, []byte(fmt.Sprintf("value%02d", i)))
		if _, err := client.SendWrapped(store.testSender(), nil, &args); err != nil {
			t.Fatal(err)
		}
	}

	truncatableIndexes, oldestIndex, err = getTruncatableIndexes(r)
	if err != nil {
		t.Errorf("expected no error, got %s", err)
	}
	if truncatableIndexes == 0 {
		t.Errorf("expected a value for truncatable index, got 0")
	}
	if oldestIndex < firstIndex {
		t.Errorf("expected oldest index (%d) to be greater than or equal to first index (%d)", oldestIndex,
			firstIndex)
	}

	// Enable the raft log scanner and and force a truncation.
	store.DisableRaftLogQueue(false)
	store.ForceRaftLogScanAndProcess()
	// Wait for tasks to finish, in case the processLoop grabbed the event
	// before ForceRaftLogScanAndProcess but is still working on it.
	stopper.Quiesce()

	r.mu.Lock()
	newFirstIndex, err := r.FirstIndex()
	r.mu.Unlock()
	if err != nil {
		t.Fatal(err)
	}

	if newFirstIndex <= firstIndex {
		t.Errorf("log was not correctly truncated, older first index:%d, current first index:%d", firstIndex,
			newFirstIndex)
	}

	// Once truncated, we should have no truncatable indexes. If this turns out
	// to be flaky, we can remove it as the same functionality is tested in
	// client_raft_log_queue_test.
	util.SucceedsSoon(t, func() error {
		store.ForceRaftLogScanAndProcess()
		truncatableIndexes, oldestIndex, err := getTruncatableIndexes(rngNew)
		if err != nil {
			return util.Errorf("expected no error, got %s", err)
		}
		if truncatableIndexes != 0 {
			return util.Errorf("expected 0 for truncatable index, got %d", truncatableIndexes)
		}
		if oldestIndex != 0 {
			return util.Errorf("expected 0 for oldest index, got %d", oldestIndex)
		}
		return nil
	})
}
<|endoftext|>


<commit_before>package search

import (
	"encoding/json"
	"fmt"
	"reflect"
	"strings"

	"github.com/algolia/algoliasearch-client-go/algolia/internal/opt"
)

type searchReq struct {
	Params string `json:"params"`
}

type searchParams struct {
	Query string `json:"query"`
	QueryParams
	ExtraParams map[string]interface{} `json:"-"`
}

func (p searchParams) MarshalJSON() ([]byte, error) {

	// First, if there is no extra parameter, the structure is
	// serialized as-is, using a type alias to avoid infinite
	// recursion of MarshalJSON calls.

	if len(p.ExtraParams) == 0 {
		type searchParamsAlias searchParams
		return json.Marshal(searchParamsAlias(p))
	}

	// By there, because we do have extra search parameters, it
	// is needed to flatten them in the same JSON payload, along
	// with the known ones.
	//
	// To do that, we create a new type at runtime using the reflect
	// package and populate it with:
	//
	//   1. the known fields: "query" + any other fields from
	//      QueryParams if they are present
	//   2. the unknown fields from the ExtraParams map
	//
	// Once the new type has been created, we will it with the
	// actual values from the initial searchParams.

	var fields []reflect.StructField

	t := reflect.TypeOf(p)
	for i := 0; i < t.NumField(); i++ {
		fields = append(fields, t.Field(i))
	}

	for k, v := range p.ExtraParams {
		fields = append(fields, reflect.StructField{
			Name: strings.ToTitle(k),
			Type: reflect.TypeOf(v),
			Tag:  reflect.StructTag(fmt.Sprintf(`json:"%s"`, k)),
		})
	}

	e := reflect.New(reflect.StructOf(fields)).Elem()
	e.FieldByName("Query").Set(reflect.ValueOf(p.Query))
	e.FieldByName("QueryParams").Set(reflect.ValueOf(p.QueryParams))
	for k, v := range p.ExtraParams {
		e.FieldByName(strings.ToTitle(k)).Set(reflect.ValueOf(v))
	}

	return json.Marshal(e.Interface())
}

func newSearchParams(query string, opts ...interface{}) searchParams {
	return searchParams{
		Query:       query,
		QueryParams: newQueryParams(opts...),
		ExtraParams: opt.ExtractExtraOptions(opts...).Get(),
	}
}

type searchForFacetValuesParams struct {
	FacetQuery string `json:"facetQuery"`
	QueryParams
}

func newSearchForFacetValuesParams(query string, opts ...interface{}) searchForFacetValuesParams {
	return searchForFacetValuesParams{
		FacetQuery:  query,
		QueryParams: newQueryParams(opts...),
	}
}
<commit_msg>doc: add missing word in comment<commit_after>package search

import (
	"encoding/json"
	"fmt"
	"reflect"
	"strings"

	"github.com/algolia/algoliasearch-client-go/algolia/internal/opt"
)

type searchReq struct {
	Params string `json:"params"`
}

type searchParams struct {
	Query string `json:"query"`
	QueryParams
	ExtraParams map[string]interface{} `json:"-"`
}

func (p searchParams) MarshalJSON() ([]byte, error) {

	// First, if there is no extra parameter, the structure is
	// serialized as-is, using a type alias to avoid infinite
	// recursion of MarshalJSON calls.

	if len(p.ExtraParams) == 0 {
		type searchParamsAlias searchParams
		return json.Marshal(searchParamsAlias(p))
	}

	// By there, because we do have extra search parameters, it
	// is needed to flatten them in the same JSON payload, along
	// with the known ones.
	//
	// To do that, we create a new type at runtime using the reflect
	// package and populate it with:
	//
	//   1. the known fields: "query" + any other fields from
	//      QueryParams if they are present
	//   2. the unknown fields from the ExtraParams map
	//
	// Once the new type has been created, we will populate it with the
	// actual values from the initial searchParams.

	var fields []reflect.StructField

	t := reflect.TypeOf(p)
	for i := 0; i < t.NumField(); i++ {
		fields = append(fields, t.Field(i))
	}

	for k, v := range p.ExtraParams {
		fields = append(fields, reflect.StructField{
			Name: strings.ToTitle(k),
			Type: reflect.TypeOf(v),
			Tag:  reflect.StructTag(fmt.Sprintf(`json:"%s"`, k)),
		})
	}

	e := reflect.New(reflect.StructOf(fields)).Elem()
	e.FieldByName("Query").Set(reflect.ValueOf(p.Query))
	e.FieldByName("QueryParams").Set(reflect.ValueOf(p.QueryParams))
	for k, v := range p.ExtraParams {
		e.FieldByName(strings.ToTitle(k)).Set(reflect.ValueOf(v))
	}

	return json.Marshal(e.Interface())
}

func newSearchParams(query string, opts ...interface{}) searchParams {
	return searchParams{
		Query:       query,
		QueryParams: newQueryParams(opts...),
		ExtraParams: opt.ExtractExtraOptions(opts...).Get(),
	}
}

type searchForFacetValuesParams struct {
	FacetQuery string `json:"facetQuery"`
	QueryParams
}

func newSearchForFacetValuesParams(query string, opts ...interface{}) searchForFacetValuesParams {
	return searchForFacetValuesParams{
		FacetQuery:  query,
		QueryParams: newQueryParams(opts...),
	}
}
<|endoftext|>


<commit_before>/* walter: a deployment pipeline template
* Copyright (C) 2014 Recruit Technologies Co., Ltd. and contributors
* (see CONTRIBUTORS.md)
*
* 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 walter

import (
	"os/exec"
	"reflect"
	"strconv"
	"time"

	"github.com/google/go-github/github"
	"github.com/recruit-tech/walter/config"
	"github.com/recruit-tech/walter/engine"
	"github.com/recruit-tech/walter/log"
	"github.com/recruit-tech/walter/services"
	"github.com/recruit-tech/walter/stages"
)

type Walter struct {
	Engine *engine.Engine
	Opts   *config.Opts
}

func New(opts *config.Opts) (*Walter, error) {
	configData := config.ReadConfig(opts.PipelineFilePath)
	resources, err := config.Parse(configData)
	if err != nil {
		return nil, err
	}
	monitorCh := make(chan stages.Mediator)
	engine := &engine.Engine{
		Resources: resources,
		Opts:      opts,
		MonitorCh: &monitorCh,
	}
	return &Walter{
		Opts:   opts,
		Engine: engine,
	}, nil
}

func (e *Walter) Run() bool {
	repoServiceValue := reflect.ValueOf(e.Engine.Resources.RepoService)
	if e.Engine.Opts.Mode == "local" ||
		repoServiceValue.Type().String() == "*services.LocalClient" {
		log.Info("Starting Walter in local mode")
		result := e.Engine.RunOnce()
		return result.IsSucceeded()
	} else {
		log.Info("Starting Walter in repository service mode")
		return e.runService()
	}
}

func (e *Walter) runService() bool {
	// load .walter-update
	log.Infof("Loading update file... \"%s\"", e.Engine.Resources.RepoService.GetUpdateFilePath())
	update, err := services.LoadLastUpdate(e.Engine.Resources.RepoService.GetUpdateFilePath())
	log.Infof("Succeeded loading update file")

	log.Info("Updating status...")
	update.Status = "inprogress"
	result := services.SaveLastUpdate(e.Engine.Resources.RepoService.GetUpdateFilePath(), update)
	if result == false {
		log.Error("Failed to save status update")
		return false
	}
	log.Info("Succeeded updating status")

	// get latest commit and pull requests
	log.Info("downloading commits and pull requests...")
	commits, err := e.Engine.Resources.RepoService.GetCommits(update)
	if err != nil {
		log.Errorf("Failed getting commits: %s", err)
		return false
	}

	log.Info("Succeeded getting commits")
	log.Info("Size of commits: " + strconv.Itoa(commits.Len()))
	is_failed_process := false
	for commit := commits.Front(); commit != nil; commit = commit.Next() {
		commitType := reflect.TypeOf(commit.Value)
		if commitType.Name() == "RepositoryCommit" {
			log.Info("Found new repository commit")
			trunkCommit := commit.Value.(github.RepositoryCommit)
			if result := e.processTrunkCommit(trunkCommit); result == false {
				is_failed_process = true
			}
		} else if commitType.Name() == "PullRequest" {
			log.Info("Found new pull request commit")
			pullreq := commit.Value.(github.PullRequest)
			if result := e.processPullRequest(pullreq); result == false {
				is_failed_process = true
			}
		} else {
			log.Errorf("Nothing commit type: %s", commitType)
			is_failed_process = true
		}
	}

	// save .walter-update
	log.Info("Saving update file...")
	update.Status = "finished"
	update.Time = time.Now()
	result = services.SaveLastUpdate(e.Engine.Resources.RepoService.GetUpdateFilePath(), update)
	if result == false {
		log.Error("Failed to save update")
		return false
	}
	return !is_failed_process
}

func (e *Walter) processTrunkCommit(commit github.RepositoryCommit) bool {
	log.Infof("Checkout master branch")
	_, err := exec.Command("git", "checkout", "master", "-f").Output()
	if err != nil {
		log.Errorf("Failed to checkout master branch: %s", err)
		return false
	}
	log.Infof("Downloading new commit from master")
	_, err = exec.Command("git", "pull", "origin", "master").Output()
	if err != nil {
		log.Errorf("Failed to download new commit from master: %s", err)
		return false
	}
	log.Infof("Running the latest commit in master")
	w, _ := New(e.Opts)
	result := w.Engine.RunOnce()

	// register the result to hosting service
	if result.IsSucceeded() {
		log.Info("Succeeded.")
		e.Engine.Resources.RepoService.RegisterResult(
			services.Result{
				State:   "success",
				Message: "Succeeded running pipeline...",
				SHA:     *commit.SHA})
		return true
	} else {
		log.Error("Error reported...")
		e.Engine.Resources.RepoService.RegisterResult(
			services.Result{
				State:   "failure",
				Message: "Failed running pipleline ...",
				SHA:     *commit.SHA})
		return false
	}
}

func (e *Walter) processPullRequest(pullrequest github.PullRequest) bool {
	// checkout pullrequest
	num := *pullrequest.Number
	_, err := exec.Command("git", "fetch", "origin", "refs/pull/"+strconv.Itoa(num)+"/head:pr_"+strconv.Itoa(num)).Output()

	defer exec.Command("git", "checkout", "master", "-f").Output() // TODO: make trunk branch configurable
	defer log.Info("returning master branch...")

	if err != nil {
		log.Errorf("Failed to fetch pull request: %s", err)
		return false
	}

	_, err = exec.Command("git", "checkout", "pr_"+strconv.Itoa(num)).Output()
	if err != nil {
		log.Errorf("Failed to checkout pullrequest branch (\"%s\") : %s", "pr_"+strconv.Itoa(num), err)
		return false
	}

	// run pipeline
	log.Info("Running pipeline...")
	w, _ := New(e.Opts)
	result := w.Engine.RunOnce()

	// register the result to hosting service
	if result.IsSucceeded() {
		log.Info("succeeded.")
		e.Engine.Resources.RepoService.RegisterResult(
			services.Result{
				State:   "success",
				Message: "Succeeded running pipeline...",
				SHA:     *pullrequest.Head.SHA})
		return true
	} else {
		log.Error("Error reported...")
		e.Engine.Resources.RepoService.RegisterResult(
			services.Result{
				State:   "failure",
				Message: "Failed running pipleline ...",
				SHA:     *pullrequest.Head.SHA})
		return false
	}
}
<commit_msg>Rename a variable from is_failed_process to has_failed_process<commit_after>/* walter: a deployment pipeline template
* Copyright (C) 2014 Recruit Technologies Co., Ltd. and contributors
* (see CONTRIBUTORS.md)
*
* 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 walter

import (
	"os/exec"
	"reflect"
	"strconv"
	"time"

	"github.com/google/go-github/github"
	"github.com/recruit-tech/walter/config"
	"github.com/recruit-tech/walter/engine"
	"github.com/recruit-tech/walter/log"
	"github.com/recruit-tech/walter/services"
	"github.com/recruit-tech/walter/stages"
)

type Walter struct {
	Engine *engine.Engine
	Opts   *config.Opts
}

func New(opts *config.Opts) (*Walter, error) {
	configData := config.ReadConfig(opts.PipelineFilePath)
	resources, err := config.Parse(configData)
	if err != nil {
		return nil, err
	}
	monitorCh := make(chan stages.Mediator)
	engine := &engine.Engine{
		Resources: resources,
		Opts:      opts,
		MonitorCh: &monitorCh,
	}
	return &Walter{
		Opts:   opts,
		Engine: engine,
	}, nil
}

func (e *Walter) Run() bool {
	repoServiceValue := reflect.ValueOf(e.Engine.Resources.RepoService)
	if e.Engine.Opts.Mode == "local" ||
		repoServiceValue.Type().String() == "*services.LocalClient" {
		log.Info("Starting Walter in local mode")
		result := e.Engine.RunOnce()
		return result.IsSucceeded()
	} else {
		log.Info("Starting Walter in repository service mode")
		return e.runService()
	}
}

func (e *Walter) runService() bool {
	// load .walter-update
	log.Infof("Loading update file... \"%s\"", e.Engine.Resources.RepoService.GetUpdateFilePath())
	update, err := services.LoadLastUpdate(e.Engine.Resources.RepoService.GetUpdateFilePath())
	log.Infof("Succeeded loading update file")

	log.Info("Updating status...")
	update.Status = "inprogress"
	result := services.SaveLastUpdate(e.Engine.Resources.RepoService.GetUpdateFilePath(), update)
	if result == false {
		log.Error("Failed to save status update")
		return false
	}
	log.Info("Succeeded updating status")

	// get latest commit and pull requests
	log.Info("downloading commits and pull requests...")
	commits, err := e.Engine.Resources.RepoService.GetCommits(update)
	if err != nil {
		log.Errorf("Failed getting commits: %s", err)
		return false
	}

	log.Info("Succeeded getting commits")
	log.Info("Size of commits: " + strconv.Itoa(commits.Len()))
	has_failed_process := false
	for commit := commits.Front(); commit != nil; commit = commit.Next() {
		commitType := reflect.TypeOf(commit.Value)
		if commitType.Name() == "RepositoryCommit" {
			log.Info("Found new repository commit")
			trunkCommit := commit.Value.(github.RepositoryCommit)
			if result := e.processTrunkCommit(trunkCommit); result == false {
				has_failed_process = true
			}
		} else if commitType.Name() == "PullRequest" {
			log.Info("Found new pull request commit")
			pullreq := commit.Value.(github.PullRequest)
			if result := e.processPullRequest(pullreq); result == false {
				has_failed_process = true
			}
		} else {
			log.Errorf("Nothing commit type: %s", commitType)
			has_failed_process = true
		}
	}

	// save .walter-update
	log.Info("Saving update file...")
	update.Status = "finished"
	update.Time = time.Now()
	result = services.SaveLastUpdate(e.Engine.Resources.RepoService.GetUpdateFilePath(), update)
	if result == false {
		log.Error("Failed to save update")
		return false
	}
	return !has_failed_process
}

func (e *Walter) processTrunkCommit(commit github.RepositoryCommit) bool {
	log.Infof("Checkout master branch")
	_, err := exec.Command("git", "checkout", "master", "-f").Output()
	if err != nil {
		log.Errorf("Failed to checkout master branch: %s", err)
		return false
	}
	log.Infof("Downloading new commit from master")
	_, err = exec.Command("git", "pull", "origin", "master").Output()
	if err != nil {
		log.Errorf("Failed to download new commit from master: %s", err)
		return false
	}
	log.Infof("Running the latest commit in master")
	w, _ := New(e.Opts)
	result := w.Engine.RunOnce()

	// register the result to hosting service
	if result.IsSucceeded() {
		log.Info("Succeeded.")
		e.Engine.Resources.RepoService.RegisterResult(
			services.Result{
				State:   "success",
				Message: "Succeeded running pipeline...",
				SHA:     *commit.SHA})
		return true
	} else {
		log.Error("Error reported...")
		e.Engine.Resources.RepoService.RegisterResult(
			services.Result{
				State:   "failure",
				Message: "Failed running pipleline ...",
				SHA:     *commit.SHA})
		return false
	}
}

func (e *Walter) processPullRequest(pullrequest github.PullRequest) bool {
	// checkout pullrequest
	num := *pullrequest.Number
	_, err := exec.Command("git", "fetch", "origin", "refs/pull/"+strconv.Itoa(num)+"/head:pr_"+strconv.Itoa(num)).Output()

	defer exec.Command("git", "checkout", "master", "-f").Output() // TODO: make trunk branch configurable
	defer log.Info("returning master branch...")

	if err != nil {
		log.Errorf("Failed to fetch pull request: %s", err)
		return false
	}

	_, err = exec.Command("git", "checkout", "pr_"+strconv.Itoa(num)).Output()
	if err != nil {
		log.Errorf("Failed to checkout pullrequest branch (\"%s\") : %s", "pr_"+strconv.Itoa(num), err)
		return false
	}

	// run pipeline
	log.Info("Running pipeline...")
	w, _ := New(e.Opts)
	result := w.Engine.RunOnce()

	// register the result to hosting service
	if result.IsSucceeded() {
		log.Info("succeeded.")
		e.Engine.Resources.RepoService.RegisterResult(
			services.Result{
				State:   "success",
				Message: "Succeeded running pipeline...",
				SHA:     *pullrequest.Head.SHA})
		return true
	} else {
		log.Error("Error reported...")
		e.Engine.Resources.RepoService.RegisterResult(
			services.Result{
				State:   "failure",
				Message: "Failed running pipleline ...",
				SHA:     *pullrequest.Head.SHA})
		return false
	}
}
<|endoftext|>


<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// Contributor: Aaron Meihm ameihm@mozilla.com [:alm]

package main

import (
	"fmt"
	"github.com/jvehent/service-go"
	"mig.ninja/mig"
	"runtime"
)

const runInterval = 900

type Context struct {
	AgentIdentifier mig.Agent
	LoaderKey       string

	Channels struct {
		Log chan mig.Log
	}
	Logging mig.Logging
}

func getLoggingConf() (ret mig.Logging, err error) {
	if runtime.GOOS == "linux" || runtime.GOOS == "darwin" {
		return getLoggingConfPosix()
	}
	err = fmt.Errorf("unable to obtain logging configuration for platform")
	return
}

func getLoggingConfPosix() (ret mig.Logging, err error) {
	ret.Mode = "file"
	ret.Level = "info"
	ret.File = "/var/log/mig-loader.log"
	ret.MaxFileSize = 10485760
	return
}

func serviceDeployInterval() error {
	svc, err := service.NewService("mig-loader", "MIG Loader", "Mozilla InvestiGator Loader")
	if err != nil {
		return err
	}
	err = svc.IntervalMode(runInterval)
	if err != nil {
		return err
	}
	// Ignore errors from stop and remove, as it may not be installed yet
	svc.Stop()
	svc.Remove()
	err = svc.Install()
	if err != nil {
		return err
	}
	err = svc.Start()
	if err != nil {
		return err
	}
	return nil
}

func serviceDeploy() error {
	// We deploy the loader as a launchd interval job on OSX, so only
	// target this platform here.
	if runtime.GOOS != "darwin" {
		return nil
	}
	return serviceDeployInterval()
}
<commit_msg>[minor] update Darwin default launchd RunInterval<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// Contributor: Aaron Meihm ameihm@mozilla.com [:alm]

package main

import (
	"fmt"
	"github.com/jvehent/service-go"
	"mig.ninja/mig"
	"runtime"
)

const runInterval = 7200

type Context struct {
	AgentIdentifier mig.Agent
	LoaderKey       string

	Channels struct {
		Log chan mig.Log
	}
	Logging mig.Logging
}

func getLoggingConf() (ret mig.Logging, err error) {
	if runtime.GOOS == "linux" || runtime.GOOS == "darwin" {
		return getLoggingConfPosix()
	}
	err = fmt.Errorf("unable to obtain logging configuration for platform")
	return
}

func getLoggingConfPosix() (ret mig.Logging, err error) {
	ret.Mode = "file"
	ret.Level = "info"
	ret.File = "/var/log/mig-loader.log"
	ret.MaxFileSize = 10485760
	return
}

func serviceDeployInterval() error {
	svc, err := service.NewService("mig-loader", "MIG Loader", "Mozilla InvestiGator Loader")
	if err != nil {
		return err
	}
	err = svc.IntervalMode(runInterval)
	if err != nil {
		return err
	}
	// Ignore errors from stop and remove, as it may not be installed yet
	svc.Stop()
	svc.Remove()
	err = svc.Install()
	if err != nil {
		return err
	}
	err = svc.Start()
	if err != nil {
		return err
	}
	return nil
}

func serviceDeploy() error {
	// We deploy the loader as a launchd interval job on OSX, so only
	// target this platform here.
	if runtime.GOOS != "darwin" {
		return nil
	}
	return serviceDeployInterval()
}
<|endoftext|>


<commit_before>package migration

import (
	"fmt"
	"os"
	"path"
	"strings"
	"time"

	"github.com/nicday/turtle/db"
)

const (
	timeFormat   = "20060102150405.000"
	migrationDir = "migrations"
)

// Generate creates up and down migration files.
func Generate(name string) error {
	assertMigrationDir()

	baseFilename := fmt.Sprintf("%s_%s", timestamp(), name)

	for _, direction := range []string{"up", "down"} {
		filename := fmt.Sprintf("%s_%s.sql", baseFilename, direction)
		createMigrationFile(filename)
	}

	return nil
}

// createMigrationFile creates the migration file in the migration directory.
func createMigrationFile(name string) error {
	_, err := os.Create(path.Join(db.MigrationsPath, name))
	if err != nil {
		fmt.Println(err)
		return err
	}

	return nil
}

// assertMigrationDir ensures that the migration direction exists and raises an error if it cannot be created.
func assertMigrationDir() error {
	_, err := os.Stat(db.MigrationsPath)
	if err != nil {
		err := os.Mkdir(db.MigrationsPath, 0755)
		if err != nil {
			return err
		}
	}
	return nil
}

// timestamp returns a timestamp with millisecond accuracy and no decimal place.
func timestamp() string {
	t := time.Now().Format(timeFormat)
	return strings.Replace(t, ".", "", 1)
}
<commit_msg>Remove old migrationDir var<commit_after>package migration

import (
	"fmt"
	"os"
	"path"
	"strings"
	"time"

	"github.com/nicday/turtle/db"
)

const (
	timeFormat = "20060102150405.000"
)

// Generate creates up and down migration files.
func Generate(name string) error {
	assertMigrationDir()

	baseFilename := fmt.Sprintf("%s_%s", timestamp(), name)

	for _, direction := range []string{"up", "down"} {
		filename := fmt.Sprintf("%s_%s.sql", baseFilename, direction)
		createMigrationFile(filename)
	}

	return nil
}

// createMigrationFile creates the migration file in the migration directory.
func createMigrationFile(name string) error {
	_, err := os.Create(path.Join(db.MigrationsPath, name))
	if err != nil {
		fmt.Println(err)
		return err
	}

	return nil
}

// assertMigrationDir ensures that the migration direction exists and raises an error if it cannot be created.
func assertMigrationDir() error {
	_, err := os.Stat(db.MigrationsPath)
	if err != nil {
		err := os.Mkdir(db.MigrationsPath, 0755)
		if err != nil {
			return err
		}
	}
	return nil
}

// timestamp returns a timestamp with millisecond accuracy and no decimal place.
func timestamp() string {
	t := time.Now().Format(timeFormat)
	return strings.Replace(t, ".", "", 1)
}
<|endoftext|>


<commit_before>// +build integration

/*
Copyright 2016 The Kubernetes Authors 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 integration

import (
	"fmt"
	"net"
	"strings"
	"testing"
	"time"

	"github.com/docker/machine/libmachine/state"
	"k8s.io/minikube/pkg/minikube/constants"
	"k8s.io/minikube/test/integration/util"
)

func TestStartStop(t *testing.T) {
	tests := []struct {
		name string
		args []string
	}{
		{"docker+no-cache+oldest", []string{
			"--container-runtime=docker",
			"--cache-images=false",
			fmt.Sprintf("--kubernetes-version=%s", constants.OldestKubernetesVersion),
		}},
		{"docker+ignore_verifications+newest+gates", []string{
			"--container-runtime=docker",
			"--extra-config",
			"kubeadm.ignore-preflight-errors=SystemVerification",
			"--feature-gates",
			fmt.Sprintf("--kubernetes-version=%s", constants.NewestKubernetesVersion),
		}},
		{"containerd", []string{
			"--container-runtime=containerd",
			"--docker-opt containerd=/var/run/containerd/containerd.sock",
		}},
		{"crio", []string{
			"--container-runtime=crio",
		}},
	}

	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			r := NewMinikubeRunner(t)
			if !strings.Contains(test.name, "docker") && usingNoneDriver(r) {
				t.Skipf("skipping %s - incompatible with none driver", test.name)
			}

			r.RunCommand("config set WantReportErrorPrompt false", true)
			r.RunCommand("delete", false)
			r.CheckStatus(state.None.String())
			r.Start(test.args...)
			r.CheckStatus(state.Running.String())

			ip := r.RunCommand("ip", true)
			ip = strings.TrimRight(ip, "\n")
			if net.ParseIP(ip) == nil {
				t.Fatalf("IP command returned an invalid address: %s", ip)
			}

			checkStop := func() error {
				r.RunCommand("stop", true)
				return r.CheckStatusNoFail(state.Stopped.String())
			}

			if err := util.Retry(t, checkStop, 5*time.Second, 6); err != nil {
				t.Fatalf("timed out while checking stopped status: %v", err)
			}

			r.Start(test.args...)
			r.CheckStatus(state.Running.String())

			r.RunCommand("delete", true)
			r.CheckStatus(state.None.String())
		})
	}
}
<commit_msg>Fix invalid feature-gates argument<commit_after>// +build integration

/*
Copyright 2016 The Kubernetes Authors 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 integration

import (
	"fmt"
	"net"
	"strings"
	"testing"
	"time"

	"github.com/docker/machine/libmachine/state"
	"k8s.io/minikube/pkg/minikube/constants"
	"k8s.io/minikube/test/integration/util"
)

func TestStartStop(t *testing.T) {
	tests := []struct {
		name string
		args []string
	}{
		{"nocache_oldest", []string{
			"--cache-images=false",
			fmt.Sprintf("--kubernetes-version=%s", constants.OldestKubernetesVersion),
		}},
		{"feature_gates_newest", []string{
			"--feature-gates",
			"ServerSideApply=true",
			fmt.Sprintf("--kubernetes-version=%s", constants.NewestKubernetesVersion),
		}},
		{"containerd", []string{
			"--container-runtime=containerd",
			"--docker-opt containerd=/var/run/containerd/containerd.sock",
		}},
		{"crio_ignore_preflights", []string{
			"--container-runtime=crio",
			"--extra-config",
			"kubeadm.ignore-preflight-errors=SystemVerification",
		}},
	}

	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			r := NewMinikubeRunner(t)
			if !strings.Contains(test.name, "docker") && usingNoneDriver(r) {
				t.Skipf("skipping %s - incompatible with none driver", test.name)
			}

			r.RunCommand("config set WantReportErrorPrompt false", true)
			r.RunCommand("delete", false)
			r.CheckStatus(state.None.String())
			r.Start(test.args...)
			r.CheckStatus(state.Running.String())

			ip := r.RunCommand("ip", true)
			ip = strings.TrimRight(ip, "\n")
			if net.ParseIP(ip) == nil {
				t.Fatalf("IP command returned an invalid address: %s", ip)
			}

			checkStop := func() error {
				r.RunCommand("stop", true)
				return r.CheckStatusNoFail(state.Stopped.String())
			}

			if err := util.Retry(t, checkStop, 5*time.Second, 6); err != nil {
				t.Fatalf("timed out while checking stopped status: %v", err)
			}

			r.Start(test.args...)
			r.CheckStatus(state.Running.String())

			r.RunCommand("delete", true)
			r.CheckStatus(state.None.String())
		})
	}
}
<|endoftext|>


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

package testclock

import (
	"context"
	"fmt"
	"testing"
	"time"

	"go.chromium.org/luci/common/clock"

	. "github.com/smartystreets/goconvey/convey"
)

func ExampleFastClock() {
	// New clock running 1M times faster than wall clock.
	clk := NewFastClock(TestRecentTimeUTC, 1000*1000)
	defer clk.Close()
	ctx := clock.Set(context.Background(), clk)
	wallStart := time.Now()
	t := clock.NewTimer(ctx)
	t.Reset(time.Hour)
	<-t.GetC()
	if wallTook := time.Since(wallStart); wallTook <= 10*time.Second {
		fmt.Printf("took less than 10 seconds\n")
		// Output: took less than 10 seconds
	} else {
		fmt.Printf("took %s, either due to a bug or CPU starvation\n", wallTook)
	}
}

func TestFastClock(t *testing.T) {
	t.Parallel()

	Convey(`A FastClock instance`, t, func() {
		epoch := time.Date(2015, 01, 01, 00, 00, 00, 00, time.UTC)
		Convey(`Tied to a wall clock but running 1000 times faster`, func() {
			fc := NewFastClock(epoch, 1000)
			defer fc.Close()
			ctx := clock.Set(context.Background(), fc)

			Convey(`Returns the current time.`, func() {
				wall0, fast0 := fc.now()
				fast1 := fc.Now()
				wall2, fast2 := fc.now()
				// Check assumptions of the wall clock, which should be monotonically
				// non-decreasing.
				So(wall2, ShouldHappenOnOrAfter, wall0)
				// Ditto for the FastClock.
				So(fast0, ShouldHappenOnOrAfter, epoch)
				So(fast1, ShouldHappenOnOrAfter, fast0)
				So(fast2, ShouldHappenOnOrAfter, fast1)

				Convey(`Runs faster than the wall clock.`, func() {
					So(fast2.Sub(fast0), ShouldAlmostEqual, wall2.Sub(wall0)*1000)
				})
			})

			Convey(`When sleeping with a time of zero, awakens quickly.`, func() {
				wall0, _ := fc.now()
				fc.Sleep(ctx, 0)
				wall1, _ := fc.now()
				// The smaller, the better, but allow for some CPU starvation.
				So(wall1.Sub(wall0), ShouldBeLessThan, time.Minute)
			})

			Convey(`Will panic if going backwards in time.`, func() {
				So(func() { fc.Add(-1 * time.Second) }, ShouldPanic)
				So(func() { fc.Set(fc.Now().Add(-1 * time.Second)) }, ShouldPanic)
			})

			Convey(`When sleeping, awakens if canceled.`, func() {
				ctx, cancelFunc := context.WithCancel(ctx)

				fc.SetTimerCallback(func(_ time.Duration, _ clock.Timer) {
					cancelFunc()
				})

				So(fc.Sleep(ctx, time.Hour).Incomplete(), ShouldBeTrue)
			})

			Convey(`Awakens after a period of time while manipulated.`, func() {
				t0 := fc.Now()
				afterC := clock.After(ctx, time.Second)
				t1 := fc.Now()
				fc.Set(t0.Add(time.Second)) // too early
				fc.Set(t1.Add(time.Second)) // more than enough
				res := <-afterC
				So(res.Time, ShouldHappenOnOrBetween, t0.Add(time.Second), t1.Add(time.Second))
			})

			Convey(`Awakens quickly without being manipulated due to passage of wall clock time.`, func() {
				const wallDelay = time.Millisecond
				const fastDelay = time.Second // 1000x faster

				wall0, fast0 := fc.now()
				fastAfter := clock.After(ctx, fastDelay)

				wallAfter := time.After(wallDelay)
				<-wallAfter
				wall1, _ := fc.now()
				So(wall1.Sub(wall0), ShouldBeGreaterThan, wallDelay)

				fastAwoken := <-fastAfter
				fastOverhead := (fastAwoken.Sub(fast0) - fastDelay)
				wallOverhead := fastOverhead / 1000
				_, _ = Println(" overhead:", "Wall", wallOverhead, "FastClock", fastOverhead)
				So(wallOverhead, ShouldBeGreaterThan, time.Duration(0)) // check sanity
				// The smaller, the better, but allow for some CPU starvation.
				So(wallOverhead, ShouldBeLessThan, time.Minute)
			})
		})

		Convey(`Tied to a wall clock mock`, func() {
			wallEpoch := time.Date(2020, 01, 01, 00, 00, 00, 00, time.UTC)
			fc := &FastClock{
				fastToSysRatio: 1000,
				initFastTime:   epoch,
				initSysTime:    wallEpoch,
				systemNow:      func() time.Time { return wallEpoch },
			}
			ctx := clock.Set(context.Background(), fc)

			Convey(`When sleeping with a time of zero, awakens immediately.`, func() {
				before := fc.Now()
				fc.Sleep(ctx, 0)
				So(fc.Now(), ShouldEqual, before)
			})

			Convey(`When sleeping for a period of time, awakens when signalled.`, func() {
				sleepingC := make(chan struct{})
				fc.SetTimerCallback(func(_ time.Duration, _ clock.Timer) {
					close(sleepingC)
				})

				awakeC := make(chan time.Time)
				go func() {
					fc.Sleep(ctx, 2*time.Second)
					awakeC <- fc.Now()
				}()

				<-sleepingC
				fc.Set(epoch.Add(1 * time.Second))
				fc.Set(epoch.Add(2 * time.Second))
				So(<-awakeC, ShouldResemble, epoch.Add(2*time.Second))
			})
		})
	})
}
<commit_msg>[testclock] de-racify FastClock tests.<commit_after>// Copyright 2015 The LUCI Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package testclock

import (
	"context"
	"fmt"
	"testing"
	"time"

	"go.chromium.org/luci/common/clock"

	. "github.com/smartystreets/goconvey/convey"
)

func ExampleFastClock() {
	// New clock running 1M times faster than wall clock.
	clk := NewFastClock(TestRecentTimeUTC, 1000*1000)
	defer clk.Close()
	ctx := clock.Set(context.Background(), clk)
	wallStart := time.Now()
	t := clock.NewTimer(ctx)
	t.Reset(time.Hour)
	<-t.GetC()
	if wallTook := time.Since(wallStart); wallTook <= 10*time.Second {
		fmt.Printf("took less than 10 seconds\n")
		// Output: took less than 10 seconds
	} else {
		fmt.Printf("took %s, either due to a bug or CPU starvation\n", wallTook)
	}
}

func TestFastClock(t *testing.T) {
	t.Parallel()

	Convey(`A FastClock instance`, t, func() {
		epoch := time.Date(2015, 01, 01, 00, 00, 00, 00, time.UTC)
		Convey(`Tied to a wall clock but running 1000 times faster`, func() {
			fc := NewFastClock(epoch, 1000)
			defer fc.Close()
			ctx := clock.Set(context.Background(), fc)

			Convey(`Returns the current time.`, func() {
				wall0, fast0 := fc.now()
				fast1 := fc.Now()
				wall2, fast2 := fc.now()
				// Check assumptions of the wall clock, which should be monotonically
				// non-decreasing.
				So(wall2, ShouldHappenOnOrAfter, wall0)
				// Ditto for the FastClock.
				So(fast0, ShouldHappenOnOrAfter, epoch)
				So(fast1, ShouldHappenOnOrAfter, fast0)
				So(fast2, ShouldHappenOnOrAfter, fast1)

				Convey(`Runs faster than the wall clock.`, func() {
					So(fast2.Sub(fast0), ShouldAlmostEqual, wall2.Sub(wall0)*1000)
				})
			})

			Convey(`When sleeping with a time of zero, awakens quickly.`, func() {
				wall0, _ := fc.now()
				fc.Sleep(ctx, 0)
				wall1, _ := fc.now()
				// The smaller, the better, but allow for some CPU starvation.
				So(wall1.Sub(wall0), ShouldBeLessThan, time.Minute)
			})

			Convey(`Will panic if going backwards in time.`, func() {
				So(func() { fc.Add(-1 * time.Second) }, ShouldPanic)
				So(func() { fc.Set(fc.Now().Add(-1 * time.Second)) }, ShouldPanic)
			})

			Convey(`When sleeping, awakens if canceled.`, func() {
				ctx, cancelFunc := context.WithCancel(ctx)

				fc.SetTimerCallback(func(_ time.Duration, _ clock.Timer) {
					cancelFunc()
				})

				So(fc.Sleep(ctx, time.Hour).Incomplete(), ShouldBeTrue)
			})

			Convey(`Awakens after a period of time while manipulated.`, func() {
				t0 := fc.Now()
				afterC := clock.After(ctx, time.Second)
				t1 := fc.Now()
				for i := 0; i < 1000 && fc.Now().Sub(t1) < time.Second; i++ {
					fc.Add(time.Millisecond)
				}
				res := <-afterC
				// The timer must not wake up earlier than necessary.
				So(res.Time.Sub(t0), ShouldBeGreaterThanOrEqualTo, time.Second)
				// The timer may wake a bit later than possible, especially if the
				// process is starving of CPU, so give it 1 hour of (fake) grace time.
				So(res.Time.Sub(t1), ShouldBeLessThan, time.Second+time.Hour)
			})

			Convey(`Awakens quickly without being manipulated due to passage of wall clock time.`, func() {
				const wallDelay = time.Millisecond
				const fastDelay = time.Second // 1000x faster

				wall0, fast0 := fc.now()
				fastAfter := clock.After(ctx, fastDelay)

				wallAfter := time.After(wallDelay)
				<-wallAfter
				wall1, _ := fc.now()
				So(wall1.Sub(wall0), ShouldBeGreaterThan, wallDelay)

				fastAwoken := <-fastAfter
				fastOverhead := (fastAwoken.Sub(fast0) - fastDelay)
				wallOverhead := fastOverhead / 1000
				_, _ = Println(" overhead:", "Wall", wallOverhead, "FastClock", fastOverhead)
				So(wallOverhead, ShouldBeGreaterThan, time.Duration(0)) // check sanity
				// The smaller, the better, but allow for some CPU starvation.
				So(wallOverhead, ShouldBeLessThan, time.Minute)
			})
		})

		Convey(`Tied to a wall clock mock`, func() {
			wallEpoch := time.Date(2020, 01, 01, 00, 00, 00, 00, time.UTC)
			fc := &FastClock{
				fastToSysRatio: 1000,
				initFastTime:   epoch,
				initSysTime:    wallEpoch,
				systemNow:      func() time.Time { return wallEpoch },
			}
			ctx := clock.Set(context.Background(), fc)

			Convey(`When sleeping with a time of zero, awakens immediately.`, func() {
				before := fc.Now()
				fc.Sleep(ctx, 0)
				So(fc.Now(), ShouldEqual, before)
			})

			Convey(`When sleeping for a period of time, awakens when signalled.`, func() {
				sleepingC := make(chan struct{})
				fc.SetTimerCallback(func(_ time.Duration, _ clock.Timer) {
					close(sleepingC)
				})

				awakeC := make(chan time.Time)
				go func() {
					fc.Sleep(ctx, 2*time.Second)
					awakeC <- fc.Now()
				}()

				<-sleepingC
				fc.Set(epoch.Add(1 * time.Second))
				fc.Set(epoch.Add(2 * time.Second))
				So(<-awakeC, ShouldResemble, epoch.Add(2*time.Second))
			})
		})
	})
}
<|endoftext|>


<commit_before>package hipchat

import (
	"fmt"
	"net/http"
	"net/url"
	"strconv"
)

// RoomService gives access to the room related methods of the API.
type RoomService struct {
	client *Client
}

// Rooms represents a HipChat room list.
type Rooms struct {
	Items      []Room    `json:"items"`
	StartIndex int       `json:"startIndex"`
	MaxResults int       `json:"maxResults"`
	Links      PageLinks `json:"links"`
}

// Room represents a HipChat room.
type Room struct {
	ID                int            `json:"id"`
	Links             RoomLinks      `json:"links"`
	Name              string         `json:"name"`
	XmppJid           string         `json:"xmpp_jid"`
	Statistics        RoomStatistics `json:"statistics"`
	Created           string         `json:"created"`
	IsArchived        bool           `json:"is_archived"`
	Privacy           string         `json:"privacy"`
	IsGuestAccessible bool           `json:"is_guess_accessible"`
	Topic             string         `json:"topic"`
	Participants      []User         `json:"participants"`
	Owner             User           `json:"owner"`
	GuestAccessURL    string         `json:"guest_access_url"`
}

// RoomStatistics represents the HipChat room statistics.
type RoomStatistics struct {
	Links Links `json:"links"`
}

// CreateRoomRequest represents a HipChat room creation request.
type CreateRoomRequest struct {
	Topic       string `json:"topic,omitempty"`
	GuestAccess bool   `json:"guest_access,omitempty"`
	Name        string `json:"name,omitempty"`
	OwnerUserID string `json:"owner_user_id,omitempty"`
	Privacy     string `json:"privacy,omitempty"`
}

// UpdateRoomRequest represents a HipChat room update request.
type UpdateRoomRequest struct {
	Name          string `json:"name"`
	Topic         string `json:"topic"`
	IsGuestAccess bool   `json:"is_guest_access"`
	IsArchived    bool   `json:"is_archived"`
	Privacy       string `json:"privacy"`
	Owner         ID     `json:"owner"`
}

// RoomLinks represents the HipChat room links.
type RoomLinks struct {
	Links
	Webhooks     string `json:"webhooks"`
	Members      string `json:"members"`
	Participants string `json:"participants"`
}

// NotificationRequest represents a HipChat room notification request.
type NotificationRequest struct {
	Color         string `json:"color,omitempty"`
	Message       string `json:"message,omitempty"`
	Notify        bool   `json:"notify,omitempty"`
	MessageFormat string `json:"message_format,omitempty"`
}

// ShareFileRequest represents a HipChat room file share request.
type ShareFileRequest struct {
	Path     string `json:"path"`
	Filename string `json:"filename,omitempty"`
	Message  string `json:"message,omitempty"`
}

// HistoryRequest represents a HipChat room chat history request.
type HistoryRequest struct {
	Date       string `json:"date"`
	Timezone   string `json:"timezone"`
	StartIndex int    `json:"start-index"`
	MaxResults int    `json:"max-results"`
	Reverse    bool   `json:"reverse"`
}

// History represents a HipChat room chat history.
type History struct {
	Items      []Message `json:"items"`
	StartIndex int       `json:"startIndex"`
	MaxResults int       `json:"maxResults"`
	Links      PageLinks `json:"links"`
}

// Message represents a HipChat message.
type Message struct {
	Date          string      `json:"date"`
	From          interface{} `json:"from"` // string | obj <- weak
	Id            string      `json:"id"`
	Mentions      []User      `json:"mentions"`
	Message       string      `json:"message"`
	MessageFormat string      `json:"message_format"`
	Type          string      `json:"type"`
}

// SetTopicRequest represents a hipchat update topic request
type SetTopicRequest struct {
	Topic string `json:"topic"`
}

// InviteRequest represents a hipchat invite to room request
type InviteRequest struct {
	Reason string `json:"reason"`
}

// List returns all the rooms authorized.
//
// HipChat API docs: https://www.hipchat.com/docs/apiv2/method/get_all_rooms
func (r *RoomService) List() (*Rooms, *http.Response, error) {
	req, err := r.client.NewRequest("GET", "room", nil)
	if err != nil {
		return nil, nil, err
	}

	rooms := new(Rooms)
	resp, err := r.client.Do(req, rooms)
	if err != nil {
		return nil, resp, err
	}
	return rooms, resp, nil
}

// Get returns the room specified by the id.
//
// HipChat API docs: https://www.hipchat.com/docs/apiv2/method/get_room
func (r *RoomService) Get(id string) (*Room, *http.Response, error) {
	req, err := r.client.NewRequest("GET", fmt.Sprintf("room/%s", id), nil)
	if err != nil {
		return nil, nil, err
	}

	room := new(Room)
	resp, err := r.client.Do(req, room)
	if err != nil {
		return nil, resp, err
	}
	return room, resp, nil
}

// Notification sends a notification to the room specified by the id.
//
// HipChat API docs: https://www.hipchat.com/docs/apiv2/method/send_room_notification
func (r *RoomService) Notification(id string, notifReq *NotificationRequest) (*http.Response, error) {
	req, err := r.client.NewRequest("POST", fmt.Sprintf("room/%s/notification", id), notifReq)
	if err != nil {
		return nil, err
	}

	return r.client.Do(req, nil)
}

// ShareFile sends a file to the room specified by the id.
//
// HipChat API docs: https://www.hipchat.com/docs/apiv2/method/share_file_with_room
func (r *RoomService) ShareFile(id string, shareFileReq *ShareFileRequest) (*http.Response, error) {
	req, err := r.client.NewFileUploadRequest("POST", fmt.Sprintf("room/%s/share/file", id), shareFileReq)
	if err != nil {
		return nil, err
	}

	return r.client.Do(req, nil)
}

// Create creates a new room.
//
// HipChat API docs: https://www.hipchat.com/docs/apiv2/method/create_room
func (r *RoomService) Create(roomReq *CreateRoomRequest) (*Room, *http.Response, error) {
	req, err := r.client.NewRequest("POST", "room", roomReq)
	if err != nil {
		return nil, nil, err
	}

	room := new(Room)
	resp, err := r.client.Do(req, room)
	if err != nil {
		return nil, resp, err
	}
	return room, resp, nil
}

// Delete deletes an existing room.
//
// HipChat API docs: https://www.hipchat.com/docs/apiv2/method/delete_room
func (r *RoomService) Delete(id string) (*http.Response, error) {
	req, err := r.client.NewRequest("DELETE", fmt.Sprintf("room/%s", id), nil)
	if err != nil {
		return nil, err
	}

	return r.client.Do(req, nil)
}

// Update updates an existing room.
//
// HipChat API docs: https://www.hipchat.com/docs/apiv2/method/update_room
func (r *RoomService) Update(id string, roomReq *UpdateRoomRequest) (*http.Response, error) {
	req, err := r.client.NewRequest("PUT", fmt.Sprintf("room/%s", id), roomReq)
	if err != nil {
		return nil, err
	}

	return r.client.Do(req, nil)
}

// History fetches a room's chat history.
//
// HipChat API docs: https://www.hipchat.com/docs/apiv2/method/view_room_history
func (r *RoomService) History(id string, roomReq *HistoryRequest) (*History, *http.Response, error) {
	u := fmt.Sprintf("room/%s/history", id)
	// Form query parameters
	if roomReq != nil {
		p := url.Values{}
		if roomReq.Date != "" {
			p.Add("date", roomReq.Date)
		}
		if roomReq.Timezone != "" {
			p.Add("timezone", roomReq.Timezone)
		}
		if roomReq.StartIndex != 0 {
			p.Add("start-index", strconv.FormatInt(int64(roomReq.StartIndex), 10))
		}
		if roomReq.MaxResults != 0 {
			p.Add("max-results", strconv.FormatInt(int64(roomReq.MaxResults), 10))
		}
		// There's no way to tell whether caller set a boolean or not. We have to always set
		// it.
		p.Add("reverse", strconv.FormatBool(roomReq.Reverse))
		u += "?" + p.Encode()
	}
	req, err := r.client.NewRequest("GET", u, nil)
	h := new(History)
	resp, err := r.client.Do(req, &h)
	if err != nil {
		return nil, resp, err
	}
	return h, resp, nil
}

// Set Room topic.
//
// HipChat API docs: https://www.hipchat.com/docs/apiv2/method/set_topic
func (r *RoomService) SetTopic(id string, topic string) (*http.Response, error) {
	topicReq := &SetTopicRequest{Topic: topic}

	req, err := r.client.NewRequest("PUT", fmt.Sprintf("room/%s/topic", id), topicReq)
	if err != nil {
		return nil, err
	}

	return r.client.Do(req, nil)
}

// Invite someone to the Room.
//
// HipChat API docs: https://www.hipchat.com/docs/apiv2/method/invite_user
func (r *RoomService) Invite(room string, user string, reason string) (*http.Response, error) {
	reasonReq := &InviteRequest{Reason: reason}

	req, err := r.client.NewRequest("POST", fmt.Sprintf("room/%s/invite/%s", room, user), reasonReq)
	if err != nil {
		return nil, err
	}

	return r.client.Do(req, nil)
}
<commit_msg>Added preliminary support for Cards<commit_after>package hipchat

import (
	"fmt"
	"net/http"
	"net/url"
	"strconv"
)

// RoomService gives access to the room related methods of the API.
type RoomService struct {
	client *Client
}

// Rooms represents a HipChat room list.
type Rooms struct {
	Items      []Room    `json:"items"`
	StartIndex int       `json:"startIndex"`
	MaxResults int       `json:"maxResults"`
	Links      PageLinks `json:"links"`
}

// Room represents a HipChat room.
type Room struct {
	ID                int            `json:"id"`
	Links             RoomLinks      `json:"links"`
	Name              string         `json:"name"`
	XmppJid           string         `json:"xmpp_jid"`
	Statistics        RoomStatistics `json:"statistics"`
	Created           string         `json:"created"`
	IsArchived        bool           `json:"is_archived"`
	Privacy           string         `json:"privacy"`
	IsGuestAccessible bool           `json:"is_guess_accessible"`
	Topic             string         `json:"topic"`
	Participants      []User         `json:"participants"`
	Owner             User           `json:"owner"`
	GuestAccessURL    string         `json:"guest_access_url"`
}

// RoomStatistics represents the HipChat room statistics.
type RoomStatistics struct {
	Links Links `json:"links"`
}

// CreateRoomRequest represents a HipChat room creation request.
type CreateRoomRequest struct {
	Topic       string `json:"topic,omitempty"`
	GuestAccess bool   `json:"guest_access,omitempty"`
	Name        string `json:"name,omitempty"`
	OwnerUserID string `json:"owner_user_id,omitempty"`
	Privacy     string `json:"privacy,omitempty"`
}

// UpdateRoomRequest represents a HipChat room update request.
type UpdateRoomRequest struct {
	Name          string `json:"name"`
	Topic         string `json:"topic"`
	IsGuestAccess bool   `json:"is_guest_access"`
	IsArchived    bool   `json:"is_archived"`
	Privacy       string `json:"privacy"`
	Owner         ID     `json:"owner"`
}

// RoomLinks represents the HipChat room links.
type RoomLinks struct {
	Links
	Webhooks     string `json:"webhooks"`
	Members      string `json:"members"`
	Participants string `json:"participants"`
}

// NotificationRequest represents a HipChat room notification request.
type NotificationRequest struct {
	Color         string `json:"color,omitempty"`
	Message       string `json:"message,omitempty"`
	Notify        bool   `json:"notify,omitempty"`
	MessageFormat string `json:"message_format,omitempty"`
	Card          Card   `json:"card,omitempty"`
}

// Card represents a HipChat card
type Card struct {
	Style       string      `json:"style"`
	ID          string      `json:"id"`
	URL         string      `json:"url"`
	Title       string      `json:"title"`
	Description string      `json:"description"`
	Site        string      `json:"site"`
	Date        uint32      `json:"date,omitempty"`
	Attributes  []Attribute `json:"attributes,omitempty"`
}

// Icon represents an icon
type Icon struct {
	URL string `json:"url"`
}

// Attribute represents an attribute on a card
type Attribute struct {
	Label string         `json:"label"`
	Value AttributeValue `json:"value"`
}

// AttributeValue represents the value of an attribute
type AttributeValue struct {
	Icon  string `json:"icon"`
	Label string `json:"label"`
	URL   string `json:"url"`
}

// ShareFileRequest represents a HipChat room file share request.
type ShareFileRequest struct {
	Path     string `json:"path"`
	Filename string `json:"filename,omitempty"`
	Message  string `json:"message,omitempty"`
}

// HistoryRequest represents a HipChat room chat history request.
type HistoryRequest struct {
	Date       string `json:"date"`
	Timezone   string `json:"timezone"`
	StartIndex int    `json:"start-index"`
	MaxResults int    `json:"max-results"`
	Reverse    bool   `json:"reverse"`
}

// History represents a HipChat room chat history.
type History struct {
	Items      []Message `json:"items"`
	StartIndex int       `json:"startIndex"`
	MaxResults int       `json:"maxResults"`
	Links      PageLinks `json:"links"`
}

// Message represents a HipChat message.
type Message struct {
	Date          string      `json:"date"`
	From          interface{} `json:"from"` // string | obj <- weak
	Id            string      `json:"id"`
	Mentions      []User      `json:"mentions"`
	Message       string      `json:"message"`
	MessageFormat string      `json:"message_format"`
	Type          string      `json:"type"`
}

// SetTopicRequest represents a hipchat update topic request
type SetTopicRequest struct {
	Topic string `json:"topic"`
}

// InviteRequest represents a hipchat invite to room request
type InviteRequest struct {
	Reason string `json:"reason"`
}

// List returns all the rooms authorized.
//
// HipChat API docs: https://www.hipchat.com/docs/apiv2/method/get_all_rooms
func (r *RoomService) List() (*Rooms, *http.Response, error) {
	req, err := r.client.NewRequest("GET", "room", nil)
	if err != nil {
		return nil, nil, err
	}

	rooms := new(Rooms)
	resp, err := r.client.Do(req, rooms)
	if err != nil {
		return nil, resp, err
	}
	return rooms, resp, nil
}

// Get returns the room specified by the id.
//
// HipChat API docs: https://www.hipchat.com/docs/apiv2/method/get_room
func (r *RoomService) Get(id string) (*Room, *http.Response, error) {
	req, err := r.client.NewRequest("GET", fmt.Sprintf("room/%s", id), nil)
	if err != nil {
		return nil, nil, err
	}

	room := new(Room)
	resp, err := r.client.Do(req, room)
	if err != nil {
		return nil, resp, err
	}
	return room, resp, nil
}

// Notification sends a notification to the room specified by the id.
//
// HipChat API docs: https://www.hipchat.com/docs/apiv2/method/send_room_notification
func (r *RoomService) Notification(id string, notifReq *NotificationRequest) (*http.Response, error) {
	req, err := r.client.NewRequest("POST", fmt.Sprintf("room/%s/notification", id), notifReq)
	if err != nil {
		return nil, err
	}

	return r.client.Do(req, nil)
}

// ShareFile sends a file to the room specified by the id.
//
// HipChat API docs: https://www.hipchat.com/docs/apiv2/method/share_file_with_room
func (r *RoomService) ShareFile(id string, shareFileReq *ShareFileRequest) (*http.Response, error) {
	req, err := r.client.NewFileUploadRequest("POST", fmt.Sprintf("room/%s/share/file", id), shareFileReq)
	if err != nil {
		return nil, err
	}

	return r.client.Do(req, nil)
}

// Create creates a new room.
//
// HipChat API docs: https://www.hipchat.com/docs/apiv2/method/create_room
func (r *RoomService) Create(roomReq *CreateRoomRequest) (*Room, *http.Response, error) {
	req, err := r.client.NewRequest("POST", "room", roomReq)
	if err != nil {
		return nil, nil, err
	}

	room := new(Room)
	resp, err := r.client.Do(req, room)
	if err != nil {
		return nil, resp, err
	}
	return room, resp, nil
}

// Delete deletes an existing room.
//
// HipChat API docs: https://www.hipchat.com/docs/apiv2/method/delete_room
func (r *RoomService) Delete(id string) (*http.Response, error) {
	req, err := r.client.NewRequest("DELETE", fmt.Sprintf("room/%s", id), nil)
	if err != nil {
		return nil, err
	}

	return r.client.Do(req, nil)
}

// Update updates an existing room.
//
// HipChat API docs: https://www.hipchat.com/docs/apiv2/method/update_room
func (r *RoomService) Update(id string, roomReq *UpdateRoomRequest) (*http.Response, error) {
	req, err := r.client.NewRequest("PUT", fmt.Sprintf("room/%s", id), roomReq)
	if err != nil {
		return nil, err
	}

	return r.client.Do(req, nil)
}

// History fetches a room's chat history.
//
// HipChat API docs: https://www.hipchat.com/docs/apiv2/method/view_room_history
func (r *RoomService) History(id string, roomReq *HistoryRequest) (*History, *http.Response, error) {
	u := fmt.Sprintf("room/%s/history", id)
	// Form query parameters
	if roomReq != nil {
		p := url.Values{}
		if roomReq.Date != "" {
			p.Add("date", roomReq.Date)
		}
		if roomReq.Timezone != "" {
			p.Add("timezone", roomReq.Timezone)
		}
		if roomReq.StartIndex != 0 {
			p.Add("start-index", strconv.FormatInt(int64(roomReq.StartIndex), 10))
		}
		if roomReq.MaxResults != 0 {
			p.Add("max-results", strconv.FormatInt(int64(roomReq.MaxResults), 10))
		}
		// There's no way to tell whether caller set a boolean or not. We have to always set
		// it.
		p.Add("reverse", strconv.FormatBool(roomReq.Reverse))
		u += "?" + p.Encode()
	}
	req, err := r.client.NewRequest("GET", u, nil)
	h := new(History)
	resp, err := r.client.Do(req, &h)
	if err != nil {
		return nil, resp, err
	}
	return h, resp, nil
}

// Set Room topic.
//
// HipChat API docs: https://www.hipchat.com/docs/apiv2/method/set_topic
func (r *RoomService) SetTopic(id string, topic string) (*http.Response, error) {
	topicReq := &SetTopicRequest{Topic: topic}

	req, err := r.client.NewRequest("PUT", fmt.Sprintf("room/%s/topic", id), topicReq)
	if err != nil {
		return nil, err
	}

	return r.client.Do(req, nil)
}

// Invite someone to the Room.
//
// HipChat API docs: https://www.hipchat.com/docs/apiv2/method/invite_user
func (r *RoomService) Invite(room string, user string, reason string) (*http.Response, error) {
	reasonReq := &InviteRequest{Reason: reason}

	req, err := r.client.NewRequest("POST", fmt.Sprintf("room/%s/invite/%s", room, user), reasonReq)
	if err != nil {
		return nil, err
	}

	return r.client.Do(req, nil)
}
<|endoftext|>


<commit_before>package main

import (
	"html/template"
	"net/http"
	"os"
	"sort"

	"github.com/coreos/go-etcd/etcd"
	"github.com/gengo/goship/lib/acl"
	"github.com/gengo/goship/lib/auth"
	"github.com/gengo/goship/lib/config"
	helpers "github.com/gengo/goship/lib/view-helpers"
	"github.com/gengo/goship/plugins/plugin"
	"github.com/golang/glog"
)

// HomeHandler is the main home screen
type HomeHandler struct {
	ac     acl.AccessControl
	ecl    *etcd.Client
	assets helpers.Assets
}

func (h HomeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	c, err := config.Load(h.ecl)
	if err != nil {
		glog.Errorf("Failed to Parse to ETCD data %s", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	u, err := auth.CurrentUser(r)
	if err != nil {
		glog.Errorf("Failed to get current user: %v", err)
		http.Error(w, err.Error(), http.StatusUnauthorized)
		return
	}
	t, err := template.New("index.html").ParseFiles("templates/index.html", "templates/base.html")
	if err != nil {
		glog.Errorf("Failed to parse template: %v", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	projs := acl.ReadableProjects(h.ac, c.Projects, u)

	sort.Sort(ByName(c.Projects))

	// columns maps a plugin name to a list of columns
	columns := make(map[string][]plugin.Column)
	for _, pl := range plugin.Plugins {
		for _, p := range c.Projects {
			cols, err := pl.Apply(p)
			if err != nil {
				glog.Errorf("Failed to apply plugin: %s", err)
				http.Error(w, err.Error(), http.StatusInternalServerError)
				return
			}
			columns[p.Name] = append(columns[p.Name], cols...)
		}
	}
	js, css := h.assets.Templates()
	gt := os.Getenv(gitHubAPITokenEnvVar)
	pt := c.Pivotal.Token

	params := map[string]interface{}{
		"Javascript":        js,
		"Stylesheet":        css,
		"Projects":          projs,
		"PluginColumns":     columns,
		"User":              u,
		"Page":              "home",
		"ConfirmDeployFlag": *confirmDeployFlag,
		"GithubToken":       gt,
		"PivotalToken":      pt,
	}
	helpers.RespondWithTemplate(w, "text/html", t, "base", params)
}

// ByName is the interface for sorting projects
type ByName []config.Project

func (slice ByName) Len() int           { return len(slice) }
func (slice ByName) Less(i, j int) bool { return slice[i].Name < slice[j].Name }
func (slice ByName) Swap(i, j int)      { slice[i], slice[j] = slice[j], slice[i] }
<commit_msg>Avoid panic when pivotal token is not configured<commit_after>package main

import (
	"html/template"
	"net/http"
	"os"
	"sort"

	"github.com/coreos/go-etcd/etcd"
	"github.com/gengo/goship/lib/acl"
	"github.com/gengo/goship/lib/auth"
	"github.com/gengo/goship/lib/config"
	helpers "github.com/gengo/goship/lib/view-helpers"
	"github.com/gengo/goship/plugins/plugin"
	"github.com/golang/glog"
)

// HomeHandler is the main home screen
type HomeHandler struct {
	ac     acl.AccessControl
	ecl    *etcd.Client
	assets helpers.Assets
}

func (h HomeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	c, err := config.Load(h.ecl)
	if err != nil {
		glog.Errorf("Failed to Parse to ETCD data %s", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	u, err := auth.CurrentUser(r)
	if err != nil {
		glog.Errorf("Failed to get current user: %v", err)
		http.Error(w, err.Error(), http.StatusUnauthorized)
		return
	}
	t, err := template.New("index.html").ParseFiles("templates/index.html", "templates/base.html")
	if err != nil {
		glog.Errorf("Failed to parse template: %v", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	projs := acl.ReadableProjects(h.ac, c.Projects, u)

	sort.Sort(ByName(c.Projects))

	// columns maps a plugin name to a list of columns
	columns := make(map[string][]plugin.Column)
	for _, pl := range plugin.Plugins {
		for _, p := range c.Projects {
			cols, err := pl.Apply(p)
			if err != nil {
				glog.Errorf("Failed to apply plugin: %s", err)
				http.Error(w, err.Error(), http.StatusInternalServerError)
				return
			}
			columns[p.Name] = append(columns[p.Name], cols...)
		}
	}
	js, css := h.assets.Templates()
	gt := os.Getenv(gitHubAPITokenEnvVar)
	var pt string
	if c.Pivotal != nil {
		pt = c.Pivotal.Token
	}

	params := map[string]interface{}{
		"Javascript":        js,
		"Stylesheet":        css,
		"Projects":          projs,
		"PluginColumns":     columns,
		"User":              u,
		"Page":              "home",
		"ConfirmDeployFlag": *confirmDeployFlag,
		"GithubToken":       gt,
		"PivotalToken":      pt,
	}
	helpers.RespondWithTemplate(w, "text/html", t, "base", params)
}

// ByName is the interface for sorting projects
type ByName []config.Project

func (slice ByName) Len() int           { return len(slice) }
func (slice ByName) Less(i, j int) bool { return slice[i].Name < slice[j].Name }
func (slice ByName) Swap(i, j int)      { slice[i], slice[j] = slice[j], slice[i] }
<|endoftext|>


<commit_before>package router

import "github.com/andrepereira/kobayashi-maru/net/controls"

type Id struct {
	IP     string //IP address
	Vendor string //Vendor of emulated hardware
	Model  string //Model of emulated hardware
	OS     string //Operating systemof emulated hardware
}

//Authorize the route to a destiny "to"
//This make the function of a router device
//Uses a to string with a IP address
//Return a boolean with authorization or not to routing (if the route
//exists at routing table
func Routing(to string) bool {

	if routertbl.GetRoute(to) {

		return true
	} else {
		return false
	}

}
<commit_msg>AddtoId struct withmore specs and state of hardware<commit_after>package router

import "github.com/andrepereira/kobayashi-maru/net/controls"

type Id struct {
	IP     string //IP address
	Vendor string //Vendor of emulated hardware
	Model  string //Model of emulated hardware
	OS     string //Operating systemof emulated hardware
	TX     int64  //Actual uplink speed in kbps
	RX     int64  //Actual downlink speed in kbps
	TXPPS  int64  //Actual uplink speed in pps
	RXPPS  int64  //Actual downlink speed in pps
	TXM    int64  //Maximum uplink in kbps
	RXM    int64  //Maximum downlink in kbps
	TXPPSM int64  //Maximum uplink in pps
	RXPPSM int64  //Maximum downlink in pps

}

//Authorize the route to a destiny "to"
//This make the function of a router device
//Uses a to string with a IP address
//Return a boolean with authorization or not to routing (if the route
//exists at routing table
func Routing(to string) bool {

	if routertbl.GetRoute(to) {

		return true
	} else {
		return false
	}

}
<|endoftext|>


<commit_before>package general

import (
	"math/rand"
	"time"

	"Fantasia/system"

	"github.com/Necroforger/dream"
	humanize "github.com/dustin/go-humanize"
)

// Module ...
type Module struct{}

// Build ...
func (m *Module) Build(s *system.System) {
	r := s.CommandRouter
	r.On("avatar", CmdAvatar).Set("", "Retrieves your avatar or the avatar of the user with the given ID.\n`avatar [userid]`")
	r.On("whois", CmdWhois).Set("", "Retrieves information abour a user. If called without any arguments, it will retrieve your user info\n`whois [userid | user mention]`")
	r.On("serverinfo", CmdServerInfo).Set("", "Retrieves information about the current server")
	r.On("quote", CmdQuote).Set("", "Quotes a user by message id.\n'quote [messageID]`")
	r.On("emojify", m.emojifyCommand).Set("", "Emojifies the given text")
	r.On("ping", Ping).Set("", "responds with the amount of time taken to send and retrieve a message")
	r.On("snowflake", Snowflake).Set("", "gives the creation date of a discord ID")
	r.On("youtube", CmdYoutube).Set("", "Searches for the youtube video with the give title.\n`youtube video name`")
	r.On("hex", CmdHexDisplay).Set("", "Returns an image representation of the given hex code. example: `hex ff00ff`")
	r.On("hexcheck", CmdHexCheck).Set("", "Returns the hex value of the center pixel of the given image")
	r.On("remind", CmdRemind).Set("", "Reminds you about something after a duration set in seconds.\n`remind 10 hello`")
	r.On("calc", CmdCalc).Set("", "Calculates the given expression.\n`calc 10 + 10`")
	r.On("tpb", CmdPirateBay).Set("", "Searches the pirate bay for the given query\n`tpb music`")
	r.On("gog", CmdGog).Set("", "Searches [GOG](http://gog.com/) for the given query")
	r.On("invite", CmdInviteURL).Set("", "Obtain an OAUTH2 invite URL for the bot")

	// Random
	r.On("rate", CmdRate).Set("", "Rates the supplied thing on a scale of 1-10")
	r.On("8ball", CmdEightBall).Set("", "Query the magic eightball")
	r.On("choose", CmdChoose).Set("", "Choose between a list of options. Enter your choices as a comma separated list. ex. `choose Orchestral arrangements, Piano arrangements`")

	rand.Seed(time.Now().UnixNano())
}

// Ping returns the time taken to send a message and recieve back the discord event
func Ping(ctx *system.Context) {
	embed := dream.NewEmbed().
		SetDescription("pinging").
		SetColor(system.StatusWarning).
		MessageEmbed

	succEmbed := dream.NewEmbed().
		SetColor(system.StatusSuccess).
		MessageEmbed

	start := time.Now()
	m, err := ctx.Ses.DG.ChannelMessageSendEmbed(ctx.Msg.ChannelID, embed)
	if err == nil {
		succEmbed.Description = time.Since(start).String()
		ctx.Ses.DG.ChannelMessageEditEmbed(m.ChannelID, m.ID, succEmbed)
	}
}

// Snowflake gives the creation date of a discord ID
func Snowflake(ctx *system.Context) {
	t, err := dream.CreationTime(ctx.Args.After())
	if err == nil {

		ctx.ReplyEmbed(dream.NewEmbed().
			SetTitle(ctx.Args.After()).
			SetDescription(
				t.Format(
					time.RFC1123) + "\n" +
					humanize.Time(t),
			).
			SetColor(system.StatusNotify).
			MessageEmbed)
	}
}
<commit_msg>Add tobinary and frombinary commands to general module<commit_after>package general

import (
	"math/rand"
	"time"

	"Fantasia/system"

	"github.com/Necroforger/dream"
	humanize "github.com/dustin/go-humanize"
)

// Module ...
type Module struct{}

// Build ...
func (m *Module) Build(s *system.System) {
	r := s.CommandRouter
	r.On("avatar", CmdAvatar).Set("", "Retrieves your avatar or the avatar of the user with the given ID.\n`avatar [userid]`")
	r.On("whois", CmdWhois).Set("", "Retrieves information abour a user. If called without any arguments, it will retrieve your user info\n`whois [userid | user mention]`")
	r.On("serverinfo", CmdServerInfo).Set("", "Retrieves information about the current server")
	r.On("quote", CmdQuote).Set("", "Quotes a user by message id.\n'quote [messageID]`")
	r.On("emojify", m.emojifyCommand).Set("", "Emojifies the given text")
	r.On("ping", Ping).Set("", "responds with the amount of time taken to send and retrieve a message")
	r.On("snowflake", Snowflake).Set("", "gives the creation date of a discord ID")
	r.On("youtube", CmdYoutube).Set("", "Searches for the youtube video with the give title.\n`youtube video name`")
	r.On("hex", CmdHexDisplay).Set("", "Returns an image representation of the given hex code. example: `hex ff00ff`")
	r.On("hexcheck", CmdHexCheck).Set("", "Returns the hex value of the center pixel of the given image")
	r.On("remind", CmdRemind).Set("", "Reminds you about something after a duration set in seconds.\n`remind 10 hello`")
	r.On("calc", CmdCalc).Set("", "Calculates the given expression.\n`calc 10 + 10`")
	r.On("tpb", CmdPirateBay).Set("", "Searches the pirate bay for the given query\n`tpb music`")
	r.On("gog", CmdGog).Set("", "Searches [GOG](http://gog.com/) for the given query")
	r.On("invite", CmdInviteURL).Set("", "Obtain an OAUTH2 invite URL for the bot")

	// Conversion
	r.On("tobinary", CmdToBinary).Set("", "convert the given text to binary")
	r.On("frombinary", CmdFromBinary).Set("", "converts the given text from binary to utf-8 text")

	// Random
	r.On("rate", CmdRate).Set("", "Rates the supplied thing on a scale of 1-10")
	r.On("8ball", CmdEightBall).Set("", "Query the magic eightball")
	r.On("choose", CmdChoose).Set("", "Choose between a list of options. Enter your choices as a comma separated list. ex. `choose Orchestral arrangements, Piano arrangements`")

	rand.Seed(time.Now().UnixNano())
}

// Ping returns the time taken to send a message and recieve back the discord event
func Ping(ctx *system.Context) {
	embed := dream.NewEmbed().
		SetDescription("pinging").
		SetColor(system.StatusWarning).
		MessageEmbed

	succEmbed := dream.NewEmbed().
		SetColor(system.StatusSuccess).
		MessageEmbed

	start := time.Now()
	m, err := ctx.Ses.DG.ChannelMessageSendEmbed(ctx.Msg.ChannelID, embed)
	if err == nil {
		succEmbed.Description = time.Since(start).String()
		ctx.Ses.DG.ChannelMessageEditEmbed(m.ChannelID, m.ID, succEmbed)
	}
}

// Snowflake gives the creation date of a discord ID
func Snowflake(ctx *system.Context) {
	t, err := dream.CreationTime(ctx.Args.After())
	if err == nil {

		ctx.ReplyEmbed(dream.NewEmbed().
			SetTitle(ctx.Args.After()).
			SetDescription(
				t.Format(
					time.RFC1123) + "\n" +
					humanize.Time(t),
			).
			SetColor(system.StatusNotify).
			MessageEmbed)
	}
}
<|endoftext|>