<commit_before>// Copyright 2014, David Howden
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package itl defines data types for importing iTunes Library XML (plist) files.
package itl

import (
	"io"
	"io/ioutil"
	"time"

	"github.com/dhowden/plist"
)

// Library represents the root iTunes library entity which includes a map of tracks and slice of
// playlists.
type Library struct {
	MajorVersion        int `plist:"Major Version"`
	MinorVersion        int `plist:"Minor Version"`
	Date                time.Time
	ApplicationVersion  string `plist:"Application Version"`
	Features            int
	ShowContentRatings  bool   `plist:"Show Content Ratings"`
	MusicFolder         string `plist:"Music Folder"`
	LibraryPersistentID string `plist:"Library Persistent ID"`
	Tracks              map[string]Track
	Playlists           []Playlist
}

// Track represents an iTunes library track, which is a media file which can either be music or video.
// Items are identified in iTunes using the TrackID.
type Track struct {
	TrackID int `plist:"Track ID"`
	Name    string
	Artist  string

	Composer string
	Year     int
	Genre    string
	Kind     string
	Size     int

	BPM int

	TrackNumber int `plist:"Track Number"`
	TrackCount  int `plist:"Track Count"`
	DiscNumber  int `plist:"Disc Number"`
	DiscCount   int `plist:"Disc Count"`

	PartOfGaplessAlbum bool   `plist:"Part Of Gapless Album"`
	ContentRating      string `plist:"Content Rating"`

	Rating         int
	RatingComputed bool `plist:"Rating Computed"`
	Disabled       bool

	Album               string
	AlbumArtist         string `plist:"Album Artist"`
	AlbumRating         int    `plist:"Album Rating"`
	AlbumRatingComputed bool   `plist:"Album Rating Computed"`

	SortName        string `plist:"Sort Name"`
	SortArtist      string `plist:"Sort Artist"`
	SortAlbumArtist string `plist:"Sort Album Artist"`
	SortAlbum       string `plist:"Sort Album"`
	SortComposer    string `plist:"Sort Composer"`

	Clean  bool
	Series string

	TotalTime        int       `plist:"Total Time"`
	DateModified     time.Time `plist:"Date Modified"`
	DateAdded        time.Time `plist:"Date Added"`
	BitRate          int       `plist:"Bit Rate"`
	SampleRate       int       `plist:"Sample Rate"`
	VolumeAdjustment int       `plist:"Volume Adjustment"`
	Comments         string

	PlayCount   int       `plist:"Play Count"`
	PlayDate    int       `plist:"Play Date"`
	PlayDateUTC time.Time `plist:"Play Date UTC"`

	Protected bool
	Purchased bool

	SkipCount int       `plist:"Skip Count"`
	SkipDate  time.Time `plist:"Skip Date"`

	ArtworkCount int `plist:"Artwork Count"`

	Episode      string
	EpisodeOrder int  `plist:"Episode Order"`
	TVShow       bool `plist:"TV Show"`
	Season       int
	Podcast      bool
	ITunesU      bool `plist:"iTunesU"`
	Unplayed     bool

	PersistentID string `plist:"Persistent ID"`
	TrackType    string `plist:"Track Type"`
	Location     string
	FileType     int `plist:"File Type"`
	Movie        bool
	MusicVideo   bool `plist:"Music Video"`
	HD           bool
	HasVideo     bool `plist:"Has Video"`
	VideoHeight  int  `plist:"Video Height"`
	VideoWidth   int  `plist:"Video Width"`

	Grouping    string
	Compilation bool
	ReleaseDate time.Time `plist:"Release Date"`

	FileFolderCount    int `plist:"File Folder Count"`
	LibraryFolderCount int `plist:"Library Folder Count"`
}

// Playlist represents an iTunes playlist.
type Playlist struct {
	Name                 string
	Master               bool
	PlaylistID           int    `plist:"Playlist ID"`
	PlaylistPersistentID string `plist:"Playlist Persistent ID"`
	Visible              bool
	AllItems             bool           `plist:"All Items"`
	PlaylistItems        []PlaylistItem `plist:"Playlist Items"`
}

// PlaylistItem represents an individual track in a an iTunes playlist.
type PlaylistItem struct {
	TrackID int `plist:"Track ID"`
}

// ReadFromXML reads iTunes XML (plist) data from the underlying io.Reader
// and returns a Library struct.
func ReadFromXML(r io.Reader) (l Library, err error) {
	b, err := ioutil.ReadAll(r)
	if err != nil {
		return
	}
	err = plist.Unmarshal(b, &l)
	return
}
<commit_msg>Improved godoc<commit_after>// Copyright 2014, David Howden
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package itl defines data types for importing iTunes Library XML (plist) files.
package itl

import (
	"io"
	"io/ioutil"
	"time"

	"github.com/dhowden/plist"
)

// Library represents the root iTunes library entity which includes a map of tracks and slice of
// playlists.
type Library struct {
	MajorVersion        int `plist:"Major Version"`
	MinorVersion        int `plist:"Minor Version"`
	Date                time.Time
	ApplicationVersion  string `plist:"Application Version"`
	Features            int
	ShowContentRatings  bool   `plist:"Show Content Ratings"`
	MusicFolder         string `plist:"Music Folder"`
	LibraryPersistentID string `plist:"Library Persistent ID"`
	Tracks              map[string]Track
	Playlists           []Playlist
}

// Track represents an iTunes library track, which is a media file which can either be music or video.
// Items are identified in iTunes using the TrackID.
type Track struct {
	TrackID int `plist:"Track ID"`
	Name    string
	Artist  string

	Composer string
	Year     int
	Genre    string
	Kind     string
	Size     int

	BPM int

	TrackNumber int `plist:"Track Number"`
	TrackCount  int `plist:"Track Count"`
	DiscNumber  int `plist:"Disc Number"`
	DiscCount   int `plist:"Disc Count"`

	PartOfGaplessAlbum bool   `plist:"Part Of Gapless Album"`
	ContentRating      string `plist:"Content Rating"`

	Rating         int
	RatingComputed bool `plist:"Rating Computed"`
	Disabled       bool

	Album               string
	AlbumArtist         string `plist:"Album Artist"`
	AlbumRating         int    `plist:"Album Rating"`
	AlbumRatingComputed bool   `plist:"Album Rating Computed"`

	SortName        string `plist:"Sort Name"`
	SortArtist      string `plist:"Sort Artist"`
	SortAlbumArtist string `plist:"Sort Album Artist"`
	SortAlbum       string `plist:"Sort Album"`
	SortComposer    string `plist:"Sort Composer"`

	Clean  bool
	Series string

	TotalTime        int       `plist:"Total Time"`
	DateModified     time.Time `plist:"Date Modified"`
	DateAdded        time.Time `plist:"Date Added"`
	BitRate          int       `plist:"Bit Rate"`
	SampleRate       int       `plist:"Sample Rate"`
	VolumeAdjustment int       `plist:"Volume Adjustment"`
	Comments         string

	PlayCount   int       `plist:"Play Count"`
	PlayDate    int       `plist:"Play Date"`
	PlayDateUTC time.Time `plist:"Play Date UTC"`

	Protected bool
	Purchased bool

	SkipCount int       `plist:"Skip Count"`
	SkipDate  time.Time `plist:"Skip Date"`

	ArtworkCount int `plist:"Artwork Count"`

	Episode      string
	EpisodeOrder int  `plist:"Episode Order"`
	TVShow       bool `plist:"TV Show"`
	Season       int
	Podcast      bool
	ITunesU      bool `plist:"iTunesU"`
	Unplayed     bool

	PersistentID string `plist:"Persistent ID"`
	TrackType    string `plist:"Track Type"`
	Location     string
	FileType     int `plist:"File Type"`
	Movie        bool
	MusicVideo   bool `plist:"Music Video"`
	HD           bool
	HasVideo     bool `plist:"Has Video"`
	VideoHeight  int  `plist:"Video Height"`
	VideoWidth   int  `plist:"Video Width"`

	Grouping    string
	Compilation bool
	ReleaseDate time.Time `plist:"Release Date"`

	FileFolderCount    int `plist:"File Folder Count"`
	LibraryFolderCount int `plist:"Library Folder Count"`
}

// Playlist represents an iTunes playlist.
type Playlist struct {
	Name                 string
	Master               bool
	PlaylistID           int    `plist:"Playlist ID"`
	PlaylistPersistentID string `plist:"Playlist Persistent ID"`
	Visible              bool
	AllItems             bool           `plist:"All Items"`
	PlaylistItems        []PlaylistItem `plist:"Playlist Items"`
}

// PlaylistItem represents an individual track in a an iTunes playlist.
type PlaylistItem struct {
	TrackID int `plist:"Track ID"`
}

// ReadFromXML reads iTunes XML (plist) data from the underlying io.Reader
// returning the resuling Library.
func ReadFromXML(r io.Reader) (l Library, err error) {
	b, err := ioutil.ReadAll(r)
	if err != nil {
		return
	}
	err = plist.Unmarshal(b, &l)
	return
}
<|endoftext|>


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

// +build ignore

/*

Ld is the portable code for a modified version of the Plan 9 linker.  The original is documented at

	http://plan9.bell-labs.com/magic/man2html/1/8l

It reads object files (.5, .6, or .8 files) and writes a binary named for the
architecture (5.out, 6.out, 8.out) by default (if $GOOS is windows, a .exe suffix
will be appended).

Major changes include:
	- support for ELF, Mach-O and PE binary files
	- support for segmented stacks (this feature is implemented here, not in the compilers).

Original options are listed on the manual page linked above.

Usage:
	go tool 6l [flags] mainObj
Substitute 6l with 8l or 5l as appropriate.

Options new in this version:

	-d
		Elide the dynamic linking header.  With this option, the binary
		is statically linked and does not refer to a dynamic linker.  Without this option
		(the default), the binary's contents are identical but it is loaded with a dynamic
		linker. This flag cannot be used when $GOOS is windows.
	-H darwin     (only in 6l/8l)
		Write Apple Mach-O binaries (default when $GOOS is darwin)
	-H dragonfly  (only in 6l/8l)
		Write DragonFly ELF binaries (default when $GOOS is dragonfly)
	-H linux
		Write Linux ELF binaries (default when $GOOS is linux)
	-H freebsd
		Write FreeBSD ELF binaries (default when $GOOS is freebsd)
	-H netbsd
		Write NetBSD ELF binaries (default when $GOOS is netbsd)
	-H openbsd    (only in 6l/8l)
		Write OpenBSD ELF binaries (default when $GOOS is openbsd)
	-H windows    (only in 6l/8l)
		Write Windows PE32+ Console binaries (default when $GOOS is windows)
	-H windowsgui (only in 6l/8l)
		Write Windows PE32+ GUI binaries
	-I interpreter
		Set the ELF dynamic linker to use.
	-L dir1 -L dir2
		Search for libraries (package files) in dir1, dir2, etc.
		The default is the single location $GOROOT/pkg/$GOOS_$GOARCH.
	-r dir1:dir2:...
		Set the dynamic linker search path when using ELF.
	-s
		Omit the symbol table and debug information.
	-V
		Print the linker version.
	-X symbol value
		Set the value of an otherwise uninitialized string variable.
		The symbol name should be of the form importpath.name,
		as displayed in the symbol table printed by "go tool nm".
	-race
		Link with race detection libraries.
	-B value
		Add a NT_GNU_BUILD_ID note when using ELF.  The value
		should start with 0x and be an even number of hex digits.
	-Z
		Zero stack on function entry. This is expensive but it might
		be useful in cases where you are suffering from false positives
		during garbage collection and are willing to trade the CPU time
		for getting rid of the false positives.
		NOTE: it only eliminates false positives caused by other function
		calls, not false positives caused by dead temporaries stored in
		the current function call.
	-linkmode argument
		Set the linkmode.  The argument must be one of
		internal, external, or auto.  The default is auto.
		This sets the linking mode as described in
		../cgo/doc.go.
	-tmpdir dir
		Set the location to use for any temporary files.  The
		default is a newly created directory that is removed
		after the linker completes.  Temporary files are only
		used in external linking mode.
	-extld name
		Set the name of the external linker to use in external
		linking mode.  The default is "gcc".
	-extldflags flags
		Set space-separated trailing flags to pass to the
		external linker in external linking mode.  The default
		is to not pass any additional trailing flags.
*/
package main
<commit_msg>cmd/ld: document the -w flag, which disables DWARF generation<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build ignore

/*

Ld is the portable code for a modified version of the Plan 9 linker.  The original is documented at

	http://plan9.bell-labs.com/magic/man2html/1/8l

It reads object files (.5, .6, or .8 files) and writes a binary named for the
architecture (5.out, 6.out, 8.out) by default (if $GOOS is windows, a .exe suffix
will be appended).

Major changes include:
	- support for ELF, Mach-O and PE binary files
	- support for segmented stacks (this feature is implemented here, not in the compilers).

Original options are listed on the manual page linked above.

Usage:
	go tool 6l [flags] mainObj
Substitute 6l with 8l or 5l as appropriate.

Options new in this version:

	-d
		Elide the dynamic linking header.  With this option, the binary
		is statically linked and does not refer to a dynamic linker.  Without this option
		(the default), the binary's contents are identical but it is loaded with a dynamic
		linker. This flag cannot be used when $GOOS is windows.
	-H darwin     (only in 6l/8l)
		Write Apple Mach-O binaries (default when $GOOS is darwin)
	-H dragonfly  (only in 6l/8l)
		Write DragonFly ELF binaries (default when $GOOS is dragonfly)
	-H linux
		Write Linux ELF binaries (default when $GOOS is linux)
	-H freebsd
		Write FreeBSD ELF binaries (default when $GOOS is freebsd)
	-H netbsd
		Write NetBSD ELF binaries (default when $GOOS is netbsd)
	-H openbsd    (only in 6l/8l)
		Write OpenBSD ELF binaries (default when $GOOS is openbsd)
	-H windows    (only in 6l/8l)
		Write Windows PE32+ Console binaries (default when $GOOS is windows)
	-H windowsgui (only in 6l/8l)
		Write Windows PE32+ GUI binaries
	-I interpreter
		Set the ELF dynamic linker to use.
	-L dir1 -L dir2
		Search for libraries (package files) in dir1, dir2, etc.
		The default is the single location $GOROOT/pkg/$GOOS_$GOARCH.
	-r dir1:dir2:...
		Set the dynamic linker search path when using ELF.
	-s
		Omit the symbol table and debug information.
	-V
		Print the linker version.
	-w
		Omit the DWARF symbol table.
	-X symbol value
		Set the value of an otherwise uninitialized string variable.
		The symbol name should be of the form importpath.name,
		as displayed in the symbol table printed by "go tool nm".
	-race
		Link with race detection libraries.
	-B value
		Add a NT_GNU_BUILD_ID note when using ELF.  The value
		should start with 0x and be an even number of hex digits.
	-Z
		Zero stack on function entry. This is expensive but it might
		be useful in cases where you are suffering from false positives
		during garbage collection and are willing to trade the CPU time
		for getting rid of the false positives.
		NOTE: it only eliminates false positives caused by other function
		calls, not false positives caused by dead temporaries stored in
		the current function call.
	-linkmode argument
		Set the linkmode.  The argument must be one of
		internal, external, or auto.  The default is auto.
		This sets the linking mode as described in
		../cgo/doc.go.
	-tmpdir dir
		Set the location to use for any temporary files.  The
		default is a newly created directory that is removed
		after the linker completes.  Temporary files are only
		used in external linking mode.
	-extld name
		Set the name of the external linker to use in external
		linking mode.  The default is "gcc".
	-extldflags flags
		Set space-separated trailing flags to pass to the
		external linker in external linking mode.  The default
		is to not pass any additional trailing flags.
*/
package main
<|endoftext|>


<commit_before>package beanstalk

import (
	"errors"
	"sync"
	"time"
)

// The errors that can be returned by any of the Job functions.
var (
	ErrJobFinished    = errors.New("Job was already finished")
	ErrLostConnection = errors.New("The connection was lost")
)

// Command describes a beanstalk command that finishes a reserved job.
type Command int

// These are the caller ids that are used when calling back to the Consumer.
const (
	Bury Command = iota
	Delete
	Release
	Touch
)

// JobCommand is sent to the consumer that reserved the job with the purpose
// of finishing a job.
type JobCommand struct {
	Command  Command
	Job      *Job
	Priority uint32
	Delay    time.Duration
	Err      chan error
}

// Job contains the data of a reserved job.
type Job struct {
	ID        uint64
	Body      []byte
	Priority  uint32
	TTR       time.Duration
	touchedAt time.Time
	commandC  chan<- *JobCommand
	sync.Mutex
}

func (job *Job) cmd(command Command, priority uint32, delay time.Duration) (err error) {
	defer func() {
		if r := recover(); r != nil {
			err = ErrLostConnection
		}
	}()

	if job.commandC == nil {
		return ErrJobFinished
	}

	jobCommand := &JobCommand{
		Command:  command,
		Job:      job,
		Priority: priority,
		Delay:    delay,
		Err:      make(chan error),
	}

	job.commandC <- jobCommand
	if command != Touch {
		job.commandC = nil
	}

	return <-jobCommand.Err
}

// Bury tells the consumer to bury this job with the same priority as this job
// was inserted with.
func (job *Job) Bury() error {
	return job.cmd(Bury, job.Priority, 0)
}

// BuryWithPriority tells the consumer to bury this job with the specified
// priority.
func (job *Job) BuryWithPriority(priority uint32) error {
	return job.cmd(Bury, priority, 0)
}

// Delete tells the consumer to delete this job.
func (job *Job) Delete() error {
	return job.cmd(Delete, 0, 0)
}

// Release tells the consumer to release this job with the same priority as
// this job was inserted with and without delay.
func (job *Job) Release() error {
	return job.cmd(Release, job.Priority, 0)
}

// ReleaseWithParams tells the consumer to release this job with the specified
// priority and delay.
func (job *Job) ReleaseWithParams(priority uint32, delay time.Duration) error {
	return job.cmd(Release, priority, delay)
}

// Touch refreshes the reserve timer for this job.
func (job *Job) Touch() error {
	return job.cmd(Touch, 0, 0)
}

// Mark the time this job was touched.
func (job *Job) touched() {
	job.Lock()
	job.touchedAt = time.Now().UTC()
	job.Unlock()
}

// TouchAt returns the duration after which a call to Touch() should be
// triggered in order to keep the job reserved.
func (job *Job) TouchAt() time.Duration {
	var margin time.Duration

	switch {
	case job.TTR <= 3*time.Second:
		margin = 800 * time.Millisecond
	case job.TTR < 60*time.Second:
		margin = time.Second
	default:
		margin = 3 * time.Second
	}

	job.Lock()
	defer job.Unlock()

	return job.touchedAt.Add(job.TTR - margin).Sub(time.Now().UTC())
}
<commit_msg>When a job as a TTR of 3 seconds or less, a margin of 200ms should be more than enough<commit_after>package beanstalk

import (
	"errors"
	"sync"
	"time"
)

// The errors that can be returned by any of the Job functions.
var (
	ErrJobFinished    = errors.New("Job was already finished")
	ErrLostConnection = errors.New("The connection was lost")
)

// Command describes a beanstalk command that finishes a reserved job.
type Command int

// These are the caller ids that are used when calling back to the Consumer.
const (
	Bury Command = iota
	Delete
	Release
	Touch
)

// JobCommand is sent to the consumer that reserved the job with the purpose
// of finishing a job.
type JobCommand struct {
	Command  Command
	Job      *Job
	Priority uint32
	Delay    time.Duration
	Err      chan error
}

// Job contains the data of a reserved job.
type Job struct {
	ID        uint64
	Body      []byte
	Priority  uint32
	TTR       time.Duration
	touchedAt time.Time
	commandC  chan<- *JobCommand
	sync.Mutex
}

func (job *Job) cmd(command Command, priority uint32, delay time.Duration) (err error) {
	defer func() {
		if r := recover(); r != nil {
			err = ErrLostConnection
		}
	}()

	if job.commandC == nil {
		return ErrJobFinished
	}

	jobCommand := &JobCommand{
		Command:  command,
		Job:      job,
		Priority: priority,
		Delay:    delay,
		Err:      make(chan error),
	}

	job.commandC <- jobCommand
	if command != Touch {
		job.commandC = nil
	}

	return <-jobCommand.Err
}

// Bury tells the consumer to bury this job with the same priority as this job
// was inserted with.
func (job *Job) Bury() error {
	return job.cmd(Bury, job.Priority, 0)
}

// BuryWithPriority tells the consumer to bury this job with the specified
// priority.
func (job *Job) BuryWithPriority(priority uint32) error {
	return job.cmd(Bury, priority, 0)
}

// Delete tells the consumer to delete this job.
func (job *Job) Delete() error {
	return job.cmd(Delete, 0, 0)
}

// Release tells the consumer to release this job with the same priority as
// this job was inserted with and without delay.
func (job *Job) Release() error {
	return job.cmd(Release, job.Priority, 0)
}

// ReleaseWithParams tells the consumer to release this job with the specified
// priority and delay.
func (job *Job) ReleaseWithParams(priority uint32, delay time.Duration) error {
	return job.cmd(Release, priority, delay)
}

// Touch refreshes the reserve timer for this job.
func (job *Job) Touch() error {
	return job.cmd(Touch, 0, 0)
}

// Mark the time this job was touched.
func (job *Job) touched() {
	job.Lock()
	job.touchedAt = time.Now().UTC()
	job.Unlock()
}

// TouchAt returns the duration after which a call to Touch() should be
// triggered in order to keep the job reserved.
func (job *Job) TouchAt() time.Duration {
	var margin time.Duration

	switch {
	case job.TTR <= 3*time.Second:
		margin = 200 * time.Millisecond
	case job.TTR < 60*time.Second:
		margin = time.Second
	default:
		margin = 3 * time.Second
	}

	job.Lock()
	defer job.Unlock()

	return job.touchedAt.Add(job.TTR - margin).Sub(time.Now().UTC())
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io"
	"os"
)

// $ glacier us-east-1 job inventory <vault> <topic> <description>
// $ glacier us-east-1 job archive <vault> <archive> <topic> <description>
// $ glacier us-east-1 job list <vault>
// $ glacier us-east-1 job describe <vault> <job>
// $ glacier us-east-1 job get inventory <vault> <job>
// $ glacier us-east-1 job get archive <vault> <job> <file>

func job(args []string) {
	if len(args) < 1 {
		fmt.Println("no job command")
		os.Exit(1)
	}
	command := args[0]
	args = args[1:]

	switch command {
	case "inventory":
		if len(args) < 1 {
			fmt.Println("no vault")
			os.Exit(1)
		}
		vault := args[0]
		args = args[1:]

		var description, topic string
		if len(args) > 0 {
			topic = args[0]
		}
		if len(args) > 1 {
			description = args[1]
		}

		jobId, err := connection.InitiateInventoryJob(vault, topic, description)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
		fmt.Println(jobId)

	case "archive":
		if len(args) < 2 {
			fmt.Println("no vault")
			os.Exit(1)
		}
		vault := args[0]
		archive := args[1]
		args = args[2:]

		var description, topic string
		if len(args) > 0 {
			topic = args[0]
		}
		if len(args) > 1 {
			description = args[1]
		}

		jobId, err := connection.InitiateRetrievalJob(vault, archive, topic, description)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
		fmt.Println(jobId)

	case "list":
		if len(args) < 1 {
			fmt.Println("no vault")
			os.Exit(1)
		}
		vault := args[0]

		jobs, _, err := connection.ListJobs(vault, "", "", "", 0)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

		for _, v := range jobs {
			fmt.Println("Action:", v.Action)
			if v.Action == "ArchiveRetrieval" {
				fmt.Println("Archive ID:", v.ArchiveId)
				fmt.Println("Archive Size:", v.ArchiveSizeInBytes, prettySize(v.ArchiveSizeInBytes))
			}
			fmt.Println("Completed:", v.Completed)
			if v.Completed {
				fmt.Println("Completion Date:", v.CompletionDate)
			}
			fmt.Println("Creation Date:", v.CreationDate)
			if v.Completed && v.Action == "InventoryRetrieval" {
				fmt.Println("Invenotry Size:", v.InventorySizeInBytes, prettySize(uint64(v.InventorySizeInBytes)))
			}
			fmt.Println("Job Description:", v.JobDescription)
			fmt.Println("Job ID:", v.JobId)
			if v.Action == "ArchiveRetrieval" {
				fmt.Println("SHA256 Tree Hash:", v.SHA256TreeHash)
			}
			fmt.Println("SNS Topic:", v.SNSTopic)
			fmt.Println("Status Code:", v.StatusCode)
			fmt.Println("Status Message:", v.StatusMessage)
			fmt.Println("Vault ARN:", v.VaultARN)
			fmt.Println()
		}

	case "describe":
		if len(args) < 2 {
			fmt.Println("no vault and/or job id")
			os.Exit(1)
		}
		vault := args[0]
		jobId := args[1]

		job, err := connection.DescribeJob(vault, jobId)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

		fmt.Println("Action:", job.Action)
		if job.Action == "ArchiveRetrieval" {
			fmt.Println("Archive ID:", job.ArchiveId)
			fmt.Println("Archive Size:", job.ArchiveSizeInBytes, prettySize(job.ArchiveSizeInBytes))
		}
		fmt.Println("Completed:", job.Completed)
		if job.Completed {
			fmt.Println("Completion Date:", job.CompletionDate)
		}
		fmt.Println("Creation Date:", job.CreationDate)
		if job.Completed && job.Action == "InventoryRetrieval" {
			fmt.Println("Invenotry Size:", job.InventorySizeInBytes, prettySize(uint64(job.InventorySizeInBytes)))
		}
		fmt.Println("Job Description:", job.JobDescription)
		fmt.Println("Job ID:", job.JobId)
		if job.Action == "ArchiveRetrieval" {
			fmt.Println("SHA256 Tree Hash:", job.SHA256TreeHash)
		}
		fmt.Println("SNS Topic:", job.SNSTopic)
		fmt.Println("Status Code:", job.StatusCode)
		fmt.Println("Status Message:", job.StatusMessage)
		fmt.Println("Vault ARN:", job.VaultARN)

	case "get":
		if len(args) < 1 {
			fmt.Println("no job sub command")
			os.Exit(1)
		}
		subCommand := args[0]
		args = args[1:]

		switch subCommand {
		case "inventory":
			if len(args) < 2 {
				fmt.Println("no vault and/or job id")
				os.Exit(1)
			}
			vault := args[0]
			job := args[1]

			inventory, err := connection.GetInventoryJob(vault, job)
			if err != nil {
				fmt.Println(err)
				os.Exit(1)
			}

			fmt.Println("Vault ARN:", inventory.VaultARN)
			fmt.Println("Inventory Date:", inventory.InventoryDate)
			for _, v := range inventory.ArchiveList {
				fmt.Println("Archive ID:", v.ArchiveId)
				fmt.Println("Archive Description:", v.ArchiveDescription)
				fmt.Println("Creation Date:", v.CreationDate)
				fmt.Println("Size:", v.Size, prettySize(v.Size))
				fmt.Println("SHA256 Tree Hash:", v.SHA256TreeHash)
				fmt.Println()
			}

		case "archive":
			// TODO retrieve parts and handle errors
			if len(args) < 3 {
				fmt.Println("no vault, job id, and/or output file")
				os.Exit(1)
			}
			vault := args[0]
			job := args[1]
			fileName := args[2]

			file, err := os.Create(fileName)
			if err != nil {
				fmt.Println(err)
				os.Exit(1)
			}
			defer file.Close()

			archive, err := connection.GetRetrievalJob(vault, job, 0, 0)
			if err != nil {
				fmt.Println(err)
				os.Exit(1)
			}
			defer archive.Close()

			_, err = io.Copy(file, archive)
			if err != nil {
				fmt.Println(err)
				os.Exit(1)
			}
		default:
			fmt.Println("unknown job sub command:", subCommand)
			os.Exit(1)
		}
	default:
		fmt.Println("unknown job command:", command)
		os.Exit(1)
	}
}
<commit_msg>Cleaning up printing of inventory output.<commit_after>package main

import (
	"fmt"
	"io"
	"os"
)

// $ glacier us-east-1 job inventory <vault> <topic> <description>
// $ glacier us-east-1 job archive <vault> <archive> <topic> <description>
// $ glacier us-east-1 job list <vault>
// $ glacier us-east-1 job describe <vault> <job>
// $ glacier us-east-1 job get inventory <vault> <job>
// $ glacier us-east-1 job get archive <vault> <job> <file>

func job(args []string) {
	if len(args) < 1 {
		fmt.Println("no job command")
		os.Exit(1)
	}
	command := args[0]
	args = args[1:]

	switch command {
	case "inventory":
		if len(args) < 1 {
			fmt.Println("no vault")
			os.Exit(1)
		}
		vault := args[0]
		args = args[1:]

		var description, topic string
		if len(args) > 0 {
			topic = args[0]
		}
		if len(args) > 1 {
			description = args[1]
		}

		jobId, err := connection.InitiateInventoryJob(vault, topic, description)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
		fmt.Println(jobId)

	case "archive":
		if len(args) < 2 {
			fmt.Println("no vault")
			os.Exit(1)
		}
		vault := args[0]
		archive := args[1]
		args = args[2:]

		var description, topic string
		if len(args) > 0 {
			topic = args[0]
		}
		if len(args) > 1 {
			description = args[1]
		}

		jobId, err := connection.InitiateRetrievalJob(vault, archive, topic, description)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
		fmt.Println(jobId)

	case "list":
		if len(args) < 1 {
			fmt.Println("no vault")
			os.Exit(1)
		}
		vault := args[0]

		jobs, _, err := connection.ListJobs(vault, "", "", "", 0)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

		for _, v := range jobs {
			fmt.Println("Action:", v.Action)
			if v.Action == "ArchiveRetrieval" {
				fmt.Println("Archive ID:", v.ArchiveId)
				fmt.Println("Archive Size:", v.ArchiveSizeInBytes, prettySize(v.ArchiveSizeInBytes))
			}
			fmt.Println("Completed:", v.Completed)
			if v.Completed {
				fmt.Println("Completion Date:", v.CompletionDate)
			}
			fmt.Println("Creation Date:", v.CreationDate)
			if v.Completed && v.Action == "InventoryRetrieval" {
				fmt.Println("Invenotry Size:", v.InventorySizeInBytes, prettySize(uint64(v.InventorySizeInBytes)))
			}
			fmt.Println("Job Description:", v.JobDescription)
			fmt.Println("Job ID:", v.JobId)
			if v.Action == "ArchiveRetrieval" {
				fmt.Println("SHA256 Tree Hash:", v.SHA256TreeHash)
			}
			fmt.Println("SNS Topic:", v.SNSTopic)
			fmt.Println("Status Code:", v.StatusCode)
			fmt.Println("Status Message:", v.StatusMessage)
			fmt.Println("Vault ARN:", v.VaultARN)
			fmt.Println()
		}

	case "describe":
		if len(args) < 2 {
			fmt.Println("no vault and/or job id")
			os.Exit(1)
		}
		vault := args[0]
		jobId := args[1]

		job, err := connection.DescribeJob(vault, jobId)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

		fmt.Println("Action:", job.Action)
		if job.Action == "ArchiveRetrieval" {
			fmt.Println("Archive ID:", job.ArchiveId)
			fmt.Println("Archive Size:", job.ArchiveSizeInBytes, prettySize(job.ArchiveSizeInBytes))
		}
		fmt.Println("Completed:", job.Completed)
		if job.Completed {
			fmt.Println("Completion Date:", job.CompletionDate)
		}
		fmt.Println("Creation Date:", job.CreationDate)
		if job.Completed && job.Action == "InventoryRetrieval" {
			fmt.Println("Invenotry Size:", job.InventorySizeInBytes, prettySize(uint64(job.InventorySizeInBytes)))
		}
		fmt.Println("Job Description:", job.JobDescription)
		fmt.Println("Job ID:", job.JobId)
		if job.Action == "ArchiveRetrieval" {
			fmt.Println("SHA256 Tree Hash:", job.SHA256TreeHash)
		}
		fmt.Println("SNS Topic:", job.SNSTopic)
		fmt.Println("Status Code:", job.StatusCode)
		fmt.Println("Status Message:", job.StatusMessage)
		fmt.Println("Vault ARN:", job.VaultARN)

	case "get":
		if len(args) < 1 {
			fmt.Println("no job sub command")
			os.Exit(1)
		}
		subCommand := args[0]
		args = args[1:]

		switch subCommand {
		case "inventory":
			if len(args) < 2 {
				fmt.Println("no vault and/or job id")
				os.Exit(1)
			}
			vault := args[0]
			job := args[1]

			inventory, err := connection.GetInventoryJob(vault, job)
			if err != nil {
				fmt.Println(err)
				os.Exit(1)
			}

			fmt.Println("Vault ARN:", inventory.VaultARN)
			fmt.Println("Inventory Date:", inventory.InventoryDate)

			for _, v := range inventory.ArchiveList {
				fmt.Println()
				fmt.Println("Archive ID:", v.ArchiveId)
				fmt.Println("Archive Description:", v.ArchiveDescription)
				fmt.Println("Creation Date:", v.CreationDate)
				fmt.Println("Size:", v.Size, prettySize(v.Size))
				fmt.Println("SHA256 Tree Hash:", v.SHA256TreeHash)
			}

		case "archive":
			// TODO retrieve parts and handle errors
			if len(args) < 3 {
				fmt.Println("no vault, job id, and/or output file")
				os.Exit(1)
			}
			vault := args[0]
			job := args[1]
			fileName := args[2]

			file, err := os.Create(fileName)
			if err != nil {
				fmt.Println(err)
				os.Exit(1)
			}
			defer file.Close()

			archive, err := connection.GetRetrievalJob(vault, job, 0, 0)
			if err != nil {
				fmt.Println(err)
				os.Exit(1)
			}
			defer archive.Close()

			_, err = io.Copy(file, archive)
			if err != nil {
				fmt.Println(err)
				os.Exit(1)
			}
		default:
			fmt.Println("unknown job sub command:", subCommand)
			os.Exit(1)
		}
	default:
		fmt.Println("unknown job command:", command)
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>package azurerm

import (
	"fmt"
	"net/http"
	"testing"

	"github.com/hashicorp/terraform/helper/acctest"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
)

func TestAccAzureRMContainerRegistryName_validation(t *testing.T) {
	cases := []struct {
		Value    string
		ErrCount int
	}{
		{
			Value:    "four",
			ErrCount: 1,
		},
		{
			Value:    "5five",
			ErrCount: 0,
		},
		{
			Value:    "hello-world",
			ErrCount: 1,
		},
		{
			Value:    "hello_world",
			ErrCount: 1,
		},
		{
			Value:    "helloWorld",
			ErrCount: 0,
		},
		{
			Value:    "helloworld12",
			ErrCount: 0,
		},
		{
			Value:    "hello@world",
			ErrCount: 1,
		},
		{
			Value:    "qfvbdsbvipqdbwsbddbdcwqffewsqwcdw21ddwqwd3324120",
			ErrCount: 0,
		},
		{
			Value:    "qfvbdsbvipqdbwsbddbdcwqffewsqwcdw21ddwqwd33241202",
			ErrCount: 0,
		},
		{
			Value:    "qfvbdsbvipqdbwsbddbdcwqfjjfewsqwcdw21ddwqwd3324120",
			ErrCount: 1,
		},
	}

	for _, tc := range cases {
		_, errors := validateAzureRMContainerRegistryName(tc.Value, "azurerm_container_registry")

		if len(errors) != tc.ErrCount {
			t.Fatalf("Expected the Azure RM Container Registry Name to trigger a validation error: %v", errors)
		}
	}
}

func TestAccAzureRMContainerRegistry_basicClassic(t *testing.T) {
	ri := acctest.RandInt()
	rs := acctest.RandString(4)
	config := testAccAzureRMContainerRegistry_basicUnmanaged(ri, rs, testLocation(), "Classic")

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testCheckAzureRMContainerRegistryDestroy,
		Steps: []resource.TestStep{
			{
				Config: config,
				Check: resource.ComposeTestCheckFunc(
					testCheckAzureRMContainerRegistryExists("azurerm_container_registry.test"),
				),
			},
		},
	})
}

func TestAccAzureRMContainerRegistry_basicBasic(t *testing.T) {
	ri := acctest.RandInt()
	config := testAccAzureRMContainerRegistry_basicManaged(ri, testLocation(), "Basic")

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testCheckAzureRMContainerRegistryDestroy,
		Steps: []resource.TestStep{
			{
				Config: config,
				Check: resource.ComposeTestCheckFunc(
					testCheckAzureRMContainerRegistryExists("azurerm_container_registry.test"),
				),
			},
		},
	})
}

func TestAccAzureRMContainerRegistry_basicStandard(t *testing.T) {
	ri := acctest.RandInt()
	rs := acctest.RandString(4)
	config := testAccAzureRMContainerRegistry_basicManaged(ri, testLocation(), "Standard")

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testCheckAzureRMContainerRegistryDestroy,
		Steps: []resource.TestStep{
			{
				Config: config,
				Check: resource.ComposeTestCheckFunc(
					testCheckAzureRMContainerRegistryExists("azurerm_container_registry.test"),
				),
			},
		},
	})
}

func TestAccAzureRMContainerRegistry_basicPremium(t *testing.T) {
	ri := acctest.RandInt()
	config := testAccAzureRMContainerRegistry_basicManaged(ri, testLocation(), "Premium")

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testCheckAzureRMContainerRegistryDestroy,
		Steps: []resource.TestStep{
			{
				Config: config,
				Check: resource.ComposeTestCheckFunc(
					testCheckAzureRMContainerRegistryExists("azurerm_container_registry.test"),
				),
			},
		},
	})
}

func TestAccAzureRMContainerRegistry_complete(t *testing.T) {
	ri := acctest.RandInt()
	rs := acctest.RandString(4)
	config := testAccAzureRMContainerRegistry_complete(ri, rs, testLocation())

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testCheckAzureRMContainerRegistryDestroy,
		Steps: []resource.TestStep{
			{
				Config: config,
				Check: resource.ComposeTestCheckFunc(
					testCheckAzureRMContainerRegistryExists("azurerm_container_registry.test"),
				),
			},
		},
	})
}

func TestAccAzureRMContainerRegistry_update(t *testing.T) {
	ri := acctest.RandInt()
	rs := acctest.RandString(4)
	location := testLocation()
	config := testAccAzureRMContainerRegistry_complete(ri, rs, location)
	updatedConfig := testAccAzureRMContainerRegistry_completeUpdated(ri, rs, location)

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testCheckAzureRMContainerRegistryDestroy,
		Steps: []resource.TestStep{
			{
				Config: config,
				Check: resource.ComposeTestCheckFunc(
					testCheckAzureRMContainerRegistryExists("azurerm_container_registry.test"),
				),
			},
			{
				Config: updatedConfig,
				Check: resource.ComposeTestCheckFunc(
					testCheckAzureRMContainerRegistryExists("azurerm_container_registry.test"),
				),
			},
		},
	})
}

func testCheckAzureRMContainerRegistryDestroy(s *terraform.State) error {
	conn := testAccProvider.Meta().(*ArmClient).containerRegistryClient

	for _, rs := range s.RootModule().Resources {
		if rs.Type != "azurerm_container_registry" {
			continue
		}

		name := rs.Primary.Attributes["name"]
		resourceGroup := rs.Primary.Attributes["resource_group_name"]

		resp, err := conn.Get(resourceGroup, name)

		if err != nil {
			return nil
		}

		if resp.StatusCode != http.StatusNotFound {
			return fmt.Errorf("Container Registry still exists:\n%#v", resp)
		}
	}

	return nil
}

func testCheckAzureRMContainerRegistryExists(name string) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		// Ensure we have enough information in state to look up in API
		rs, ok := s.RootModule().Resources[name]
		if !ok {
			return fmt.Errorf("Not found: %s", name)
		}

		name := rs.Primary.Attributes["name"]
		resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"]
		if !hasResourceGroup {
			return fmt.Errorf("Bad: no resource group found in state for Container Registry: %s", name)
		}

		conn := testAccProvider.Meta().(*ArmClient).containerRegistryClient

		resp, err := conn.Get(resourceGroup, name)
		if err != nil {
			return fmt.Errorf("Bad: Get on containerRegistryClient: %+v", err)
		}

		if resp.StatusCode == http.StatusNotFound {
			return fmt.Errorf("Bad: Container Registry %q (resource group: %q) does not exist", name, resourceGroup)
		}

		return nil
	}
}

func testAccAzureRMContainerRegistry_basicManaged(rInt int, location string, sku string) string {
	return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
  name     = "testAccRg-%d"
  location = "%s"
}

resource "azurerm_container_registry" "test" {
  name                = "testacccr%d"
  resource_group_name = "${azurerm_resource_group.test.name}"
  location            = "${azurerm_resource_group.test.location}"
  sku                 = "%s"
  storage_account_id = "${azurerm_storage_account.test.id}"
}
`, rInt, location, rInt, sku)
}

func testAccAzureRMContainerRegistry_basicUnmanaged(rInt int, rStr string, location string, sku string) string {
	return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
  name     = "testAccRg-%d"
  location = "%s"
}

resource "azurerm_storage_account" "test" {
  name                     = "testaccsa%s"
  resource_group_name      = "${azurerm_resource_group.test.name}"
  location                 = "${azurerm_resource_group.test.location}"
  account_tier             = "Standard"
  account_replication_type = "LRS"
}

resource "azurerm_container_registry" "test" {
  name                = "testacccr%d"
  resource_group_name = "${azurerm_resource_group.test.name}"
  location            = "${azurerm_resource_group.test.location}"
  sku                 = "%s"
  storage_account_id = "${azurerm_storage_account.test.id}"
}
`, rInt, location, rStr, rInt, sku)
}

func testAccAzureRMContainerRegistry_complete(rInt int, rStr string, location string) string {
	return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
  name     = "testAccRg-%d"
  location = "%s"
}

resource "azurerm_storage_account" "test" {
  name                     = "testaccsa%s"
  resource_group_name      = "${azurerm_resource_group.test.name}"
  location                 = "${azurerm_resource_group.test.location}"
  account_tier             = "Standard"
  account_replication_type = "LRS"
}

resource "azurerm_container_registry" "test" {
  name                = "testacccr%d"
  resource_group_name = "${azurerm_resource_group.test.name}"
  location            = "${azurerm_resource_group.test.location}"
  admin_enabled       = false
  sku                 = "Classic"
  storage_account_id = "${azurerm_storage_account.test.id}"

  tags {
    environment = "production"
  }
}
`, rInt, location, rStr, rInt)
}

func testAccAzureRMContainerRegistry_completeUpdated(rInt int, rStr string, location string) string {
	return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
  name     = "testAccRg-%d"
  location = "%s"
}

resource "azurerm_storage_account" "test" {
  name                     = "testaccsa%s"
  resource_group_name      = "${azurerm_resource_group.test.name}"
  location                 = "${azurerm_resource_group.test.location}"
  account_tier             = "Standard"
  account_replication_type = "LRS"
}

resource "azurerm_container_registry" "test" {
  name                = "testacccr%d"
  resource_group_name = "${azurerm_resource_group.test.name}"
  location            = "${azurerm_resource_group.test.location}"
  admin_enabled       = true
  sku                 = "Classic"
  storage_account_id = "${azurerm_storage_account.test.id}"

  tags {
    environment = "production"
  }
}
`, rInt, location, rStr, rInt)
}
<commit_msg>Linting<commit_after>package azurerm

import (
	"fmt"
	"net/http"
	"testing"

	"github.com/hashicorp/terraform/helper/acctest"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
)

func TestAccAzureRMContainerRegistryName_validation(t *testing.T) {
	cases := []struct {
		Value    string
		ErrCount int
	}{
		{
			Value:    "four",
			ErrCount: 1,
		},
		{
			Value:    "5five",
			ErrCount: 0,
		},
		{
			Value:    "hello-world",
			ErrCount: 1,
		},
		{
			Value:    "hello_world",
			ErrCount: 1,
		},
		{
			Value:    "helloWorld",
			ErrCount: 0,
		},
		{
			Value:    "helloworld12",
			ErrCount: 0,
		},
		{
			Value:    "hello@world",
			ErrCount: 1,
		},
		{
			Value:    "qfvbdsbvipqdbwsbddbdcwqffewsqwcdw21ddwqwd3324120",
			ErrCount: 0,
		},
		{
			Value:    "qfvbdsbvipqdbwsbddbdcwqffewsqwcdw21ddwqwd33241202",
			ErrCount: 0,
		},
		{
			Value:    "qfvbdsbvipqdbwsbddbdcwqfjjfewsqwcdw21ddwqwd3324120",
			ErrCount: 1,
		},
	}

	for _, tc := range cases {
		_, errors := validateAzureRMContainerRegistryName(tc.Value, "azurerm_container_registry")

		if len(errors) != tc.ErrCount {
			t.Fatalf("Expected the Azure RM Container Registry Name to trigger a validation error: %v", errors)
		}
	}
}

func TestAccAzureRMContainerRegistry_basicClassic(t *testing.T) {
	ri := acctest.RandInt()
	rs := acctest.RandString(4)
	config := testAccAzureRMContainerRegistry_basicUnmanaged(ri, rs, testLocation(), "Classic")

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testCheckAzureRMContainerRegistryDestroy,
		Steps: []resource.TestStep{
			{
				Config: config,
				Check: resource.ComposeTestCheckFunc(
					testCheckAzureRMContainerRegistryExists("azurerm_container_registry.test"),
				),
			},
		},
	})
}

func TestAccAzureRMContainerRegistry_basicBasic(t *testing.T) {
	ri := acctest.RandInt()
	config := testAccAzureRMContainerRegistry_basicManaged(ri, testLocation(), "Basic")

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testCheckAzureRMContainerRegistryDestroy,
		Steps: []resource.TestStep{
			{
				Config: config,
				Check: resource.ComposeTestCheckFunc(
					testCheckAzureRMContainerRegistryExists("azurerm_container_registry.test"),
				),
			},
		},
	})
}

func TestAccAzureRMContainerRegistry_basicStandard(t *testing.T) {
	ri := acctest.RandInt()
	config := testAccAzureRMContainerRegistry_basicManaged(ri, testLocation(), "Standard")

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testCheckAzureRMContainerRegistryDestroy,
		Steps: []resource.TestStep{
			{
				Config: config,
				Check: resource.ComposeTestCheckFunc(
					testCheckAzureRMContainerRegistryExists("azurerm_container_registry.test"),
				),
			},
		},
	})
}

func TestAccAzureRMContainerRegistry_basicPremium(t *testing.T) {
	ri := acctest.RandInt()
	config := testAccAzureRMContainerRegistry_basicManaged(ri, testLocation(), "Premium")

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testCheckAzureRMContainerRegistryDestroy,
		Steps: []resource.TestStep{
			{
				Config: config,
				Check: resource.ComposeTestCheckFunc(
					testCheckAzureRMContainerRegistryExists("azurerm_container_registry.test"),
				),
			},
		},
	})
}

func TestAccAzureRMContainerRegistry_complete(t *testing.T) {
	ri := acctest.RandInt()
	rs := acctest.RandString(4)
	config := testAccAzureRMContainerRegistry_complete(ri, rs, testLocation())

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testCheckAzureRMContainerRegistryDestroy,
		Steps: []resource.TestStep{
			{
				Config: config,
				Check: resource.ComposeTestCheckFunc(
					testCheckAzureRMContainerRegistryExists("azurerm_container_registry.test"),
				),
			},
		},
	})
}

func TestAccAzureRMContainerRegistry_update(t *testing.T) {
	ri := acctest.RandInt()
	rs := acctest.RandString(4)
	location := testLocation()
	config := testAccAzureRMContainerRegistry_complete(ri, rs, location)
	updatedConfig := testAccAzureRMContainerRegistry_completeUpdated(ri, rs, location)

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testCheckAzureRMContainerRegistryDestroy,
		Steps: []resource.TestStep{
			{
				Config: config,
				Check: resource.ComposeTestCheckFunc(
					testCheckAzureRMContainerRegistryExists("azurerm_container_registry.test"),
				),
			},
			{
				Config: updatedConfig,
				Check: resource.ComposeTestCheckFunc(
					testCheckAzureRMContainerRegistryExists("azurerm_container_registry.test"),
				),
			},
		},
	})
}

func testCheckAzureRMContainerRegistryDestroy(s *terraform.State) error {
	conn := testAccProvider.Meta().(*ArmClient).containerRegistryClient

	for _, rs := range s.RootModule().Resources {
		if rs.Type != "azurerm_container_registry" {
			continue
		}

		name := rs.Primary.Attributes["name"]
		resourceGroup := rs.Primary.Attributes["resource_group_name"]

		resp, err := conn.Get(resourceGroup, name)

		if err != nil {
			return nil
		}

		if resp.StatusCode != http.StatusNotFound {
			return fmt.Errorf("Container Registry still exists:\n%#v", resp)
		}
	}

	return nil
}

func testCheckAzureRMContainerRegistryExists(name string) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		// Ensure we have enough information in state to look up in API
		rs, ok := s.RootModule().Resources[name]
		if !ok {
			return fmt.Errorf("Not found: %s", name)
		}

		name := rs.Primary.Attributes["name"]
		resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"]
		if !hasResourceGroup {
			return fmt.Errorf("Bad: no resource group found in state for Container Registry: %s", name)
		}

		conn := testAccProvider.Meta().(*ArmClient).containerRegistryClient

		resp, err := conn.Get(resourceGroup, name)
		if err != nil {
			return fmt.Errorf("Bad: Get on containerRegistryClient: %+v", err)
		}

		if resp.StatusCode == http.StatusNotFound {
			return fmt.Errorf("Bad: Container Registry %q (resource group: %q) does not exist", name, resourceGroup)
		}

		return nil
	}
}

func testAccAzureRMContainerRegistry_basicManaged(rInt int, location string, sku string) string {
	return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
  name     = "testAccRg-%d"
  location = "%s"
}

resource "azurerm_container_registry" "test" {
  name                = "testacccr%d"
  resource_group_name = "${azurerm_resource_group.test.name}"
  location            = "${azurerm_resource_group.test.location}"
  sku                 = "%s"
  storage_account_id = "${azurerm_storage_account.test.id}"
}
`, rInt, location, rInt, sku)
}

func testAccAzureRMContainerRegistry_basicUnmanaged(rInt int, rStr string, location string, sku string) string {
	return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
  name     = "testAccRg-%d"
  location = "%s"
}

resource "azurerm_storage_account" "test" {
  name                     = "testaccsa%s"
  resource_group_name      = "${azurerm_resource_group.test.name}"
  location                 = "${azurerm_resource_group.test.location}"
  account_tier             = "Standard"
  account_replication_type = "LRS"
}

resource "azurerm_container_registry" "test" {
  name                = "testacccr%d"
  resource_group_name = "${azurerm_resource_group.test.name}"
  location            = "${azurerm_resource_group.test.location}"
  sku                 = "%s"
  storage_account_id = "${azurerm_storage_account.test.id}"
}
`, rInt, location, rStr, rInt, sku)
}

func testAccAzureRMContainerRegistry_complete(rInt int, rStr string, location string) string {
	return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
  name     = "testAccRg-%d"
  location = "%s"
}

resource "azurerm_storage_account" "test" {
  name                     = "testaccsa%s"
  resource_group_name      = "${azurerm_resource_group.test.name}"
  location                 = "${azurerm_resource_group.test.location}"
  account_tier             = "Standard"
  account_replication_type = "LRS"
}

resource "azurerm_container_registry" "test" {
  name                = "testacccr%d"
  resource_group_name = "${azurerm_resource_group.test.name}"
  location            = "${azurerm_resource_group.test.location}"
  admin_enabled       = false
  sku                 = "Classic"
  storage_account_id = "${azurerm_storage_account.test.id}"

  tags {
    environment = "production"
  }
}
`, rInt, location, rStr, rInt)
}

func testAccAzureRMContainerRegistry_completeUpdated(rInt int, rStr string, location string) string {
	return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
  name     = "testAccRg-%d"
  location = "%s"
}

resource "azurerm_storage_account" "test" {
  name                     = "testaccsa%s"
  resource_group_name      = "${azurerm_resource_group.test.name}"
  location                 = "${azurerm_resource_group.test.location}"
  account_tier             = "Standard"
  account_replication_type = "LRS"
}

resource "azurerm_container_registry" "test" {
  name                = "testacccr%d"
  resource_group_name = "${azurerm_resource_group.test.name}"
  location            = "${azurerm_resource_group.test.location}"
  admin_enabled       = true
  sku                 = "Classic"
  storage_account_id = "${azurerm_storage_account.test.id}"

  tags {
    environment = "production"
  }
}
`, rInt, location, rStr, rInt)
}
<|endoftext|>


<commit_before>package log

import (
	"code.google.com/p/go.crypto/ssh/terminal"
	"fmt"
	"github.com/mgutz/ansi"
	"io"
	l "log"
	"os"
)

const (
	MUTE = iota
	DEBUG
	INFO
	WARN
	CRITICAL
	ERROR = 99
)

// configurations
var LogLevel = DEBUG
var Logger = l.New(defaultOutput, "", l.LstdFlags|l.Lshortfile)

var Colors = map[int]string{
	DEBUG:    "",
	INFO:     "green",
	WARN:     "yellow",
	CRITICAL: "red+b",
	ERROR:    "red",
}

var Tags = map[int]string{
	DEBUG:    "debug",
	INFO:     "info",
	WARN:     "warn",
	CRITICAL: "critical",
	ERROR:    "error",
}

type fder interface {
	Fd() uintptr
}

var defaultOutput io.Writer = os.Stderr

func SetOutput(out io.Writer, prefix string, flag int) {
	defaultOutput = out
	Logger = l.New(out, prefix, flag)
}

func Debugf(format string, args ...interface{}) {
	if levelOK(DEBUG) {
		logf(DEBUG, format, args...)
	}
}

func Debug(args ...interface{}) {
	if levelOK(DEBUG) {
		log(DEBUG, args...)
	}
}

func Infof(format string, args ...interface{}) {
	if levelOK(INFO) {
		logf(INFO, format, args...)
	}
}

func Info(args ...interface{}) {
	if levelOK(INFO) {
		log(INFO, args...)
	}
}

func Warnf(format string, args ...interface{}) {
	if levelOK(WARN) {
		logf(WARN, format, args...)
	}
}

func Warn(args ...interface{}) {
	if levelOK(WARN) {
		log(WARN, args...)
	}
}

func Critf(format string, args ...interface{}) {
	if levelOK(CRITICAL) {
		logf(CRITICAL, format, args...)
	}
}

func Crit(args ...interface{}) {
	if levelOK(CRITICAL) {
		log(CRITICAL, args...)
	}
}

func Errorf(format string, args ...interface{}) {
	if levelOK(ERROR) {
		logf(ERROR, format, args...)
	}
}

func Error(args ...interface{}) {
	if levelOK(ERROR) {
		log(ERROR, args...)
	}
}

func levelOK(level int) bool {
	if level == MUTE {
		return false
	}
	return LogLevel <= level
}

func logf(level int, format string, args ...interface{}) {
	format = "[" + Tags[level] + "] " + format
	output(level, fmt.Sprintf(format, args...))
}

func log(level int, args ...interface{}) {
	_args := []interface{}{"[" + Tags[level] + "] "}
	args = append(_args, args...)
	output(level, fmt.Sprint(args...))
}

func output(level int, v string) {
	if file, ok := defaultOutput.(fder); ok && terminal.IsTerminal(int(file.Fd())) {
		v = ansi.Color(v, Colors[level])
	}
	Logger.Output(4, v)
}
<commit_msg>add Fatal(f) for wrapping Error(f) + os.Exit(1)<commit_after>package log

import (
	"code.google.com/p/go.crypto/ssh/terminal"
	"fmt"
	"github.com/mgutz/ansi"
	"io"
	l "log"
	"os"
)

const (
	MUTE = iota
	DEBUG
	INFO
	WARN
	CRITICAL
	ERROR = 99
)

// configurations
var LogLevel = DEBUG
var Logger = l.New(defaultOutput, "", l.LstdFlags|l.Lshortfile)

var Colors = map[int]string{
	DEBUG:    "",
	INFO:     "green",
	WARN:     "yellow",
	CRITICAL: "red+b",
	ERROR:    "red",
}

var Tags = map[int]string{
	DEBUG:    "debug",
	INFO:     "info",
	WARN:     "warn",
	CRITICAL: "critical",
	ERROR:    "error",
}

type fder interface {
	Fd() uintptr
}

var defaultOutput io.Writer = os.Stderr

func SetOutput(out io.Writer, prefix string, flag int) {
	defaultOutput = out
	Logger = l.New(out, prefix, flag)
}

func Debugf(format string, args ...interface{}) {
	if levelOK(DEBUG) {
		logf(DEBUG, format, args...)
	}
}

func Debug(args ...interface{}) {
	if levelOK(DEBUG) {
		log(DEBUG, args...)
	}
}

func Infof(format string, args ...interface{}) {
	if levelOK(INFO) {
		logf(INFO, format, args...)
	}
}

func Info(args ...interface{}) {
	if levelOK(INFO) {
		log(INFO, args...)
	}
}

func Warnf(format string, args ...interface{}) {
	if levelOK(WARN) {
		logf(WARN, format, args...)
	}
}

func Warn(args ...interface{}) {
	if levelOK(WARN) {
		log(WARN, args...)
	}
}

func Critf(format string, args ...interface{}) {
	if levelOK(CRITICAL) {
		logf(CRITICAL, format, args...)
	}
}

func Crit(args ...interface{}) {
	if levelOK(CRITICAL) {
		log(CRITICAL, args...)
	}
}

func Errorf(format string, args ...interface{}) {
	if levelOK(ERROR) {
		logf(ERROR, format, args...)
	}
}

func Error(args ...interface{}) {
	if levelOK(ERROR) {
		log(ERROR, args...)
	}
}

func Fatalf(format string, args ...interface{}) {
	Errorf(format, args...)
	os.Exit(1)
}

func Fatal(args ...interface{}) {
	Error(args...)
	os.Exit(1)
}

func levelOK(level int) bool {
	if level == MUTE {
		return false
	}
	return LogLevel <= level
}

func logf(level int, format string, args ...interface{}) {
	format = "[" + Tags[level] + "] " + format
	output(level, fmt.Sprintf(format, args...))
}

func log(level int, args ...interface{}) {
	_args := []interface{}{"[" + Tags[level] + "] "}
	args = append(_args, args...)
	output(level, fmt.Sprint(args...))
}

func output(level int, v string) {
	if file, ok := defaultOutput.(fder); ok && terminal.IsTerminal(int(file.Fd())) {
		v = ansi.Color(v, Colors[level])
	}
	Logger.Output(4, v)
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"github.com/Stantheman/youtube-gif-go/config"
	"github.com/Stantheman/youtube-gif-go/logger"
	"github.com/Stantheman/youtube-gif-go/redisPool"
	"github.com/garyburd/redigo/redis"
	"os"
	"os/exec"
)

// pubsubmessages is the structure after decoding the JSON
// published via Redis
type pubsubmessage map[string]string

// workerfunc takes a decoded message and does work on it
type workerfunc func(payload pubsubmessage, workdir string) error

type worker struct {
	proc workerfunc
	tell string
}

var jobs = map[string]worker{
	"download": {
		proc: download,
		tell: "chop",
	},
	"chop": {
		proc: chop,
		tell: "stitch",
	},
	"stitch": {
		proc: stitch,
		tell: "",
	},
}

var conf = config.Get()
var l = logger.Get()

func main() {
	// get the worker name
	if len(os.Args) != 2 {
		fmt.Println("Usage: " + os.Args[0] + " worker-name")
		return
	}
	if _, ok := jobs[os.Args[1]]; ok != true {
		fmt.Println("Usage: " + os.Args[0] + " worker-name")
		return
	}

	jobname := os.Args[1]

	// set up the workdir
	if err := os.MkdirAll(conf.Worker.Dir, os.ModeDir); err != nil {
		l.Err(err.Error())
		return
	}

	// each worker listens to its -queue for work
	queue := jobname + "-queue"
	// get a nicely wrapped pubsub connection
	psc := redis.PubSubConn{redisPool.Pool.Get()}
	defer psc.Close()

	if err := psc.Subscribe(queue); err != nil {
		l.Err("Can't subscribe to the " + queue + ": " + err.Error())
		return
	}

	for {
		switch v := psc.Receive().(type) {
		case redis.Message:
			if err := work(v.Data, jobname); err != nil {
				l.Err(err.Error())
				return
			}
		case redis.Subscription:
			fmt.Printf("%s: %s %d\n", v.Channel, v.Kind, v.Count)
		case error:
			fmt.Println(v.Error())
			return
		}
	}
}

/* update tells redis about updates to images, including status,
sending pubsub messages, and potentially adding the image to
the list of active images.
It takes both the serialized and unserialized json data for easy resubmission.
Not sure how I feel about that, but doing the work twice seems silly too.
I make up for feeling bad by thinking I could be passing different data for the
next job*/
func update(data []byte, payload pubsubmessage, job string) (err error) {
	// get ready to update the image status and continue pubsubbin
	c := redisPool.Pool.Get()
	keyname := "gif:" + payload["id"]

	// if there's no one left to tell, we're done processing
	if jobs[job].tell == "" {
		// Add the image to active_image list, set image to avail
		c.Send("MULTI")
		c.Send("RPUSH", "active_images", payload["id"])
		c.Send("HSET", keyname, "status", "available")
		if _, err := c.Do("EXEC"); err != nil {
			return err
		}
		return nil
	}

	// otherwise we need to update status and tell people
	c.Send("MULTI")
	c.Send("HSET", keyname, "status", "pending "+jobs[job].tell)
	c.Send("PUBLISH", jobs[job].tell+"-queue", data)
	if _, err := c.Do("EXEC"); err != nil {
		return err
	}
	return nil
}

/* work is a wrapper method that does the setup and teardown around jobs */
func work(data []byte, job string) (err error) {
	// decode json
	payload := make(map[string]string)
	if err := json.Unmarshal(data, &payload); err != nil {
		return err
	}

	workspace := conf.Worker.Dir + "/" + payload["id"] + "/"

	// make workspace
	if err := os.MkdirAll(workspace, 0777); err != nil {
		return err
	}

	// do the job
	if err := jobs[job].proc(payload, workspace); err != nil {
		return err
	}

	// update the status
	if err := update(data, payload, job); err != nil {
		return err
	}

	return nil
}

/* download uses youtube-dl to take a youtube URL and place it on disk */
func download(payload pubsubmessage, workspace string) error {

	// 1.youtube
	outFile := workspace + payload["id"] + ".youtube"

	// needs config for youtube-dl path
	cmd := exec.Command("/opt/youtube-dl",
		"--no-progress",
		"--max-filesize", "10M",
		"--output", outFile,
		"--write-info-json",
		"--quiet",
		"--format", "worstvideo",
		payload["url"],
	)

	// needs logging, stdout
	if err := cmd.Run(); err != nil {
		return err
	}

	// verify that the file is actually there
	if _, err := os.Stat(outFile); os.IsNotExist(err) {
		return err
	}

	return nil
}

/* chop takes a workspace directory with an <id>.youtube file
and uses mplayer to create a PNG file for every frame in the video*/
func chop(payload pubsubmessage, workspace string) error {

	// https://www.youtube.com/watch?v=dgKGixi8bp8 short video
	// need to think more about more specific flags
	cmd := exec.Command("/usr/bin/mplayer",
		"-ss", "0",
		"-vo", "png:z=9:outdir="+workspace,
		"-ao", "null",
		"-really-quiet",
		workspace+payload["id"]+".youtube",
	)

	if output, err := cmd.CombinedOutput(); err != nil {
		fmt.Printf("%#v\n", cmd)
		l.Err(string(output))
		return err
	}

	// bash script would rm [0,2,4,6,8].png to make gifmaking quicker, gif smaller
	// think about doing that at some boundary

	// mplayer uses the following format to make pngs, so the 00000001.png assumption
	// is technically...ok. replace w/ subdir for pngs, subdir per job type?
	//   snprintf (buf, 100, "%s/%s%08d.png", png_outdir, png_outfile_prefix, ++framenum);
	// verify that the file is actually there
	if _, err := os.Stat(workspace + "00000001.png"); os.IsNotExist(err) {
		return err
	}

	return nil
}

/* stitch takes a workspace directory of PNG files and transforms them
into a gif on STDOUT using imagemagick, which is piped into
gifsicle for optimization */
func stitch(payload pubsubmessage, workspace string) error {

	// hmmmmm
	gifname := "/srv/git/go/src/github.com/Stantheman/youtube-gif-go/gifs/" +
		payload["id"] + ".gif"

	// should be configurable, make proper tmpdir etc
	// mad lazy, shell + constant filename
	cmd := exec.Command("/bin/bash", "-c",
		"/usr/bin/convert +repage -fuzz 1.6% -delay 6 -loop 0 "+workspace+"*.png "+
			"-layers OptimizePlus -layers OptimizeTransparency gif:- "+
			"| /usr/bin/gifsicle -O3 --colors 256 > "+gifname,
	)

	if err := cmd.Run(); err != nil {
		return err
	}

	// verify that the file is actually there
	if _, err := os.Stat(gifname); os.IsNotExist(err) {
		return err
	}

	return nil
}
<commit_msg>dont allow webm files<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"github.com/Stantheman/youtube-gif-go/config"
	"github.com/Stantheman/youtube-gif-go/logger"
	"github.com/Stantheman/youtube-gif-go/redisPool"
	"github.com/garyburd/redigo/redis"
	"os"
	"os/exec"
)

// pubsubmessages is the structure after decoding the JSON
// published via Redis
type pubsubmessage map[string]string

// workerfunc takes a decoded message and does work on it
type workerfunc func(payload pubsubmessage, workdir string) error

type worker struct {
	proc workerfunc
	tell string
}

var jobs = map[string]worker{
	"download": {
		proc: download,
		tell: "chop",
	},
	"chop": {
		proc: chop,
		tell: "stitch",
	},
	"stitch": {
		proc: stitch,
		tell: "",
	},
}

var conf = config.Get()
var l = logger.Get()

func main() {
	// get the worker name
	if len(os.Args) != 2 {
		fmt.Println("Usage: " + os.Args[0] + " worker-name")
		return
	}
	if _, ok := jobs[os.Args[1]]; ok != true {
		fmt.Println("Usage: " + os.Args[0] + " worker-name")
		return
	}

	jobname := os.Args[1]

	// set up the workdir
	if err := os.MkdirAll(conf.Worker.Dir, os.ModeDir); err != nil {
		l.Err(err.Error())
		return
	}

	// each worker listens to its -queue for work
	queue := jobname + "-queue"
	// get a nicely wrapped pubsub connection
	psc := redis.PubSubConn{redisPool.Pool.Get()}
	defer psc.Close()

	if err := psc.Subscribe(queue); err != nil {
		l.Err("Can't subscribe to the " + queue + ": " + err.Error())
		return
	}

	for {
		switch v := psc.Receive().(type) {
		case redis.Message:
			if err := work(v.Data, jobname); err != nil {
				l.Err(err.Error())
				return
			}
		case redis.Subscription:
			fmt.Printf("%s: %s %d\n", v.Channel, v.Kind, v.Count)
		case error:
			fmt.Println(v.Error())
			return
		}
	}
}

/* update tells redis about updates to images, including status,
sending pubsub messages, and potentially adding the image to
the list of active images.
It takes both the serialized and unserialized json data for easy resubmission.
Not sure how I feel about that, but doing the work twice seems silly too.
I make up for feeling bad by thinking I could be passing different data for the
next job*/
func update(data []byte, payload pubsubmessage, job string) (err error) {
	// get ready to update the image status and continue pubsubbin
	c := redisPool.Pool.Get()
	keyname := "gif:" + payload["id"]

	// if there's no one left to tell, we're done processing
	if jobs[job].tell == "" {
		// Add the image to active_image list, set image to avail
		c.Send("MULTI")
		c.Send("RPUSH", "active_images", payload["id"])
		c.Send("HSET", keyname, "status", "available")
		if _, err := c.Do("EXEC"); err != nil {
			return err
		}
		return nil
	}

	// otherwise we need to update status and tell people
	c.Send("MULTI")
	c.Send("HSET", keyname, "status", "pending "+jobs[job].tell)
	c.Send("PUBLISH", jobs[job].tell+"-queue", data)
	if _, err := c.Do("EXEC"); err != nil {
		return err
	}
	return nil
}

/* work is a wrapper method that does the setup and teardown around jobs */
func work(data []byte, job string) (err error) {
	// decode json
	payload := make(map[string]string)
	if err := json.Unmarshal(data, &payload); err != nil {
		return err
	}

	workspace := conf.Worker.Dir + "/" + payload["id"] + "/"

	// make workspace
	if err := os.MkdirAll(workspace, 0777); err != nil {
		return err
	}

	// do the job
	if err := jobs[job].proc(payload, workspace); err != nil {
		return err
	}

	// update the status
	if err := update(data, payload, job); err != nil {
		return err
	}

	return nil
}

/* download uses youtube-dl to take a youtube URL and place it on disk */
func download(payload pubsubmessage, workspace string) error {

	// 1.youtube
	outFile := workspace + payload["id"] + ".youtube"

	// needs config for youtube-dl path
	cmd := exec.Command("/opt/youtube-dl",
		"--no-progress",
		"--max-filesize", "10M",
		"--output", outFile,
		"--write-info-json",
		"--quiet",
		"--format", "mp4", "--format", "flv",
		payload["url"],
	)

	// needs logging, stdout
	if err := cmd.Run(); err != nil {
		return err
	}

	// verify that the file is actually there
	if _, err := os.Stat(outFile); os.IsNotExist(err) {
		return err
	}

	return nil
}

/* chop takes a workspace directory with an <id>.youtube file
and uses mplayer to create a PNG file for every frame in the video*/
func chop(payload pubsubmessage, workspace string) error {

	// https://www.youtube.com/watch?v=dgKGixi8bp8 short video
	// need to think more about more specific flags
	cmd := exec.Command("/usr/bin/mplayer",
		"-ss", "0",
		"-vo", "png:z=9:outdir="+workspace,
		"-ao", "null",
		"-really-quiet",
		workspace+payload["id"]+".youtube",
	)

	if output, err := cmd.CombinedOutput(); err != nil {
		fmt.Printf("%#v\n", cmd)
		l.Err(string(output))
		return err
	}

	// bash script would rm [0,2,4,6,8].png to make gifmaking quicker, gif smaller
	// think about doing that at some boundary

	// mplayer uses the following format to make pngs, so the 00000001.png assumption
	// is technically...ok. replace w/ subdir for pngs, subdir per job type?
	//   snprintf (buf, 100, "%s/%s%08d.png", png_outdir, png_outfile_prefix, ++framenum);
	// verify that the file is actually there
	if _, err := os.Stat(workspace + "00000001.png"); os.IsNotExist(err) {
		return err
	}

	return nil
}

/* stitch takes a workspace directory of PNG files and transforms them
into a gif on STDOUT using imagemagick, which is piped into
gifsicle for optimization */
func stitch(payload pubsubmessage, workspace string) error {

	// hmmmmm
	gifname := "/srv/git/go/src/github.com/Stantheman/youtube-gif-go/gifs/" +
		payload["id"] + ".gif"

	// should be configurable, make proper tmpdir etc
	// mad lazy, shell + constant filename
	cmd := exec.Command("/bin/bash", "-c",
		"/usr/bin/convert +repage -fuzz 1.6% -delay 6 -loop 0 "+workspace+"*.png "+
			"-layers OptimizePlus -layers OptimizeTransparency gif:- "+
			"| /usr/bin/gifsicle -O3 --colors 256 > "+gifname,
	)

	if err := cmd.Run(); err != nil {
		return err
	}

	// verify that the file is actually there
	if _, err := os.Stat(gifname); os.IsNotExist(err) {
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>// (c) Copyright 2015-2017 JONNALAGADDA Srinivas
//
// 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 flow

import (
	"database/sql"
	"testing"

	_ "github.com/go-sql-driver/mysql"
)

const (
	wflowName = "DATA_PLAT:STOR_REQ"
)

// Driver test function.
func TestWorkflows01(t *testing.T) {
	// Connect to the database.
	driver, connStr := "mysql", "travis@/flow"
	db, err := sql.Open(driver, connStr)
	if err != nil {
		t.Fatalf("could not connect to database : %v\n", err)
	}
	defer db.Close()
	err = db.Ping()
	if err != nil {
		t.Fatalf("could not ping the database : %v\n", err)
	}
	RegisterDB(db)

	// Test-local state.
	var dtypeStorReqID DocTypeID
	var dstateID DocStateID
	var wid WorkflowID

	// Register a few new workflows.
	t.Run("CRL", func(t *testing.T) {
		tx, err := db.Begin()
		if err != nil {
			t.Fatalf("error starting transaction : %v\n", err)
		}
		defer tx.Rollback()

		dtypeStorReqID, err = DocTypes().New(tx, dtypeStorReq)
		if err != nil {
			t.Fatalf("error creating document type '%s' : %v\n", dtypeStorReq, err)
		}
		for _, name := range storReqStates {
			dstateID, err = DocStates().New(tx, dtypeStorReqID, name)
			if err != nil {
				t.Fatalf("error creating document type:state '%d:%s' : %v\n", dtypeStorReqID, name, err)
			}
		}

		wid, err = Workflows().New(tx, wflowName, dtypeStorReqID, dstateID)
		if err != nil {
			t.Fatalf("error creating workflow : %v\n", err)
		}

		err = tx.Commit()
		if err != nil {
			t.Fatalf("error committing transaction : %v\n", err)
		}

		_, err = Workflows().Get(wid)
		if err != nil {
			t.Fatalf("error getting workflow : %v\n", err)
		}

		_, err = Workflows().GetByName(wflowName)
		if err != nil {
			t.Errorf("error getting workflow : %v\n", err)
		}

		_, err = Workflows().List(0, 0)
		if err != nil {
			t.Fatalf("error : %v", err)
		}
	})

	// Tear down.
	tx, err := db.Begin()
	if err != nil {
		t.Fatalf("error starting transaction : %v\n", err)
	}
	defer tx.Rollback()

	_, err = tx.Exec(`DELETE FROM wf_workflows`)
	if err != nil {
		t.Fatalf("error running transaction : %v\n", err)
	}

	_, err = tx.Exec(`DELETE FROM wf_docstates_master`)
	if err != nil {
		t.Fatalf("error running transaction : %v\n", err)
	}

	_, err = tx.Exec(`DELETE FROM wf_doctypes_master`)
	if err != nil {
		t.Fatalf("error running transaction : %v\n", err)
	}

	err = tx.Commit()
	if err != nil {
		t.Fatalf("error committing transaction : %v\n", err)
	}
}
<commit_msg>Modify tests for `Workflow` to be self-contained<commit_after>// (c) Copyright 2015-2017 JONNALAGADDA Srinivas
//
// 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 flow

import (
	"database/sql"
	"testing"

	_ "github.com/go-sql-driver/mysql"
)

const (
	wflowName = "DATA_PLAT:STOR_REQ"
)

// Driver test function.
func TestWorkflows01(t *testing.T) {
	// Connect to the database.
	driver, connStr := "mysql", "travis@/flow"
	db, err := sql.Open(driver, connStr)
	if err != nil {
		t.Fatalf("could not connect to database : %v\n", err)
	}
	defer db.Close()
	err = db.Ping()
	if err != nil {
		t.Fatalf("could not ping the database : %v\n", err)
	}
	RegisterDB(db)

	// Tear down.
	defer func() {
		tx, err := db.Begin()
		if err != nil {
			t.Fatalf("error starting transaction : %v\n", err)
		}
		defer tx.Rollback()

		_, err = tx.Exec(`DELETE FROM wf_workflows`)
		if err != nil {
			t.Fatalf("error running transaction : %v\n", err)
		}

		_, err = tx.Exec(`DELETE FROM wf_docstates_master`)
		if err != nil {
			t.Fatalf("error running transaction : %v\n", err)
		}

		_, err = tx.Exec(`DELETE FROM wf_doctypes_master`)
		if err != nil {
			t.Fatalf("error running transaction : %v\n", err)
		}

		err = tx.Commit()
		if err != nil {
			t.Fatalf("error committing transaction : %v\n", err)
		}
	}()

	// Test-local state.
	var dtypeStorReqID DocTypeID
	var dstateID DocStateID
	var wid WorkflowID

	// Register a few new workflows.
	t.Run("CRL", func(t *testing.T) {
		tx, err := db.Begin()
		if err != nil {
			t.Fatalf("error starting transaction : %v\n", err)
		}
		defer tx.Rollback()

		dtypeStorReqID, err = DocTypes().New(tx, dtypeStorReq)
		if err != nil {
			t.Fatalf("error creating document type '%s' : %v\n", dtypeStorReq, err)
		}
		for _, name := range storReqStates {
			dstateID, err = DocStates().New(tx, dtypeStorReqID, name)
			if err != nil {
				t.Fatalf("error creating document type:state '%d:%s' : %v\n", dtypeStorReqID, name, err)
			}
		}

		wid, err = Workflows().New(tx, wflowName, dtypeStorReqID, dstateID)
		if err != nil {
			t.Fatalf("error creating workflow : %v\n", err)
		}

		err = tx.Commit()
		if err != nil {
			t.Fatalf("error committing transaction : %v\n", err)
		}

		_, err = Workflows().Get(wid)
		if err != nil {
			t.Fatalf("error getting workflow : %v\n", err)
		}

		_, err = Workflows().GetByName(wflowName)
		if err != nil {
			t.Errorf("error getting workflow : %v\n", err)
		}

		_, err = Workflows().List(0, 0)
		if err != nil {
			t.Fatalf("error : %v", err)
		}
	})
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/urfave/cli"
	"log"
	"os"
)

const VERSION = "0.2.0"

func main() {
	log.Printf("GL00N")
	s := Settings{}
	s.Hostnames = []string{}
	app := cli.NewApp()
	app.Name = "gloon"
	app.Usage = "Custom dns resolver with build in docker container support"
	app.UsageText = "gloon [options]"
	app.Version = VERSION
	app.Action = func(c *cli.Context) error {
		if c.StringSlice("hostname") != nil {
			s.Hostnames = c.StringSlice("hostname")
		}
		return appMain(&s)
	}
	app.Flags = []cli.Flag{
		cli.BoolFlag{
			Name:        "disable-forward",
			Usage:       "Disable request forwarding",
			Destination: &s.DisableForwarding,
		},
		cli.BoolFlag{
			Name:        "disable-docker",
			Usage:       "Disable docker support",
			Destination: &s.DisableDocker,
		},
		cli.StringFlag{
			Name:        "resolvconf, r",
			Value:       "/etc/resolv.conf",
			Usage:       "resolv.conf compatible `FILE` to use for request forwarding",
			Destination: &s.ResolvFile,
		},
		cli.StringFlag{
			Name:        "listen, l",
			Value:       ":53",
			Usage:       "Resolver listens on `ADDR`",
			Destination: &s.ResolverAddr,
		},
		cli.StringFlag{
			Name:        "api-addr, a",
			Value:       "",
			Usage:       "Api http server listens on `ADDR`. Default is no api server",
			Destination: &s.ApiAddr,
		},
		cli.StringFlag{
			Name:        "hostname-filter, f",
			Value:       "",
			Usage:       "Only docker containers with hostnames matching this `REGEX`  will have A records published",
			Destination: &s.HostnameFilter,
		},
		cli.StringFlag{
			Name:        "append-domain, d",
			Value:       "",
			Usage:       "Append `DOMAIN NAME` to all configured A records",
			Destination: &s.AppendDomain,
		},
		cli.StringFlag{
			Name:        "hostfile",
			Value:       "",
			Usage:       "Load up `FILE` at startup and add any records found. Wilcards are supported",
			Destination: &s.Hostfile,
		},
		cli.IntFlag{
			Name:        "reload-interval, i",
			Value:       0,
			Usage:       "Reload hostfile (where applicable) every `SEC` seconds. If unset, default is to try inotify or similiar where available",
			Destination: &s.HostfileReloadInterval,
		},
		cli.StringSliceFlag{
			Name:  "hostname, n",
			Usage: "Add A records in the form of `HOSTNAME=IP`  ",
		},
		cli.StringFlag{
			Name:        "store",
			Value:       "memory",
			Usage:       "Set local dns record storage type. Defaults to 'memory'. Valid values are 'redis' and 'memory'",
			Destination: &s.Store,
		},
		cli.IntFlag{
			Name:        "ttl",
			Value:       10,
			Usage:       "Returnd ttl in `SEC` seconds",
			Destination: &s.Ttl,
		},
	}

	app.Run(os.Args)
}

func appMain(settings *Settings) (err error) {
	log.Printf("gloon %s starting...", VERSION)
	s, err := NewServer(settings.ResolverAddr, settings)
	if err != nil {
		log.Fatalf("Unable to create server: %s", err.Error())
	}
	if !settings.DisableDocker {
		dm, err := NewDockerMonitor(s.RecordSet, settings)
		if err != nil {
			log.Printf("WARNING: unable to start docker monitor: %s. Docker hostname support will be disabled", err.Error())
		}
		go func() {
			dm.Run()
		}()
	}
	if settings.Hostfile != "" {
		hf := NewHostfile(settings.Hostfile, s.RecordSet, settings.HostfileReloadInterval)
		go func() {
			hf.Run()
		}()
	}

	if settings.ApiAddr != "" {
		go func() {
			RunApiServer(settings, s.RecordSet)
		}()
	}
	err = s.ListenAndServe()
	defer s.Shutdown()
	if err != nil {
		log.Fatalf("Unable to start server: %s", err.Error())
	}
	return
}
<commit_msg>help fixes<commit_after>package main

import (
	"github.com/urfave/cli"
	"log"
	"os"
)

const VERSION = "0.2.0"

func main() {
	log.Printf("GL00N")
	s := Settings{}
	s.Hostnames = []string{}
	app := cli.NewApp()
	app.Name = "gloon"
	app.Usage = "Custom dns resolver with build in docker container support"
	app.UsageText = "gloon [options]"
	app.Version = VERSION
	app.Action = func(c *cli.Context) error {
		if c.StringSlice("hostname") != nil {
			s.Hostnames = c.StringSlice("hostname")
		}
		return appMain(&s)
	}
	app.Flags = []cli.Flag{
		cli.BoolFlag{
			Name:        "disable-forward",
			Usage:       "Disable request forwarding",
			Destination: &s.DisableForwarding,
		},
		cli.BoolFlag{
			Name:        "disable-docker",
			Usage:       "Disable docker support",
			Destination: &s.DisableDocker,
		},
		cli.StringFlag{
			Name:        "resolvconf, r",
			Value:       "/etc/resolv.conf",
			Usage:       "resolv.conf compatible `FILE` to use for request forwarding",
			Destination: &s.ResolvFile,
		},
		cli.StringFlag{
			Name:        "listen, l",
			Value:       ":53",
			Usage:       "Resolver listens on `ADDR`",
			Destination: &s.ResolverAddr,
		},
		cli.StringFlag{
			Name:        "api-addr, a",
			Value:       "",
			Usage:       "Api http server listens on `ADDR`. Default is no api server",
			Destination: &s.ApiAddr,
		},
		cli.StringFlag{
			Name:        "hostname-filter, f",
			Value:       "",
			Usage:       "Only docker containers with hostnames matching this `REGEX`  will have A records published",
			Destination: &s.HostnameFilter,
		},
		cli.StringFlag{
			Name:        "append-domain, d",
			Value:       "",
			Usage:       "Append `DOMAIN NAME` to all configured A records",
			Destination: &s.AppendDomain,
		},
		cli.StringFlag{
			Name:        "hostfile",
			Value:       "",
			Usage:       "Load up `FILE` at startup and add any records found. Wilcards are supported",
			Destination: &s.Hostfile,
		},
		cli.IntFlag{
			Name:        "reload-interval, i",
			Value:       0,
			Usage:       "Reload hostfile (where applicable) every `SEC` seconds. If unset, default is to try inotify or similiar where available",
			Destination: &s.HostfileReloadInterval,
		},
		cli.StringSliceFlag{
			Name:  "hostname, n",
			Usage: "Add A records in the form of `HOSTNAME=IP`  ",
		},
		cli.StringFlag{
			Name:        "store",
			Value:       "memory",
			Usage:       "Set local dns record storage `TYPE`. Valid values are 'redis' and 'memory'",
			Destination: &s.Store,
		},
		cli.IntFlag{
			Name:        "ttl",
			Value:       10,
			Usage:       "Returned ttl in `SEC` seconds",
			Destination: &s.Ttl,
		},
	}

	app.Run(os.Args)
}

func appMain(settings *Settings) (err error) {
	log.Printf("gloon %s starting...", VERSION)
	s, err := NewServer(settings.ResolverAddr, settings)
	if err != nil {
		log.Fatalf("Unable to create server: %s", err.Error())
	}
	if !settings.DisableDocker {
		dm, err := NewDockerMonitor(s.RecordSet, settings)
		if err != nil {
			log.Printf("WARNING: unable to start docker monitor: %s. Docker hostname support will be disabled", err.Error())
		}
		go func() {
			dm.Run()
		}()
	}
	if settings.Hostfile != "" {
		hf := NewHostfile(settings.Hostfile, s.RecordSet, settings.HostfileReloadInterval)
		go func() {
			hf.Run()
		}()
	}

	if settings.ApiAddr != "" {
		go func() {
			RunApiServer(settings, s.RecordSet)
		}()
	}
	err = s.ListenAndServe()
	defer s.Shutdown()
	if err != nil {
		log.Fatalf("Unable to start server: %s", err.Error())
	}
	return
}
<|endoftext|>


<commit_before>package main

import (
	"time"
	"fmt"
)

const (
	MON_REQ_TASK = 1
	MON_REQ_STATE = 2
)

type MON struct {
	Op int
	Data interface{}
}

/*
 * This generates a "MON" Object which is sent up to the monitor channel for relay to the server
 */
func MON_Gen_Task(Type string, Policy *Policy, Subject string, Body string) (*MON) {
	mon := new(MON)

	mon.Op = MON_REQ_TASK
	mon.Data = MON_Gen_Task_Raw(Type, Policy, Subject, Body)

	Debug("MON_Gen_Task:MON_REQ_TASK:%q\n", mon)

	return mon
}

func MON_Gen_Task_Raw(Type string, Policy *Policy, Subject string, Body string) (*Task) {

	task := new(Task)
	task.Type = Type
	task.Name = Policy.Name
	task.Idx = Policy.Idx
	task.Subject = fmt.Sprintf("DARQIOS: %s:%s - (%s) - %s", Policy.Name, Policy.Idx, Subject)
	task.Body = Body
	task.Time = time.Now()

	return task
}

func MON_Gen_State(State *State) (*MON) {

	mon := new(MON)

	mon.Op = MON_REQ_STATE
	mon.Data = MON_Gen_State_Raw(State)

	Debug("MON_Gen_State:MON_REQ_STATE:%q\n",mon)

	return mon
}

func MON_Gen_State_Raw(State *State) (*State_Report) {

	state_report := new(State_Report)

	state_report.LoadAvg = State.LoadAvg
	state_report.Proc.Total = len(State.Processes.Map)

	for _,user := range State.Users.Map {
		state_report.Users.Total += user.Count
	}

//	state_report.Memory = State.Memory
	mem_free := State.Memory["MemFree"]

	state_report.Memory.Total = float64(State.Memory["MemTotal"])
	state_report.Memory.Free = float64(mem_free) / float64(state_report.Memory.Total) * float64(100)

	state_report.Network = *State.Network
	Debug("%q\n",state_report.Network)
//	log.Fatal(state_report.Network)
	state_report.Interfaces = STATE_XInterfaces_2MAP(State.Interfaces)
	state_report.Disks = State.Disks

//	state_report.Network.Connections = State.Network.Connections
//	state_report.Network.Map,_ = bson.Marshal(State.Network.Map)
//	state_report.Interfaces = State.Interfaces

	state_report.Ts = time.Now()

	return state_report
}

func MON_Gen_Truthy(P *Policy) ([]bool, error) {

	truthy := make([]bool, len(P.Params))

	return truthy, nil
}
<commit_msg>alert level was missing from subject<commit_after>package main

import (
	"time"
	"fmt"
)

const (
	MON_REQ_TASK = 1
	MON_REQ_STATE = 2
)

type MON struct {
	Op int
	Data interface{}
}

/*
 * This generates a "MON" Object which is sent up to the monitor channel for relay to the server
 */
func MON_Gen_Task(Type string, Policy *Policy, Subject string, Body string) (*MON) {
	mon := new(MON)

	mon.Op = MON_REQ_TASK
	mon.Data = MON_Gen_Task_Raw(Type, Policy, Subject, Body)

	Debug("MON_Gen_Task:MON_REQ_TASK:%q\n", mon)

	return mon
}

func MON_Gen_Task_Raw(Type string, Policy *Policy, Subject string, Body string) (*Task) {

	task := new(Task)
	task.Type = Type
	task.Name = Policy.Name
	task.Idx = Policy.Idx
	task.Subject = fmt.Sprintf("DARQIOS: %s:%s - (%s) - %s", Policy.Name, Policy.Idx, Type, Subject)
	task.Body = Body
	task.Time = time.Now()

	return task
}

func MON_Gen_State(State *State) (*MON) {

	mon := new(MON)

	mon.Op = MON_REQ_STATE
	mon.Data = MON_Gen_State_Raw(State)

	Debug("MON_Gen_State:MON_REQ_STATE:%q\n",mon)

	return mon
}

func MON_Gen_State_Raw(State *State) (*State_Report) {

	state_report := new(State_Report)

	state_report.LoadAvg = State.LoadAvg
	state_report.Proc.Total = len(State.Processes.Map)

	for _,user := range State.Users.Map {
		state_report.Users.Total += user.Count
	}

//	state_report.Memory = State.Memory
	mem_free := State.Memory["MemFree"]

	state_report.Memory.Total = float64(State.Memory["MemTotal"])
	state_report.Memory.Free = float64(mem_free) / float64(state_report.Memory.Total) * float64(100)

	state_report.Network = *State.Network
	Debug("%q\n",state_report.Network)
//	log.Fatal(state_report.Network)
	state_report.Interfaces = STATE_XInterfaces_2MAP(State.Interfaces)
	state_report.Disks = State.Disks

//	state_report.Network.Connections = State.Network.Connections
//	state_report.Network.Map,_ = bson.Marshal(State.Network.Map)
//	state_report.Interfaces = State.Interfaces

	state_report.Ts = time.Now()

	return state_report
}

func MON_Gen_Truthy(P *Policy) ([]bool, error) {

	truthy := make([]bool, len(P.Params))

	return truthy, nil
}
<|endoftext|>


<commit_before>package wango

import "encoding/json"

type wampMsg struct {
	ID   interface{}
	URI  string
	Args []interface{}
}

func createMessage(args ...interface{}) ([]byte, error) {
	return json.Marshal(args)
}

func createHeartbeatEvent(counter int) ([]byte, error) {
	return createMessage(msgHeartbeat, counter)
}

func createHeartbeatTxtEvent(counter int) ([]byte, error) {
	return createMessage(msgIntTypes[msgHeartbeat], counter)
}

func createWelcomeMessage(id string) ([]byte, error) {
	return createMessage(msgWelcome, id, 1, identity)
}

func createError(err interface{}) string {
	var text string
	switch err.(type) {
	case error:
		text = err.(error).Error()
	case string:
		text = err.(string)
	}
	return "error#" + text
}
<commit_msg>Remove extra error text<commit_after>package wango

import "encoding/json"

type wampMsg struct {
	ID   interface{}
	URI  string
	Args []interface{}
}

func createMessage(args ...interface{}) ([]byte, error) {
	return json.Marshal(args)
}

func createHeartbeatEvent(counter int) ([]byte, error) {
	return createMessage(msgHeartbeat, counter)
}

func createHeartbeatTxtEvent(counter int) ([]byte, error) {
	return createMessage(msgIntTypes[msgHeartbeat], counter)
}

func createWelcomeMessage(id string) ([]byte, error) {
	return createMessage(msgWelcome, id, 1, identity)
}

func createError(err interface{}) string {
	var text string
	switch err.(type) {
	case error:
		text = err.(error).Error()
	case string:
		text = err.(string)
	}
	return text
}
<|endoftext|>