<commit_before>package server

import (
	"context"
	"os"
	"testing"
	"time"

	"github.com/Sirupsen/logrus"
	"github.com/coreos/dex/api"
	"github.com/coreos/dex/server/internal"
	"github.com/coreos/dex/storage"
	"github.com/coreos/dex/storage/memory"
)

// Attempts to create, update and delete a test Password
func TestPassword(t *testing.T) {
	logger := &logrus.Logger{
		Out:       os.Stderr,
		Formatter: &logrus.TextFormatter{DisableColors: true},
		Level:     logrus.DebugLevel,
	}

	s := memory.New(logger)
	serv := NewAPI(s, logger)

	ctx := context.Background()
	p := api.Password{
		Email: "test@example.com",
		// bcrypt hash of the value "test1" with cost 10
		Hash:     []byte("$2a$10$XVMN/Fid.Ks4CXgzo8fpR.iU1khOMsP5g9xQeXuBm1wXjRX8pjUtO"),
		Username: "test",
		UserId:   "test123",
	}

	createReq := api.CreatePasswordReq{
		Password: &p,
	}

	if resp, err := serv.CreatePassword(ctx, &createReq); err != nil || resp.AlreadyExists {
		if resp.AlreadyExists {
			t.Fatalf("Unable to create password since %s already exists", createReq.Password.Email)
		}
		t.Fatalf("Unable to create password: %v", err)
	}

	// Attempt to create a password that already exists.
	if resp, _ := serv.CreatePassword(ctx, &createReq); !resp.AlreadyExists {
		t.Fatalf("Created password %s twice", createReq.Password.Email)
	}

	updateReq := api.UpdatePasswordReq{
		Email:       "test@example.com",
		NewUsername: "test1",
	}

	if _, err := serv.UpdatePassword(ctx, &updateReq); err != nil {
		t.Fatalf("Unable to update password: %v", err)
	}

	pass, err := s.GetPassword(updateReq.Email)
	if err != nil {
		t.Fatalf("Unable to retrieve password: %v", err)
	}

	if pass.Username != updateReq.NewUsername {
		t.Fatalf("UpdatePassword failed. Expected username %s retrieved %s", updateReq.NewUsername, pass.Username)
	}

	deleteReq := api.DeletePasswordReq{
		Email: "test@example.com",
	}

	if _, err := serv.DeletePassword(ctx, &deleteReq); err != nil {
		t.Fatalf("Unable to delete password: %v", err)
	}

}

// Attempts to list and revoke an exisiting refresh token.
func TestRefreshToken(t *testing.T) {
	logger := &logrus.Logger{
		Out:       os.Stderr,
		Formatter: &logrus.TextFormatter{DisableColors: true},
		Level:     logrus.DebugLevel,
	}

	s := memory.New(logger)
	serv := NewAPI(s, logger)

	ctx := context.Background()

	// Creating a storage with an existing refresh token and offline session for the user.
	id := storage.NewID()
	r := storage.RefreshToken{
		ID:          id,
		Token:       "bar",
		Nonce:       "foo",
		ClientID:    "client_id",
		ConnectorID: "client_secret",
		Scopes:      []string{"openid", "email", "profile"},
		CreatedAt:   time.Now().UTC().Round(time.Millisecond),
		LastUsed:    time.Now().UTC().Round(time.Millisecond),
		Claims: storage.Claims{
			UserID:        "1",
			Username:      "jane",
			Email:         "jane.doe@example.com",
			EmailVerified: true,
			Groups:        []string{"a", "b"},
		},
		ConnectorData: []byte(`{"some":"data"}`),
	}

	if err := s.CreateRefresh(r); err != nil {
		t.Fatalf("create refresh token: %v", err)
	}

	tokenRef := storage.RefreshTokenRef{
		ID:        r.ID,
		ClientID:  r.ClientID,
		CreatedAt: r.CreatedAt,
		LastUsed:  r.LastUsed,
	}

	session := storage.OfflineSessions{
		UserID:  r.Claims.UserID,
		ConnID:  r.ConnectorID,
		Refresh: make(map[string]*storage.RefreshTokenRef),
	}
	session.Refresh[tokenRef.ClientID] = &tokenRef

	if err := s.CreateOfflineSessions(session); err != nil {
		t.Fatalf("create offline session: %v", err)
	}

	subjectString, err := internal.Marshal(&internal.IDTokenSubject{
		UserId: r.Claims.UserID,
		ConnId: r.ConnectorID,
	})
	if err != nil {
		t.Errorf("failed to marshal offline session ID: %v", err)
	}

	//Testing the api.
	listReq := api.ListRefreshReq{
		UserId: subjectString,
	}

	listResp, err := serv.ListRefresh(ctx, &listReq)
	if err != nil {
		t.Fatalf("Unable to list refresh tokens for user: %v", err)
	}

	for _, tok := range listResp.RefreshTokens {
		if tok.CreatedAt != r.CreatedAt.Unix() {
			t.Errorf("Expected CreatedAt timestamp %v, got %v", r.CreatedAt.Unix(), tok.CreatedAt)
		}

		if tok.LastUsed != r.LastUsed.Unix() {
			t.Errorf("Expected LastUsed timestamp %v, got %v", r.LastUsed.Unix(), tok.LastUsed)
		}
	}

	revokeReq := api.RevokeRefreshReq{
		UserId:   subjectString,
		ClientId: r.ClientID,
	}

	resp, err := serv.RevokeRefresh(ctx, &revokeReq)
	if err != nil || resp.NotFound {
		t.Fatalf("Unable to revoke refresh tokens for user: %v", err)
	}

	if resp, _ := serv.ListRefresh(ctx, &listReq); len(resp.RefreshTokens) != 0 {
		t.Fatalf("Refresh token returned inspite of revoking it.")
	}
}
<commit_msg>server: use client connected to remove server for gRPC tests<commit_after>package server

import (
	"context"
	"net"
	"os"
	"testing"
	"time"

	"github.com/Sirupsen/logrus"
	"github.com/coreos/dex/api"
	"github.com/coreos/dex/server/internal"
	"github.com/coreos/dex/storage"
	"github.com/coreos/dex/storage/memory"
	"google.golang.org/grpc"
)

// apiClient is a test gRPC client. When constructed, it runs a server in
// the background to exercise the serialization and network configuration
// instead of just this package's server implementation.
type apiClient struct {
	// Embedded gRPC client to talk to the server.
	api.DexClient
	// Close releases resources associated with this client, includuing shutting
	// down the background server.
	Close func()
}

// newAPI constructs a gRCP client connected to a backing server.
func newAPI(s storage.Storage, logger logrus.FieldLogger, t *testing.T) *apiClient {
	l, err := net.Listen("tcp", "127.0.0.1:0")
	if err != nil {
		t.Fatal(err)
	}

	serv := grpc.NewServer()
	api.RegisterDexServer(serv, NewAPI(s, logger))
	go serv.Serve(l)

	// Dial will retry automatically if the serv.Serve() goroutine
	// hasn't started yet.
	conn, err := grpc.Dial(l.Addr().String(), grpc.WithInsecure())
	if err != nil {
		t.Fatal(err)
	}

	return &apiClient{
		DexClient: api.NewDexClient(conn),
		Close: func() {
			conn.Close()
			serv.Stop()
			l.Close()
		},
	}
}

// Attempts to create, update and delete a test Password
func TestPassword(t *testing.T) {
	logger := &logrus.Logger{
		Out:       os.Stderr,
		Formatter: &logrus.TextFormatter{DisableColors: true},
		Level:     logrus.DebugLevel,
	}

	s := memory.New(logger)
	client := newAPI(s, logger, t)
	defer client.Close()

	ctx := context.Background()
	p := api.Password{
		Email: "test@example.com",
		// bcrypt hash of the value "test1" with cost 10
		Hash:     []byte("$2a$10$XVMN/Fid.Ks4CXgzo8fpR.iU1khOMsP5g9xQeXuBm1wXjRX8pjUtO"),
		Username: "test",
		UserId:   "test123",
	}

	createReq := api.CreatePasswordReq{
		Password: &p,
	}

	if resp, err := client.CreatePassword(ctx, &createReq); err != nil || resp.AlreadyExists {
		if resp.AlreadyExists {
			t.Fatalf("Unable to create password since %s already exists", createReq.Password.Email)
		}
		t.Fatalf("Unable to create password: %v", err)
	}

	// Attempt to create a password that already exists.
	if resp, _ := client.CreatePassword(ctx, &createReq); !resp.AlreadyExists {
		t.Fatalf("Created password %s twice", createReq.Password.Email)
	}

	updateReq := api.UpdatePasswordReq{
		Email:       "test@example.com",
		NewUsername: "test1",
	}

	if _, err := client.UpdatePassword(ctx, &updateReq); err != nil {
		t.Fatalf("Unable to update password: %v", err)
	}

	pass, err := s.GetPassword(updateReq.Email)
	if err != nil {
		t.Fatalf("Unable to retrieve password: %v", err)
	}

	if pass.Username != updateReq.NewUsername {
		t.Fatalf("UpdatePassword failed. Expected username %s retrieved %s", updateReq.NewUsername, pass.Username)
	}

	deleteReq := api.DeletePasswordReq{
		Email: "test@example.com",
	}

	if _, err := client.DeletePassword(ctx, &deleteReq); err != nil {
		t.Fatalf("Unable to delete password: %v", err)
	}

}

// Attempts to list and revoke an exisiting refresh token.
func TestRefreshToken(t *testing.T) {
	logger := &logrus.Logger{
		Out:       os.Stderr,
		Formatter: &logrus.TextFormatter{DisableColors: true},
		Level:     logrus.DebugLevel,
	}

	s := memory.New(logger)
	client := newAPI(s, logger, t)
	defer client.Close()

	ctx := context.Background()

	// Creating a storage with an existing refresh token and offline session for the user.
	id := storage.NewID()
	r := storage.RefreshToken{
		ID:          id,
		Token:       "bar",
		Nonce:       "foo",
		ClientID:    "client_id",
		ConnectorID: "client_secret",
		Scopes:      []string{"openid", "email", "profile"},
		CreatedAt:   time.Now().UTC().Round(time.Millisecond),
		LastUsed:    time.Now().UTC().Round(time.Millisecond),
		Claims: storage.Claims{
			UserID:        "1",
			Username:      "jane",
			Email:         "jane.doe@example.com",
			EmailVerified: true,
			Groups:        []string{"a", "b"},
		},
		ConnectorData: []byte(`{"some":"data"}`),
	}

	if err := s.CreateRefresh(r); err != nil {
		t.Fatalf("create refresh token: %v", err)
	}

	tokenRef := storage.RefreshTokenRef{
		ID:        r.ID,
		ClientID:  r.ClientID,
		CreatedAt: r.CreatedAt,
		LastUsed:  r.LastUsed,
	}

	session := storage.OfflineSessions{
		UserID:  r.Claims.UserID,
		ConnID:  r.ConnectorID,
		Refresh: make(map[string]*storage.RefreshTokenRef),
	}
	session.Refresh[tokenRef.ClientID] = &tokenRef

	if err := s.CreateOfflineSessions(session); err != nil {
		t.Fatalf("create offline session: %v", err)
	}

	subjectString, err := internal.Marshal(&internal.IDTokenSubject{
		UserId: r.Claims.UserID,
		ConnId: r.ConnectorID,
	})
	if err != nil {
		t.Errorf("failed to marshal offline session ID: %v", err)
	}

	//Testing the api.
	listReq := api.ListRefreshReq{
		UserId: subjectString,
	}

	listResp, err := client.ListRefresh(ctx, &listReq)
	if err != nil {
		t.Fatalf("Unable to list refresh tokens for user: %v", err)
	}

	for _, tok := range listResp.RefreshTokens {
		if tok.CreatedAt != r.CreatedAt.Unix() {
			t.Errorf("Expected CreatedAt timestamp %v, got %v", r.CreatedAt.Unix(), tok.CreatedAt)
		}

		if tok.LastUsed != r.LastUsed.Unix() {
			t.Errorf("Expected LastUsed timestamp %v, got %v", r.LastUsed.Unix(), tok.LastUsed)
		}
	}

	revokeReq := api.RevokeRefreshReq{
		UserId:   subjectString,
		ClientId: r.ClientID,
	}

	resp, err := client.RevokeRefresh(ctx, &revokeReq)
	if err != nil || resp.NotFound {
		t.Fatalf("Unable to revoke refresh tokens for user: %v", err)
	}

	if resp, _ := client.ListRefresh(ctx, &listReq); len(resp.RefreshTokens) != 0 {
		t.Fatalf("Refresh token returned inspite of revoking it.")
	}
}
<|endoftext|>


<commit_before>// Package periodic is part of github.com/jbenet/gp.
// It provides a simple periodic processor that calls a function
// periodically based on some options.
//
// For example:
//
//    // use a time.Duration
//    p := periodicproc.Every(time.Second, func(proc gp.Process) {
//    	fmt.Printf("the time is %s and all is well", time.Now())
//    })
//
//    <-time.After(5*time.Second)
//    p.Close()
//
//    // use a time.Time channel (like time.Ticker)
//    p := periodicproc.Tick(time.Tick(time.Second), func(proc gp.Process) {
//    	fmt.Printf("the time is %s and all is well", time.Now())
//    })
//
//    <-time.After(5*time.Second)
//    p.Close()
//
//    // or arbitrary signals
//    signal := make(chan struct{})
//    p := periodicproc.OnSignal(signal, func(proc gp.Process) {
//    	fmt.Printf("the time is %s and all is well", time.Now())
//    })
//
//    signal<- struct{}{}
//    signal<- struct{}{}
//    <-time.After(5 * time.Second)
//    signal<- struct{}{}
//    p.Close()
//
package periodicproc

import (
	"time"

	gp "github.com/jbenet/goprocess"
)

// Every calls the given ProcessFunc at periodic intervals. Internally, it uses
// <-time.After(interval), so it will have the behavior of waiting _at least_
// interval in between calls. If you'd prefer the time.Ticker behavior, use
// periodicproc.Tick instead.
// This is sequentially rate limited, only one call will be in-flight at a time.
func Every(interval time.Duration, procfunc gp.ProcessFunc) gp.Process {
	return gp.Go(func(proc gp.Process) {
		for {
			select {
			case <-time.After(interval):
				select {
				case <-proc.Go(procfunc).Closed(): // spin it out as a child, and wait till it's done.
				case <-proc.Closing(): // we're told to close
					return
				}
			case <-proc.Closing(): // we're told to close
				return
			}
		}
	})
}

// EveryGo calls the given ProcessFunc at periodic intervals. Internally, it uses
// <-time.After(interval)
// This is not rate limited, multiple calls could be in-flight at the same time.
func EveryGo(interval time.Duration, procfunc gp.ProcessFunc) gp.Process {
	return gp.Go(func(proc gp.Process) {
		for {
			select {
			case <-time.After(interval):
				proc.Go(procfunc)
			case <-proc.Closing(): // we're told to close
				return
			}
		}
	})
}

// Tick constructs a ticker with interval, and calls the given ProcessFunc every
// time the ticker fires.
// This is sequentially rate limited, only one call will be in-flight at a time.
func Tick(interval time.Duration, procfunc gp.ProcessFunc) gp.Process {
	return gp.Go(func(proc gp.Process) {
		ticker := time.NewTicker(interval)
		callOnTicker(ticker.C, procfunc)(proc)
		ticker.Stop()
	})
}

// TickGo constructs a ticker with interval, and calls the given ProcessFunc every
// time the ticker fires.
// This is not rate limited, multiple calls could be in-flight at the same time.
func TickGo(interval time.Duration, procfunc gp.ProcessFunc) gp.Process {
	return gp.Go(func(proc gp.Process) {
		ticker := time.NewTicker(interval)
		goCallOnTicker(ticker.C, procfunc)(proc)
		ticker.Stop()
	})
}

// Ticker calls the given ProcessFunc every time the ticker fires.
// This is sequentially rate limited, only one call will be in-flight at a time.
func Ticker(ticker <-chan time.Time, procfunc gp.ProcessFunc) gp.Process {
	return gp.Go(callOnTicker(ticker, procfunc))
}

// TickerGo calls the given ProcessFunc every time the ticker fires.
// This is not rate limited, multiple calls could be in-flight at the same time.
func TickerGo(ticker <-chan time.Time, procfunc gp.ProcessFunc) gp.Process {
	return gp.Go(goCallOnTicker(ticker, procfunc))
}

func callOnTicker(ticker <-chan time.Time, pf gp.ProcessFunc) gp.ProcessFunc {
	return func(proc gp.Process) {
		for {
			select {
			case <-ticker:
				select {
				case <-proc.Go(pf).Closed(): // spin it out as a child, and wait till it's done.
				case <-proc.Closing(): // we're told to close
					return
				}
			case <-proc.Closing(): // we're told to close
				return
			}
		}
	}
}

func goCallOnTicker(ticker <-chan time.Time, pf gp.ProcessFunc) gp.ProcessFunc {
	return func(proc gp.Process) {
		for {
			select {
			case <-ticker:
				proc.Go(pf)
			case <-proc.Closing(): // we're told to close
				return
			}
		}
	}
}

// OnSignal calls the given ProcessFunc every time the signal fires, and waits for it to exit.
// This is sequentially rate limited, only one call will be in-flight at a time.
func OnSignal(sig <-chan struct{}, procfunc gp.ProcessFunc) gp.Process {
	return gp.Go(func(proc gp.Process) {
		for {
			select {
			case <-sig:
				select {
				case <-proc.Go(procfunc).Closed(): // spin it out as a child, and wait till it's done.
				case <-proc.Closing(): // we're told to close
					return
				}
			case <-proc.Closing(): // we're told to close
				return
			}
		}
	})
}

// OnSignalGo calls the given ProcessFunc every time the signal fires.
// This is not rate limited, multiple calls could be in-flight at the same time.
func OnSignalGo(sig <-chan struct{}, procfunc gp.ProcessFunc) gp.Process {
	return gp.Go(func(proc gp.Process) {
		for {
			select {
			case <-sig:
				proc.Go(procfunc)
			case <-proc.Closing(): // we're told to close
				return
			}
		}
	})
}
<commit_msg>abbrev<commit_after>// Package periodic is part of github.com/jbenet/goprocess.
// It provides a simple periodic processor that calls a function
// periodically based on some options.
//
// For example:
//
//    // use a time.Duration
//    p := periodicproc.Every(time.Second, func(proc goprocess.Process) {
//    	fmt.Printf("the time is %s and all is well", time.Now())
//    })
//
//    <-time.After(5*time.Second)
//    p.Close()
//
//    // use a time.Time channel (like time.Ticker)
//    p := periodicproc.Tick(time.Tick(time.Second), func(proc goprocess.Process) {
//    	fmt.Printf("the time is %s and all is well", time.Now())
//    })
//
//    <-time.After(5*time.Second)
//    p.Close()
//
//    // or arbitrary signals
//    signal := make(chan struct{})
//    p := periodicproc.OnSignal(signal, func(proc goprocess.Process) {
//    	fmt.Printf("the time is %s and all is well", time.Now())
//    })
//
//    signal<- struct{}{}
//    signal<- struct{}{}
//    <-time.After(5 * time.Second)
//    signal<- struct{}{}
//    p.Close()
//
package periodicproc

import (
	"time"

	gp "github.com/jbenet/goprocess"
)

// Every calls the given ProcessFunc at periodic intervals. Internally, it uses
// <-time.After(interval), so it will have the behavior of waiting _at least_
// interval in between calls. If you'd prefer the time.Ticker behavior, use
// periodicproc.Tick instead.
// This is sequentially rate limited, only one call will be in-flight at a time.
func Every(interval time.Duration, procfunc gp.ProcessFunc) gp.Process {
	return gp.Go(func(proc gp.Process) {
		for {
			select {
			case <-time.After(interval):
				select {
				case <-proc.Go(procfunc).Closed(): // spin it out as a child, and wait till it's done.
				case <-proc.Closing(): // we're told to close
					return
				}
			case <-proc.Closing(): // we're told to close
				return
			}
		}
	})
}

// EveryGo calls the given ProcessFunc at periodic intervals. Internally, it uses
// <-time.After(interval)
// This is not rate limited, multiple calls could be in-flight at the same time.
func EveryGo(interval time.Duration, procfunc gp.ProcessFunc) gp.Process {
	return gp.Go(func(proc gp.Process) {
		for {
			select {
			case <-time.After(interval):
				proc.Go(procfunc)
			case <-proc.Closing(): // we're told to close
				return
			}
		}
	})
}

// Tick constructs a ticker with interval, and calls the given ProcessFunc every
// time the ticker fires.
// This is sequentially rate limited, only one call will be in-flight at a time.
func Tick(interval time.Duration, procfunc gp.ProcessFunc) gp.Process {
	return gp.Go(func(proc gp.Process) {
		ticker := time.NewTicker(interval)
		callOnTicker(ticker.C, procfunc)(proc)
		ticker.Stop()
	})
}

// TickGo constructs a ticker with interval, and calls the given ProcessFunc every
// time the ticker fires.
// This is not rate limited, multiple calls could be in-flight at the same time.
func TickGo(interval time.Duration, procfunc gp.ProcessFunc) gp.Process {
	return gp.Go(func(proc gp.Process) {
		ticker := time.NewTicker(interval)
		goCallOnTicker(ticker.C, procfunc)(proc)
		ticker.Stop()
	})
}

// Ticker calls the given ProcessFunc every time the ticker fires.
// This is sequentially rate limited, only one call will be in-flight at a time.
func Ticker(ticker <-chan time.Time, procfunc gp.ProcessFunc) gp.Process {
	return gp.Go(callOnTicker(ticker, procfunc))
}

// TickerGo calls the given ProcessFunc every time the ticker fires.
// This is not rate limited, multiple calls could be in-flight at the same time.
func TickerGo(ticker <-chan time.Time, procfunc gp.ProcessFunc) gp.Process {
	return gp.Go(goCallOnTicker(ticker, procfunc))
}

func callOnTicker(ticker <-chan time.Time, pf gp.ProcessFunc) gp.ProcessFunc {
	return func(proc gp.Process) {
		for {
			select {
			case <-ticker:
				select {
				case <-proc.Go(pf).Closed(): // spin it out as a child, and wait till it's done.
				case <-proc.Closing(): // we're told to close
					return
				}
			case <-proc.Closing(): // we're told to close
				return
			}
		}
	}
}

func goCallOnTicker(ticker <-chan time.Time, pf gp.ProcessFunc) gp.ProcessFunc {
	return func(proc gp.Process) {
		for {
			select {
			case <-ticker:
				proc.Go(pf)
			case <-proc.Closing(): // we're told to close
				return
			}
		}
	}
}

// OnSignal calls the given ProcessFunc every time the signal fires, and waits for it to exit.
// This is sequentially rate limited, only one call will be in-flight at a time.
func OnSignal(sig <-chan struct{}, procfunc gp.ProcessFunc) gp.Process {
	return gp.Go(func(proc gp.Process) {
		for {
			select {
			case <-sig:
				select {
				case <-proc.Go(procfunc).Closed(): // spin it out as a child, and wait till it's done.
				case <-proc.Closing(): // we're told to close
					return
				}
			case <-proc.Closing(): // we're told to close
				return
			}
		}
	})
}

// OnSignalGo calls the given ProcessFunc every time the signal fires.
// This is not rate limited, multiple calls could be in-flight at the same time.
func OnSignalGo(sig <-chan struct{}, procfunc gp.ProcessFunc) gp.Process {
	return gp.Go(func(proc gp.Process) {
		for {
			select {
			case <-sig:
				proc.Go(procfunc)
			case <-proc.Closing(): // we're told to close
				return
			}
		}
	})
}
<|endoftext|>


<commit_before>// +build linux

package main

import (
	"encoding/hex"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"log/syslog"
	"os"
	"strings"

	"github.com/godbus/dbus"
	"gopkg.in/yaml.v1"
)

var conn *dbus.Conn

type State struct {
	Version    string `json:"version"`
	ID         string `json:"id"`
	Pid        int    `json:"pid"`
	Root       string `json:"root"`
	BundlePath string `json:"bundlePath"`
}

type Process struct {
	Env []string `json:"env"`
}

type Config struct {
	Process *Process `json:"process"`
}

func Validate(id string) (string, error) {
	for len(id) < 32 {
		id += "0"
	}
	return hex.EncodeToString([]byte(id)), nil
}

// RegisterMachine with systemd on the host system
func RegisterMachine(name string, id string, pid int, root_directory string) error {
	var (
		av  []byte
		err error
	)
	if conn == nil {
		conn, err = dbus.SystemBus()
		if err != nil {
			return err
		}
	}

	av, err = hex.DecodeString(id[0:32])
	if err != nil {
		return err
	}
	obj := conn.Object("org.freedesktop.machine1", "/org/freedesktop/machine1")
	service := os.Getenv("container")
	if service == "" {
		service = "runc"
	}
	if len(name) > 32 {
		name = name[0:32]
	}

	return obj.Call("org.freedesktop.machine1.Manager.RegisterMachine", 0, name, av, service, "container", uint32(pid), root_directory).Err
}

// TerminateMachine registered with systemd on the host system
func TerminateMachine(name string) error {
	var err error
	if conn == nil {
		conn, err = dbus.SystemBus()
		if err != nil {
			return err
		}
	}
	if len(name) > 32 {
		name = name[0:32]
	}

	obj := conn.Object("org.freedesktop.machine1", "/org/freedesktop/machine1")
	return obj.Call("org.freedesktop.machine1.Manager.TerminateMachine", 0, name).Err
}

const CONFIG = "/etc/oci-register-machine.conf"

var settings struct {
	Disabled bool `yaml:"disabled"`
}

func main() {
	var state State

	logwriter, err := syslog.New(syslog.LOG_NOTICE, "oci-register-machine")
	if err == nil {
		log.SetOutput(logwriter)
	}
	// then config file settings

	data, err := ioutil.ReadFile(CONFIG)
	if err != nil {
		if !os.IsNotExist(err) {
			log.Fatalf("RegisterMachine Failed to read %s %m", CONFIG)
		}
	} else {
		if err := yaml.Unmarshal(data, &settings); err != nil {
			log.Fatalf("RegisterMachine Failed to parse %s %m", CONFIG)
		}
		if settings.Disabled {
			return
		}
	}

	if err := json.NewDecoder(os.Stdin).Decode(&state); err != nil {
		log.Fatalf("RegisterMachine Failed %m")
	}

	command := map[bool]string{true: "prestart", false: "poststop"}[state.Pid > 0]
	if len(os.Args) > 1 {
		command = os.Args[1]
	}

	log.Printf("Register machine: %s %s %d %s", command, state.ID, state.Pid, state.Root)
	passId := state.ID
	// If id is shorter than 32, then read container_uuid from the container process environment variables
	if len(passId) < 32 && state.Pid > 0 {
		var config Config
		configFile := fmt.Sprintf("%s/config.json", state.BundlePath)
		data, err := ioutil.ReadFile(configFile)
		if err != nil {
			log.Fatalf("RegisterMachine Failed to read %s %m", configFile)
		}
		if err := yaml.Unmarshal(data, &config); err != nil {
			log.Fatalf("RegisterMachine Failed to parse %s %m", configFile)
		}
		for _, env := range config.Process.Env {
			const PREFIX = "container_uuid="
			if strings.HasPrefix(env, PREFIX) {
				passId = strings.Replace(env[len(PREFIX):], "-", "", -1)
				break
			}
		}
	}
	// ensure id is a hex string at least 32 chars
	passId, err = Validate(passId)
	if err != nil {
		log.Fatalf("RegisterMachine Failed %m")
	}

	switch command {
	case "prestart":
		{
			if err = RegisterMachine(state.ID, passId, int(state.Pid), state.Root); err != nil {
				log.Fatalf("Register machine failed: %m")
			}
			return
		}
	case "poststop":
		{
			if err := TerminateMachine(state.ID); err != nil {
				if !strings.Contains(err.Error(), "No machine") {
					log.Fatalf("TerminateMachine failed: %m")
				}
			}
			return
		}
		log.Fatalf("Invalid command %q must be prestart|poststop", command)
	}
}
<commit_msg>Support bundle in addition to bundlePath<commit_after>// +build linux

package main

import (
	"encoding/hex"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"log/syslog"
	"os"
	"strings"

	"github.com/godbus/dbus"
	"gopkg.in/yaml.v1"
)

var conn *dbus.Conn

type State struct {
	Version    string `json:"version"`
	ID         string `json:"id"`
	Pid        int    `json:"pid"`
	Root       string `json:"root"`
	Bundle     string `json:"bundle"`
	BundlePath string `json:"bundlePath"`
}

type Process struct {
	Env []string `json:"env"`
}

type Config struct {
	Process *Process `json:"process"`
}

func Validate(id string) (string, error) {
	for len(id) < 32 {
		id += "0"
	}
	return hex.EncodeToString([]byte(id)), nil
}

// RegisterMachine with systemd on the host system
func RegisterMachine(name string, id string, pid int, root_directory string) error {
	var (
		av  []byte
		err error
	)
	if conn == nil {
		conn, err = dbus.SystemBus()
		if err != nil {
			return err
		}
	}

	av, err = hex.DecodeString(id[0:32])
	if err != nil {
		return err
	}
	obj := conn.Object("org.freedesktop.machine1", "/org/freedesktop/machine1")
	service := os.Getenv("container")
	if service == "" {
		service = "runc"
	}
	if len(name) > 32 {
		name = name[0:32]
	}

	return obj.Call("org.freedesktop.machine1.Manager.RegisterMachine", 0, name, av, service, "container", uint32(pid), root_directory).Err
}

// TerminateMachine registered with systemd on the host system
func TerminateMachine(name string) error {
	var err error
	if conn == nil {
		conn, err = dbus.SystemBus()
		if err != nil {
			return err
		}
	}
	if len(name) > 32 {
		name = name[0:32]
	}

	obj := conn.Object("org.freedesktop.machine1", "/org/freedesktop/machine1")
	return obj.Call("org.freedesktop.machine1.Manager.TerminateMachine", 0, name).Err
}

const CONFIG = "/etc/oci-register-machine.conf"

var settings struct {
	Disabled bool `yaml:"disabled"`
}

func main() {
	var state State

	logwriter, err := syslog.New(syslog.LOG_NOTICE, "oci-register-machine")
	if err == nil {
		log.SetOutput(logwriter)
	}
	// then config file settings

	data, err := ioutil.ReadFile(CONFIG)
	if err != nil {
		if !os.IsNotExist(err) {
			log.Fatalf("RegisterMachine Failed to read %s %m", CONFIG)
		}
	} else {
		if err := yaml.Unmarshal(data, &settings); err != nil {
			log.Fatalf("RegisterMachine Failed to parse %s %m", CONFIG)
		}
		if settings.Disabled {
			return
		}
	}

	if err := json.NewDecoder(os.Stdin).Decode(&state); err != nil {
		log.Fatalf("RegisterMachine Failed %m")
	}

	command := map[bool]string{true: "prestart", false: "poststop"}[state.Pid > 0]
	if len(os.Args) > 1 {
		command = os.Args[1]
	}

	log.Printf("Register machine: %s %s %d %s", command, state.ID, state.Pid, state.Root)
	passId := state.ID
	// If id is shorter than 32, then read container_uuid from the container process environment variables
	if len(passId) < 32 && state.Pid > 0 {
		var config Config
		var bundle string
		if state.Bundle != "" {
			bundle = state.Bundle
		} else {
			bundle = state.BundlePath
		}
		configFile := fmt.Sprintf("%s/config.json", bundle)
		data, err := ioutil.ReadFile(configFile)
		if err != nil {
			log.Fatalf("RegisterMachine Failed to read %s %m", configFile)
		}
		if err := yaml.Unmarshal(data, &config); err != nil {
			log.Fatalf("RegisterMachine Failed to parse %s %m", configFile)
		}
		for _, env := range config.Process.Env {
			const PREFIX = "container_uuid="
			if strings.HasPrefix(env, PREFIX) {
				passId = strings.Replace(env[len(PREFIX):], "-", "", -1)
				break
			}
		}
	}
	// ensure id is a hex string at least 32 chars
	passId, err = Validate(passId)
	if err != nil {
		log.Fatalf("RegisterMachine Failed %m")
	}

	switch command {
	case "prestart":
		{
			if err = RegisterMachine(state.ID, passId, int(state.Pid), state.Root); err != nil {
				log.Fatalf("Register machine failed: %m")
			}
			return
		}
	case "poststop":
		{
			if err := TerminateMachine(state.ID); err != nil {
				if !strings.Contains(err.Error(), "No machine") {
					log.Fatalf("TerminateMachine failed: %m")
				}
			}
			return
		}
		log.Fatalf("Invalid command %q must be prestart|poststop", command)
	}
}
<|endoftext|>


<commit_before>package lib

import (
	"bufio"
	"bytes"
	"fmt"
	"os"
	"strconv"
	"strings"
)

const (
	Tab   = '\t'
	Space = ' '
	Lf    = '\n'
)

type Interpreter struct {
	origin   []byte
	source   []byte
	commands *CommandList
	heapMem  *Heap
	stackMem *Stack
}

func NewInterpreter(data []byte) *Interpreter {
	return &Interpreter{origin: data, heapMem: NewHeap(), stackMem: NewStack()}
}

func (inter *Interpreter) ToChar() ([]byte, error) {
	inp := *inter
	var ret []byte
	for _, b := range inp.origin {
		switch b {
		case Space:
			ret = append(ret, 'S')
		case Tab:
			ret = append(ret, 'T')
		case Lf:
			ret = append(ret, Lf)
		}
	}
	return ret, nil
}

func (inter *Interpreter) ToCode() error {
	inter.filter()
	return inter.parseCommands()
}

func (inter *Interpreter) Run(data []byte) {
	err := inter.ToCode()
	if err != nil {
		panic(err)
	}

	call_stack := NewStack()
	stack := NewStack()
	heap := NewHeap()

	max := inter.commands.Len()
	for p := 1; p <= max; p++ {
		cmd := inter.commands.Get(p)
		switch cmd.cmd {
		case "stack":
			switch cmd.subcmd {
			case "push":
				stack.Push(cmd.param)
			case "copy":
				b := stack.Pop()
				stack.Push(b)
				stack.Push(b)
			case "swap":
				stack.Swap()
			case "remove":
				stack.Pop()
			}
		case "heap":
			switch cmd.subcmd {
			case "push":
				v := stack.Pop()
				k := stack.Pop()
				heap.Push(k, v)
			case "pop":
				k := stack.Pop()
				stack.Push(heap.Pop(k))
			}
		case "putc":
			fmt.Print(string(stack.Pop()))
		case "putn":
			fmt.Print(stack.Pop())
		case "getc":
			line, err := ReadStdin()
			if err != nil {
				fmt.Println(err)
				return
			}

			bl := []byte(line)
			for pos := len(bl); 0 < pos; pos-- {
				k := stack.Pop()
				heap.Push(k, int(bl[pos]))
			}
		case "getn":
			line, err := ReadStdin()
			if err != nil {
				fmt.Println(err)
				return
			}

			num, err := strconv.Atoi(line)
			if err != nil {
				fmt.Println(err)
				return
			}

			k := stack.Pop()
			heap.Push(k, num)
		case "return":
			p = call_stack.Pop()
		case "exit":
			fmt.Println("exit program")
			break
		// case "label":
		case "call":
			call_stack.Push(p)
			p, err = inter.commands.Search(NewSubCommand("label", cmd.subcmd))
			if err != nil {
				panic(err)
			}
		case "goto":
			p, err = inter.commands.Search(NewSubCommand("label", cmd.subcmd))
			if err != nil {
				panic(err)
			}
		case "if stack==0 then goto":
			if stack.Pop() == 0 {
				p, err = inter.commands.Search(NewSubCommand("label", cmd.subcmd))
				if err != nil {
					panic(err)
				}
			}
		case "if stack!=0 then goto":
			if stack.Pop() != 0 {
				p, err = inter.commands.Search(NewSubCommand("label", cmd.subcmd))
				if err != nil {
					panic(err)
				}
			}
		case "add":
			two, one := stack.Pop(), stack.Pop()
			stack.Push(one + two)
		case "sub":
			two, one := stack.Pop(), stack.Pop()
			stack.Push(one - two)
		case "mul":
			two, one := stack.Pop(), stack.Pop()
			stack.Push(one * two)
		case "div":
			two, one := stack.Pop(), stack.Pop()
			stack.Push(one / two)
		case "mod":
			two, one := stack.Pop(), stack.Pop()
			stack.Push(one % two)
		}
	}
}

func (inter *Interpreter) filter() {
	inp := *inter
	for _, b := range inp.origin {
		if bytes.IndexByte([]byte{Space, Tab, Lf}, b) >= 0 {
			inp.source = append(inp.source, b)
		}
	}
	*inter = inp
}

func (inter *Interpreter) parseCommands() error {
	inp := *inter
	data := inp.source
	inp.commands = NewCommandList()
	for pos := 0; pos < len(data); pos++ {

		fn, err := createFunction(data[pos])
		pos += 1
		command, seek, err := fn(data[pos:])
		if err != nil {
			return err
		}

		pos += seek
		inp.commands.Add(command)
	}
	*inter = inp
	return nil
}

func ReadStdin() (string, error) {
	rd := bufio.NewReader(os.Stdin)
	line, err := rd.ReadString('\n')
	if err != nil {
		return "", err
	}
	return strings.Trim(line, "\r\n"), nil
}
<commit_msg>toCodeを内部メソッドに変更して新しくコマンドを標準出力に表示するメソッドを追加<commit_after>package lib

import (
	"bufio"
	"bytes"
	"fmt"
	"os"
	"strconv"
	"strings"
)

const (
	Tab   = '\t'
	Space = ' '
	Lf    = '\n'
)

type Interpreter struct {
	origin   []byte
	source   []byte
	commands *CommandList
	heapMem  *Heap
	stackMem *Stack
}

func NewInterpreter(data []byte) *Interpreter {
	return &Interpreter{origin: data, heapMem: NewHeap(), stackMem: NewStack()}
}

func (inter *Interpreter) ToChar() ([]byte, error) {
	inp := *inter
	var ret []byte
	for _, b := range inp.origin {
		switch b {
		case Space:
			ret = append(ret, 'S')
		case Tab:
			ret = append(ret, 'T')
		case Lf:
			ret = append(ret, Lf)
		}
	}
	return ret, nil
}

func (inter *Interpreter) toCode() error {
	inter.filter()
	return inter.parseCommands()
}

func (inter *Interpreter) PrintCode() {
	err := inter.toCode()
	if err != nil {
		panic(err)
	}
	for _, cmd := range *inter.commands {
		fmt.Println(cmd)
	}
}

func (inter *Interpreter) Run() {
	err := inter.toCode()
	if err != nil {
		panic(err)
	}

	call_stack := NewStack()
	stack := NewStack()
	heap := NewHeap()

	max := inter.commands.Len()
	for p := 1; p <= max; p++ {
		cmd := inter.commands.Get(p)
		switch cmd.cmd {
		case "stack":
			switch cmd.subcmd {
			case "push":
				stack.Push(cmd.param)
			case "copy":
				b := stack.Pop()
				stack.Push(b)
				stack.Push(b)
			case "swap":
				stack.Swap()
			case "remove":
				stack.Pop()
			}
		case "heap":
			switch cmd.subcmd {
			case "push":
				v := stack.Pop()
				k := stack.Pop()
				heap.Push(k, v)
			case "pop":
				k := stack.Pop()
				stack.Push(heap.Pop(k))
			}
		case "putc":
			fmt.Print(string(stack.Pop()))
		case "putn":
			fmt.Print(stack.Pop())
		case "getc":
			line, err := ReadStdin()
			if err != nil {
				fmt.Println(err)
				return
			}

			bl := []byte(line)
			for pos := len(bl); 0 < pos; pos-- {
				k := stack.Pop()
				heap.Push(k, int(bl[pos]))
			}
		case "getn":
			line, err := ReadStdin()
			if err != nil {
				fmt.Println(err)
				return
			}

			num, err := strconv.Atoi(line)
			if err != nil {
				fmt.Println(err)
				return
			}

			k := stack.Pop()
			heap.Push(k, num)
		case "return":
			p = call_stack.Pop()
		case "exit":
			fmt.Println("exit program")
			break
		// case "label":
		case "call":
			call_stack.Push(p)
			p, err = inter.commands.Search(NewSubCommand("label", cmd.subcmd))
			if err != nil {
				panic(err)
			}
		case "goto":
			p, err = inter.commands.Search(NewSubCommand("label", cmd.subcmd))
			if err != nil {
				panic(err)
			}
		case "if stack==0 then goto":
			if stack.Pop() == 0 {
				p, err = inter.commands.Search(NewSubCommand("label", cmd.subcmd))
				if err != nil {
					panic(err)
				}
			}
		case "if stack!=0 then goto":
			if stack.Pop() != 0 {
				p, err = inter.commands.Search(NewSubCommand("label", cmd.subcmd))
				if err != nil {
					panic(err)
				}
			}
		case "add":
			two, one := stack.Pop(), stack.Pop()
			stack.Push(one + two)
		case "sub":
			two, one := stack.Pop(), stack.Pop()
			stack.Push(one - two)
		case "mul":
			two, one := stack.Pop(), stack.Pop()
			stack.Push(one * two)
		case "div":
			two, one := stack.Pop(), stack.Pop()
			stack.Push(one / two)
		case "mod":
			two, one := stack.Pop(), stack.Pop()
			stack.Push(one % two)
		}
	}
}

func (inter *Interpreter) filter() {
	inp := *inter
	for _, b := range inp.origin {
		if bytes.IndexByte([]byte{Space, Tab, Lf}, b) >= 0 {
			inp.source = append(inp.source, b)
		}
	}
	*inter = inp
}

func (inter *Interpreter) parseCommands() error {
	inp := *inter
	data := inp.source
	inp.commands = NewCommandList()
	for pos := 0; pos < len(data); pos++ {

		fn, err := createFunction(data[pos])
		pos += 1
		command, seek, err := fn(data[pos:])
		if err != nil {
			return err
		}

		pos += seek
		inp.commands.Add(command)
	}
	*inter = inp
	return nil
}

func ReadStdin() (string, error) {
	rd := bufio.NewReader(os.Stdin)
	line, err := rd.ReadString('\n')
	if err != nil {
		return "", err
	}
	return strings.Trim(line, "\r\n"), nil
}
<|endoftext|>


<commit_before>package ecs

import (
	"context"
	"fmt"
	"strings"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/aws/defaults"
	"github.com/aws/aws-sdk-go/aws/ec2metadata"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/aws/aws-sdk-go/service/ecs"
	"github.com/cenk/backoff"
	"github.com/containous/traefik/job"
	"github.com/containous/traefik/old/log"
	"github.com/containous/traefik/old/provider"
	"github.com/containous/traefik/old/types"
	"github.com/containous/traefik/safe"
)

var _ provider.Provider = (*Provider)(nil)

// Provider holds configurations of the provider.
type Provider struct {
	provider.BaseProvider `mapstructure:",squash" export:"true"`

	Domain           string `description:"Default domain used"`
	ExposedByDefault bool   `description:"Expose containers by default" export:"true"`
	RefreshSeconds   int    `description:"Polling interval (in seconds)" export:"true"`

	// Provider lookup parameters
	Clusters             Clusters `description:"ECS Clusters name"`
	AutoDiscoverClusters bool     `description:"Auto discover cluster" export:"true"`
	Region               string   `description:"The AWS region to use for requests" export:"true"`
	AccessKeyID          string   `description:"The AWS credentials access key to use for making requests"`
	SecretAccessKey      string   `description:"The AWS credentials access key to use for making requests"`
}

type ecsInstance struct {
	Name                string
	ID                  string
	containerDefinition *ecs.ContainerDefinition
	machine             *machine
	TraefikLabels       map[string]string
	SegmentLabels       map[string]string
	SegmentName         string
}

type portMapping struct {
	containerPort int64
	hostPort      int64
}

type machine struct {
	state     string
	privateIP string
	ports     []portMapping
}

type awsClient struct {
	ecs *ecs.ECS
	ec2 *ec2.EC2
}

// Init the provider
func (p *Provider) Init(constraints types.Constraints) error {
	return p.BaseProvider.Init(constraints)
}

func (p *Provider) createClient() (*awsClient, error) {
	sess, err := session.NewSession()
	if err != nil {
		return nil, err
	}

	ec2meta := ec2metadata.New(sess)
	if p.Region == "" {
		log.Infoln("No EC2 region provided, querying instance metadata endpoint...")
		identity, err := ec2meta.GetInstanceIdentityDocument()
		if err != nil {
			return nil, err
		}
		p.Region = identity.Region
	}

	cfg := &aws.Config{
		Region: &p.Region,
		Credentials: credentials.NewChainCredentials(
			[]credentials.Provider{
				&credentials.StaticProvider{
					Value: credentials.Value{
						AccessKeyID:     p.AccessKeyID,
						SecretAccessKey: p.SecretAccessKey,
					},
				},
				&credentials.EnvProvider{},
				&credentials.SharedCredentialsProvider{},
				defaults.RemoteCredProvider(*(defaults.Config()), defaults.Handlers()),
			}),
	}

	if p.Trace {
		cfg.WithLogger(aws.LoggerFunc(func(args ...interface{}) {
			log.Debug(args...)
		}))
	}

	return &awsClient{
		ecs: ecs.New(sess, cfg),
		ec2: ec2.New(sess, cfg),
	}, nil
}

// Provide allows the ecs provider to provide configurations to traefik
// using the given configuration channel.
func (p *Provider) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool) error {
	handleCanceled := func(ctx context.Context, err error) error {
		if ctx.Err() == context.Canceled || err == context.Canceled {
			return nil
		}
		return err
	}

	pool.Go(func(stop chan bool) {
		ctx, cancel := context.WithCancel(context.Background())
		safe.Go(func() {
			<-stop
			cancel()
		})

		operation := func() error {
			awsClient, err := p.createClient()
			if err != nil {
				return err
			}

			configuration, err := p.loadECSConfig(ctx, awsClient)
			if err != nil {
				return handleCanceled(ctx, err)
			}

			configurationChan <- types.ConfigMessage{
				ProviderName:  "ecs",
				Configuration: configuration,
			}

			if p.Watch {
				reload := time.NewTicker(time.Second * time.Duration(p.RefreshSeconds))
				defer reload.Stop()
				for {
					select {
					case <-reload.C:
						configuration, err := p.loadECSConfig(ctx, awsClient)
						if err != nil {
							return handleCanceled(ctx, err)
						}

						configurationChan <- types.ConfigMessage{
							ProviderName:  "ecs",
							Configuration: configuration,
						}
					case <-ctx.Done():
						return handleCanceled(ctx, ctx.Err())
					}
				}
			}

			return nil
		}

		notify := func(err error, time time.Duration) {
			log.Errorf("Provider connection error %+v, retrying in %s", err, time)
		}
		err := backoff.RetryNotify(safe.OperationWithRecover(operation), job.NewBackOff(backoff.NewExponentialBackOff()), notify)
		if err != nil {
			log.Errorf("Cannot connect to Provider api %+v", err)
		}
	})

	return nil
}

// Find all running Provider tasks in a cluster, also collect the task definitions (for docker labels)
// and the EC2 instance data
func (p *Provider) listInstances(ctx context.Context, client *awsClient) ([]ecsInstance, error) {
	var clustersArn []*string
	var clusters Clusters

	if p.AutoDiscoverClusters {
		input := &ecs.ListClustersInput{}
		for {
			result, err := client.ecs.ListClusters(input)
			if err != nil {
				return nil, err
			}
			if result != nil {
				clustersArn = append(clustersArn, result.ClusterArns...)
				input.NextToken = result.NextToken
				if result.NextToken == nil {
					break
				}
			} else {
				break
			}
		}
		for _, cArn := range clustersArn {
			clusters = append(clusters, *cArn)
		}
	} else {
		clusters = p.Clusters
	}

	var instances []ecsInstance

	log.Debugf("ECS Clusters: %s", clusters)

	for _, c := range clusters {

		input := &ecs.ListTasksInput{
			Cluster:       &c,
			DesiredStatus: aws.String(ecs.DesiredStatusRunning),
		}
		tasks := make(map[string]*ecs.Task)
		err := client.ecs.ListTasksPagesWithContext(ctx, input, func(page *ecs.ListTasksOutput, lastPage bool) bool {
			if len(page.TaskArns) > 0 {
				resp, err := client.ecs.DescribeTasksWithContext(ctx, &ecs.DescribeTasksInput{
					Tasks:   page.TaskArns,
					Cluster: &c,
				})
				if err != nil {
					log.Errorf("Unable to describe tasks for %v", page.TaskArns)
				} else {
					for _, t := range resp.Tasks {
						tasks[aws.StringValue(t.TaskArn)] = t
					}
				}
			}
			return !lastPage
		})

		if err != nil {
			log.Error("Unable to list tasks")
			return nil, err
		}

		// Skip to the next cluster if there are no tasks found on
		// this cluster.
		if len(tasks) == 0 {
			continue
		}

		ec2Instances, err := p.lookupEc2Instances(ctx, client, &c, tasks)
		if err != nil {
			return nil, err
		}

		taskDefinitions, err := p.lookupTaskDefinitions(ctx, client, tasks)
		if err != nil {
			return nil, err
		}

		for key, task := range tasks {

			containerInstance := ec2Instances[aws.StringValue(task.ContainerInstanceArn)]
			taskDef := taskDefinitions[key]

			for _, container := range task.Containers {

				var containerDefinition *ecs.ContainerDefinition
				for _, def := range taskDef.ContainerDefinitions {
					if aws.StringValue(container.Name) == aws.StringValue(def.Name) {
						containerDefinition = def
						break
					}
				}

				if containerDefinition == nil {
					log.Debugf("Unable to find container definition for %s", aws.StringValue(container.Name))
					continue
				}

				var mach *machine
				if aws.StringValue(task.LaunchType) == ecs.LaunchTypeFargate {
					var ports []portMapping
					for _, mapping := range containerDefinition.PortMappings {
						if mapping != nil {
							ports = append(ports, portMapping{
								hostPort:      aws.Int64Value(mapping.HostPort),
								containerPort: aws.Int64Value(mapping.ContainerPort),
							})
						}
					}
					mach = &machine{
						privateIP: aws.StringValue(container.NetworkInterfaces[0].PrivateIpv4Address),
						ports:     ports,
						state:     aws.StringValue(task.LastStatus),
					}
				} else {
					var ports []portMapping
					for _, mapping := range container.NetworkBindings {
						if mapping != nil {
							ports = append(ports, portMapping{
								hostPort:      aws.Int64Value(mapping.HostPort),
								containerPort: aws.Int64Value(mapping.ContainerPort),
							})
						}
					}
					mach = &machine{
						privateIP: aws.StringValue(containerInstance.PrivateIpAddress),
						ports:     ports,
						state:     aws.StringValue(containerInstance.State.Name),
					}
				}

				instances = append(instances, ecsInstance{
					Name:                fmt.Sprintf("%s-%s", strings.Replace(aws.StringValue(task.Group), ":", "-", 1), *container.Name),
					ID:                  key[len(key)-12:],
					containerDefinition: containerDefinition,
					machine:             mach,
					TraefikLabels:       aws.StringValueMap(containerDefinition.DockerLabels),
				})
			}
		}
	}

	return instances, nil
}

func (p *Provider) lookupEc2Instances(ctx context.Context, client *awsClient, clusterName *string, ecsDatas map[string]*ecs.Task) (map[string]*ec2.Instance, error) {

	instanceIds := make(map[string]string)
	ec2Instances := make(map[string]*ec2.Instance)

	var containerInstancesArns []*string
	var instanceArns []*string

	for _, task := range ecsDatas {
		if task.ContainerInstanceArn != nil {
			containerInstancesArns = append(containerInstancesArns, task.ContainerInstanceArn)
		}
	}

	for _, arns := range p.chunkIDs(containerInstancesArns) {
		resp, err := client.ecs.DescribeContainerInstancesWithContext(ctx, &ecs.DescribeContainerInstancesInput{
			ContainerInstances: arns,
			Cluster:            clusterName,
		})

		if err != nil {
			log.Errorf("Unable to describe container instances: %v", err)
			return nil, err
		}

		for _, container := range resp.ContainerInstances {
			instanceIds[aws.StringValue(container.Ec2InstanceId)] = aws.StringValue(container.ContainerInstanceArn)
			instanceArns = append(instanceArns, container.Ec2InstanceId)
		}
	}

	if len(instanceArns) > 0 {
		for _, ids := range p.chunkIDs(instanceArns) {
			input := &ec2.DescribeInstancesInput{
				InstanceIds: ids,
			}

			err := client.ec2.DescribeInstancesPagesWithContext(ctx, input, func(page *ec2.DescribeInstancesOutput, lastPage bool) bool {
				if len(page.Reservations) > 0 {
					for _, r := range page.Reservations {
						for _, i := range r.Instances {
							if i.InstanceId != nil {
								ec2Instances[instanceIds[aws.StringValue(i.InstanceId)]] = i
							}
						}
					}
				}
				return !lastPage
			})

			if err != nil {
				log.Errorf("Unable to describe instances: %v", err)
				return nil, err
			}
		}
	}

	return ec2Instances, nil
}

func (p *Provider) lookupTaskDefinitions(ctx context.Context, client *awsClient, taskDefArns map[string]*ecs.Task) (map[string]*ecs.TaskDefinition, error) {
	taskDef := make(map[string]*ecs.TaskDefinition)
	for arn, task := range taskDefArns {
		resp, err := client.ecs.DescribeTaskDefinitionWithContext(ctx, &ecs.DescribeTaskDefinitionInput{
			TaskDefinition: task.TaskDefinitionArn,
		})

		if err != nil {
			log.Errorf("Unable to describe task definition: %s", err)
			return nil, err
		}

		taskDef[arn] = resp.TaskDefinition
	}
	return taskDef, nil
}

func (p *Provider) loadECSConfig(ctx context.Context, client *awsClient) (*types.Configuration, error) {
	instances, err := p.listInstances(ctx, client)
	if err != nil {
		return nil, err
	}

	return p.buildConfiguration(instances)
}

// chunkIDs ECS expects no more than 100 parameters be passed to a API call;
// thus, pack each string into an array capped at 100 elements
func (p *Provider) chunkIDs(ids []*string) [][]*string {
	var chuncked [][]*string
	for i := 0; i < len(ids); i += 100 {
		var sliceEnd int
		if i+100 < len(ids) {
			sliceEnd = i + 100
		} else {
			sliceEnd = len(ids)
		}
		chuncked = append(chuncked, ids[i:sliceEnd])
	}
	return chuncked
}
<commit_msg>Filter ECS tasks by LastStatus before adding to list of service tasks<commit_after>package ecs

import (
	"context"
	"fmt"
	"strings"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/aws/defaults"
	"github.com/aws/aws-sdk-go/aws/ec2metadata"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/aws/aws-sdk-go/service/ecs"
	"github.com/cenk/backoff"
	"github.com/containous/traefik/job"
	"github.com/containous/traefik/old/log"
	"github.com/containous/traefik/old/provider"
	"github.com/containous/traefik/old/types"
	"github.com/containous/traefik/safe"
)

var _ provider.Provider = (*Provider)(nil)

// Provider holds configurations of the provider.
type Provider struct {
	provider.BaseProvider `mapstructure:",squash" export:"true"`

	Domain           string `description:"Default domain used"`
	ExposedByDefault bool   `description:"Expose containers by default" export:"true"`
	RefreshSeconds   int    `description:"Polling interval (in seconds)" export:"true"`

	// Provider lookup parameters
	Clusters             Clusters `description:"ECS Clusters name"`
	AutoDiscoverClusters bool     `description:"Auto discover cluster" export:"true"`
	Region               string   `description:"The AWS region to use for requests" export:"true"`
	AccessKeyID          string   `description:"The AWS credentials access key to use for making requests"`
	SecretAccessKey      string   `description:"The AWS credentials access key to use for making requests"`
}

type ecsInstance struct {
	Name                string
	ID                  string
	containerDefinition *ecs.ContainerDefinition
	machine             *machine
	TraefikLabels       map[string]string
	SegmentLabels       map[string]string
	SegmentName         string
}

type portMapping struct {
	containerPort int64
	hostPort      int64
}

type machine struct {
	state     string
	privateIP string
	ports     []portMapping
}

type awsClient struct {
	ecs *ecs.ECS
	ec2 *ec2.EC2
}

// Init the provider
func (p *Provider) Init(constraints types.Constraints) error {
	return p.BaseProvider.Init(constraints)
}

func (p *Provider) createClient() (*awsClient, error) {
	sess, err := session.NewSession()
	if err != nil {
		return nil, err
	}

	ec2meta := ec2metadata.New(sess)
	if p.Region == "" {
		log.Infoln("No EC2 region provided, querying instance metadata endpoint...")
		identity, err := ec2meta.GetInstanceIdentityDocument()
		if err != nil {
			return nil, err
		}
		p.Region = identity.Region
	}

	cfg := &aws.Config{
		Region: &p.Region,
		Credentials: credentials.NewChainCredentials(
			[]credentials.Provider{
				&credentials.StaticProvider{
					Value: credentials.Value{
						AccessKeyID:     p.AccessKeyID,
						SecretAccessKey: p.SecretAccessKey,
					},
				},
				&credentials.EnvProvider{},
				&credentials.SharedCredentialsProvider{},
				defaults.RemoteCredProvider(*(defaults.Config()), defaults.Handlers()),
			}),
	}

	if p.Trace {
		cfg.WithLogger(aws.LoggerFunc(func(args ...interface{}) {
			log.Debug(args...)
		}))
	}

	return &awsClient{
		ecs: ecs.New(sess, cfg),
		ec2: ec2.New(sess, cfg),
	}, nil
}

// Provide allows the ecs provider to provide configurations to traefik
// using the given configuration channel.
func (p *Provider) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool) error {
	handleCanceled := func(ctx context.Context, err error) error {
		if ctx.Err() == context.Canceled || err == context.Canceled {
			return nil
		}
		return err
	}

	pool.Go(func(stop chan bool) {
		ctx, cancel := context.WithCancel(context.Background())
		safe.Go(func() {
			<-stop
			cancel()
		})

		operation := func() error {
			awsClient, err := p.createClient()
			if err != nil {
				return err
			}

			configuration, err := p.loadECSConfig(ctx, awsClient)
			if err != nil {
				return handleCanceled(ctx, err)
			}

			configurationChan <- types.ConfigMessage{
				ProviderName:  "ecs",
				Configuration: configuration,
			}

			if p.Watch {
				reload := time.NewTicker(time.Second * time.Duration(p.RefreshSeconds))
				defer reload.Stop()
				for {
					select {
					case <-reload.C:
						configuration, err := p.loadECSConfig(ctx, awsClient)
						if err != nil {
							return handleCanceled(ctx, err)
						}

						configurationChan <- types.ConfigMessage{
							ProviderName:  "ecs",
							Configuration: configuration,
						}
					case <-ctx.Done():
						return handleCanceled(ctx, ctx.Err())
					}
				}
			}

			return nil
		}

		notify := func(err error, time time.Duration) {
			log.Errorf("Provider connection error %+v, retrying in %s", err, time)
		}
		err := backoff.RetryNotify(safe.OperationWithRecover(operation), job.NewBackOff(backoff.NewExponentialBackOff()), notify)
		if err != nil {
			log.Errorf("Cannot connect to Provider api %+v", err)
		}
	})

	return nil
}

// Find all running Provider tasks in a cluster, also collect the task definitions (for docker labels)
// and the EC2 instance data
func (p *Provider) listInstances(ctx context.Context, client *awsClient) ([]ecsInstance, error) {
	var clustersArn []*string
	var clusters Clusters

	if p.AutoDiscoverClusters {
		input := &ecs.ListClustersInput{}
		for {
			result, err := client.ecs.ListClusters(input)
			if err != nil {
				return nil, err
			}
			if result != nil {
				clustersArn = append(clustersArn, result.ClusterArns...)
				input.NextToken = result.NextToken
				if result.NextToken == nil {
					break
				}
			} else {
				break
			}
		}
		for _, cArn := range clustersArn {
			clusters = append(clusters, *cArn)
		}
	} else {
		clusters = p.Clusters
	}

	var instances []ecsInstance

	log.Debugf("ECS Clusters: %s", clusters)

	for _, c := range clusters {

		input := &ecs.ListTasksInput{
			Cluster:       &c,
			DesiredStatus: aws.String(ecs.DesiredStatusRunning),
		}
		tasks := make(map[string]*ecs.Task)
		err := client.ecs.ListTasksPagesWithContext(ctx, input, func(page *ecs.ListTasksOutput, lastPage bool) bool {
			if len(page.TaskArns) > 0 {
				resp, err := client.ecs.DescribeTasksWithContext(ctx, &ecs.DescribeTasksInput{
					Tasks:   page.TaskArns,
					Cluster: &c,
				})
				if err != nil {
					log.Errorf("Unable to describe tasks for %v", page.TaskArns)
				} else {
					for _, t := range resp.Tasks {
						if aws.StringValue(t.LastStatus) == ecs.DesiredStatusRunning {
							tasks[aws.StringValue(t.TaskArn)] = t
						}
					}
				}
			}
			return !lastPage
		})

		if err != nil {
			log.Error("Unable to list tasks")
			return nil, err
		}

		// Skip to the next cluster if there are no tasks found on
		// this cluster.
		if len(tasks) == 0 {
			continue
		}

		ec2Instances, err := p.lookupEc2Instances(ctx, client, &c, tasks)
		if err != nil {
			return nil, err
		}

		taskDefinitions, err := p.lookupTaskDefinitions(ctx, client, tasks)
		if err != nil {
			return nil, err
		}

		for key, task := range tasks {

			containerInstance := ec2Instances[aws.StringValue(task.ContainerInstanceArn)]
			taskDef := taskDefinitions[key]

			for _, container := range task.Containers {

				var containerDefinition *ecs.ContainerDefinition
				for _, def := range taskDef.ContainerDefinitions {
					if aws.StringValue(container.Name) == aws.StringValue(def.Name) {
						containerDefinition = def
						break
					}
				}

				if containerDefinition == nil {
					log.Debugf("Unable to find container definition for %s", aws.StringValue(container.Name))
					continue
				}

				var mach *machine
				if aws.StringValue(task.LaunchType) == ecs.LaunchTypeFargate {
					var ports []portMapping
					for _, mapping := range containerDefinition.PortMappings {
						if mapping != nil {
							ports = append(ports, portMapping{
								hostPort:      aws.Int64Value(mapping.HostPort),
								containerPort: aws.Int64Value(mapping.ContainerPort),
							})
						}
					}
					mach = &machine{
						privateIP: aws.StringValue(container.NetworkInterfaces[0].PrivateIpv4Address),
						ports:     ports,
						state:     aws.StringValue(task.LastStatus),
					}
				} else {
					var ports []portMapping
					for _, mapping := range container.NetworkBindings {
						if mapping != nil {
							ports = append(ports, portMapping{
								hostPort:      aws.Int64Value(mapping.HostPort),
								containerPort: aws.Int64Value(mapping.ContainerPort),
							})
						}
					}
					mach = &machine{
						privateIP: aws.StringValue(containerInstance.PrivateIpAddress),
						ports:     ports,
						state:     aws.StringValue(containerInstance.State.Name),
					}
				}

				instances = append(instances, ecsInstance{
					Name:                fmt.Sprintf("%s-%s", strings.Replace(aws.StringValue(task.Group), ":", "-", 1), *container.Name),
					ID:                  key[len(key)-12:],
					containerDefinition: containerDefinition,
					machine:             mach,
					TraefikLabels:       aws.StringValueMap(containerDefinition.DockerLabels),
				})
			}
		}
	}

	return instances, nil
}

func (p *Provider) lookupEc2Instances(ctx context.Context, client *awsClient, clusterName *string, ecsDatas map[string]*ecs.Task) (map[string]*ec2.Instance, error) {

	instanceIds := make(map[string]string)
	ec2Instances := make(map[string]*ec2.Instance)

	var containerInstancesArns []*string
	var instanceArns []*string

	for _, task := range ecsDatas {
		if task.ContainerInstanceArn != nil {
			containerInstancesArns = append(containerInstancesArns, task.ContainerInstanceArn)
		}
	}

	for _, arns := range p.chunkIDs(containerInstancesArns) {
		resp, err := client.ecs.DescribeContainerInstancesWithContext(ctx, &ecs.DescribeContainerInstancesInput{
			ContainerInstances: arns,
			Cluster:            clusterName,
		})

		if err != nil {
			log.Errorf("Unable to describe container instances: %v", err)
			return nil, err
		}

		for _, container := range resp.ContainerInstances {
			instanceIds[aws.StringValue(container.Ec2InstanceId)] = aws.StringValue(container.ContainerInstanceArn)
			instanceArns = append(instanceArns, container.Ec2InstanceId)
		}
	}

	if len(instanceArns) > 0 {
		for _, ids := range p.chunkIDs(instanceArns) {
			input := &ec2.DescribeInstancesInput{
				InstanceIds: ids,
			}

			err := client.ec2.DescribeInstancesPagesWithContext(ctx, input, func(page *ec2.DescribeInstancesOutput, lastPage bool) bool {
				if len(page.Reservations) > 0 {
					for _, r := range page.Reservations {
						for _, i := range r.Instances {
							if i.InstanceId != nil {
								ec2Instances[instanceIds[aws.StringValue(i.InstanceId)]] = i
							}
						}
					}
				}
				return !lastPage
			})

			if err != nil {
				log.Errorf("Unable to describe instances: %v", err)
				return nil, err
			}
		}
	}

	return ec2Instances, nil
}

func (p *Provider) lookupTaskDefinitions(ctx context.Context, client *awsClient, taskDefArns map[string]*ecs.Task) (map[string]*ecs.TaskDefinition, error) {
	taskDef := make(map[string]*ecs.TaskDefinition)
	for arn, task := range taskDefArns {
		resp, err := client.ecs.DescribeTaskDefinitionWithContext(ctx, &ecs.DescribeTaskDefinitionInput{
			TaskDefinition: task.TaskDefinitionArn,
		})

		if err != nil {
			log.Errorf("Unable to describe task definition: %s", err)
			return nil, err
		}

		taskDef[arn] = resp.TaskDefinition
	}
	return taskDef, nil
}

func (p *Provider) loadECSConfig(ctx context.Context, client *awsClient) (*types.Configuration, error) {
	instances, err := p.listInstances(ctx, client)
	if err != nil {
		return nil, err
	}

	return p.buildConfiguration(instances)
}

// chunkIDs ECS expects no more than 100 parameters be passed to a API call;
// thus, pack each string into an array capped at 100 elements
func (p *Provider) chunkIDs(ids []*string) [][]*string {
	var chuncked [][]*string
	for i := 0; i < len(ids); i += 100 {
		var sliceEnd int
		if i+100 < len(ids) {
			sliceEnd = i + 100
		} else {
			sliceEnd = len(ids)
		}
		chuncked = append(chuncked, ids[i:sliceEnd])
	}
	return chuncked
}
<|endoftext|>


<commit_before>package cron_eval
import (
	"fmt"
	"time"
	"math"
	"github.com/gorhill/cronexpr"
)

func GetCurrentMinute(now time.Time) time.Time {
	fixed_now := time.Date(
		now.Year(),
		now.Month(),
		int(now.Day()),
		now.Hour(),
		now.Minute(),
		0,
		0,
		now.Location())
	return fixed_now

}

func GetNextCronRun(cron_line string, current_minute time.Time) time.Time {
	nextTime := cronexpr.MustParse(cron_line).Next(current_minute)
	return nextTime
}

func EvalCronLine(cron_line string) (bool, bool, int){
	now := time.Now()
	var DEBUG = true
	current_minute := GetCurrentMinute(now)
	next_cron_minute := current_minute.Add(-1 * time.Minute)
	next_cron_run := GetNextCronRun(cron_line, next_cron_minute)
	var run_now = false
	var run_after = false
    var sleep_seconds = 0
	if current_minute == next_cron_run {
		run_now = true
		sleep_seconds = 0
	} else {
		time_diff := time.Since(next_cron_run)
		sleep_seconds = int(math.Abs(time_diff.Seconds()))
		if DEBUG {
			fmt.Println("Sleep Seconds: ", sleep_seconds)
			fmt.Println("current_minute: ", current_minute)
			fmt.Println("next_cron_minute: ", next_cron_minute)
		}
		if sleep_seconds <= 86400 {
			run_after = true
		}
		if sleep_seconds <= 3 {
			sleep_seconds = 3
		}
	}
	return run_now, run_after, sleep_seconds
}<commit_msg>fixed formatting in cron_eval.go<commit_after>package cron_eval

import (
	"fmt"
	"github.com/gorhill/cronexpr"
	"math"
	"time"
)

func GetCurrentMinute(now time.Time) time.Time {
	fixed_now := time.Date(
		now.Year(),
		now.Month(),
		int(now.Day()),
		now.Hour(),
		now.Minute(),
		0,
		0,
		now.Location())
	return fixed_now

}

func GetNextCronRun(cron_line string, current_minute time.Time) time.Time {
	nextTime := cronexpr.MustParse(cron_line).Next(current_minute)
	return nextTime
}

func EvalCronLine(cron_line string) (bool, bool, int) {
	now := time.Now()
	var DEBUG = true
	current_minute := GetCurrentMinute(now)
	next_cron_minute := current_minute.Add(-1 * time.Minute)
	next_cron_run := GetNextCronRun(cron_line, next_cron_minute)
	var run_now = false
	var run_after = false
	var sleep_seconds = 0
	if current_minute == next_cron_run {
		run_now = true
		sleep_seconds = 0
	} else {
		time_diff := time.Since(next_cron_run)
		sleep_seconds = int(math.Abs(time_diff.Seconds()))
		if DEBUG {
			fmt.Println("Sleep Seconds: ", sleep_seconds)
			fmt.Println("current_minute: ", current_minute)
			fmt.Println("next_cron_minute: ", next_cron_minute)
		}
		if sleep_seconds <= 86400 {
			run_after = true
		}
		if sleep_seconds <= 3 {
			sleep_seconds = 3
		}
	}
	return run_now, run_after, sleep_seconds
}
<|endoftext|>


<commit_before>package parser

import (
	"errors"
	"fmt"
	"path"
	"path/filepath"
	"strconv"
	"strings"
	"time"

	"github.com/mithrandie/csvq/lib/cmd"
	"github.com/mithrandie/csvq/lib/ternary"
)

func StrToTime(s string) (time.Time, error) {
	flags := cmd.GetFlags()
	if 0 < len(flags.DatetimeFormat) {
		if t, e := time.Parse(ConvertDatetimeFormat(flags.DatetimeFormat), s); e == nil {
			return t, nil
		}
	}

	if t, e := time.Parse(time.RFC3339Nano, s); e == nil {
		return t, nil
	} else if t, e := time.ParseInLocation(DATETIME_FORMAT, s, cmd.GetLocation()); e == nil {
		return t, nil
	} else if t, e := time.Parse(DATETIME_FORMAT+" MST", s); e == nil {
		return t, nil
	} else if t, e := time.ParseInLocation("2006-01-02", s, cmd.GetLocation()); e == nil {
		return t, nil
	} else if t, e := time.ParseInLocation("2006/01/02 15:04:05.999999999", s, cmd.GetLocation()); e == nil {
		return t, nil
	} else if t, e := time.Parse("2006/01/02 15:04:05.999999999 MST", s); e == nil {
		return t, nil
	} else if t, e := time.ParseInLocation("2006/01/02", s, cmd.GetLocation()); e == nil {
		return t, nil
	} else if t, e := time.Parse(time.RFC822, s); e == nil {
		return t, nil
	} else if t, e := time.Parse(time.RFC822Z, s); e == nil {
		return t, nil
	}
	return time.Time{}, errors.New(fmt.Sprintf("%q does not match with datetime format", s))
}

func ConvertDatetimeFormat(format string) string {
	runes := []rune(format)
	dtfmt := []rune{}

	escaped := false
	for _, r := range runes {
		if !escaped {
			switch r {
			case '%':
				escaped = true
			default:
				dtfmt = append(dtfmt, r)
			}
			continue
		}

		switch r {
		case 'a':
			dtfmt = append(dtfmt, []rune("Mon")...)
		case 'b':
			dtfmt = append(dtfmt, []rune("Jan")...)
		case 'c':
			dtfmt = append(dtfmt, []rune("1")...)
		case 'd':
			dtfmt = append(dtfmt, []rune("02")...)
		case 'E':
			dtfmt = append(dtfmt, []rune("_2")...)
		case 'e':
			dtfmt = append(dtfmt, []rune("2")...)
		case 'F':
			dtfmt = append(dtfmt, []rune(".999999")...)
		case 'f':
			dtfmt = append(dtfmt, []rune(".000000")...)
		case 'H':
			dtfmt = append(dtfmt, []rune("15")...)
		case 'h':
			dtfmt = append(dtfmt, []rune("03")...)
		case 'i':
			dtfmt = append(dtfmt, []rune("04")...)
		case 'l':
			dtfmt = append(dtfmt, []rune("3")...)
		case 'M':
			dtfmt = append(dtfmt, []rune("January")...)
		case 'm':
			dtfmt = append(dtfmt, []rune("01")...)
		case 'N':
			dtfmt = append(dtfmt, []rune(".999999999")...)
		case 'n':
			dtfmt = append(dtfmt, []rune(".000000000")...)
		case 'p':
			dtfmt = append(dtfmt, []rune("PM")...)
		case 'r':
			dtfmt = append(dtfmt, []rune("03:04:05 PM")...)
		case 's':
			dtfmt = append(dtfmt, []rune("05")...)
		case 'T':
			dtfmt = append(dtfmt, []rune("15:04:05")...)
		case 'W':
			dtfmt = append(dtfmt, []rune("Monday")...)
		case 'Y':
			dtfmt = append(dtfmt, []rune("2006")...)
		case 'y':
			dtfmt = append(dtfmt, []rune("06")...)
		case 'Z':
			dtfmt = append(dtfmt, []rune("Z07:00")...)
		case 'z':
			dtfmt = append(dtfmt, []rune("MST")...)
		default:
			dtfmt = append(dtfmt, r)
		}
		escaped = false
	}

	return string(dtfmt)
}

func Int64ToStr(i int64) string {
	return strconv.FormatInt(i, 10)
}

func Float64ToStr(f float64) string {
	return strconv.FormatFloat(f, 'f', -1, 64)
}

func Float64ToPrimary(f float64) Primary {
	s := Float64ToStr(f)
	if i, e := strconv.ParseInt(s, 10, 64); e == nil {
		return NewInteger(i)
	}
	return NewFloat(f)
}

func PrimaryToInteger(p Primary) Primary {
	switch p.(type) {
	case Integer:
		return p
	case Float:
		if i, e := strconv.ParseInt(p.(Float).literal, 10, 64); e == nil {
			return NewInteger(i)
		}
	case String:
		if i, e := strconv.ParseInt(p.(String).Value(), 10, 64); e == nil {
			return NewInteger(i)
		}
	}

	return NewNull()
}

func PrimaryToFloat(p Primary) Primary {
	switch p.(type) {
	case Integer:
		return NewFloat(float64(p.(Integer).Value()))
	case Float:
		return p
	case String:
		if f, e := strconv.ParseFloat(p.(String).Value(), 64); e == nil {
			return NewFloat(f)
		}
	}

	return NewNull()
}

func PrimaryToDatetime(p Primary) Primary {
	switch p.(type) {
	case Integer:
		dt := time.Unix(p.(Integer).Value(), 0)
		return NewDatetime(dt)
	case Float:
		dt := float64ToTime(p.(Float).Value())
		return NewDatetime(dt)
	case Datetime:
		return p
	case String:
		if f, e := strconv.ParseFloat(p.(String).Value(), 64); e == nil {
			dt := float64ToTime(f)
			return NewDatetime(dt)
		}

		if dt, e := StrToTime(p.(String).Value()); e == nil {
			return NewDatetime(dt)
		}
	}

	return NewNull()
}

func PrimaryToBoolean(p Primary) Primary {
	switch p.(type) {
	case Boolean:
		return p
	case Ternary:
		if p.(Ternary).Ternary() != ternary.UNKNOWN {
			return NewBoolean(p.(Ternary).Bool())
		}
	case String:
		if b, e := strconv.ParseBool(p.(String).Value()); e == nil {
			return NewBoolean(b)
		}
	}
	return NewNull()
}

func PrimaryToString(p Primary) Primary {
	switch p.(type) {
	case String:
		return p
	case Integer:
		return NewString(Int64ToStr(p.(Integer).Value()))
	case Float:
		return NewString(Float64ToStr(p.(Float).Value()))
	}
	return NewNull()
}

func float64ToTime(f float64) time.Time {
	s := Float64ToStr(f)
	ns := strings.Split(s, ".")
	sec, _ := strconv.ParseInt(ns[0], 10, 64)
	var nsec int64
	if 1 < len(ns) {
		nsec, _ = strconv.ParseInt(ns[1]+strings.Repeat("0", 9-len(ns[1])), 10, 64)
	}
	return time.Unix(sec, nsec)
}

func FormatTableName(s string) string {
	return strings.TrimSuffix(path.Base(s), filepath.Ext(s))
}
<commit_msg>Fix a bug of type convertion.<commit_after>package parser

import (
	"errors"
	"fmt"
	"path"
	"path/filepath"
	"strconv"
	"strings"
	"time"

	"github.com/mithrandie/csvq/lib/cmd"
	"github.com/mithrandie/csvq/lib/ternary"
)

func StrToTime(s string) (time.Time, error) {
	flags := cmd.GetFlags()
	if 0 < len(flags.DatetimeFormat) {
		if t, e := time.Parse(ConvertDatetimeFormat(flags.DatetimeFormat), s); e == nil {
			return t, nil
		}
	}

	if t, e := time.Parse(time.RFC3339Nano, s); e == nil {
		return t, nil
	} else if t, e := time.ParseInLocation(DATETIME_FORMAT, s, cmd.GetLocation()); e == nil {
		return t, nil
	} else if t, e := time.Parse(DATETIME_FORMAT+" MST", s); e == nil {
		return t, nil
	} else if t, e := time.ParseInLocation("2006-01-02", s, cmd.GetLocation()); e == nil {
		return t, nil
	} else if t, e := time.ParseInLocation("2006/01/02 15:04:05.999999999", s, cmd.GetLocation()); e == nil {
		return t, nil
	} else if t, e := time.Parse("2006/01/02 15:04:05.999999999 MST", s); e == nil {
		return t, nil
	} else if t, e := time.ParseInLocation("2006/01/02", s, cmd.GetLocation()); e == nil {
		return t, nil
	} else if t, e := time.Parse(time.RFC822, s); e == nil {
		return t, nil
	} else if t, e := time.Parse(time.RFC822Z, s); e == nil {
		return t, nil
	}
	return time.Time{}, errors.New(fmt.Sprintf("%q does not match with datetime format", s))
}

func ConvertDatetimeFormat(format string) string {
	runes := []rune(format)
	dtfmt := []rune{}

	escaped := false
	for _, r := range runes {
		if !escaped {
			switch r {
			case '%':
				escaped = true
			default:
				dtfmt = append(dtfmt, r)
			}
			continue
		}

		switch r {
		case 'a':
			dtfmt = append(dtfmt, []rune("Mon")...)
		case 'b':
			dtfmt = append(dtfmt, []rune("Jan")...)
		case 'c':
			dtfmt = append(dtfmt, []rune("1")...)
		case 'd':
			dtfmt = append(dtfmt, []rune("02")...)
		case 'E':
			dtfmt = append(dtfmt, []rune("_2")...)
		case 'e':
			dtfmt = append(dtfmt, []rune("2")...)
		case 'F':
			dtfmt = append(dtfmt, []rune(".999999")...)
		case 'f':
			dtfmt = append(dtfmt, []rune(".000000")...)
		case 'H':
			dtfmt = append(dtfmt, []rune("15")...)
		case 'h':
			dtfmt = append(dtfmt, []rune("03")...)
		case 'i':
			dtfmt = append(dtfmt, []rune("04")...)
		case 'l':
			dtfmt = append(dtfmt, []rune("3")...)
		case 'M':
			dtfmt = append(dtfmt, []rune("January")...)
		case 'm':
			dtfmt = append(dtfmt, []rune("01")...)
		case 'N':
			dtfmt = append(dtfmt, []rune(".999999999")...)
		case 'n':
			dtfmt = append(dtfmt, []rune(".000000000")...)
		case 'p':
			dtfmt = append(dtfmt, []rune("PM")...)
		case 'r':
			dtfmt = append(dtfmt, []rune("03:04:05 PM")...)
		case 's':
			dtfmt = append(dtfmt, []rune("05")...)
		case 'T':
			dtfmt = append(dtfmt, []rune("15:04:05")...)
		case 'W':
			dtfmt = append(dtfmt, []rune("Monday")...)
		case 'Y':
			dtfmt = append(dtfmt, []rune("2006")...)
		case 'y':
			dtfmt = append(dtfmt, []rune("06")...)
		case 'Z':
			dtfmt = append(dtfmt, []rune("Z07:00")...)
		case 'z':
			dtfmt = append(dtfmt, []rune("MST")...)
		default:
			dtfmt = append(dtfmt, r)
		}
		escaped = false
	}

	return string(dtfmt)
}

func Int64ToStr(i int64) string {
	return strconv.FormatInt(i, 10)
}

func Float64ToStr(f float64) string {
	return strconv.FormatFloat(f, 'f', -1, 64)
}

func Float64ToPrimary(f float64) Primary {
	s := Float64ToStr(f)
	if i, e := strconv.ParseInt(s, 10, 64); e == nil {
		return NewInteger(i)
	}
	return NewFloat(f)
}

func PrimaryToInteger(p Primary) Primary {
	switch p.(type) {
	case Integer:
		return p
	case Float:
		if i, e := strconv.ParseInt(p.(Float).literal, 10, 64); e == nil {
			return NewInteger(i)
		}
	case String:
		if i, e := strconv.ParseInt(p.(String).Value(), 10, 64); e == nil {
			return NewInteger(i)
		}
	}

	return NewNull()
}

func PrimaryToFloat(p Primary) Primary {
	switch p.(type) {
	case Integer:
		return NewFloat(float64(p.(Integer).Value()))
	case Float:
		return p
	case String:
		if f, e := strconv.ParseFloat(p.(String).Value(), 64); e == nil {
			return NewFloat(f)
		}
	}

	return NewNull()
}

func PrimaryToDatetime(p Primary) Primary {
	switch p.(type) {
	case Integer:
		dt := time.Unix(p.(Integer).Value(), 0)
		return NewDatetime(dt)
	case Float:
		dt := float64ToTime(p.(Float).Value())
		return NewDatetime(dt)
	case Datetime:
		return p
	case String:
		if f, e := strconv.ParseFloat(p.(String).Value(), 64); e == nil {
			dt := float64ToTime(f)
			return NewDatetime(dt)
		}

		if dt, e := StrToTime(p.(String).Value()); e == nil {
			return NewDatetime(dt)
		}
	}

	return NewNull()
}

func PrimaryToBoolean(p Primary) Primary {
	switch p.(type) {
	case Boolean:
		return p
	case Ternary:
		if p.(Ternary).Ternary() != ternary.UNKNOWN {
			return NewBoolean(p.(Ternary).Bool())
		}
	case Integer, Float:
		return NewBoolean(p.Bool())
	case String:
		if b, e := strconv.ParseBool(p.(String).Value()); e == nil {
			return NewBoolean(b)
		}
	}
	return NewNull()
}

func PrimaryToString(p Primary) Primary {
	switch p.(type) {
	case String:
		return p
	case Integer:
		return NewString(Int64ToStr(p.(Integer).Value()))
	case Float:
		return NewString(Float64ToStr(p.(Float).Value()))
	}
	return NewNull()
}

func float64ToTime(f float64) time.Time {
	s := Float64ToStr(f)
	ns := strings.Split(s, ".")
	sec, _ := strconv.ParseInt(ns[0], 10, 64)
	var nsec int64
	if 1 < len(ns) {
		nsec, _ = strconv.ParseInt(ns[1]+strings.Repeat("0", 9-len(ns[1])), 10, 64)
	}
	return time.Unix(sec, nsec)
}

func FormatTableName(s string) string {
	return strings.TrimSuffix(path.Base(s), filepath.Ext(s))
}
<|endoftext|>


<commit_before>package library

const (
	_ = iota
	// GraphTypeArea represents an area graph type.
	GraphTypeArea
	// GraphTypeLine represents a line graph type.
	GraphTypeLine
)

const (
	_ = iota
	// StackModeNone represents a null stack mode.
	StackModeNone
	// StackModeNormal represents a normal stack mode.
	StackModeNormal
	// StackModePercent represents a percentage stack mode.
	StackModePercent
)

// Graph represents a graph containing list of series.
type Graph struct {
	Item
	Type      int          `json:"type"`
	StackMode int          `json:"stack_mode"`
	Groups    []*OperGroup `json:"groups"`
}

// OperGroup represents an operation group entry.
type OperGroup struct {
	Name    string                 `json:"name"`
	Type    int                    `json:"type"`
	StackID int                    `json:"stack_id"`
	Series  []*Serie               `json:"series"`
	Scale   float64                `json:"scale"`
	Options map[string]interface{} `json:"options"`
}

// Serie represents a serie entry.
type Serie struct {
	Name   string  `json:"name"`
	Origin string  `json:"origin"`
	Source string  `json:"source"`
	Metric string  `json:"metric"`
	Scale  float64 `json:"scale"`
}
<commit_msg>Add `String()` method to library/graph structs<commit_after>package library

import (
	"fmt"
	"strings"
)

const (
	_ = iota
	// GraphTypeArea represents an area graph type.
	GraphTypeArea
	// GraphTypeLine represents a line graph type.
	GraphTypeLine
)

const (
	_ = iota
	// StackModeNone represents a null stack mode.
	StackModeNone
	// StackModeNormal represents a normal stack mode.
	StackModeNormal
	// StackModePercent represents a percentage stack mode.
	StackModePercent
)

// Graph represents a graph containing list of series.
type Graph struct {
	Item
	Type      int          `json:"type"`
	StackMode int          `json:"stack_mode"`
	Groups    []*OperGroup `json:"groups"`
}

// OperGroup represents an operation group entry.
type OperGroup struct {
	Name    string                 `json:"name"`
	Type    int                    `json:"type"`
	StackID int                    `json:"stack_id"`
	Series  []*Serie               `json:"series"`
	Scale   float64                `json:"scale"`
	Options map[string]interface{} `json:"options"`
}

// Serie represents a serie entry.
type Serie struct {
	Name   string  `json:"name"`
	Origin string  `json:"origin"`
	Source string  `json:"source"`
	Metric string  `json:"metric"`
	Scale  float64 `json:"scale"`
}

func (graph *Graph) String() string {
	return fmt.Sprintf(
		"Graph{ID:\"%s\" Name:\"%s\" Type:%d Groups:[%s]}",
		graph.Name,
		graph.ID,
		graph.Type,
		func(groups []*OperGroup) string {
			groupStrings := make([]string, len(groups))

			for i, group := range groups {
				groupStrings[i] = fmt.Sprintf("%s", group)
			}

			return strings.Join(groupStrings, ", ")
		}(graph.Groups),
	)
}

func (group *OperGroup) String() string {
	return fmt.Sprintf(
		"OperGroup{Name:\"%s\" Type:%d Scale:%f Series:[%s]}",
		group.Name,
		group.Type,
		group.Scale,
		func(series []*Serie) string {
			serieStrings := make([]string, len(series))

			for i, serie := range series {
				serieStrings[i] = fmt.Sprintf("%s", serie)
			}

			return strings.Join(serieStrings, ", ")
		}(group.Series),
	)
}

func (serie *Serie) String() string {
	return fmt.Sprintf(
		"Serie{Name:\"%s\" Origin:\"%s\" Source:\"%s\" Metric:\"%s\" Scale:%f}",
		serie.Name,
		serie.Origin,
		serie.Source,
		serie.Metric,
		serie.Scale,
	)
}
<|endoftext|>


<commit_before>// Package runutil provides functions for running commands and
// functions and logging their outcome.
package runutil

import (
	"fmt"
	"io"
	"os"
	"os/exec"
	"strings"
	"syscall"
	"time"

	"tools/lib/envutil"
)

const (
	prefix = ">>"
)

var (
	CommandTimedoutErr = fmt.Errorf("command timed out")
)

type Run struct {
	indent  int
	Stdout  io.Writer
	Verbose bool
}

func New(verbose bool, stdout io.Writer) *Run {
	return &Run{
		indent:  0,
		Stdout:  stdout,
		Verbose: verbose,
	}
}

// Command runs the given command and logs its outcome using the default verbosity.
func (r *Run) Command(stdout, stderr io.Writer, env map[string]string, path string, args ...string) error {
	return r.command(r.Verbose, stdout, stderr, env, path, 0, args...)
}

// CommandWithTimeout runs the given command with timeout and logs its outcome using the default verbosity.
func (r *Run) CommandWithTimeout(stdout, stderr io.Writer, env map[string]string, path string, timeout time.Duration, args ...string) error {
	return r.command(r.Verbose, stdout, stderr, env, path, timeout, args...)
}

// CommandWithVerbosity runs the given command and logs its outcome using the given verbosity.
func (r *Run) CommandWithVerbosity(verbose bool, stdout, stderr io.Writer, env map[string]string, path string, args ...string) error {
	return r.command(verbose, stdout, stderr, env, path, 0, args...)
}

func (r *Run) command(verbose bool, stdout, stderr io.Writer, env map[string]string, path string, timeout time.Duration, args ...string) error {
	r.increaseIndent()
	defer r.decreaseIndent()
	command := exec.Command(path, args...)
	command.Stdin = os.Stdin
	command.Stdout = stdout
	command.Stderr = stderr
	command.Env = envutil.ToSlice(env)
	// Make the process of this command a new process group leader
	// to facilitate clean up of processes that time out.
	// command.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
	if verbose {
		r.printf(r.Stdout, strings.Join(command.Args, " "))
	}

	if timeout == 0 {
		// No timeout.
		var err error
		if err = command.Run(); err != nil {
			if verbose {
				r.printf(r.Stdout, "FAILED")
			}
		} else {
			if verbose {
				r.printf(r.Stdout, "OK")
			}
		}
		return err
	}
	// Has timeout.
	if err := command.Start(); err != nil {
		if verbose {
			r.printf(r.Stdout, "FAILED")
		}
		return err
	}
	done := make(chan error, 1)
	go func() {
		done <- command.Wait()
	}()
	select {
	case <-time.After(timeout):
		// The command has timed out.
		// Sending SIGTERM to the process group (the negative value of the process's pid)
		// will kill all the processes in that group.
		if err := syscall.Kill(-command.Process.Pid, syscall.SIGTERM); err != nil {
			fmt.Fprintf(r.Stdout, "Kill(%v, %v) failed: %v\n", -command.Process.Pid, syscall.SIGTERM, err)
		}
		time.Sleep(10 * time.Second)
		if err := syscall.Kill(-command.Process.Pid, syscall.SIGKILL); err != nil {
			fmt.Fprintf(r.Stdout, "Kill(%v, %v) failed: %v\n", -command.Process.Pid, syscall.SIGKILL, err)
		}
		// Allow goroutine to exit.
		<-done
		if verbose {
			r.printf(r.Stdout, "TIMED OUT")
		}
		return CommandTimedoutErr
	case err := <-done:
		if err != nil {
			if verbose {
				r.printf(r.Stdout, "FAILED")
			}
		} else {
			if verbose {
				r.printf(r.Stdout, "OK")
			}
		}
		return err
	}

	return nil
}

// Function runs the given function and logs its outcome using the
// default verbosity.
func (r *Run) Function(fn func() error, format string, args ...interface{}) error {
	return r.FunctionWithVerbosity(r.Verbose, fn, format, args...)
}

// FunctionWithVerbosity runs the given function and logs its outcome
// using the given verbosity.
func (r *Run) FunctionWithVerbosity(verbose bool, fn func() error, format string, args ...interface{}) error {
	r.increaseIndent()
	defer r.decreaseIndent()
	if verbose {
		r.printf(r.Stdout, format, args...)
	}
	err := fn()
	if err != nil {
		if verbose {
			r.printf(r.Stdout, "FAILED")
		}
	} else {
		if verbose {
			r.printf(r.Stdout, "OK")
		}
	}
	return err
}

// Output logs the given list of lines using the default verbosity.
func (r *Run) Output(output []string) {
	r.OutputWithVerbosity(r.Verbose, output)
}

// OutputWithVerbosity logs the given list of lines using the given
// verbosity.
func (r *Run) OutputWithVerbosity(verbose bool, output []string) {
	if verbose {
		for _, line := range output {
			r.logLine(line)
		}
	}
}

func (r *Run) decreaseIndent() {
	r.indent--
}

func (r *Run) increaseIndent() {
	r.indent++
}

func (r *Run) logLine(line string) {
	if !strings.HasPrefix(line, prefix) {
		r.increaseIndent()
		defer r.decreaseIndent()
	}
	r.printf(r.Stdout, "%v", line)
}

func (r *Run) printf(stdout io.Writer, format string, args ...interface{}) {
	args = append([]interface{}{strings.Repeat(prefix, r.indent)}, args...)
	fmt.Fprintf(stdout, "%v "+format+"\n", args...)
}
<commit_msg>TBR: tools/lib/runutil/run: only set Setpgid if timeout is not zero.<commit_after>// Package runutil provides functions for running commands and
// functions and logging their outcome.
package runutil

import (
	"fmt"
	"io"
	"os"
	"os/exec"
	"strings"
	"syscall"
	"time"

	"tools/lib/envutil"
)

const (
	prefix = ">>"
)

var (
	CommandTimedoutErr = fmt.Errorf("command timed out")
)

type Run struct {
	indent  int
	Stdout  io.Writer
	Verbose bool
}

func New(verbose bool, stdout io.Writer) *Run {
	return &Run{
		indent:  0,
		Stdout:  stdout,
		Verbose: verbose,
	}
}

// Command runs the given command and logs its outcome using the default verbosity.
func (r *Run) Command(stdout, stderr io.Writer, env map[string]string, path string, args ...string) error {
	return r.command(r.Verbose, stdout, stderr, env, path, 0, args...)
}

// CommandWithTimeout runs the given command with timeout and logs its outcome using the default verbosity.
func (r *Run) CommandWithTimeout(stdout, stderr io.Writer, env map[string]string, path string, timeout time.Duration, args ...string) error {
	return r.command(r.Verbose, stdout, stderr, env, path, timeout, args...)
}

// CommandWithVerbosity runs the given command and logs its outcome using the given verbosity.
func (r *Run) CommandWithVerbosity(verbose bool, stdout, stderr io.Writer, env map[string]string, path string, args ...string) error {
	return r.command(verbose, stdout, stderr, env, path, 0, args...)
}

func (r *Run) command(verbose bool, stdout, stderr io.Writer, env map[string]string, path string, timeout time.Duration, args ...string) error {
	r.increaseIndent()
	defer r.decreaseIndent()
	command := exec.Command(path, args...)
	command.Stdin = os.Stdin
	command.Stdout = stdout
	command.Stderr = stderr
	command.Env = envutil.ToSlice(env)
	if verbose {
		r.printf(r.Stdout, strings.Join(command.Args, " "))
	}

	if timeout == 0 {
		// No timeout.
		var err error
		if err = command.Run(); err != nil {
			if verbose {
				r.printf(r.Stdout, "FAILED")
			}
		} else {
			if verbose {
				r.printf(r.Stdout, "OK")
			}
		}
		return err
	}
	// Has timeout.
	// Make the process of this command a new process group leader
	// to facilitate clean up of processes that time out.
	command.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
	if err := command.Start(); err != nil {
		if verbose {
			r.printf(r.Stdout, "FAILED")
		}
		return err
	}
	done := make(chan error, 1)
	go func() {
		done <- command.Wait()
	}()
	select {
	case <-time.After(timeout):
		// The command has timed out.
		// Sending SIGTERM to the process group (the negative value of the process's pid)
		// will kill all the processes in that group.
		if err := syscall.Kill(-command.Process.Pid, syscall.SIGTERM); err != nil {
			fmt.Fprintf(r.Stdout, "Kill(%v, %v) failed: %v\n", -command.Process.Pid, syscall.SIGTERM, err)
		}
		time.Sleep(10 * time.Second)
		if err := syscall.Kill(-command.Process.Pid, syscall.SIGKILL); err != nil {
			fmt.Fprintf(r.Stdout, "Kill(%v, %v) failed: %v\n", -command.Process.Pid, syscall.SIGKILL, err)
		}
		// Allow goroutine to exit.
		<-done
		if verbose {
			r.printf(r.Stdout, "TIMED OUT")
		}
		return CommandTimedoutErr
	case err := <-done:
		if err != nil {
			if verbose {
				r.printf(r.Stdout, "FAILED")
			}
		} else {
			if verbose {
				r.printf(r.Stdout, "OK")
			}
		}
		return err
	}

	return nil
}

// Function runs the given function and logs its outcome using the
// default verbosity.
func (r *Run) Function(fn func() error, format string, args ...interface{}) error {
	return r.FunctionWithVerbosity(r.Verbose, fn, format, args...)
}

// FunctionWithVerbosity runs the given function and logs its outcome
// using the given verbosity.
func (r *Run) FunctionWithVerbosity(verbose bool, fn func() error, format string, args ...interface{}) error {
	r.increaseIndent()
	defer r.decreaseIndent()
	if verbose {
		r.printf(r.Stdout, format, args...)
	}
	err := fn()
	if err != nil {
		if verbose {
			r.printf(r.Stdout, "FAILED")
		}
	} else {
		if verbose {
			r.printf(r.Stdout, "OK")
		}
	}
	return err
}

// Output logs the given list of lines using the default verbosity.
func (r *Run) Output(output []string) {
	r.OutputWithVerbosity(r.Verbose, output)
}

// OutputWithVerbosity logs the given list of lines using the given
// verbosity.
func (r *Run) OutputWithVerbosity(verbose bool, output []string) {
	if verbose {
		for _, line := range output {
			r.logLine(line)
		}
	}
}

func (r *Run) decreaseIndent() {
	r.indent--
}

func (r *Run) increaseIndent() {
	r.indent++
}

func (r *Run) logLine(line string) {
	if !strings.HasPrefix(line, prefix) {
		r.increaseIndent()
		defer r.decreaseIndent()
	}
	r.printf(r.Stdout, "%v", line)
}

func (r *Run) printf(stdout io.Writer, format string, args ...interface{}) {
	args = append([]interface{}{strings.Repeat(prefix, r.indent)}, args...)
	fmt.Fprintf(stdout, "%v "+format+"\n", args...)
}
<|endoftext|>


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

package sparc64

import (
	"cmd/internal/obj"
	"encoding/binary"
)

var Linksparc64 = obj.LinkArch{
	ByteOrder: binary.BigEndian,
	Name:      "sparc64",
	Thechar:   'u',
	Minlc:     4,
	Ptrsize:   8,
	Regsize:   8,
}
<commit_msg>cmd/internal/obj/sparc64: add UnaryDst<commit_after>// Copyright 2015 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.

package sparc64

import (
	"cmd/internal/obj"
	"encoding/binary"
)

var unaryDst = map[int]bool{
	AWORD:   true,
	ADWORD:  true,
	ARDPC:   true,
	ARDTICK: true,
	ARDCCR:  true,
}

var Linksparc64 = obj.LinkArch{
	ByteOrder: binary.BigEndian,
	Name:      "sparc64",
	Thechar:   'u',
	UnaryDst:  unaryDst,
	Minlc:     4,
	Ptrsize:   8,
	Regsize:   8,
}
<|endoftext|>


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

import "k8s.io/apimachinery/pkg/util/sets"

// Phase is a portion of work that kops completes.
type Phase string

const (
	// PhaseStageAssets uploads various assets such as containers in a private registry
	PhaseStageAssets Phase = "assets"
	// PhaseNetwork creates network infrastructure.
	PhaseNetwork Phase = "network"
	// PhaseIAM creates IAM profiles and roles, security groups and firewalls
	PhaseSecurity Phase = "security"
	// PhaseCluster creates the servers, and load-alancers
	PhaseCluster Phase = "cluster"
)

// Phases are used for validation and cli help.
var Phases = sets.NewString(
	string(PhaseStageAssets),
	string(PhaseSecurity),
	string(PhaseNetwork),
	string(PhaseCluster),
)
<commit_msg>Fix code comment on PhaseSecurity<commit_after>/*
Copyright 2017 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 cloudup

import "k8s.io/apimachinery/pkg/util/sets"

// Phase is a portion of work that kops completes.
type Phase string

const (
	// PhaseStageAssets uploads various assets such as containers in a private registry
	PhaseStageAssets Phase = "assets"
	// PhaseNetwork creates network infrastructure.
	PhaseNetwork Phase = "network"
	// PhaseSecurity creates IAM profiles and roles, security groups and firewalls
	PhaseSecurity Phase = "security"
	// PhaseCluster creates the servers, and load-alancers
	PhaseCluster Phase = "cluster"
)

// Phases are used for validation and cli help.
var Phases = sets.NewString(
	string(PhaseStageAssets),
	string(PhaseSecurity),
	string(PhaseNetwork),
	string(PhaseCluster),
)
<|endoftext|>