<commit_before>// Package team provides api functions for team worker
package team

import (
	"errors"
	mongomodels "koding/db/models"
	"socialapi/config"
	"socialapi/models"
	notymodels "socialapi/workers/notification/models"
	"strings"

	"koding/db/mongodb/modelhelper"
	"strconv"

	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"

	"github.com/f2prateek/clearbit-go"
	"github.com/hashicorp/go-multierror"
	"github.com/koding/bongo"
	"github.com/koding/logging"
	"github.com/streadway/amqp"
)

var (
	ErrCompanyNameNotFound     = errors.New("company name not found")
	ErrCompanyMetricsNotFound  = errors.New("company metrics not found")
	ErrCompanyEmployeeNotFound = errors.New("company employee not found")
	ErrCompanyDomainNotFound   = errors.New("company domain not found")
)

// Controller holds the required parameters for team async operations
type Controller struct {
	log      logging.Logger
	config   *config.Config
	clearbit clearbit.Clearbit
}

// NewController creates a handler for consuming async operations of team
func NewController(log logging.Logger, config *config.Config) *Controller {
	return &Controller{
		log:      log,
		config:   config,
		clearbit: clearbit.New(config.Clearbit),
	}
}

// DefaultErrHandler handles the errors, we dont need to ack a message,
// continue to the success
func (c *Controller) DefaultErrHandler(delivery amqp.Delivery, err error) bool {
	c.log.Error("an error occurred putting message back to queue", err)
	delivery.Nack(false, true)
	return false
}

// HandleChannel handles channel operations
func (c *Controller) HandleChannel(channel *models.Channel) error {
	if channel.TypeConstant != models.Channel_TYPE_GROUP {
		return nil
	}

	chans, err := channel.FetchAllChannelsOfGroup()
	if err != nil {
		return err
	}

	var errs *multierror.Error

	for _, ch := range chans {
		// we'r gonna innore all `not found` errors while deleting datas
		if err := ch.Delete(); err != nil && err != bongo.RecordNotFound {
			errs = multierror.Append(errs, err)
		}

		err = ch.RemoveChannelLinks()
		if err != nil && (err != models.ErrChannelNotFound || err != bongo.RecordNotFound) {
			errs = multierror.Append(errs, err)
		}

		if err := ch.DeleteChannelParticipants(); err != nil {
			return err
		}

	}

	if errs.ErrorOrNil() != nil {
		return errs
	}

	return nil
}

// HandleCreator finds the creator of the channel, and tries to find its
// company name according to its email address
func (c *Controller) HandleCreator(channel *models.Channel) error {
	if channel.TypeConstant != models.Channel_TYPE_GROUP {
		return nil
	}

	creator, err := models.Cache.Account.ById(channel.CreatorId)
	if err != nil {
		return err
	}

	user, err := modelhelper.GetUser(creator.Nick)
	if err != nil {
		return err
	}

	// if user already has company, no need to fetch user's company info again.
	if user.CompanyId.Hex() != "" {
		return nil
	}

	// if user has no company data, then try to fetch info about company of user.
	userData, err := c.clearbit.Enrichment().Combined(user.Email)
	if err != nil {
		return err
	}

	if userData.Company == nil {
		return nil
	}

	if userData.Company.Name == nil {
		return nil
	}

	// if code line reach to here, it means that we got user's company data,
	// after that we are going to update user's data.
	var company *mongomodels.Company

	company, err = modelhelper.GetCompanyByNameOrSlug(*userData.Company.Name)
	if err != nil && err != mgo.ErrNotFound {
		return err
	}

	// if company is not found in db, then create new one
	// after creation, update user's company with company id
	if err == mgo.ErrNotFound {
		companyData, err := checkValuesForCompany(userData.Company)
		if err != nil {
			return nil
		}

		// create company in db if it doesn't exist
		if err := modelhelper.CreateCompany(companyData); err != nil {
			return err
		}
		company, err = modelhelper.GetCompanyByNameOrSlug(companyData.Name)
		if err != nil {
			return err
		}

	}

	// update the company info of user if company exist in mongo
	selector := bson.M{"username": user.Name}
	update := bson.M{"companyId": company.Id}
	if err := modelhelper.UpdateUser(selector, update); err != nil {
		return err
	}

	return nil
}

func checkValuesForCompany(company *clearbit.Company) (*mongomodels.Company, error) {
	if company.Name == nil {
		return nil, ErrCompanyNameNotFound
	}
	if company.Metrics == nil {
		return nil, ErrCompanyMetricsNotFound
	}
	if company.Metrics.Employees == nil {
		return nil, ErrCompanyEmployeeNotFound
	}
	if company.Domain == nil {
		return nil, ErrCompanyDomainNotFound
	}

	return &mongomodels.Company{
		Name:      *company.Name,
		Slug:      strings.ToLower(*company.Name),
		Employees: *company.Metrics.Employees,
		Domain:    *company.Domain,
	}, nil
}

// HandleParticipant handles participant operations
func (c *Controller) HandleParticipant(cp *models.ChannelParticipant) error {
	channel, err := models.Cache.Channel.ById(cp.ChannelId)
	if err != nil {
		c.log.Error("Channel: %d is not found", cp.ChannelId)
		return nil
	}

	if channel.TypeConstant != models.Channel_TYPE_GROUP {
		return nil // following logic ensures that channel is a group channel
	}

	group, err := modelhelper.GetGroup(channel.GroupName)
	if err != nil && err != mgo.ErrNotFound {
		return err
	}

	if err == mgo.ErrNotFound {
		c.log.Error("Group: %s is not found in mongo", channel.GroupName)
		return nil
	}

	if err := c.handleDefaultChannels(group.DefaultChannels, cp); err != nil {
		return err
	}

	if err := c.handleParticipantRemove(cp); err != nil {
		return err
	}

	return nil
}

func (c *Controller) handleDefaultChannels(defaultChannels []string, cp *models.ChannelParticipant) error {
	for _, channelId := range defaultChannels {
		ci, err := strconv.ParseInt(channelId, 10, 64)
		if err != nil {
			c.log.Error("Couldnt parse channelId: %s, err: %s", channelId, err.Error())
			continue
		}

		if err := c.handleDefaultChannel(ci, cp); err != nil {
			return err
		}
	}

	return nil
}

func (c *Controller) handleDefaultChannel(channelId int64, cp *models.ChannelParticipant) error {
	defChan, err := models.Cache.Channel.ById(channelId)
	if err != nil && err != bongo.RecordNotFound {
		return err
	}

	if err == bongo.RecordNotFound {
		c.log.Error("Channel: %d is not found", channelId)
		return nil
	}

	// i wrote all of them to have a referance for future, because we
	// are gonna need this logic while implementing invitations ~ CS
	switch cp.StatusConstant {
	case models.ChannelParticipant_STATUS_ACTIVE:
		_, err = defChan.AddParticipant(cp.AccountId)
	case models.ChannelParticipant_STATUS_BLOCKED:
		err = defChan.RemoveParticipant(cp.AccountId)
	case models.ChannelParticipant_STATUS_LEFT:
		err = defChan.RemoveParticipant(cp.AccountId)
	}

	switch err {
	case models.ErrChannelIsLinked:
		// if channel is linked to another, add it to root channel
		root, err := defChan.FetchRoot()
		if err != nil && err != bongo.RecordNotFound {
			return err
		}

		if err == bongo.RecordNotFound {
			c.log.Error("Root Channel of %d not found", cp.ChannelId)
			return nil
		}

		// self handling with root channel
		return c.handleDefaultChannel(root.Id, cp)
	case models.ErrParticipantBlocked:
		// nothing to do here, user should be unblocked first
		return nil

	default:
		return nil
	}
}

// handleParticipantRemove removes a user from all channel participated channels
// in given group
func (c *Controller) handleParticipantRemove(cp *models.ChannelParticipant) error {
	channel, err := models.Cache.Channel.ById(cp.ChannelId)
	if err != nil {
		c.log.Error("Channel: %d is not found", cp.ChannelId)
		return nil
	}

	if channel.TypeConstant != models.Channel_TYPE_GROUP {
		return nil
	}

	if !models.IsIn(cp.StatusConstant,
		models.ChannelParticipant_STATUS_BLOCKED,
		models.ChannelParticipant_STATUS_LEFT,
	) {
		return nil
	}

	cpp := models.NewChannelParticipant()
	ids, err := cpp.FetchAllParticipatedChannelIdsInGroup(cp.AccountId, channel.GroupName)
	if err != nil && err != bongo.RecordNotFound {
		return err
	}

	if err == bongo.RecordNotFound {
		return nil
	}

	for _, id := range ids {
		ch := models.NewChannel()
		ch.Id = id
		if err := ch.RemoveParticipant(cp.AccountId); err != nil {
			return err
		}
	}
	nt := notymodels.NewNotification()
	err = nt.RemoveAllContentsRelatedWithNotification(cp.AccountId, channel.Id)
	if err != nil {
		return err
	}

	return nil
}
<commit_msg>go/team: parse company data of clearbit package<commit_after>// Package team provides api functions for team worker
package team

import (
	"errors"
	mongomodels "koding/db/models"
	"socialapi/config"
	"socialapi/models"
	notymodels "socialapi/workers/notification/models"
	"strings"

	"koding/db/mongodb/modelhelper"
	"strconv"

	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"

	"github.com/f2prateek/clearbit-go"
	"github.com/hashicorp/go-multierror"
	"github.com/koding/bongo"
	"github.com/koding/logging"
	"github.com/streadway/amqp"
)

var (
	ErrCompanyNameNotFound     = errors.New("company name not found")
	ErrCompanyMetricsNotFound  = errors.New("company metrics not found")
	ErrCompanyEmployeeNotFound = errors.New("company employee not found")
	ErrCompanyDomainNotFound   = errors.New("company domain not found")
)

// Controller holds the required parameters for team async operations
type Controller struct {
	log      logging.Logger
	config   *config.Config
	clearbit clearbit.Clearbit
}

// NewController creates a handler for consuming async operations of team
func NewController(log logging.Logger, config *config.Config) *Controller {
	return &Controller{
		log:      log,
		config:   config,
		clearbit: clearbit.New(config.Clearbit),
	}
}

// DefaultErrHandler handles the errors, we dont need to ack a message,
// continue to the success
func (c *Controller) DefaultErrHandler(delivery amqp.Delivery, err error) bool {
	c.log.Error("an error occurred putting message back to queue", err)
	delivery.Nack(false, true)
	return false
}

// HandleChannel handles channel operations
func (c *Controller) HandleChannel(channel *models.Channel) error {
	if channel.TypeConstant != models.Channel_TYPE_GROUP {
		return nil
	}

	chans, err := channel.FetchAllChannelsOfGroup()
	if err != nil {
		return err
	}

	var errs *multierror.Error

	for _, ch := range chans {
		// we'r gonna innore all `not found` errors while deleting datas
		if err := ch.Delete(); err != nil && err != bongo.RecordNotFound {
			errs = multierror.Append(errs, err)
		}

		err = ch.RemoveChannelLinks()
		if err != nil && (err != models.ErrChannelNotFound || err != bongo.RecordNotFound) {
			errs = multierror.Append(errs, err)
		}

		if err := ch.DeleteChannelParticipants(); err != nil {
			return err
		}

	}

	if errs.ErrorOrNil() != nil {
		return errs
	}

	return nil
}

// HandleCreator finds the creator of the channel, and tries to find its
// company name according to its email address
func (c *Controller) HandleCreator(channel *models.Channel) error {
	if channel.TypeConstant != models.Channel_TYPE_GROUP {
		return nil
	}

	creator, err := models.Cache.Account.ById(channel.CreatorId)
	if err != nil {
		return nil
	}
	user, err := modelhelper.GetUser(creator.Nick)
	if err != nil {
		return nil
	}
	// if user already has company, no need to fetch user's company info again.
	if user.CompanyId.Hex() != "" {
		return nil
	}
	// if user has no company data, then try to fetch info about company of user.
	userData, err := c.clearbit.Enrichment().Combined(user.Email)
	if err != nil {
		return err
	}

	if userData.Company == nil {
		return nil
	}

	if userData.Company.Name == nil {
		return nil
	}

	// if code line reach to here, it means that we got user's company data,
	// after that we are going to update user's data.
	var company *mongomodels.Company

	company, err = modelhelper.GetCompanyByNameOrSlug(*userData.Company.Name)
	if err != nil && err != mgo.ErrNotFound {
		return err
	}
	// if company is not found in db, then create new one
	// after creation, update user's company with company id
	if err == mgo.ErrNotFound {
		err := checkValuesForCompany(userData.Company)
		if err != nil {
			return nil
		}

		// parse company data of clearbit package into our company model struct
		companyData := parseClearbitCompany(userData.Company)

		// create company in db if it doesn't exist
		company, err = modelhelper.CreateCompany(companyData)
		if err != nil {
			return err
		}
	}

	// update the company info of user if company exist in mongo
	selector := bson.M{"username": user.Name}
	update := bson.M{"companyId": company.Id}
	if err := modelhelper.UpdateUser(selector, update); err != nil {
		return err
	}
	return nil
}

func checkValuesForCompany(company *clearbit.Company) error {
	if company.Name == nil {
		return ErrCompanyNameNotFound
	}
	if company.Metrics == nil {
		return ErrCompanyMetricsNotFound
	}
	if company.Metrics.Employees == nil {
		return ErrCompanyEmployeeNotFound
	}
	if company.Domain == nil {
		return ErrCompanyDomainNotFound
	}

	return nil
}

func parseClearbitCompany(company *clearbit.Company) *mongomodels.Company {
	return &mongomodels.Company{
		Name:      *company.Name,
		Slug:      strings.ToLower(*company.Name),
		Employees: *company.Metrics.Employees,
		Domain:    *company.Domain,
	}
}

// HandleParticipant handles participant operations
func (c *Controller) HandleParticipant(cp *models.ChannelParticipant) error {
	channel, err := models.Cache.Channel.ById(cp.ChannelId)
	if err != nil {
		c.log.Error("Channel: %d is not found", cp.ChannelId)
		return nil
	}

	if channel.TypeConstant != models.Channel_TYPE_GROUP {
		return nil // following logic ensures that channel is a group channel
	}

	group, err := modelhelper.GetGroup(channel.GroupName)
	if err != nil && err != mgo.ErrNotFound {
		return err
	}

	if err == mgo.ErrNotFound {
		c.log.Error("Group: %s is not found in mongo", channel.GroupName)
		return nil
	}

	if err := c.handleDefaultChannels(group.DefaultChannels, cp); err != nil {
		return err
	}

	if err := c.handleParticipantRemove(cp); err != nil {
		return err
	}

	return nil
}

func (c *Controller) handleDefaultChannels(defaultChannels []string, cp *models.ChannelParticipant) error {
	for _, channelId := range defaultChannels {
		ci, err := strconv.ParseInt(channelId, 10, 64)
		if err != nil {
			c.log.Error("Couldnt parse channelId: %s, err: %s", channelId, err.Error())
			continue
		}

		if err := c.handleDefaultChannel(ci, cp); err != nil {
			return err
		}
	}

	return nil
}

func (c *Controller) handleDefaultChannel(channelId int64, cp *models.ChannelParticipant) error {
	defChan, err := models.Cache.Channel.ById(channelId)
	if err != nil && err != bongo.RecordNotFound {
		return err
	}

	if err == bongo.RecordNotFound {
		c.log.Error("Channel: %d is not found", channelId)
		return nil
	}

	// i wrote all of them to have a referance for future, because we
	// are gonna need this logic while implementing invitations ~ CS
	switch cp.StatusConstant {
	case models.ChannelParticipant_STATUS_ACTIVE:
		_, err = defChan.AddParticipant(cp.AccountId)
	case models.ChannelParticipant_STATUS_BLOCKED:
		err = defChan.RemoveParticipant(cp.AccountId)
	case models.ChannelParticipant_STATUS_LEFT:
		err = defChan.RemoveParticipant(cp.AccountId)
	}

	switch err {
	case models.ErrChannelIsLinked:
		// if channel is linked to another, add it to root channel
		root, err := defChan.FetchRoot()
		if err != nil && err != bongo.RecordNotFound {
			return err
		}

		if err == bongo.RecordNotFound {
			c.log.Error("Root Channel of %d not found", cp.ChannelId)
			return nil
		}

		// self handling with root channel
		return c.handleDefaultChannel(root.Id, cp)
	case models.ErrParticipantBlocked:
		// nothing to do here, user should be unblocked first
		return nil

	default:
		return nil
	}
}

// handleParticipantRemove removes a user from all channel participated channels
// in given group
func (c *Controller) handleParticipantRemove(cp *models.ChannelParticipant) error {
	channel, err := models.Cache.Channel.ById(cp.ChannelId)
	if err != nil {
		c.log.Error("Channel: %d is not found", cp.ChannelId)
		return nil
	}

	if channel.TypeConstant != models.Channel_TYPE_GROUP {
		return nil
	}

	if !models.IsIn(cp.StatusConstant,
		models.ChannelParticipant_STATUS_BLOCKED,
		models.ChannelParticipant_STATUS_LEFT,
	) {
		return nil
	}

	cpp := models.NewChannelParticipant()
	ids, err := cpp.FetchAllParticipatedChannelIdsInGroup(cp.AccountId, channel.GroupName)
	if err != nil && err != bongo.RecordNotFound {
		return err
	}

	if err == bongo.RecordNotFound {
		return nil
	}

	for _, id := range ids {
		ch := models.NewChannel()
		ch.Id = id
		if err := ch.RemoveParticipant(cp.AccountId); err != nil {
			return err
		}
	}
	nt := notymodels.NewNotification()
	err = nt.RemoveAllContentsRelatedWithNotification(cp.AccountId, channel.Id)
	if err != nil {
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>// Copyright 2010 The win Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package win

import (
	"syscall"
	"unsafe"
)

// Button control messages
const (
	BCM_FIRST            = 0x1600
	BCM_GETIDEALSIZE     = BCM_FIRST + 0x0001
	BCM_SETIMAGELIST     = BCM_FIRST + 0x0002
	BCM_GETIMAGELIST     = BCM_FIRST + 0x0003
	BCM_SETTEXTMARGIN    = BCM_FIRST + 0x0004
	BCM_GETTEXTMARGIN    = BCM_FIRST + 0x0005
	BCM_SETDROPDOWNSTATE = BCM_FIRST + 0x0006
	BCM_SETSPLITINFO     = BCM_FIRST + 0x0007
	BCM_GETSPLITINFO     = BCM_FIRST + 0x0008
	BCM_SETNOTE          = BCM_FIRST + 0x0009
	BCM_GETNOTE          = BCM_FIRST + 0x000A
	BCM_GETNOTELENGTH    = BCM_FIRST + 0x000B
)

const (
	CCM_FIRST            = 0x2000
	CCM_LAST             = CCM_FIRST + 0x200
	CCM_SETBKCOLOR       = 8193
	CCM_SETCOLORSCHEME   = 8194
	CCM_GETCOLORSCHEME   = 8195
	CCM_GETDROPTARGET    = 8196
	CCM_SETUNICODEFORMAT = 8197
	CCM_GETUNICODEFORMAT = 8198
	CCM_SETVERSION       = 0x2007
	CCM_GETVERSION       = 0x2008
	CCM_SETNOTIFYWINDOW  = 0x2009
	CCM_SETWINDOWTHEME   = 0x200b
	CCM_DPISCALE         = 0x200c
)

// Common controls styles
const (
	CCS_TOP           = 1
	CCS_NOMOVEY       = 2
	CCS_BOTTOM        = 3
	CCS_NORESIZE      = 4
	CCS_NOPARENTALIGN = 8
	CCS_ADJUSTABLE    = 32
	CCS_NODIVIDER     = 64
	CCS_VERT          = 128
	CCS_LEFT          = 129
	CCS_NOMOVEX       = 130
	CCS_RIGHT         = 131
)

// InitCommonControlsEx flags
const (
	ICC_LISTVIEW_CLASSES   = 1
	ICC_TREEVIEW_CLASSES   = 2
	ICC_BAR_CLASSES        = 4
	ICC_TAB_CLASSES        = 8
	ICC_UPDOWN_CLASS       = 16
	ICC_PROGRESS_CLASS     = 32
	ICC_HOTKEY_CLASS       = 64
	ICC_ANIMATE_CLASS      = 128
	ICC_WIN95_CLASSES      = 255
	ICC_DATE_CLASSES       = 256
	ICC_USEREX_CLASSES     = 512
	ICC_COOL_CLASSES       = 1024
	ICC_INTERNET_CLASSES   = 2048
	ICC_PAGESCROLLER_CLASS = 4096
	ICC_NATIVEFNTCTL_CLASS = 8192
	INFOTIPSIZE            = 1024
	ICC_STANDARD_CLASSES   = 0x00004000
	ICC_LINK_CLASS         = 0x00008000
)

// WM_NOTITY messages
const (
	NM_FIRST           = 0
	NM_OUTOFMEMORY     = ^uint32(0)  // NM_FIRST - 1
	NM_CLICK           = ^uint32(1)  // NM_FIRST - 2
	NM_DBLCLK          = ^uint32(2)  // NM_FIRST - 3
	NM_RETURN          = ^uint32(3)  // NM_FIRST - 4
	NM_RCLICK          = ^uint32(4)  // NM_FIRST - 5
	NM_RDBLCLK         = ^uint32(5)  // NM_FIRST - 6
	NM_SETFOCUS        = ^uint32(6)  // NM_FIRST - 7
	NM_KILLFOCUS       = ^uint32(7)  // NM_FIRST - 8
	NM_CUSTOMDRAW      = ^uint32(11) // NM_FIRST - 12
	NM_HOVER           = ^uint32(12) // NM_FIRST - 13
	NM_NCHITTEST       = ^uint32(13) // NM_FIRST - 14
	NM_KEYDOWN         = ^uint32(14) // NM_FIRST - 15
	NM_RELEASEDCAPTURE = ^uint32(15) // NM_FIRST - 16
	NM_SETCURSOR       = ^uint32(16) // NM_FIRST - 17
	NM_CHAR            = ^uint32(17) // NM_FIRST - 18
	NM_TOOLTIPSCREATED = ^uint32(18) // NM_FIRST - 19
	NM_LAST            = ^uint32(98) // NM_FIRST - 99
)

// ProgressBar messages
const (
	PBM_SETPOS      = WM_USER + 2
	PBM_DELTAPOS    = WM_USER + 3
	PBM_SETSTEP     = WM_USER + 4
	PBM_STEPIT      = WM_USER + 5
	PBM_SETRANGE32  = 1030
	PBM_GETRANGE    = 1031
	PBM_GETPOS      = 1032
	PBM_SETBARCOLOR = 1033
	PBM_SETBKCOLOR  = CCM_SETBKCOLOR
	PBS_SMOOTH      = 1
	PBS_VERTICAL    = 4
)

// ImageList creation flags
const (
	ILC_MASK          = 0x00000001
	ILC_COLOR         = 0x00000000
	ILC_COLORDDB      = 0x000000FE
	ILC_COLOR4        = 0x00000004
	ILC_COLOR8        = 0x00000008
	ILC_COLOR16       = 0x00000010
	ILC_COLOR24       = 0x00000018
	ILC_COLOR32       = 0x00000020
	ILC_PALETTE       = 0x00000800
	ILC_MIRROR        = 0x00002000
	ILC_PERITEMMIRROR = 0x00008000
)

const (
	CDDS_PREPAINT      = 0x00000001
	CDDS_POSTPAINT     = 0x00000002
	CDDS_PREERASE      = 0x00000003
	CDDS_POSTERASE     = 0x00000004
	CDDS_ITEM          = 0x00010000
	CDDS_ITEMPREPAINT  = CDDS_ITEM | CDDS_PREPAINT
	CDDS_ITEMPOSTPAINT = CDDS_ITEM | CDDS_POSTPAINT
	CDDS_ITEMPREERASE  = CDDS_ITEM | CDDS_PREERASE
	CDDS_ITEMPOSTERASE = CDDS_ITEM | CDDS_POSTERASE
	CDDS_SUBITEM       = 0x00020000
)

const (
	CDIS_SELECTED         = 0x0001
	CDIS_GRAYED           = 0x0002
	CDIS_DISABLED         = 0x0004
	CDIS_CHECKED          = 0x0008
	CDIS_FOCUS            = 0x0010
	CDIS_DEFAULT          = 0x0020
	CDIS_HOT              = 0x0040
	CDIS_MARKED           = 0x0080
	CDIS_INDETERMINATE    = 0x0100
	CDIS_SHOWKEYBOARDCUES = 0x0200
	CDIS_NEARHOT          = 0x0400
	CDIS_OTHERSIDEHOT     = 0x0800
	CDIS_DROPHILITED      = 0x1000
)

const (
	CDRF_DODEFAULT         = 0x00000000
	CDRF_NEWFONT           = 0x00000002
	CDRF_SKIPDEFAULT       = 0x00000004
	CDRF_DOERASE           = 0x00000008
	CDRF_NOTIFYPOSTPAINT   = 0x00000010
	CDRF_NOTIFYITEMDRAW    = 0x00000020
	CDRF_NOTIFYSUBITEMDRAW = 0x00000020
	CDRF_NOTIFYPOSTERASE   = 0x00000040
	CDRF_SKIPPOSTPAINT     = 0x00000100
)

const (
	LPSTR_TEXTCALLBACK = ^uintptr(0)
	I_CHILDRENCALLBACK = -1
)

type HIMAGELIST HANDLE

type INITCOMMONCONTROLSEX struct {
	DwSize, DwICC uint32
}

type NMCUSTOMDRAW struct {
	Hdr         NMHDR
	DwDrawStage uint32
	Hdc         HDC
	Rc          RECT
	DwItemSpec  uintptr
	UItemState  uint32
	LItemlParam uintptr
}

var (
	// Library
	libcomctl32 uintptr

	// Functions
	imageList_Add         uintptr
	imageList_AddMasked   uintptr
	imageList_Create      uintptr
	imageList_Destroy     uintptr
	imageList_ReplaceIcon uintptr
	initCommonControlsEx  uintptr
)

func init() {
	// Library
	libcomctl32 = MustLoadLibrary("comctl32.dll")

	// Functions
	imageList_Add = MustGetProcAddress(libcomctl32, "ImageList_Add")
	imageList_AddMasked = MustGetProcAddress(libcomctl32, "ImageList_AddMasked")
	imageList_Create = MustGetProcAddress(libcomctl32, "ImageList_Create")
	imageList_Destroy = MustGetProcAddress(libcomctl32, "ImageList_Destroy")
	imageList_ReplaceIcon = MustGetProcAddress(libcomctl32, "ImageList_ReplaceIcon")
	initCommonControlsEx = MustGetProcAddress(libcomctl32, "InitCommonControlsEx")

	// Initialize the common controls we support
	var initCtrls INITCOMMONCONTROLSEX
	initCtrls.DwSize = uint32(unsafe.Sizeof(initCtrls))
	initCtrls.DwICC = ICC_LISTVIEW_CLASSES | ICC_PROGRESS_CLASS | ICC_TAB_CLASSES | ICC_TREEVIEW_CLASSES

	InitCommonControlsEx(&initCtrls)
}

func ImageList_Add(himl HIMAGELIST, hbmImage, hbmMask HBITMAP) int32 {
	ret, _, _ := syscall.Syscall(imageList_Add, 3,
		uintptr(himl),
		uintptr(hbmImage),
		uintptr(hbmMask))

	return int32(ret)
}

func ImageList_AddMasked(himl HIMAGELIST, hbmImage HBITMAP, crMask COLORREF) int32 {
	ret, _, _ := syscall.Syscall(imageList_AddMasked, 3,
		uintptr(himl),
		uintptr(hbmImage),
		uintptr(crMask))

	return int32(ret)
}

func ImageList_Create(cx, cy int32, flags uint32, cInitial, cGrow int32) HIMAGELIST {
	ret, _, _ := syscall.Syscall6(imageList_Create, 5,
		uintptr(cx),
		uintptr(cy),
		uintptr(flags),
		uintptr(cInitial),
		uintptr(cGrow),
		0)

	return HIMAGELIST(ret)
}

func ImageList_Destroy(hIml HIMAGELIST) bool {
	ret, _, _ := syscall.Syscall(imageList_Destroy, 1,
		uintptr(hIml),
		0,
		0)

	return ret != 0
}

func ImageList_ReplaceIcon(himl HIMAGELIST, i int32, hicon HICON) int32 {
	ret, _, _ := syscall.Syscall(imageList_ReplaceIcon, 3,
		uintptr(himl),
		uintptr(i),
		uintptr(hicon))

	return int32(ret)
}

func InitCommonControlsEx(lpInitCtrls *INITCOMMONCONTROLSEX) bool {
	ret, _, _ := syscall.Syscall(initCommonControlsEx, 1,
		uintptr(unsafe.Pointer(lpInitCtrls)),
		0,
		0)

	return ret != 0
}
<commit_msg>Add some progress bar stuff<commit_after>// Copyright 2010 The win Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package win

import (
	"syscall"
	"unsafe"
)

// Button control messages
const (
	BCM_FIRST            = 0x1600
	BCM_GETIDEALSIZE     = BCM_FIRST + 0x0001
	BCM_SETIMAGELIST     = BCM_FIRST + 0x0002
	BCM_GETIMAGELIST     = BCM_FIRST + 0x0003
	BCM_SETTEXTMARGIN    = BCM_FIRST + 0x0004
	BCM_GETTEXTMARGIN    = BCM_FIRST + 0x0005
	BCM_SETDROPDOWNSTATE = BCM_FIRST + 0x0006
	BCM_SETSPLITINFO     = BCM_FIRST + 0x0007
	BCM_GETSPLITINFO     = BCM_FIRST + 0x0008
	BCM_SETNOTE          = BCM_FIRST + 0x0009
	BCM_GETNOTE          = BCM_FIRST + 0x000A
	BCM_GETNOTELENGTH    = BCM_FIRST + 0x000B
)

const (
	CCM_FIRST            = 0x2000
	CCM_LAST             = CCM_FIRST + 0x200
	CCM_SETBKCOLOR       = 8193
	CCM_SETCOLORSCHEME   = 8194
	CCM_GETCOLORSCHEME   = 8195
	CCM_GETDROPTARGET    = 8196
	CCM_SETUNICODEFORMAT = 8197
	CCM_GETUNICODEFORMAT = 8198
	CCM_SETVERSION       = 0x2007
	CCM_GETVERSION       = 0x2008
	CCM_SETNOTIFYWINDOW  = 0x2009
	CCM_SETWINDOWTHEME   = 0x200b
	CCM_DPISCALE         = 0x200c
)

// Common controls styles
const (
	CCS_TOP           = 1
	CCS_NOMOVEY       = 2
	CCS_BOTTOM        = 3
	CCS_NORESIZE      = 4
	CCS_NOPARENTALIGN = 8
	CCS_ADJUSTABLE    = 32
	CCS_NODIVIDER     = 64
	CCS_VERT          = 128
	CCS_LEFT          = 129
	CCS_NOMOVEX       = 130
	CCS_RIGHT         = 131
)

// InitCommonControlsEx flags
const (
	ICC_LISTVIEW_CLASSES   = 1
	ICC_TREEVIEW_CLASSES   = 2
	ICC_BAR_CLASSES        = 4
	ICC_TAB_CLASSES        = 8
	ICC_UPDOWN_CLASS       = 16
	ICC_PROGRESS_CLASS     = 32
	ICC_HOTKEY_CLASS       = 64
	ICC_ANIMATE_CLASS      = 128
	ICC_WIN95_CLASSES      = 255
	ICC_DATE_CLASSES       = 256
	ICC_USEREX_CLASSES     = 512
	ICC_COOL_CLASSES       = 1024
	ICC_INTERNET_CLASSES   = 2048
	ICC_PAGESCROLLER_CLASS = 4096
	ICC_NATIVEFNTCTL_CLASS = 8192
	INFOTIPSIZE            = 1024
	ICC_STANDARD_CLASSES   = 0x00004000
	ICC_LINK_CLASS         = 0x00008000
)

// WM_NOTITY messages
const (
	NM_FIRST           = 0
	NM_OUTOFMEMORY     = ^uint32(0)  // NM_FIRST - 1
	NM_CLICK           = ^uint32(1)  // NM_FIRST - 2
	NM_DBLCLK          = ^uint32(2)  // NM_FIRST - 3
	NM_RETURN          = ^uint32(3)  // NM_FIRST - 4
	NM_RCLICK          = ^uint32(4)  // NM_FIRST - 5
	NM_RDBLCLK         = ^uint32(5)  // NM_FIRST - 6
	NM_SETFOCUS        = ^uint32(6)  // NM_FIRST - 7
	NM_KILLFOCUS       = ^uint32(7)  // NM_FIRST - 8
	NM_CUSTOMDRAW      = ^uint32(11) // NM_FIRST - 12
	NM_HOVER           = ^uint32(12) // NM_FIRST - 13
	NM_NCHITTEST       = ^uint32(13) // NM_FIRST - 14
	NM_KEYDOWN         = ^uint32(14) // NM_FIRST - 15
	NM_RELEASEDCAPTURE = ^uint32(15) // NM_FIRST - 16
	NM_SETCURSOR       = ^uint32(16) // NM_FIRST - 17
	NM_CHAR            = ^uint32(17) // NM_FIRST - 18
	NM_TOOLTIPSCREATED = ^uint32(18) // NM_FIRST - 19
	NM_LAST            = ^uint32(98) // NM_FIRST - 99
)

// ProgressBar messages
const (
	PBM_SETPOS      = WM_USER + 2
	PBM_DELTAPOS    = WM_USER + 3
	PBM_SETSTEP     = WM_USER + 4
	PBM_STEPIT      = WM_USER + 5
	PBM_SETMARQUEE  = WM_USER + 10
	PBM_SETRANGE32  = 1030
	PBM_GETRANGE    = 1031
	PBM_GETPOS      = 1032
	PBM_SETBARCOLOR = 1033
	PBM_SETBKCOLOR  = CCM_SETBKCOLOR
)

// ProgressBar styles
const (
	PBS_SMOOTH   = 0x01
	PBS_VERTICAL = 0x04
	PBS_MARQUEE  = 0x08
)

// ImageList creation flags
const (
	ILC_MASK          = 0x00000001
	ILC_COLOR         = 0x00000000
	ILC_COLORDDB      = 0x000000FE
	ILC_COLOR4        = 0x00000004
	ILC_COLOR8        = 0x00000008
	ILC_COLOR16       = 0x00000010
	ILC_COLOR24       = 0x00000018
	ILC_COLOR32       = 0x00000020
	ILC_PALETTE       = 0x00000800
	ILC_MIRROR        = 0x00002000
	ILC_PERITEMMIRROR = 0x00008000
)

const (
	CDDS_PREPAINT      = 0x00000001
	CDDS_POSTPAINT     = 0x00000002
	CDDS_PREERASE      = 0x00000003
	CDDS_POSTERASE     = 0x00000004
	CDDS_ITEM          = 0x00010000
	CDDS_ITEMPREPAINT  = CDDS_ITEM | CDDS_PREPAINT
	CDDS_ITEMPOSTPAINT = CDDS_ITEM | CDDS_POSTPAINT
	CDDS_ITEMPREERASE  = CDDS_ITEM | CDDS_PREERASE
	CDDS_ITEMPOSTERASE = CDDS_ITEM | CDDS_POSTERASE
	CDDS_SUBITEM       = 0x00020000
)

const (
	CDIS_SELECTED         = 0x0001
	CDIS_GRAYED           = 0x0002
	CDIS_DISABLED         = 0x0004
	CDIS_CHECKED          = 0x0008
	CDIS_FOCUS            = 0x0010
	CDIS_DEFAULT          = 0x0020
	CDIS_HOT              = 0x0040
	CDIS_MARKED           = 0x0080
	CDIS_INDETERMINATE    = 0x0100
	CDIS_SHOWKEYBOARDCUES = 0x0200
	CDIS_NEARHOT          = 0x0400
	CDIS_OTHERSIDEHOT     = 0x0800
	CDIS_DROPHILITED      = 0x1000
)

const (
	CDRF_DODEFAULT         = 0x00000000
	CDRF_NEWFONT           = 0x00000002
	CDRF_SKIPDEFAULT       = 0x00000004
	CDRF_DOERASE           = 0x00000008
	CDRF_NOTIFYPOSTPAINT   = 0x00000010
	CDRF_NOTIFYITEMDRAW    = 0x00000020
	CDRF_NOTIFYSUBITEMDRAW = 0x00000020
	CDRF_NOTIFYPOSTERASE   = 0x00000040
	CDRF_SKIPPOSTPAINT     = 0x00000100
)

const (
	LPSTR_TEXTCALLBACK = ^uintptr(0)
	I_CHILDRENCALLBACK = -1
)

type HIMAGELIST HANDLE

type INITCOMMONCONTROLSEX struct {
	DwSize, DwICC uint32
}

type NMCUSTOMDRAW struct {
	Hdr         NMHDR
	DwDrawStage uint32
	Hdc         HDC
	Rc          RECT
	DwItemSpec  uintptr
	UItemState  uint32
	LItemlParam uintptr
}

var (
	// Library
	libcomctl32 uintptr

	// Functions
	imageList_Add         uintptr
	imageList_AddMasked   uintptr
	imageList_Create      uintptr
	imageList_Destroy     uintptr
	imageList_ReplaceIcon uintptr
	initCommonControlsEx  uintptr
)

func init() {
	// Library
	libcomctl32 = MustLoadLibrary("comctl32.dll")

	// Functions
	imageList_Add = MustGetProcAddress(libcomctl32, "ImageList_Add")
	imageList_AddMasked = MustGetProcAddress(libcomctl32, "ImageList_AddMasked")
	imageList_Create = MustGetProcAddress(libcomctl32, "ImageList_Create")
	imageList_Destroy = MustGetProcAddress(libcomctl32, "ImageList_Destroy")
	imageList_ReplaceIcon = MustGetProcAddress(libcomctl32, "ImageList_ReplaceIcon")
	initCommonControlsEx = MustGetProcAddress(libcomctl32, "InitCommonControlsEx")

	// Initialize the common controls we support
	var initCtrls INITCOMMONCONTROLSEX
	initCtrls.DwSize = uint32(unsafe.Sizeof(initCtrls))
	initCtrls.DwICC = ICC_LISTVIEW_CLASSES | ICC_PROGRESS_CLASS | ICC_TAB_CLASSES | ICC_TREEVIEW_CLASSES

	InitCommonControlsEx(&initCtrls)
}

func ImageList_Add(himl HIMAGELIST, hbmImage, hbmMask HBITMAP) int32 {
	ret, _, _ := syscall.Syscall(imageList_Add, 3,
		uintptr(himl),
		uintptr(hbmImage),
		uintptr(hbmMask))

	return int32(ret)
}

func ImageList_AddMasked(himl HIMAGELIST, hbmImage HBITMAP, crMask COLORREF) int32 {
	ret, _, _ := syscall.Syscall(imageList_AddMasked, 3,
		uintptr(himl),
		uintptr(hbmImage),
		uintptr(crMask))

	return int32(ret)
}

func ImageList_Create(cx, cy int32, flags uint32, cInitial, cGrow int32) HIMAGELIST {
	ret, _, _ := syscall.Syscall6(imageList_Create, 5,
		uintptr(cx),
		uintptr(cy),
		uintptr(flags),
		uintptr(cInitial),
		uintptr(cGrow),
		0)

	return HIMAGELIST(ret)
}

func ImageList_Destroy(hIml HIMAGELIST) bool {
	ret, _, _ := syscall.Syscall(imageList_Destroy, 1,
		uintptr(hIml),
		0,
		0)

	return ret != 0
}

func ImageList_ReplaceIcon(himl HIMAGELIST, i int32, hicon HICON) int32 {
	ret, _, _ := syscall.Syscall(imageList_ReplaceIcon, 3,
		uintptr(himl),
		uintptr(i),
		uintptr(hicon))

	return int32(ret)
}

func InitCommonControlsEx(lpInitCtrls *INITCOMMONCONTROLSEX) bool {
	ret, _, _ := syscall.Syscall(initCommonControlsEx, 1,
		uintptr(unsafe.Pointer(lpInitCtrls)),
		0,
		0)

	return ret != 0
}
<|endoftext|>


<commit_before>package raven

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

type testInterface struct{}

func (t *testInterface) Class() string   { return "sentry.interfaces.Test" }
func (t *testInterface) Culprit() string { return "codez" }

func TestShouldExcludeErr(t *testing.T) {
	regexpStrs := []string{"ERR_TIMEOUT", "should.exclude", "(?i)^big$"}

	client := &Client{
		Transport: newTransport(),
		Tags:      nil,
		context:   &context{},
		queue:     make(chan *outgoingPacket, MaxQueueBuffer),
	}

	if err := client.SetIgnoreErrors(regexpStrs); err != nil {
		t.Fatalf("invalid regexps %v: %v", regexpStrs, err)
	}

	testCases := []string{
		"there was a ERR_TIMEOUT in handlers.go",
		"do not log should.exclude at all",
		"BIG",
	}

	for _, tc := range testCases {
		if !client.shouldExcludeErr(tc) {
			t.Fatalf("failed to exclude err %q with regexps %v", tc, regexpStrs)
		}
	}
}

func TestPacketJSON(t *testing.T) {
	packet := &Packet{
		Project:     "1",
		EventID:     "2",
		Platform:    "linux",
		Culprit:     "caused_by",
		ServerName:  "host1",
		Release:     "721e41770371db95eee98ca2707686226b993eda",
		Environment: "production",
		Message:     "test",
		Timestamp:   Timestamp(time.Date(2000, 01, 01, 0, 0, 0, 0, time.UTC)),
		Level:       ERROR,
		Logger:      "com.getsentry.raven-go.logger-test-packet-json",
		Tags:        []Tag{Tag{"foo", "bar"}},
		Modules:     map[string]string{"foo": "bar"},
		Fingerprint: []string{"{{ default }}", "a-custom-fingerprint"},
		Interfaces:  []Interface{&Message{Message: "foo"}},
	}

	packet.AddTags(map[string]string{"foo": "foo"})
	packet.AddTags(map[string]string{"baz": "buzz"})

	expected := `{"message":"test","event_id":"2","project":"1","timestamp":"2000-01-01T00:00:00.00","level":"error","logger":"com.getsentry.raven-go.logger-test-packet-json","platform":"linux","culprit":"caused_by","server_name":"host1","release":"721e41770371db95eee98ca2707686226b993eda","environment":"production","tags":[["foo","bar"],["foo","foo"],["baz","buzz"]],"modules":{"foo":"bar"},"fingerprint":["{{ default }}","a-custom-fingerprint"],"logentry":{"message":"foo"}}`
	j, err := packet.JSON()
	if err != nil {
		t.Fatalf("JSON marshalling should not fail: %v", err)
	}
	actual := string(j)

	if actual != expected {
		t.Errorf("incorrect json; got %s, want %s", actual, expected)
	}
}

func TestPacketJSONNilInterface(t *testing.T) {
	packet := &Packet{
		Project:     "1",
		EventID:     "2",
		Platform:    "linux",
		Culprit:     "caused_by",
		ServerName:  "host1",
		Release:     "721e41770371db95eee98ca2707686226b993eda",
		Environment: "production",
		Message:     "test",
		Timestamp:   Timestamp(time.Date(2000, 01, 01, 0, 0, 0, 0, time.UTC)),
		Level:       ERROR,
		Logger:      "com.getsentry.raven-go.logger-test-packet-json",
		Tags:        []Tag{Tag{"foo", "bar"}},
		Modules:     map[string]string{"foo": "bar"},
		Fingerprint: []string{"{{ default }}", "a-custom-fingerprint"},
		Interfaces:  []Interface{&Message{Message: "foo"}, nil},
	}

	expected := `{"message":"test","event_id":"2","project":"1","timestamp":"2000-01-01T00:00:00.00","level":"error","logger":"com.getsentry.raven-go.logger-test-packet-json","platform":"linux","culprit":"caused_by","server_name":"host1","release":"721e41770371db95eee98ca2707686226b993eda","environment":"production","tags":[["foo","bar"]],"modules":{"foo":"bar"},"fingerprint":["{{ default }}","a-custom-fingerprint"],"logentry":{"message":"foo"}}`
	j, err := packet.JSON()
	if err != nil {
		t.Fatalf("JSON marshalling should not fail: %v", err)
	}
	actual := string(j)

	if actual != expected {
		t.Errorf("incorrect json; got %s, want %s", actual, expected)
	}
}

func TestPacketInit(t *testing.T) {
	packet := &Packet{Message: "a", Interfaces: []Interface{&testInterface{}}}
	packet.Init("foo")

	if packet.Project != "foo" {
		t.Error("incorrect Project:", packet.Project)
	}
	if packet.Culprit != "codez" {
		t.Error("incorrect Culprit:", packet.Culprit)
	}
	if packet.ServerName == "" {
		t.Errorf("ServerName should not be empty")
	}
	if packet.Level != ERROR {
		t.Errorf("incorrect Level: got %d, want %d", packet.Level, ERROR)
	}
	if packet.Logger != "root" {
		t.Errorf("incorrect Logger: got %s, want %s", packet.Logger, "root")
	}
	if time.Time(packet.Timestamp).IsZero() {
		t.Error("Timestamp is zero")
	}
	if len(packet.EventID) != 32 {
		t.Error("incorrect EventID:", packet.EventID)
	}
}

func TestSetDSN(t *testing.T) {
	client := &Client{}
	client.SetDSN("https://u:p@example.com/sentry/1")

	if client.url != "https://example.com/sentry/api/1/store/" {
		t.Error("incorrect url:", client.url)
	}
	if client.projectID != "1" {
		t.Error("incorrect projectID:", client.projectID)
	}
	if client.authHeader != "Sentry sentry_version=4, sentry_key=u, sentry_secret=p" {
		t.Error("incorrect authHeader:", client.authHeader)
	}
}

func TestNewClient(t *testing.T) {
	client := newClient(nil)
	if client.sampleRate != 1.0 {
		t.Error("invalid default sample rate")
	}
}

func TestSetSampleRate(t *testing.T) {
	client := &Client{}
	err := client.SetSampleRate(0.2)

	if err != nil {
		t.Error("invalid sample rate")
	}

	if client.sampleRate != 0.2 {
		t.Error("incorrect sample rate: ", client.sampleRate)
	}
}

func TestSetSampleRateInvalid(t *testing.T) {
	client := &Client{}
	err := client.SetSampleRate(-1.0)

	if err != ErrInvalidSampleRate {
		t.Error("invalid sample rate should return ErrInvalidSampleRate")
	}
}

func TestUnmarshalTag(t *testing.T) {
	actual := new(Tag)
	if err := json.Unmarshal([]byte(`["foo","bar"]`), actual); err != nil {
		t.Fatal("unable to decode JSON:", err)
	}

	expected := &Tag{Key: "foo", Value: "bar"}
	if !reflect.DeepEqual(actual, expected) {
		t.Errorf("incorrect Tag: wanted '%+v' and got '%+v'", expected, actual)
	}
}

func TestUnmarshalTags(t *testing.T) {
	tests := []struct {
		Input    string
		Expected Tags
	}{
		{
			`{"foo":"bar"}`,
			Tags{Tag{Key: "foo", Value: "bar"}},
		},
		{
			`[["foo","bar"],["bar","baz"]]`,
			Tags{Tag{Key: "foo", Value: "bar"}, Tag{Key: "bar", Value: "baz"}},
		},
	}

	for _, test := range tests {
		var actual Tags
		if err := json.Unmarshal([]byte(test.Input), &actual); err != nil {
			t.Fatal("unable to decode JSON:", err)
		}

		if !reflect.DeepEqual(actual, test.Expected) {
			t.Errorf("incorrect Tags: wanted '%+v' and got '%+v'", test.Expected, actual)
		}
	}
}

func TestMarshalTimestamp(t *testing.T) {
	timestamp := Timestamp(time.Date(2000, 01, 02, 03, 04, 05, 0, time.UTC))
	expected := `"2000-01-02T03:04:05.00"`

	actual, err := json.Marshal(timestamp)
	if err != nil {
		t.Error(err)
	}

	if string(actual) != expected {
		t.Errorf("incorrect string; got %s, want %s", actual, expected)
	}
}

func TestUnmarshalTimestamp(t *testing.T) {
	timestamp := `"2000-01-02T03:04:05.00"`
	expected := Timestamp(time.Date(2000, 01, 02, 03, 04, 05, 0, time.UTC))

	var actual Timestamp
	err := json.Unmarshal([]byte(timestamp), &actual)
	if err != nil {
		t.Error(err)
	}

	if actual != expected {
		t.Errorf("incorrect string; got %s, want %s", actual, expected)
	}
}

func TestNilClient(t *testing.T) {
	var client *Client = nil
	eventID, ch := client.Capture(nil, nil)
	if eventID != "" {
		t.Error("expected empty eventID:", eventID)
	}
	// wait on ch: no send should succeed immediately
	err := <-ch
	if err != nil {
		t.Error("expected nil err:", err)
	}
}
<commit_msg>Update client_test.go with gofmt for better report card.<commit_after>package raven

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

type testInterface struct{}

func (t *testInterface) Class() string   { return "sentry.interfaces.Test" }
func (t *testInterface) Culprit() string { return "codez" }

func TestShouldExcludeErr(t *testing.T) {
        regexpStrs := []string{"ERR_TIMEOUT", "should.exclude", "(?i)^big$"}

        client := &Client{
                Transport: newTransport(),
                Tags:      nil,
                context:   &context{},
                queue:     make(chan *outgoingPacket, MaxQueueBuffer),
        }

        if err := client.SetIgnoreErrors(regexpStrs); err != nil {
                t.Fatalf("invalid regexps %v: %v", regexpStrs, err)
        }

        testCases := []string{
                "there was a ERR_TIMEOUT in handlers.go",
                "do not log should.exclude at all",
                "BIG",
        }

        for _, tc := range testCases {
                if !client.shouldExcludeErr(tc) {
                        t.Fatalf("failed to exclude err %q with regexps %v", tc, regexpStrs)
                }
        }
}

func TestPacketJSON(t *testing.T) {
        packet := &Packet{
                Project:     "1",
                EventID:     "2",
                Platform:    "linux",
                Culprit:     "caused_by",
                ServerName:  "host1",
                Release:     "721e41770371db95eee98ca2707686226b993eda",
                Environment: "production",
                Message:     "test",
                Timestamp:   Timestamp(time.Date(2000, 01, 01, 0, 0, 0, 0, time.UTC)),
                Level:       ERROR,
                Logger:      "com.getsentry.raven-go.logger-test-packet-json",
                Tags:        []Tag{Tag{"foo", "bar"}},
                Modules:     map[string]string{"foo": "bar"},
                Fingerprint: []string{"{{ default }}", "a-custom-fingerprint"},
                Interfaces:  []Interface{&Message{Message: "foo"}},
        }

        packet.AddTags(map[string]string{"foo": "foo"})
        packet.AddTags(map[string]string{"baz": "buzz"})

        expected := `{"message":"test","event_id":"2","project":"1","timestamp":"2000-01-01T00:00:00.00","level":"error","logger":"com.getsentry.raven-go.logger-test-packet-json","platform":"linux","culprit":"caused_by","server_name":"host1","release":"721e41770371db95eee98ca2707686226b993eda","environment":"production","tags":[["foo","bar"],["foo","foo"],["baz","buzz"]],"modules":{"foo":"bar"},"fingerprint":["{{ default }}","a-custom-fingerprint"],"logentry":{"message":"foo"}}`
        j, err := packet.JSON()
        if err != nil {
                t.Fatalf("JSON marshalling should not fail: %v", err)
        }
        actual := string(j)

        if actual != expected {
                t.Errorf("incorrect json; got %s, want %s", actual, expected)
        }
}

func TestPacketJSONNilInterface(t *testing.T) {
        packet := &Packet{
                Project:     "1",
                EventID:     "2",
                Platform:    "linux",
                Culprit:     "caused_by",
                ServerName:  "host1",
                Release:     "721e41770371db95eee98ca2707686226b993eda",
                Environment: "production",
                Message:     "test",
                Timestamp:   Timestamp(time.Date(2000, 01, 01, 0, 0, 0, 0, time.UTC)),
                Level:       ERROR,
                Logger:      "com.getsentry.raven-go.logger-test-packet-json",
                Tags:        []Tag{Tag{"foo", "bar"}},
                Modules:     map[string]string{"foo": "bar"},
                Fingerprint: []string{"{{ default }}", "a-custom-fingerprint"},
                Interfaces:  []Interface{&Message{Message: "foo"}, nil},
        }

        expected := `{"message":"test","event_id":"2","project":"1","timestamp":"2000-01-01T00:00:00.00","level":"error","logger":"com.getsentry.raven-go.logger-test-packet-json","platform":"linux","culprit":"caused_by","server_name":"host1","release":"721e41770371db95eee98ca2707686226b993eda","environment":"production","tags":[["foo","bar"]],"modules":{"foo":"bar"},"fingerprint":["{{ default }}","a-custom-fingerprint"],"logentry":{"message":"foo"}}`
        j, err := packet.JSON()
        if err != nil {
                t.Fatalf("JSON marshalling should not fail: %v", err)
        }
        actual := string(j)

        if actual != expected {
                t.Errorf("incorrect json; got %s, want %s", actual, expected)
        }
}

func TestPacketInit(t *testing.T) {
        packet := &Packet{Message: "a", Interfaces: []Interface{&testInterface{}}}
        packet.Init("foo")

        if packet.Project != "foo" {
                t.Error("incorrect Project:", packet.Project)
        }
        if packet.Culprit != "codez" {
                t.Error("incorrect Culprit:", packet.Culprit)
        }
        if packet.ServerName == "" {
                t.Errorf("ServerName should not be empty")
        }
        if packet.Level != ERROR {
                t.Errorf("incorrect Level: got %d, want %d", packet.Level, ERROR)
        }
        if packet.Logger != "root" {
                t.Errorf("incorrect Logger: got %s, want %s", packet.Logger, "root")
        }
        if time.Time(packet.Timestamp).IsZero() {
                t.Error("Timestamp is zero")
        }
        if len(packet.EventID) != 32 {
                t.Error("incorrect EventID:", packet.EventID)
        }
}

func TestSetDSN(t *testing.T) {
        client := &Client{}
        client.SetDSN("https://u:p@example.com/sentry/1")

        if client.url != "https://example.com/sentry/api/1/store/" {
                t.Error("incorrect url:", client.url)
        }
        if client.projectID != "1" {
                t.Error("incorrect projectID:", client.projectID)
        }
        if client.authHeader != "Sentry sentry_version=4, sentry_key=u, sentry_secret=p" {
                t.Error("incorrect authHeader:", client.authHeader)
        }
}

func TestNewClient(t *testing.T) {
        client := newClient(nil)
        if client.sampleRate != 1.0 {
                t.Error("invalid default sample rate")
        }
}

func TestSetSampleRate(t *testing.T) {
        client := &Client{}
        err := client.SetSampleRate(0.2)

        if err != nil {
                t.Error("invalid sample rate")
        }

        if client.sampleRate != 0.2 {
                t.Error("incorrect sample rate: ", client.sampleRate)
        }
}

func TestSetSampleRateInvalid(t *testing.T) {
        client := &Client{}
        err := client.SetSampleRate(-1.0)

        if err != ErrInvalidSampleRate {
                t.Error("invalid sample rate should return ErrInvalidSampleRate")
        }
}

func TestUnmarshalTag(t *testing.T) {
        actual := new(Tag)
        if err := json.Unmarshal([]byte(`["foo","bar"]`), actual); err != nil {
                t.Fatal("unable to decode JSON:", err)
        }

        expected := &Tag{Key: "foo", Value: "bar"}
        if !reflect.DeepEqual(actual, expected) {
                t.Errorf("incorrect Tag: wanted '%+v' and got '%+v'", expected, actual)
        }
}

func TestUnmarshalTags(t *testing.T) {
        tests := []struct {
                Input    string
                Expected Tags
        }{
                {
                        `{"foo":"bar"}`,
                        Tags{Tag{Key: "foo", Value: "bar"}},
                },
                {
                        `[["foo","bar"],["bar","baz"]]`,
                        Tags{Tag{Key: "foo", Value: "bar"}, Tag{Key: "bar", Value: "baz"}},
                },
        }

        for _, test := range tests {
                var actual Tags
                if err := json.Unmarshal([]byte(test.Input), &actual); err != nil{
                        t.Fatal("unable to decode JSON:", err)
                }

                if !reflect.DeepEqual(actual, test.Expected) {
                        t.Errorf("incorrect Tags: wanted '%+v' and got '%+v'", test.Expected, actual)
                }
        }
}

func TestMarshalTimestamp(t *testing.T) {
        timestamp := Timestamp(time.Date(2000, 01, 02, 03, 04, 05, 0, time.UTC))
        expected := `"2000-01-02T03:04:05.00"`

        actual, err := json.Marshal(timestamp)
        if err != nil {
                t.Error(err)
        }

        if string(actual) != expected {
                t.Errorf("incorrect string; got %s, want %s", actual, expected)
        }
}

func TestUnmarshalTimestamp(t *testing.T) {
        timestamp := `"2000-01-02T03:04:05.00"`
        expected := Timestamp(time.Date(2000, 01, 02, 03, 04, 05, 0, time.UTC))

        var actual Timestamp
        err := json.Unmarshal([]byte(timestamp), &actual)
        if err != nil {
                t.Error(err)
        }

        if actual != expected {
                t.Errorf("incorrect string; got %s, want %s", actual, expected)
        }
}

func TestNilClient(t *testing.T) {
        var client *Client = nil
        eventID, ch := client.Capture(nil, nil)
        if eventID != "" {
                t.Error("expected empty eventID:", eventID)
        }
        // wait on ch: no send should succeed immediately
        err := <-ch
        if err != nil {
                t.Error("expected nil err:", err)
        }
}
<|endoftext|>


<commit_before>package untappd

import (
	"testing"
)

// TestNewClient tests for all possible errors which can occur during a call
// to NewClient.
func TestNewClient(t *testing.T) {
	var tests = []struct {
		description  string
		clientID     string
		clientSecret string
		expErr       error
	}{
		{"no client ID or client secret", "", "", ErrNoClientID},
		{"no client ID", "", "bar", ErrNoClientID},
		{"no client secret", "foo", "", ErrNoClientSecret},
		{"ok", "foo", "bar", nil},
	}

	for _, tt := range tests {
		if _, err := NewClient(tt.clientID, tt.clientSecret, nil); err != tt.expErr {
			t.Fatalf("unexpected error for test %q: %v != %v", tt.description, err, tt.expErr)
		}
	}
}
<commit_msg>client_test: add TestErrorError, to verify consistent Error.Error method output<commit_after>package untappd

import (
	"testing"
)

// TestNewClient tests for all possible errors which can occur during a call
// to NewClient.
func TestNewClient(t *testing.T) {
	var tests = []struct {
		description  string
		clientID     string
		clientSecret string
		expErr       error
	}{
		{"no client ID or client secret", "", "", ErrNoClientID},
		{"no client ID", "", "bar", ErrNoClientID},
		{"no client secret", "foo", "", ErrNoClientSecret},
		{"ok", "foo", "bar", nil},
	}

	for _, tt := range tests {
		if _, err := NewClient(tt.clientID, tt.clientSecret, nil); err != tt.expErr {
			t.Fatalf("unexpected error for test %q: %v != %v", tt.description, err, tt.expErr)
		}
	}
}

// TestErrorError tests for consistent output from the Error.Error method.
func TestErrorError(t *testing.T) {
	var tests = []struct {
		description string
		code        int
		eType       string
		details     string
		developer   string
		result      string
	}{
		{
			description: "only details",
			code:        500,
			eType:       "auth_failed",
			details:     "authentication failed",
			developer:   "",
			result:      "500 [auth_failed]: authentication failed",
		},
		{
			description: "only developer friendly",
			code:        501,
			eType:       "auth_failed",
			details:     "",
			developer:   "authentication failed due to server error",
			result:      "501 [auth_failed]: authentication failed due to server error",
		},
		{
			description: "both details and developer friendly",
			code:        502,
			eType:       "auth_failed",
			details:     "authentication failed",
			developer:   "authentication failed due to server error",
			result:      "502 [auth_failed]: authentication failed due to server error",
		},
	}

	for _, tt := range tests {
		err := &Error{
			Code:              tt.code,
			Detail:            tt.details,
			Type:              tt.eType,
			DeveloperFriendly: tt.developer,
		}

		if res := err.Error(); res != tt.result {
			t.Fatalf("unexpected result string for test %q: %q != %q", tt.description, res, tt.result)
		}
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2019 The Kubernetes 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 resources

import (
	"fmt"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/pkg/errors"
	"k8s.io/klog"
)

// InternetGateways: https://docs.aws.amazon.com/sdk-for-go/api/service/ec2/#EC2.DescribeInternetGateways

type InternetGateways struct{}

func (InternetGateways) MarkAndSweep(sess *session.Session, acct string, region string, set *Set) error {
	svc := ec2.New(sess, &aws.Config{Region: aws.String(region)})

	resp, err := svc.DescribeInternetGateways(nil)
	if err != nil {
		return err
	}

	vpcResp, err := svc.DescribeVpcs(&ec2.DescribeVpcsInput{
		Filters: []*ec2.Filter{
			{
				Name:   aws.String("isDefault"),
				Values: []*string{aws.String("true")},
			},
		},
	})

	if err != nil {
		return err
	}

	defaultVpc := vpcResp.Vpcs[0]

	for _, ig := range resp.InternetGateways {
		i := &internetGateway{Account: acct, Region: region, ID: *ig.InternetGatewayId}

		if set.Mark(i) {
			isDefault := false
			klog.Warningf("%s: deleting %T: %s", i.ARN(), ig, i.ID)

			for _, att := range ig.Attachments {
				if att.VpcId == defaultVpc.VpcId {
					isDefault = true
					break
				}

				detachReq := &ec2.DetachInternetGatewayInput{
					InternetGatewayId: ig.InternetGatewayId,
					VpcId:             att.VpcId,
				}

				if _, err := svc.DetachInternetGateway(detachReq); err != nil {
					klog.Warningf("%s: detach from %s failed: %v", i.ARN(), *att.VpcId, err)
				}
			}

			if isDefault {
				klog.Infof("%s: skipping delete as IGW is the default for the VPC %T: %s", i.ARN(), ig, i.ID)
				continue
			}

			deleteReq := &ec2.DeleteInternetGatewayInput{
				InternetGatewayId: ig.InternetGatewayId,
			}

			if _, err := svc.DeleteInternetGateway(deleteReq); err != nil {
				klog.Warningf("%s: delete failed: %v", i.ARN(), err)
			}
		}
	}

	return nil
}

func (InternetGateways) ListAll(sess *session.Session, acct, region string) (*Set, error) {
	svc := ec2.New(sess, aws.NewConfig().WithRegion(region))
	set := NewSet(0)
	input := &ec2.DescribeInternetGatewaysInput{}

	gateways, err := svc.DescribeInternetGateways(input)
	if err != nil {
		return set, errors.Wrapf(err, "couldn't describe internet gateways for %q in %q", acct, region)
	}
	now := time.Now()
	for _, gateway := range gateways.InternetGateways {
		arn := internetGateway{
			Account: acct,
			Region:  region,
			ID:      *gateway.InternetGatewayId,
		}.ARN()
		set.firstSeen[arn] = now
	}

	return set, nil
}

type internetGateway struct {
	Account string
	Region  string
	ID      string
}

func (ig internetGateway) ARN() string {
	return fmt.Sprintf("arn:aws:ec2:%s:%s:internet-gateway/%s", ig.Region, ig.Account, ig.ID)
}

func (ig internetGateway) ResourceKey() string {
	return ig.ARN()
}
<commit_msg>aws-janitor: don't assume a default VPC exists<commit_after>/*
Copyright 2019 The Kubernetes 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 resources

import (
	"fmt"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/pkg/errors"
	"k8s.io/klog"
)

// InternetGateways: https://docs.aws.amazon.com/sdk-for-go/api/service/ec2/#EC2.DescribeInternetGateways

type InternetGateways struct{}

func (InternetGateways) MarkAndSweep(sess *session.Session, acct string, region string, set *Set) error {
	svc := ec2.New(sess, &aws.Config{Region: aws.String(region)})

	resp, err := svc.DescribeInternetGateways(nil)
	if err != nil {
		return err
	}

	vpcResp, err := svc.DescribeVpcs(&ec2.DescribeVpcsInput{
		Filters: []*ec2.Filter{
			{
				Name:   aws.String("isDefault"),
				Values: []*string{aws.String("true")},
			},
		},
	})

	if err != nil {
		return err
	}

	// Use a map to tolerate both more than one default vpc
	// (shouldn't happen) as well as no default VPC (not uncommon)
	defaultVPC := make(map[string]bool)
	for _, vpc := range vpcResp.Vpcs {
		defaultVPC[aws.StringValue(vpc.VpcId)] = true
	}

	for _, ig := range resp.InternetGateways {
		i := &internetGateway{Account: acct, Region: region, ID: *ig.InternetGatewayId}

		if set.Mark(i) {
			isDefault := false
			klog.Warningf("%s: deleting %T: %s", i.ARN(), ig, i.ID)

			for _, att := range ig.Attachments {
				if defaultVPC[aws.StringValue(att.VpcId)] {
					isDefault = true
					break
				}

				detachReq := &ec2.DetachInternetGatewayInput{
					InternetGatewayId: ig.InternetGatewayId,
					VpcId:             att.VpcId,
				}

				if _, err := svc.DetachInternetGateway(detachReq); err != nil {
					klog.Warningf("%s: detach from %s failed: %v", i.ARN(), *att.VpcId, err)
				}
			}

			if isDefault {
				klog.Infof("%s: skipping delete as IGW is the default for the VPC %T: %s", i.ARN(), ig, i.ID)
				continue
			}

			deleteReq := &ec2.DeleteInternetGatewayInput{
				InternetGatewayId: ig.InternetGatewayId,
			}

			if _, err := svc.DeleteInternetGateway(deleteReq); err != nil {
				klog.Warningf("%s: delete failed: %v", i.ARN(), err)
			}
		}
	}

	return nil
}

func (InternetGateways) ListAll(sess *session.Session, acct, region string) (*Set, error) {
	svc := ec2.New(sess, aws.NewConfig().WithRegion(region))
	set := NewSet(0)
	input := &ec2.DescribeInternetGatewaysInput{}

	gateways, err := svc.DescribeInternetGateways(input)
	if err != nil {
		return set, errors.Wrapf(err, "couldn't describe internet gateways for %q in %q", acct, region)
	}
	now := time.Now()
	for _, gateway := range gateways.InternetGateways {
		arn := internetGateway{
			Account: acct,
			Region:  region,
			ID:      *gateway.InternetGatewayId,
		}.ARN()
		set.firstSeen[arn] = now
	}

	return set, nil
}

type internetGateway struct {
	Account string
	Region  string
	ID      string
}

func (ig internetGateway) ARN() string {
	return fmt.Sprintf("arn:aws:ec2:%s:%s:internet-gateway/%s", ig.Region, ig.Account, ig.ID)
}

func (ig internetGateway) ResourceKey() string {
	return ig.ARN()
}
<|endoftext|>


<commit_before>/*
Copyright 2017 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 cmd

import (
	"strings"

	"github.com/kubernetes/kompose/pkg/app"
	"github.com/kubernetes/kompose/pkg/kobject"
	log "github.com/sirupsen/logrus"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
)

// TODO: comment
var (
	ConvertOut                   string
	ConvertBuildRepo             string
	ConvertBuildBranch           string
	ConvertBuild                 string
	ConvertVolumes               string
	ConvertPVCRequestSize        string
	ConvertChart                 bool
	ConvertDeployment            bool
	ConvertDaemonSet             bool
	ConvertReplicationController bool
	ConvertYaml                  bool
	ConvertJSON                  bool
	ConvertStdout                bool
	ConvertEmptyVols             bool
	ConvertInsecureRepo          bool
	ConvertDeploymentConfig      bool
	ConvertReplicas              int
	ConvertController            string
	ConvertPushImage             bool
	ConvertPushImageRegistry     string
	ConvertOpt                   kobject.ConvertOptions
	ConvertYAMLIndent            int

	UpBuild string

	// WithKomposeAnnotation decides if we will add metadata about this convert to resource's annotation.
	// default is true.
	WithKomposeAnnotation bool

	// MultipleContainerMode which enables creating multi containers in a single pod is a developping function.
	// default is false
	MultipleContainerMode bool

	ServiceGroupMode string
	ServiceGroupName string
)

var convertCmd = &cobra.Command{
	Use:   "convert [file]",
	Short: "Convert a Docker Compose file",
	PreRun: func(cmd *cobra.Command, args []string) {

		// Check that build-config wasn't passed in with --provider=kubernetes
		if GlobalProvider == "kubernetes" && UpBuild == "build-config" {
			log.Fatalf("build-config is not a valid --build parameter with provider Kubernetes")
		}

		// Create the Convert Options.
		ConvertOpt = kobject.ConvertOptions{
			ToStdout:                    ConvertStdout,
			CreateChart:                 ConvertChart,
			GenerateYaml:                ConvertYaml,
			GenerateJSON:                ConvertJSON,
			Replicas:                    ConvertReplicas,
			InputFiles:                  GlobalFiles,
			OutFile:                     ConvertOut,
			Provider:                    GlobalProvider,
			CreateD:                     ConvertDeployment,
			CreateDS:                    ConvertDaemonSet,
			CreateRC:                    ConvertReplicationController,
			Build:                       ConvertBuild,
			BuildRepo:                   ConvertBuildRepo,
			BuildBranch:                 ConvertBuildBranch,
			PushImage:                   ConvertPushImage,
			PushImageRegistry:           ConvertPushImageRegistry,
			CreateDeploymentConfig:      ConvertDeploymentConfig,
			EmptyVols:                   ConvertEmptyVols,
			Volumes:                     ConvertVolumes,
			PVCRequestSize:              ConvertPVCRequestSize,
			InsecureRepository:          ConvertInsecureRepo,
			IsDeploymentFlag:            cmd.Flags().Lookup("deployment").Changed,
			IsDaemonSetFlag:             cmd.Flags().Lookup("daemon-set").Changed,
			IsReplicationControllerFlag: cmd.Flags().Lookup("replication-controller").Changed,
			Controller:                  strings.ToLower(ConvertController),
			IsReplicaSetFlag:            cmd.Flags().Lookup("replicas").Changed,
			IsDeploymentConfigFlag:      cmd.Flags().Lookup("deployment-config").Changed,
			YAMLIndent:                  ConvertYAMLIndent,
			WithKomposeAnnotation:       WithKomposeAnnotation,
			MultipleContainerMode:       MultipleContainerMode,
			ServiceGroupMode:            ServiceGroupMode,
			ServiceGroupName:            ServiceGroupName,
		}

		if ServiceGroupMode == "" && MultipleContainerMode {
			ConvertOpt.ServiceGroupMode = "label"
		}

		app.ValidateFlags(args, cmd, &ConvertOpt)
		app.ValidateComposeFile(&ConvertOpt)
	},
	Run: func(cmd *cobra.Command, args []string) {

		app.Convert(ConvertOpt)
	},
}

func init() {
	// Automatically grab environment variables
	viper.AutomaticEnv()

	// Kubernetes only
	convertCmd.Flags().BoolVarP(&ConvertChart, "chart", "c", false, "Create a Helm chart for converted objects")
	convertCmd.Flags().BoolVar(&ConvertDaemonSet, "daemon-set", false, "Generate a Kubernetes daemonset object (deprecated, use --controller instead)")
	convertCmd.Flags().BoolVarP(&ConvertDeployment, "deployment", "d", false, "Generate a Kubernetes deployment object (deprecated, use --controller instead)")
	convertCmd.Flags().BoolVar(&ConvertReplicationController, "replication-controller", false, "Generate a Kubernetes replication controller object (deprecated, use --controller instead)")
	convertCmd.Flags().StringVar(&ConvertController, "controller", "", `Set the output controller ("deployment"|"daemonSet"|"replicationController")`)
	convertCmd.Flags().MarkDeprecated("daemon-set", "use --controller")
	convertCmd.Flags().MarkDeprecated("deployment", "use --controller")
	convertCmd.Flags().MarkDeprecated("replication-controller", "use --controller")
	convertCmd.Flags().MarkHidden("chart")
	convertCmd.Flags().MarkHidden("daemon-set")
	convertCmd.Flags().MarkHidden("replication-controller")
	convertCmd.Flags().MarkHidden("deployment")
	convertCmd.Flags().BoolVar(&MultipleContainerMode, "multiple-container-mode", false, "Create multiple containers grouped by 'kompose.service.group' label")
	convertCmd.Flags().StringVar(&ServiceGroupMode, "service-group-mode", "", "Group multiple service to create single workload by `label`(`kompose.service.group`) or `volume`(shared volumes)")
	convertCmd.Flags().StringVar(&ServiceGroupName, "service-group-name", "", "Using with --service-group-mode=volume to specific a final service name for the group")
	convertCmd.Flags().MarkDeprecated("multiple-container-mode", "use --service-group-mode=label")

	// OpenShift only
	convertCmd.Flags().BoolVar(&ConvertDeploymentConfig, "deployment-config", true, "Generate an OpenShift deploymentconfig object")
	convertCmd.Flags().BoolVar(&ConvertInsecureRepo, "insecure-repository", false, "Use an insecure Docker repository for OpenShift ImageStream")
	convertCmd.Flags().StringVar(&ConvertBuildRepo, "build-repo", "", "Specify source repository for buildconfig (default remote origin)")
	convertCmd.Flags().StringVar(&ConvertBuildBranch, "build-branch", "", "Specify repository branch to use for buildconfig (default master)")
	convertCmd.Flags().MarkDeprecated("deployment-config", "use --controller")
	convertCmd.Flags().MarkHidden("deployment-config")
	convertCmd.Flags().MarkHidden("insecure-repository")
	convertCmd.Flags().MarkHidden("build-repo")
	convertCmd.Flags().MarkHidden("build-branch")

	// Standard between the two
	convertCmd.Flags().StringVar(&ConvertBuild, "build", "none", `Set the type of build ("local"|"build-config"(OpenShift only)|"none")`)
	convertCmd.Flags().BoolVar(&ConvertPushImage, "push-image", false, "If we should push the docker image we built")
	convertCmd.Flags().StringVar(&ConvertPushImageRegistry, "push-image-registry", "", "Specify registry for pushing image, which will override registry from image name.")
	convertCmd.Flags().BoolVarP(&ConvertYaml, "yaml", "y", false, "Generate resource files into YAML format")
	convertCmd.Flags().MarkDeprecated("yaml", "YAML is the default format now.")
	convertCmd.Flags().MarkShorthandDeprecated("y", "YAML is the default format now.")
	convertCmd.Flags().BoolVarP(&ConvertJSON, "json", "j", false, "Generate resource files into JSON format")
	convertCmd.Flags().BoolVar(&ConvertStdout, "stdout", false, "Print converted objects to stdout")
	convertCmd.Flags().StringVarP(&ConvertOut, "out", "o", "", "Specify a file name or directory to save objects to (if path does not exist, a file will be created)")
	convertCmd.Flags().IntVar(&ConvertReplicas, "replicas", 1, "Specify the number of replicas in the generated resource spec")
	convertCmd.Flags().StringVar(&ConvertVolumes, "volumes", "persistentVolumeClaim", `Volumes to be generated ("persistentVolumeClaim"|"emptyDir"|"hostPath" | "configMap")`)
	convertCmd.Flags().StringVar(&ConvertPVCRequestSize, "pvc-request-size", "", `Specify the size of pvc storage requests in the generated resource spec`)

	convertCmd.Flags().BoolVar(&WithKomposeAnnotation, "with-kompose-annotation", true, "Add kompose annotations to generated resource")

	// Deprecated commands
	convertCmd.Flags().BoolVar(&ConvertEmptyVols, "emptyvols", false, "Use Empty Volumes. Do not generate PVCs")
	convertCmd.Flags().MarkDeprecated("emptyvols", "emptyvols has been marked as deprecated. Use --volumes emptyDir")

	convertCmd.Flags().IntVar(&ConvertYAMLIndent, "indent", 2, "Spaces length to indent generated yaml files")

	// In order to 'separate' both OpenShift and Kubernetes only flags. A custom help page is created
	customHelp := `Usage:{{if .Runnable}}
  {{if .HasAvailableFlags}}{{appendIfNotPresent .UseLine "[flags]"}}{{else}}{{.UseLine}}{{end}}{{end}}{{if .HasAvailableSubCommands}}
  {{ .CommandPath}} [command]{{end}}{{if gt .Aliases 0}}

Aliases:
  {{.NameAndAliases}}
{{end}}{{if .HasExample}}

Examples:
{{ .Example }}{{end}}{{ if .HasAvailableSubCommands}}
Available Commands:{{range .Commands}}{{if .IsAvailableCommand}}
  {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{ if .HasAvailableLocalFlags}}

Kubernetes Flags:
  -c, --chart                    Create a Helm chart for converted objects
      --controller               Set the output controller ("deployment"|"daemonSet"|"replicationController")
      --service-group-mode       Group multiple service to create single workload by "label"("kompose.service.group") or "volume"(shared volumes)
      --service-group-name       Using with --service-group-mode=volume to specific a final service name for the group

OpenShift Flags:
      --build-branch             Specify repository branch to use for buildconfig (default is current branch name)
      --build-repo               Specify source repository for buildconfig (default is current branch's remote url)
      --insecure-repository      Specify to use insecure docker repository while generating Openshift image stream object

Flags:
{{.LocalFlags.FlagUsages | trimRightSpace}}{{end}}{{ if .HasAvailableInheritedFlags}}

Global Flags:
{{.InheritedFlags.FlagUsages | trimRightSpace}}{{end}}{{if .HasHelpSubCommands}}

Additional help topics:{{range .Commands}}{{if .IsHelpCommand}}
  {{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{ if .HasAvailableSubCommands }}
Use "{{.CommandPath}} [command] --help" for more information about a command.{{end}}
`
	// Set the help template + add the command to root
	convertCmd.SetUsageTemplate(customHelp)

	RootCmd.AddCommand(convertCmd)
}
<commit_msg>Remove [file] from convert helptext<commit_after>/*
Copyright 2017 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 cmd

import (
	"strings"

	"github.com/kubernetes/kompose/pkg/app"
	"github.com/kubernetes/kompose/pkg/kobject"
	log "github.com/sirupsen/logrus"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
)

// TODO: comment
var (
	ConvertOut                   string
	ConvertBuildRepo             string
	ConvertBuildBranch           string
	ConvertBuild                 string
	ConvertVolumes               string
	ConvertPVCRequestSize        string
	ConvertChart                 bool
	ConvertDeployment            bool
	ConvertDaemonSet             bool
	ConvertReplicationController bool
	ConvertYaml                  bool
	ConvertJSON                  bool
	ConvertStdout                bool
	ConvertEmptyVols             bool
	ConvertInsecureRepo          bool
	ConvertDeploymentConfig      bool
	ConvertReplicas              int
	ConvertController            string
	ConvertPushImage             bool
	ConvertPushImageRegistry     string
	ConvertOpt                   kobject.ConvertOptions
	ConvertYAMLIndent            int

	UpBuild string

	// WithKomposeAnnotation decides if we will add metadata about this convert to resource's annotation.
	// default is true.
	WithKomposeAnnotation bool

	// MultipleContainerMode which enables creating multi containers in a single pod is a developping function.
	// default is false
	MultipleContainerMode bool

	ServiceGroupMode string
	ServiceGroupName string
)

var convertCmd = &cobra.Command{
	Use:   "convert",
	Short: "Convert a Docker Compose file",
	PreRun: func(cmd *cobra.Command, args []string) {

		// Check that build-config wasn't passed in with --provider=kubernetes
		if GlobalProvider == "kubernetes" && UpBuild == "build-config" {
			log.Fatalf("build-config is not a valid --build parameter with provider Kubernetes")
		}

		// Create the Convert Options.
		ConvertOpt = kobject.ConvertOptions{
			ToStdout:                    ConvertStdout,
			CreateChart:                 ConvertChart,
			GenerateYaml:                ConvertYaml,
			GenerateJSON:                ConvertJSON,
			Replicas:                    ConvertReplicas,
			InputFiles:                  GlobalFiles,
			OutFile:                     ConvertOut,
			Provider:                    GlobalProvider,
			CreateD:                     ConvertDeployment,
			CreateDS:                    ConvertDaemonSet,
			CreateRC:                    ConvertReplicationController,
			Build:                       ConvertBuild,
			BuildRepo:                   ConvertBuildRepo,
			BuildBranch:                 ConvertBuildBranch,
			PushImage:                   ConvertPushImage,
			PushImageRegistry:           ConvertPushImageRegistry,
			CreateDeploymentConfig:      ConvertDeploymentConfig,
			EmptyVols:                   ConvertEmptyVols,
			Volumes:                     ConvertVolumes,
			PVCRequestSize:              ConvertPVCRequestSize,
			InsecureRepository:          ConvertInsecureRepo,
			IsDeploymentFlag:            cmd.Flags().Lookup("deployment").Changed,
			IsDaemonSetFlag:             cmd.Flags().Lookup("daemon-set").Changed,
			IsReplicationControllerFlag: cmd.Flags().Lookup("replication-controller").Changed,
			Controller:                  strings.ToLower(ConvertController),
			IsReplicaSetFlag:            cmd.Flags().Lookup("replicas").Changed,
			IsDeploymentConfigFlag:      cmd.Flags().Lookup("deployment-config").Changed,
			YAMLIndent:                  ConvertYAMLIndent,
			WithKomposeAnnotation:       WithKomposeAnnotation,
			MultipleContainerMode:       MultipleContainerMode,
			ServiceGroupMode:            ServiceGroupMode,
			ServiceGroupName:            ServiceGroupName,
		}

		if ServiceGroupMode == "" && MultipleContainerMode {
			ConvertOpt.ServiceGroupMode = "label"
		}

		app.ValidateFlags(args, cmd, &ConvertOpt)
		app.ValidateComposeFile(&ConvertOpt)
	},
	Run: func(cmd *cobra.Command, args []string) {

		app.Convert(ConvertOpt)
	},
}

func init() {
	// Automatically grab environment variables
	viper.AutomaticEnv()

	// Kubernetes only
	convertCmd.Flags().BoolVarP(&ConvertChart, "chart", "c", false, "Create a Helm chart for converted objects")
	convertCmd.Flags().BoolVar(&ConvertDaemonSet, "daemon-set", false, "Generate a Kubernetes daemonset object (deprecated, use --controller instead)")
	convertCmd.Flags().BoolVarP(&ConvertDeployment, "deployment", "d", false, "Generate a Kubernetes deployment object (deprecated, use --controller instead)")
	convertCmd.Flags().BoolVar(&ConvertReplicationController, "replication-controller", false, "Generate a Kubernetes replication controller object (deprecated, use --controller instead)")
	convertCmd.Flags().StringVar(&ConvertController, "controller", "", `Set the output controller ("deployment"|"daemonSet"|"replicationController")`)
	convertCmd.Flags().MarkDeprecated("daemon-set", "use --controller")
	convertCmd.Flags().MarkDeprecated("deployment", "use --controller")
	convertCmd.Flags().MarkDeprecated("replication-controller", "use --controller")
	convertCmd.Flags().MarkHidden("chart")
	convertCmd.Flags().MarkHidden("daemon-set")
	convertCmd.Flags().MarkHidden("replication-controller")
	convertCmd.Flags().MarkHidden("deployment")
	convertCmd.Flags().BoolVar(&MultipleContainerMode, "multiple-container-mode", false, "Create multiple containers grouped by 'kompose.service.group' label")
	convertCmd.Flags().StringVar(&ServiceGroupMode, "service-group-mode", "", "Group multiple service to create single workload by `label`(`kompose.service.group`) or `volume`(shared volumes)")
	convertCmd.Flags().StringVar(&ServiceGroupName, "service-group-name", "", "Using with --service-group-mode=volume to specific a final service name for the group")
	convertCmd.Flags().MarkDeprecated("multiple-container-mode", "use --service-group-mode=label")

	// OpenShift only
	convertCmd.Flags().BoolVar(&ConvertDeploymentConfig, "deployment-config", true, "Generate an OpenShift deploymentconfig object")
	convertCmd.Flags().BoolVar(&ConvertInsecureRepo, "insecure-repository", false, "Use an insecure Docker repository for OpenShift ImageStream")
	convertCmd.Flags().StringVar(&ConvertBuildRepo, "build-repo", "", "Specify source repository for buildconfig (default remote origin)")
	convertCmd.Flags().StringVar(&ConvertBuildBranch, "build-branch", "", "Specify repository branch to use for buildconfig (default master)")
	convertCmd.Flags().MarkDeprecated("deployment-config", "use --controller")
	convertCmd.Flags().MarkHidden("deployment-config")
	convertCmd.Flags().MarkHidden("insecure-repository")
	convertCmd.Flags().MarkHidden("build-repo")
	convertCmd.Flags().MarkHidden("build-branch")

	// Standard between the two
	convertCmd.Flags().StringVar(&ConvertBuild, "build", "none", `Set the type of build ("local"|"build-config"(OpenShift only)|"none")`)
	convertCmd.Flags().BoolVar(&ConvertPushImage, "push-image", false, "If we should push the docker image we built")
	convertCmd.Flags().StringVar(&ConvertPushImageRegistry, "push-image-registry", "", "Specify registry for pushing image, which will override registry from image name.")
	convertCmd.Flags().BoolVarP(&ConvertYaml, "yaml", "y", false, "Generate resource files into YAML format")
	convertCmd.Flags().MarkDeprecated("yaml", "YAML is the default format now.")
	convertCmd.Flags().MarkShorthandDeprecated("y", "YAML is the default format now.")
	convertCmd.Flags().BoolVarP(&ConvertJSON, "json", "j", false, "Generate resource files into JSON format")
	convertCmd.Flags().BoolVar(&ConvertStdout, "stdout", false, "Print converted objects to stdout")
	convertCmd.Flags().StringVarP(&ConvertOut, "out", "o", "", "Specify a file name or directory to save objects to (if path does not exist, a file will be created)")
	convertCmd.Flags().IntVar(&ConvertReplicas, "replicas", 1, "Specify the number of replicas in the generated resource spec")
	convertCmd.Flags().StringVar(&ConvertVolumes, "volumes", "persistentVolumeClaim", `Volumes to be generated ("persistentVolumeClaim"|"emptyDir"|"hostPath" | "configMap")`)
	convertCmd.Flags().StringVar(&ConvertPVCRequestSize, "pvc-request-size", "", `Specify the size of pvc storage requests in the generated resource spec`)

	convertCmd.Flags().BoolVar(&WithKomposeAnnotation, "with-kompose-annotation", true, "Add kompose annotations to generated resource")

	// Deprecated commands
	convertCmd.Flags().BoolVar(&ConvertEmptyVols, "emptyvols", false, "Use Empty Volumes. Do not generate PVCs")
	convertCmd.Flags().MarkDeprecated("emptyvols", "emptyvols has been marked as deprecated. Use --volumes emptyDir")

	convertCmd.Flags().IntVar(&ConvertYAMLIndent, "indent", 2, "Spaces length to indent generated yaml files")

	// In order to 'separate' both OpenShift and Kubernetes only flags. A custom help page is created
	customHelp := `Usage:{{if .Runnable}}
  {{if .HasAvailableFlags}}{{appendIfNotPresent .UseLine "[flags]"}}{{else}}{{.UseLine}}{{end}}{{end}}{{if .HasAvailableSubCommands}}
  {{ .CommandPath}} [command]{{end}}{{if gt .Aliases 0}}

Aliases:
  {{.NameAndAliases}}
{{end}}{{if .HasExample}}

Examples:
{{ .Example }}{{end}}{{ if .HasAvailableSubCommands}}
Available Commands:{{range .Commands}}{{if .IsAvailableCommand}}
  {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{ if .HasAvailableLocalFlags}}

Kubernetes Flags:
  -c, --chart                    Create a Helm chart for converted objects
      --controller               Set the output controller ("deployment"|"daemonSet"|"replicationController")
      --service-group-mode       Group multiple service to create single workload by "label"("kompose.service.group") or "volume"(shared volumes)
      --service-group-name       Using with --service-group-mode=volume to specific a final service name for the group

OpenShift Flags:
      --build-branch             Specify repository branch to use for buildconfig (default is current branch name)
      --build-repo               Specify source repository for buildconfig (default is current branch's remote url)
      --insecure-repository      Specify to use insecure docker repository while generating Openshift image stream object

Flags:
{{.LocalFlags.FlagUsages | trimRightSpace}}{{end}}{{ if .HasAvailableInheritedFlags}}

Global Flags:
{{.InheritedFlags.FlagUsages | trimRightSpace}}{{end}}{{if .HasHelpSubCommands}}

Additional help topics:{{range .Commands}}{{if .IsHelpCommand}}
  {{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{ if .HasAvailableSubCommands }}
Use "{{.CommandPath}} [command] --help" for more information about a command.{{end}}
`
	// Set the help template + add the command to root
	convertCmd.SetUsageTemplate(customHelp)

	RootCmd.AddCommand(convertCmd)
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"net/http"
	"time"

	"github.com/abrander/gansoi/web/client/browser"
	"github.com/abrander/gansoi/web/client/rest"
	"github.com/abrander/gansoi/web/client/router"
	"github.com/abrander/gansoi/web/client/template"
)

type (
	// Check mimics checks.Check.
	Check struct {
		ID        string        `json:"id"`
		AgentID   string        `json:"agent"`
		Interval  time.Duration `json:"interval"`
		Node      string        `json:"node"`
		Arguments interface{}   `json:"arguments"`
	}

	checkList struct {
		List []Check
	}
)

func (c checkList) DeleteCheck(id string) {
	fmt.Printf("Delete %s\n", id)
}

func (c checkList) EditCheck(id string) {
	fmt.Printf("Edit %s\n", id)
}

func main() {
	browser.WaitForLoad()

	url := browser.Url()

	c := rest.NewClient(url.RawPath+"/checks/", "")

	var cl checkList

	err := c.List(&cl.List)

	if err != nil {
		fmt.Println(err.Error())
	}

	for _, check := range cl.List {
		fmt.Printf("%s: %+v\n", check.AgentID, check.Arguments)
	}

	templates := template.NewCollection("template")

	r := router.New(browser.ID("main"))
	r.AddRoute("overview", func(c *router.Context) {
		c.Render(templates, "overview", nil)
	})

	r.AddRoute("gansoi", func(c *router.Context) {
		type nodeInfo struct {
			Name    string            `json:"name" storm:"id"`
			Started time.Time         `json:"started"`
			Updated time.Time         `json:"updated"`
			Raft    map[string]string `json:"raft"`
		}

		var nodes []nodeInfo
		resp, err := http.Get("/raft/nodes")
		if err != nil {
			c.Render(templates, "error", err.Error())
			return
		}

		decoder := json.NewDecoder(resp.Body)
		decoder.Decode(&nodes)
		err = c.Render(templates, "gansoi", nodes)
		if err != nil {
			c.Render(templates, "error", err.Error())
			return
		}
	})

	r.AddRoute("checks", func(c *router.Context) {
		c.Render(templates, "checks", cl)
	})

	r.Run()
}
<commit_msg>Update check list before displaying.<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"net/http"
	"time"

	"github.com/abrander/gansoi/web/client/browser"
	"github.com/abrander/gansoi/web/client/rest"
	"github.com/abrander/gansoi/web/client/router"
	"github.com/abrander/gansoi/web/client/template"
)

type (
	// Check mimics checks.Check.
	Check struct {
		ID        string        `json:"id"`
		AgentID   string        `json:"agent"`
		Interval  time.Duration `json:"interval"`
		Node      string        `json:"node"`
		Arguments interface{}   `json:"arguments"`
	}

	checkList struct {
		List []Check
	}
)

func (c checkList) DeleteCheck(id string) {
	fmt.Printf("Delete %s\n", id)
}

func (c checkList) EditCheck(id string) {
	fmt.Printf("Edit %s\n", id)
}

func main() {
	browser.WaitForLoad()

	url := browser.Url()

	checks := rest.NewClient(url.RawPath+"/checks/", "")

	templates := template.NewCollection("template")

	r := router.New(browser.ID("main"))
	r.AddRoute("overview", func(c *router.Context) {
		c.Render(templates, "overview", nil)
	})

	r.AddRoute("gansoi", func(c *router.Context) {
		type nodeInfo struct {
			Name    string            `json:"name" storm:"id"`
			Started time.Time         `json:"started"`
			Updated time.Time         `json:"updated"`
			Raft    map[string]string `json:"raft"`
		}

		var nodes []nodeInfo
		resp, err := http.Get("/raft/nodes")
		if err != nil {
			c.Render(templates, "error", err.Error())
			return
		}

		decoder := json.NewDecoder(resp.Body)
		decoder.Decode(&nodes)
		err = c.Render(templates, "gansoi", nodes)
		if err != nil {
			c.Render(templates, "error", err.Error())
			return
		}
	})

	r.AddRoute("checks", func(c *router.Context) {
		var list checkList
		err := checks.List(&list.List)

		if err != nil {
			fmt.Println(err.Error())
			c.Render(templates, "error", err.Error())
			return
		}

		err = c.Render(templates, "checks", list)
		if err != nil {
			c.Render(templates, "error", err.Error())
			return
		}
	})

	r.Run()
}
<|endoftext|>


<commit_before>package cmd

import (
	"fmt"
	"os"
	"text/tabwriter"
)
import (
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/aws/aws-sdk-go/service/iam"
	"github.com/fatih/color"
)

func display(item interface{}, err error, format ...string) {
	if err != nil {
		fmt.Println(err.Error())
		return
	}

	if len(format) > 0 {
		switch format[0] {
		case "raw":
			fmt.Println(item)
		default:
			lineDisplay(item)
		}
	} else {
		lineDisplay(item)
	}
}

var simpleDay = "Mon, Jan 2, 2006"

func lineDisplay(item interface{}) {
	w := tabwriter.NewWriter(os.Stdout, 20, 1, 1, ' ', 0)

	switch item.(type) {
	case *iam.ListUsersOutput:
		for _, user := range item.(*iam.ListUsersOutput).Users {
			fmt.Fprintln(w, fmt.Sprintf("name: %s\tid: %s\tcreated: %s\t", *user.UserName, *user.UserId, (*user.CreateDate).Format(simpleDay)))
		}
	case *iam.ListGroupsOutput:
		for _, group := range item.(*iam.ListGroupsOutput).Groups {
			fmt.Fprintln(w, fmt.Sprintf("name:%s\tid:%s\tcreated: %s\t", *group.GroupName, *group.GroupId, (*group.CreateDate).Format(simpleDay)))
		}
	case *iam.ListRolesOutput:
		for _, role := range item.(*iam.ListRolesOutput).Roles {
			fmt.Fprintln(w, fmt.Sprintf("name: %s\tid: %s\tcreated: %s\t", *role.RoleName, *role.RoleId, (*role.CreateDate).Format(simpleDay)))
		}
	case *iam.ListPoliciesOutput:
		for _, policy := range item.(*iam.ListPoliciesOutput).Policies {
			fmt.Fprintln(w, fmt.Sprintf("name: %s\tid: %s\tcreated: %s\t", *policy.PolicyName, *policy.PolicyId, (*policy.CreateDate).Format(simpleDay)))
		}
	case *ec2.DescribeInstancesOutput:
		for _, reserv := range item.(*ec2.DescribeInstancesOutput).Reservations {
			for _, inst := range reserv.Instances {
				fmt.Fprintln(w, fmt.Sprintf("id: %s\ttype: %s\tstate: %s\tpriv-ip: %s\tpub-ip: %s\tlaunched: %s\t", aws.StringValue(inst.InstanceId), aws.StringValue(inst.State.Name), aws.StringValue(inst.InstanceType), aws.StringValue(inst.PrivateIpAddress), aws.StringValue(inst.PublicIpAddress), (*inst.LaunchTime).Format(simpleDay)))
			}
		}
	case *ec2.Reservation:
		for _, inst := range item.(*ec2.Reservation).Instances {
			fmt.Fprintln(w, fmt.Sprintf("id: %s\ttype: %s\tstate: %s\tpriv-ip: %s\tpub-ip: %s\tlaunched: %s\t", aws.StringValue(inst.InstanceId), aws.StringValue(inst.State.Name), aws.StringValue(inst.InstanceType), aws.StringValue(inst.PrivateIpAddress), aws.StringValue(inst.PublicIpAddress), (*inst.LaunchTime).Format(simpleDay)))
		}
	case *ec2.DescribeVpcsOutput:
		for _, vpc := range item.(*ec2.DescribeVpcsOutput).Vpcs {
			fmt.Fprintln(w, fmt.Sprintf("id: %s\tdefault: %s\tstate: %s\tcidr: %s\t", *vpc.VpcId, printColorIf(*vpc.IsDefault), *vpc.State, *vpc.CidrBlock))
		}
	case *ec2.DescribeSubnetsOutput:
		for _, subnet := range item.(*ec2.DescribeSubnetsOutput).Subnets {
			fmt.Fprintln(w, fmt.Sprintf("id: %s\tpublic-vms: %s\tstate: %s\tcidr: %s\t", *subnet.SubnetId, printColorIf(*subnet.MapPublicIpOnLaunch, color.FgRed), *subnet.State, *subnet.CidrBlock))
		}
	default:
		fmt.Println(item)
		return
	}

	w.Flush()
}

func printColorIf(cond bool, c ...color.Attribute) string {
	col := color.FgGreen
	if len(c) > 0 {
		col = c[0]
	}

	var fn func(string, ...interface{}) string
	if cond {
		fn = color.New(col).SprintfFunc()
	} else {
		fn = color.New().SprintfFunc()
	}

	return fn(fmt.Sprintf("%t", cond))
}
<commit_msg>For resources display: using tab headers<commit_after>package cmd

import (
	"fmt"
	"os"
	"text/tabwriter"
)
import (
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/aws/aws-sdk-go/service/iam"
	"github.com/fatih/color"
)

func display(item interface{}, err error, format ...string) {
	if err != nil {
		fmt.Println(err.Error())
		return
	}

	if len(format) > 0 {
		switch format[0] {
		case "raw":
			fmt.Println(item)
		default:
			lineDisplay(item)
		}
	} else {
		lineDisplay(item)
	}
}

var simpleDay = "Mon, Jan 2, 2006"

func lineDisplay(item interface{}) {
	w := tabwriter.NewWriter(os.Stdout, 25, 1, 1, ' ', 0)

	switch item.(type) {
	case *iam.ListUsersOutput:
		fmt.Fprintln(w, "Name\tId\tCreated")
		for _, user := range item.(*iam.ListUsersOutput).Users {
			fmt.Fprintln(w, fmt.Sprintf("%s\t%s\t%s", *user.UserName, *user.UserId, (*user.CreateDate).Format(simpleDay)))
		}
	case *iam.ListGroupsOutput:
		fmt.Fprintln(w, "Name\tId\tCreated")
		for _, group := range item.(*iam.ListGroupsOutput).Groups {
			fmt.Fprintln(w, fmt.Sprintf("%s\t%s\t%s", *group.GroupName, *group.GroupId, (*group.CreateDate).Format(simpleDay)))
		}
	case *iam.ListRolesOutput:
		fmt.Fprintln(w, "Name\tId\tCreated")
		for _, role := range item.(*iam.ListRolesOutput).Roles {
			fmt.Fprintln(w, fmt.Sprintf("%s\t%s\t%s", *role.RoleName, *role.RoleId, (*role.CreateDate).Format(simpleDay)))
		}
	case *iam.ListPoliciesOutput:
		fmt.Fprintln(w, "Name\tId\tCreated")
		for _, policy := range item.(*iam.ListPoliciesOutput).Policies {
			fmt.Fprintln(w, fmt.Sprintf("%s\t%s\t%s", *policy.PolicyName, *policy.PolicyId, (*policy.CreateDate).Format(simpleDay)))
		}
	case *ec2.DescribeInstancesOutput:
		fmt.Fprintln(w, "Id\tType\tState\tPriv IP\tPub IP\tLaunched")
		for _, reserv := range item.(*ec2.DescribeInstancesOutput).Reservations {
			for _, inst := range reserv.Instances {
				fmt.Fprintln(w, fmt.Sprintf("%s\t%s\t%s\t%s\t%s\t%s", aws.StringValue(inst.InstanceId), aws.StringValue(inst.State.Name), aws.StringValue(inst.InstanceType), aws.StringValue(inst.PrivateIpAddress), aws.StringValue(inst.PublicIpAddress), (*inst.LaunchTime).Format(simpleDay)))
			}
		}
	case *ec2.Reservation:
		fmt.Fprintln(w, "Id\tType\tState\tPriv IP\tPub IP\tLaunched")
		for _, inst := range item.(*ec2.Reservation).Instances {
			fmt.Fprintln(w, fmt.Sprintf("%s\t%s\t%s\t%s\t%s\t%s", aws.StringValue(inst.InstanceId), aws.StringValue(inst.State.Name), aws.StringValue(inst.InstanceType), aws.StringValue(inst.PrivateIpAddress), aws.StringValue(inst.PublicIpAddress), (*inst.LaunchTime).Format(simpleDay)))
		}
	case *ec2.DescribeVpcsOutput:
		fmt.Fprintln(w, "Id\tDefault\tState\tCidr")
		for _, vpc := range item.(*ec2.DescribeVpcsOutput).Vpcs {
			fmt.Fprintln(w, fmt.Sprintf("%s\t%s\t%s\t%s", *vpc.VpcId, printColorIf(*vpc.IsDefault), *vpc.State, *vpc.CidrBlock))
		}
	case *ec2.DescribeSubnetsOutput:
		fmt.Fprintln(w, "Id\tPublic VMs\tState\tCidr")
		for _, subnet := range item.(*ec2.DescribeSubnetsOutput).Subnets {
			fmt.Fprintln(w, fmt.Sprintf("%s\t%s\t%s\t%s", *subnet.SubnetId, printColorIf(*subnet.MapPublicIpOnLaunch, color.FgRed), *subnet.State, *subnet.CidrBlock))
		}
	default:
		fmt.Println(item)
		return
	}

	w.Flush()
}

func printColorIf(cond bool, c ...color.Attribute) string {
	col := color.FgGreen
	if len(c) > 0 {
		col = c[0]
	}

	var fn func(string, ...interface{}) string
	if cond {
		fn = color.New(col).SprintfFunc()
	} else {
		fn = color.New().SprintfFunc()
	}

	return fn(fmt.Sprintf("%t", cond))
}
<|endoftext|>