<commit_before>package app_runner

import (
	"encoding/json"
	"errors"
	"fmt"
	"strconv"
	"time"

	"github.com/cloudfoundry-incubator/lattice/ltc/logs/reserved_app_ids"
	"github.com/cloudfoundry-incubator/lattice/ltc/route_helpers"
	"github.com/cloudfoundry-incubator/receptor"
	"github.com/cloudfoundry-incubator/runtime-schema/models"
)

type MonitorMethod int

//go:generate counterfeiter -o fake_app_runner/fake_app_runner.go . AppRunner
type AppRunner interface {
	CreateApp(params CreateAppParams) error
	SubmitLrp(lrpJSON []byte) (string, error)
	ScaleApp(name string, instances int) error
	UpdateAppRoutes(name string, routes RouteOverrides) error
	RemoveApp(name string) error
}

type MonitorConfig struct {
	Method  MonitorMethod
	URI     string
	Port    uint16
	Timeout time.Duration
}

type RouteOverrides []RouteOverride

type RouteOverride struct {
	HostnamePrefix string
	Port           uint16
}

type AppEnvironmentParams struct {
	EnvironmentVariables map[string]string
	Privileged           bool
	Monitor              MonitorConfig
	Instances            int
	CPUWeight            uint
	MemoryMB             int
	DiskMB               int
	ExposedPorts         []uint16
	WorkingDir           string
	RouteOverrides       RouteOverrides
	NoRoutes             bool
}

type CreateAppParams struct {
	AppEnvironmentParams

	Name         string
	StartCommand string
	RootFS       string
	AppArgs      []string
	Timeout      time.Duration
	Setup        models.Action
}

const (
	NoMonitor MonitorMethod = iota
	PortMonitor
	URLMonitor

	AttemptedToCreateLatticeDebugErrorMessage = reserved_app_ids.LatticeDebugLogStreamAppId + " is a reserved app name. It is used internally to stream debug logs for lattice components."
)

const (
	healthcheckDownloadUrl string = "http://file_server.service.dc1.consul:8080/v1/static/healthcheck.tgz"
	lrpDomain              string = "lattice"
)

type appRunner struct {
	receptorClient receptor.Client
	systemDomain   string
}

func New(receptorClient receptor.Client, systemDomain string) AppRunner {
	return &appRunner{receptorClient, systemDomain}
}

func (appRunner *appRunner) CreateApp(params CreateAppParams) error {
	if params.Name == reserved_app_ids.LatticeDebugLogStreamAppId {
		return errors.New(AttemptedToCreateLatticeDebugErrorMessage)
	}
	if exists, err := appRunner.desiredLRPExists(params.Name); err != nil {
		return err
	} else if exists {
		return newExistingAppError(params.Name)
	}

	if err := appRunner.receptorClient.UpsertDomain(lrpDomain, 0); err != nil {
		return err
	}

	return appRunner.desireLrp(params)
}

func (appRunner *appRunner) SubmitLrp(lrpJSON []byte) (string, error) {
	desiredLRP := receptor.DesiredLRPCreateRequest{}

	if err := json.Unmarshal(lrpJSON, &desiredLRP); err != nil {
		return "", err
	}

	if desiredLRP.ProcessGuid == reserved_app_ids.LatticeDebugLogStreamAppId {
		return desiredLRP.ProcessGuid, errors.New(AttemptedToCreateLatticeDebugErrorMessage)
	}

	if exists, err := appRunner.desiredLRPExists(desiredLRP.ProcessGuid); err != nil {
		return desiredLRP.ProcessGuid, err
	} else if exists {
		return desiredLRP.ProcessGuid, newExistingAppError(desiredLRP.ProcessGuid)
	}

	if err := appRunner.receptorClient.UpsertDomain(lrpDomain, 0); err != nil {
		return desiredLRP.ProcessGuid, err
	}

	return desiredLRP.ProcessGuid, appRunner.receptorClient.CreateDesiredLRP(desiredLRP)
}

func (appRunner *appRunner) ScaleApp(name string, instances int) error {
	if exists, err := appRunner.desiredLRPExists(name); err != nil {
		return err
	} else if !exists {
		return newAppNotStartedError(name)
	}

	return appRunner.updateLrpInstances(name, instances)
}

func (appRunner *appRunner) UpdateAppRoutes(name string, routes RouteOverrides) error {
	if exists, err := appRunner.desiredLRPExists(name); err != nil {
		return err
	} else if !exists {
		return newAppNotStartedError(name)
	}

	return appRunner.updateLrpRoutes(name, routes)
}

func (appRunner *appRunner) RemoveApp(name string) error {
	if lrpExists, err := appRunner.desiredLRPExists(name); err != nil {
		return err
	} else if !lrpExists {
		return newAppNotStartedError(name)
	}

	return appRunner.receptorClient.DeleteDesiredLRP(name)
}

func (appRunner *appRunner) desiredLRPExists(name string) (exists bool, err error) {
	desiredLRPs, err := appRunner.receptorClient.DesiredLRPs()
	if err != nil {
		return false, err
	}

	for _, desiredLRP := range desiredLRPs {
		if desiredLRP.ProcessGuid == name {
			return true, nil
		}
	}

	return false, nil
}

func (appRunner *appRunner) desireLrp(params CreateAppParams) error {

	envVars := buildEnvironmentVariables(params.EnvironmentVariables)
	envVars = append(envVars, receptor.EnvironmentVariable{Name: "PORT", Value: fmt.Sprintf("%d", params.Monitor.Port)})

	var appRoutes route_helpers.AppRoutes
	if params.NoRoutes {
		appRoutes = route_helpers.AppRoutes{}
	} else if len(params.RouteOverrides) > 0 {
		routeMap := make(map[uint16][]string)
		for _, override := range params.RouteOverrides {
			routeMap[override.Port] = append(routeMap[override.Port], fmt.Sprintf("%s.%s", override.HostnamePrefix, appRunner.systemDomain))
		}
		for port, hostnames := range routeMap {
			appRoutes = append(appRoutes, route_helpers.AppRoute{
				Hostnames: hostnames,
				Port:      port,
			})
		}
	} else {
		appRoutes = appRunner.buildDefaultRoutingInfo(params.Name, params.ExposedPorts, params.Monitor.Port)
	}

	req := receptor.DesiredLRPCreateRequest{
		ProcessGuid:          params.Name,
		Domain:               lrpDomain,
		RootFS:               params.RootFS,
		Instances:            params.Instances,
		Routes:               appRoutes.RoutingInfo(),
		CPUWeight:            params.CPUWeight,
		MemoryMB:             params.MemoryMB,
		DiskMB:               params.DiskMB,
		Privileged:           params.Privileged,
		Ports:                params.ExposedPorts,
		LogGuid:              params.Name,
		LogSource:            "APP",
		MetricsGuid:          params.Name,
		EnvironmentVariables: envVars,
		Setup:                params.Setup,
		Action: &models.RunAction{
			Path: params.StartCommand,
			Args: params.AppArgs,
			Dir:  params.WorkingDir,
		},
	}

	var healthCheckArgs []string
	if params.Monitor.Timeout != 0 {
		healthCheckArgs = append(healthCheckArgs, "-timeout", fmt.Sprint(params.Monitor.Timeout))
	}
	switch params.Monitor.Method {
	case PortMonitor:
		req.Monitor = &models.RunAction{
			Path:      "/tmp/healthcheck",
			Args:      append(healthCheckArgs, "-port", fmt.Sprint(params.Monitor.Port)),
			LogSource: "HEALTH",
		}
	case URLMonitor:
		req.Monitor = &models.RunAction{
			Path:      "/tmp/healthcheck",
			Args:      append(healthCheckArgs, "-port", fmt.Sprint(params.Monitor.Port), "-uri", params.Monitor.URI),
			LogSource: "HEALTH",
		}
	}

	return appRunner.receptorClient.CreateDesiredLRP(req)
}

func (appRunner *appRunner) updateLrpInstances(name string, instances int) error {
	err := appRunner.receptorClient.UpdateDesiredLRP(
		name,
		receptor.DesiredLRPUpdateRequest{
			Instances: &instances,
		},
	)

	return err
}

func (appRunner *appRunner) updateLrpRoutes(name string, routes RouteOverrides) error {
	appRoutes := route_helpers.AppRoutes{}

	routeMap := make(map[uint16][]string)
	for _, override := range routes {
		routeMap[override.Port] = append(routeMap[override.Port], fmt.Sprintf("%s.%s", override.HostnamePrefix, appRunner.systemDomain))
	}
	for port, hostnames := range routeMap {
		appRoutes = append(appRoutes, route_helpers.AppRoute{
			Hostnames: hostnames,
			Port:      port,
		})
	}

	err := appRunner.receptorClient.UpdateDesiredLRP(
		name,
		receptor.DesiredLRPUpdateRequest{
			Routes: appRoutes.RoutingInfo(),
		},
	)

	return err
}

func (appRunner *appRunner) buildDefaultRoutingInfo(appName string, exposedPorts []uint16, monitorPort uint16) route_helpers.AppRoutes {
	appRoutes := route_helpers.AppRoutes{}

	for _, port := range exposedPorts {
		hostnames := []string{}
		if port == monitorPort {
			hostnames = append(hostnames, fmt.Sprintf("%s.%s", appName, appRunner.systemDomain))
		}

		hostnames = append(hostnames, fmt.Sprintf("%s-%s.%s", appName, strconv.Itoa(int(port)), appRunner.systemDomain))
		appRoutes = append(appRoutes, route_helpers.AppRoute{
			Hostnames: hostnames,
			Port:      port,
		})
	}

	return appRoutes
}

func buildEnvironmentVariables(environmentVariables map[string]string) []receptor.EnvironmentVariable {
	appEnvVars := make([]receptor.EnvironmentVariable, 0, len(environmentVariables)+1)
	for name, value := range environmentVariables {
		appEnvVars = append(appEnvVars, receptor.EnvironmentVariable{Name: name, Value: value})
	}
	return appEnvVars
}
<commit_msg>Make sure default route is published on `ltc launch-droplet --no-monitor`<commit_after>package app_runner

import (
	"encoding/json"
	"errors"
	"fmt"
	"strconv"
	"time"

	"github.com/cloudfoundry-incubator/lattice/ltc/logs/reserved_app_ids"
	"github.com/cloudfoundry-incubator/lattice/ltc/route_helpers"
	"github.com/cloudfoundry-incubator/receptor"
	"github.com/cloudfoundry-incubator/runtime-schema/models"
)

type MonitorMethod int

//go:generate counterfeiter -o fake_app_runner/fake_app_runner.go . AppRunner
type AppRunner interface {
	CreateApp(params CreateAppParams) error
	SubmitLrp(lrpJSON []byte) (string, error)
	ScaleApp(name string, instances int) error
	UpdateAppRoutes(name string, routes RouteOverrides) error
	RemoveApp(name string) error
}

type MonitorConfig struct {
	Method  MonitorMethod
	URI     string
	Port    uint16
	Timeout time.Duration
}

type RouteOverrides []RouteOverride

type RouteOverride struct {
	HostnamePrefix string
	Port           uint16
}

type AppEnvironmentParams struct {
	EnvironmentVariables map[string]string
	Privileged           bool
	Monitor              MonitorConfig
	Instances            int
	CPUWeight            uint
	MemoryMB             int
	DiskMB               int
	ExposedPorts         []uint16
	WorkingDir           string
	RouteOverrides       RouteOverrides
	NoRoutes             bool
}

type CreateAppParams struct {
	AppEnvironmentParams

	Name         string
	StartCommand string
	RootFS       string
	AppArgs      []string
	Timeout      time.Duration
	Setup        models.Action
}

const (
	NoMonitor MonitorMethod = iota
	PortMonitor
	URLMonitor

	AttemptedToCreateLatticeDebugErrorMessage = reserved_app_ids.LatticeDebugLogStreamAppId + " is a reserved app name. It is used internally to stream debug logs for lattice components."
)

const (
	healthcheckDownloadUrl string = "http://file_server.service.dc1.consul:8080/v1/static/healthcheck.tgz"
	lrpDomain              string = "lattice"
)

type appRunner struct {
	receptorClient receptor.Client
	systemDomain   string
}

func New(receptorClient receptor.Client, systemDomain string) AppRunner {
	return &appRunner{receptorClient, systemDomain}
}

func (appRunner *appRunner) CreateApp(params CreateAppParams) error {
	if params.Name == reserved_app_ids.LatticeDebugLogStreamAppId {
		return errors.New(AttemptedToCreateLatticeDebugErrorMessage)
	}
	if exists, err := appRunner.desiredLRPExists(params.Name); err != nil {
		return err
	} else if exists {
		return newExistingAppError(params.Name)
	}

	if err := appRunner.receptorClient.UpsertDomain(lrpDomain, 0); err != nil {
		return err
	}

	return appRunner.desireLrp(params)
}

func (appRunner *appRunner) SubmitLrp(lrpJSON []byte) (string, error) {
	desiredLRP := receptor.DesiredLRPCreateRequest{}

	if err := json.Unmarshal(lrpJSON, &desiredLRP); err != nil {
		return "", err
	}

	if desiredLRP.ProcessGuid == reserved_app_ids.LatticeDebugLogStreamAppId {
		return desiredLRP.ProcessGuid, errors.New(AttemptedToCreateLatticeDebugErrorMessage)
	}

	if exists, err := appRunner.desiredLRPExists(desiredLRP.ProcessGuid); err != nil {
		return desiredLRP.ProcessGuid, err
	} else if exists {
		return desiredLRP.ProcessGuid, newExistingAppError(desiredLRP.ProcessGuid)
	}

	if err := appRunner.receptorClient.UpsertDomain(lrpDomain, 0); err != nil {
		return desiredLRP.ProcessGuid, err
	}

	return desiredLRP.ProcessGuid, appRunner.receptorClient.CreateDesiredLRP(desiredLRP)
}

func (appRunner *appRunner) ScaleApp(name string, instances int) error {
	if exists, err := appRunner.desiredLRPExists(name); err != nil {
		return err
	} else if !exists {
		return newAppNotStartedError(name)
	}

	return appRunner.updateLrpInstances(name, instances)
}

func (appRunner *appRunner) UpdateAppRoutes(name string, routes RouteOverrides) error {
	if exists, err := appRunner.desiredLRPExists(name); err != nil {
		return err
	} else if !exists {
		return newAppNotStartedError(name)
	}

	return appRunner.updateLrpRoutes(name, routes)
}

func (appRunner *appRunner) RemoveApp(name string) error {
	if lrpExists, err := appRunner.desiredLRPExists(name); err != nil {
		return err
	} else if !lrpExists {
		return newAppNotStartedError(name)
	}

	return appRunner.receptorClient.DeleteDesiredLRP(name)
}

func (appRunner *appRunner) desiredLRPExists(name string) (exists bool, err error) {
	desiredLRPs, err := appRunner.receptorClient.DesiredLRPs()
	if err != nil {
		return false, err
	}

	for _, desiredLRP := range desiredLRPs {
		if desiredLRP.ProcessGuid == name {
			return true, nil
		}
	}

	return false, nil
}

func (appRunner *appRunner) desireLrp(params CreateAppParams) error {
	var primaryPort uint16
	if params.Monitor.Port != 0 {
		primaryPort = params.Monitor.Port
	} else {
		primaryPort = params.ExposedPorts[0]
	}

	envVars := buildEnvironmentVariables(params.EnvironmentVariables)
	envVars = append(envVars, receptor.EnvironmentVariable{Name: "PORT", Value: fmt.Sprintf("%d", primaryPort)})

	var appRoutes route_helpers.AppRoutes
	if params.NoRoutes {
		appRoutes = route_helpers.AppRoutes{}
	} else if len(params.RouteOverrides) > 0 {
		routeMap := make(map[uint16][]string)
		for _, override := range params.RouteOverrides {
			routeMap[override.Port] = append(routeMap[override.Port], fmt.Sprintf("%s.%s", override.HostnamePrefix, appRunner.systemDomain))
		}
		for port, hostnames := range routeMap {
			appRoutes = append(appRoutes, route_helpers.AppRoute{
				Hostnames: hostnames,
				Port:      port,
			})
		}
	} else {
		appRoutes = appRunner.buildDefaultRoutingInfo(params.Name, params.ExposedPorts, primaryPort)
	}

	req := receptor.DesiredLRPCreateRequest{
		ProcessGuid:          params.Name,
		Domain:               lrpDomain,
		RootFS:               params.RootFS,
		Instances:            params.Instances,
		Routes:               appRoutes.RoutingInfo(),
		CPUWeight:            params.CPUWeight,
		MemoryMB:             params.MemoryMB,
		DiskMB:               params.DiskMB,
		Privileged:           params.Privileged,
		Ports:                params.ExposedPorts,
		LogGuid:              params.Name,
		LogSource:            "APP",
		MetricsGuid:          params.Name,
		EnvironmentVariables: envVars,
		Setup:                params.Setup,
		Action: &models.RunAction{
			Path: params.StartCommand,
			Args: params.AppArgs,
			Dir:  params.WorkingDir,
		},
	}

	var healthCheckArgs []string
	if params.Monitor.Timeout != 0 {
		healthCheckArgs = append(healthCheckArgs, "-timeout", fmt.Sprint(params.Monitor.Timeout))
	}
	switch params.Monitor.Method {
	case PortMonitor:
		req.Monitor = &models.RunAction{
			Path:      "/tmp/healthcheck",
			Args:      append(healthCheckArgs, "-port", fmt.Sprint(params.Monitor.Port)),
			LogSource: "HEALTH",
		}
	case URLMonitor:
		req.Monitor = &models.RunAction{
			Path:      "/tmp/healthcheck",
			Args:      append(healthCheckArgs, "-port", fmt.Sprint(params.Monitor.Port), "-uri", params.Monitor.URI),
			LogSource: "HEALTH",
		}
	}

	return appRunner.receptorClient.CreateDesiredLRP(req)
}

func (appRunner *appRunner) updateLrpInstances(name string, instances int) error {
	err := appRunner.receptorClient.UpdateDesiredLRP(
		name,
		receptor.DesiredLRPUpdateRequest{
			Instances: &instances,
		},
	)

	return err
}

func (appRunner *appRunner) updateLrpRoutes(name string, routes RouteOverrides) error {
	appRoutes := route_helpers.AppRoutes{}

	routeMap := make(map[uint16][]string)
	for _, override := range routes {
		routeMap[override.Port] = append(routeMap[override.Port], fmt.Sprintf("%s.%s", override.HostnamePrefix, appRunner.systemDomain))
	}
	for port, hostnames := range routeMap {
		appRoutes = append(appRoutes, route_helpers.AppRoute{
			Hostnames: hostnames,
			Port:      port,
		})
	}

	err := appRunner.receptorClient.UpdateDesiredLRP(
		name,
		receptor.DesiredLRPUpdateRequest{
			Routes: appRoutes.RoutingInfo(),
		},
	)

	return err
}

func (appRunner *appRunner) buildDefaultRoutingInfo(appName string, exposedPorts []uint16, primaryPort uint16) route_helpers.AppRoutes {
	appRoutes := route_helpers.AppRoutes{}

	for _, port := range exposedPorts {
		hostnames := []string{}
		if port == primaryPort {
			hostnames = append(hostnames, fmt.Sprintf("%s.%s", appName, appRunner.systemDomain))
		}

		hostnames = append(hostnames, fmt.Sprintf("%s-%s.%s", appName, strconv.Itoa(int(port)), appRunner.systemDomain))
		appRoutes = append(appRoutes, route_helpers.AppRoute{
			Hostnames: hostnames,
			Port:      port,
		})
	}

	return appRoutes
}

func buildEnvironmentVariables(environmentVariables map[string]string) []receptor.EnvironmentVariable {
	appEnvVars := make([]receptor.EnvironmentVariable, 0, len(environmentVariables)+1)
	for name, value := range environmentVariables {
		appEnvVars = append(appEnvVars, receptor.EnvironmentVariable{Name: name, Value: value})
	}
	return appEnvVars
}
<|endoftext|>


<commit_before>// Copyright 2013 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package multiwatcher

import (
	"bytes"
	"encoding/json"
	"fmt"
	"time"

	"github.com/juju/errors"
	"gopkg.in/juju/charm.v6-unstable"

	"github.com/juju/juju/constraints"
	"github.com/juju/juju/instance"
	"github.com/juju/juju/status"
)

// Life describes the lifecycle state of an entity ("alive", "dying"
// or "dead").
type Life string

// EntityInfo is implemented by all entity Info types.
type EntityInfo interface {
	// EntityId returns an identifier that will uniquely
	// identify the entity within its kind
	EntityId() EntityId
}

// EntityId uniquely identifies an entity being tracked by the
// multiwatcherStore.
type EntityId struct {
	Kind      string `json:"kind"`
	ModelUUID string `json:"model-uuid"`
	Id        string `json:"id"`
}

// Delta holds details of a change to the model.
type Delta struct {
	// If Removed is true, the entity has been removed;
	// otherwise it has been created or changed.
	Removed bool `json:"removed"`
	// Entity holds data about the entity that has changed.
	Entity EntityInfo `json:"entity"`
}

// MarshalJSON implements json.Marshaler.
func (d *Delta) MarshalJSON() ([]byte, error) {
	b, err := json.Marshal(d.Entity)
	if err != nil {
		return nil, err
	}
	var buf bytes.Buffer
	buf.WriteByte('[')
	c := "change"
	if d.Removed {
		c = "remove"
	}
	fmt.Fprintf(&buf, "%q,%q,", d.Entity.EntityId().Kind, c)
	buf.Write(b)
	buf.WriteByte(']')
	return buf.Bytes(), nil
}

// UnmarshalJSON implements json.Unmarshaler.
func (d *Delta) UnmarshalJSON(data []byte) error {
	var elements []json.RawMessage
	if err := json.Unmarshal(data, &elements); err != nil {
		return err
	}
	if len(elements) != 3 {
		return fmt.Errorf(
			"Expected 3 elements in top-level of JSON but got %d",
			len(elements))
	}
	var entityKind, operation string
	if err := json.Unmarshal(elements[0], &entityKind); err != nil {
		return err
	}
	if err := json.Unmarshal(elements[1], &operation); err != nil {
		return err
	}
	if operation == "remove" {
		d.Removed = true
	} else if operation != "change" {
		return fmt.Errorf("Unexpected operation %q", operation)
	}
	switch entityKind {
	case "model":
		d.Entity = new(ModelInfo)
	case "machine":
		d.Entity = new(MachineInfo)
	case "application":
		d.Entity = new(ApplicationInfo)
	case "remoteApplication":
		d.Entity = new(RemoteApplicationInfo)
	case "unit":
		d.Entity = new(UnitInfo)
	case "relation":
		d.Entity = new(RelationInfo)
	case "annotation":
		d.Entity = new(AnnotationInfo)
	case "block":
		d.Entity = new(BlockInfo)
	case "action":
		d.Entity = new(ActionInfo)
	default:
		return errors.Errorf("Unexpected entity name %q", entityKind)
	}
	return json.Unmarshal(elements[2], &d.Entity)
}

// Address describes a network address.
type Address struct {
	Value           string `json:"value"`
	Type            string `json:"type"`
	Scope           string `json:"scope"`
	SpaceName       string `json:"space-name,omitempty"`
	SpaceProviderId string `json:"space-provider-id,omitempty"`
}

// MachineInfo holds the information about a machine
// that is tracked by multiwatcherStore.
type MachineInfo struct {
	ModelUUID                string                            `json:"model-uuid"`
	Id                       string                            `json:"id"`
	InstanceId               string                            `json:"instance-id"`
	AgentStatus              StatusInfo                        `json:"agent-status"`
	InstanceStatus           StatusInfo                        `json:"instance-status"`
	Life                     Life                              `json:"life"`
	Config                   map[string]interface{}            `json:"config,omitempty"`
	Series                   string                            `json:"series"`
	SupportedContainers      []instance.ContainerType          `json:"supported-containers"`
	SupportedContainersKnown bool                              `json:"supported-containers-known"`
	HardwareCharacteristics  *instance.HardwareCharacteristics `json:"hardware-characteristics,omitempty"`
	Jobs                     []MachineJob                      `json:"jobs"`
	Addresses                []Address                         `json:"addresses"`
	HasVote                  bool                              `json:"has-vote"`
	WantsVote                bool                              `json:"wants-vote"`
}

// EntityId returns a unique identifier for a machine across
// models.
func (i *MachineInfo) EntityId() EntityId {
	return EntityId{
		Kind:      "machine",
		ModelUUID: i.ModelUUID,
		Id:        i.Id,
	}
}

// StatusInfo holds the unit and machine status information. It is
// used by ApplicationInfo and UnitInfo.
type StatusInfo struct {
	Err     error                  `json:"err,omitempty"`
	Current status.Status          `json:"current"`
	Message string                 `json:"message"`
	Since   *time.Time             `json:"since,omitempty"`
	Version string                 `json:"version"`
	Data    map[string]interface{} `json:"data,omitempty"`
}

// NewStatusInfo return a new multiwatcher StatusInfo from a
// status StatusInfo.
func NewStatusInfo(s status.StatusInfo, err error) StatusInfo {
	return StatusInfo{
		Err:     err,
		Current: s.Status,
		Message: s.Message,
		Since:   s.Since,
		Data:    s.Data,
	}
}

// ApplicationInfo holds the information about an application that is tracked
// by multiwatcherStore.
type ApplicationInfo struct {
	ModelUUID   string                 `json:"model-uuid"`
	Name        string                 `json:"name"`
	Exposed     bool                   `json:"exposed"`
	CharmURL    string                 `json:"charm-url"`
	OwnerTag    string                 `json:"owner-tag"`
	Life        Life                   `json:"life"`
	MinUnits    int                    `json:"min-units"`
	Constraints constraints.Value      `json:"constraints"`
	Config      map[string]interface{} `json:"config,omitempty"`
	Subordinate bool                   `json:"subordinate"`
	Status      StatusInfo             `json:"status"`
}

// EntityId returns a unique identifier for an application across
// models.
func (i *ApplicationInfo) EntityId() EntityId {
	return EntityId{
		Kind:      "application",
		ModelUUID: i.ModelUUID,
		Id:        i.Name,
	}
}

// RemoteApplicationInfo holds the information about a remote application that is
// tracked by multiwatcherStore.
type RemoteApplicationInfo struct {
	ModelUUID      string
	Name           string
	ApplicationURL string
	Life           Life
	Status         StatusInfo
}

// EntityId returns a unique identifier for a remote application across
// environments.
func (i *RemoteApplicationInfo) EntityId() EntityId {
	return EntityId{
		Kind:      "remoteApplication",
		ModelUUID: i.ModelUUID,
		Id:        i.Name,
	}
}

// Port identifies a network port number for a particular protocol.
type Port struct {
	Protocol string `json:"protocol"`
	Number   int    `json:"number"`
}

// PortRange represents a single range of ports.
type PortRange struct {
	FromPort int    `json:"from-port"`
	ToPort   int    `json:"to-port"`
	Protocol string `json:"protocol"`
}

// UnitInfo holds the information about a unit
// that is tracked by multiwatcherStore.
type UnitInfo struct {
	ModelUUID      string      `json:"model-uuid"`
	Name           string      `json:"name"`
	Application    string      `json:"application"`
	Series         string      `json:"series"`
	CharmURL       string      `json:"charm-url"`
	PublicAddress  string      `json:"public-address"`
	PrivateAddress string      `json:"private-address"`
	MachineId      string      `json:"machine-id"`
	Ports          []Port      `json:"ports"`
	PortRanges     []PortRange `json:"port-ranges"`
	Subordinate    bool        `json:"subordinate"`
	// Workload and agent state are modelled separately.
	WorkloadStatus StatusInfo `json:"workload-status"`
	AgentStatus    StatusInfo `json:"agent-status"`
}

// EntityId returns a unique identifier for a unit across
// models.
func (i *UnitInfo) EntityId() EntityId {
	return EntityId{
		Kind:      "unit",
		ModelUUID: i.ModelUUID,
		Id:        i.Name,
	}
}

// ActionInfo holds the information about a action that is tracked by
// multiwatcherStore.
type ActionInfo struct {
	ModelUUID  string                 `json:"model-uuid"`
	Id         string                 `json:"id"`
	Receiver   string                 `json:"receiver"`
	Name       string                 `json:"name"`
	Parameters map[string]interface{} `json:"parameters,omitempty"`
	Status     string                 `json:"status"`
	Message    string                 `json:"message"`
	Results    map[string]interface{} `json:"results,omitempty"`
	Enqueued   time.Time              `json:"enqueued"`
	Started    time.Time              `json:"started"`
	Completed  time.Time              `json:"completed"`
}

// EntityId returns a unique identifier for an action across
// models.
func (i *ActionInfo) EntityId() EntityId {
	return EntityId{
		Kind:      "action",
		ModelUUID: i.ModelUUID,
		Id:        i.Id,
	}
}

// RelationInfo holds the information about a relation that is tracked
// by multiwatcherStore.
type RelationInfo struct {
	ModelUUID string     `json:"model-uuid"`
	Key       string     `json:"key"`
	Id        int        `json:"id"`
	Endpoints []Endpoint `json:"endpoints"`
}

// CharmRelation is a mirror struct for charm.Relation.
type CharmRelation struct {
	Name      string `json:"name"`
	Role      string `json:"role"`
	Interface string `json:"interface"`
	Optional  bool   `json:"optional"`
	Limit     int    `json:"limit"`
	Scope     string `json:"scope"`
}

// NewCharmRelation creates a new local CharmRelation structure from  the
// charm.Relation structure. NOTE: when we update the database to not store a
// charm.Relation directly in the database, this method should take the state
// structure type.
func NewCharmRelation(cr charm.Relation) CharmRelation {
	return CharmRelation{
		Name:      cr.Name,
		Role:      string(cr.Role),
		Interface: cr.Interface,
		Optional:  cr.Optional,
		Limit:     cr.Limit,
		Scope:     string(cr.Scope),
	}
}

// Endpoint holds an application-relation pair.
type Endpoint struct {
	ApplicationName string        `json:"application-name"`
	Relation        CharmRelation `json:"relation"`
}

// EntityId returns a unique identifier for a relation across
// models.
func (i *RelationInfo) EntityId() EntityId {
	return EntityId{
		Kind:      "relation",
		ModelUUID: i.ModelUUID,
		Id:        i.Key,
	}
}

// AnnotationInfo holds the information about an annotation that is
// tracked by multiwatcherStore.
type AnnotationInfo struct {
	ModelUUID   string            `json:"model-uuid"`
	Tag         string            `json:"tag"`
	Annotations map[string]string `json:"annotations"`
}

// EntityId returns a unique identifier for an annotation across
// models.
func (i *AnnotationInfo) EntityId() EntityId {
	return EntityId{
		Kind:      "annotation",
		ModelUUID: i.ModelUUID,
		Id:        i.Tag,
	}
}

// MachineJob values define responsibilities that machines may be
// expected to fulfil.
type MachineJob string

const (
	JobHostUnits   MachineJob = "JobHostUnits"
	JobManageModel MachineJob = "JobManageModel"
)

// NeedsState returns true if the job requires a state connection.
func (job MachineJob) NeedsState() bool {
	return job == JobManageModel
}

// AnyJobNeedsState returns true if any of the provided jobs
// require a state connection.
func AnyJobNeedsState(jobs ...MachineJob) bool {
	for _, j := range jobs {
		if j.NeedsState() {
			return true
		}
	}
	return false
}

// BlockInfo holds the information about a block that is tracked by
// multiwatcherStore.
type BlockInfo struct {
	ModelUUID string    `json:"model-uuid"`
	Id        string    `json:"id"`
	Type      BlockType `json:"type"`
	Message   string    `json:"message"`
	Tag       string    `json:"tag"`
}

// EntityId returns a unique identifier for a block across
// models.
func (i *BlockInfo) EntityId() EntityId {
	return EntityId{
		Kind:      "block",
		ModelUUID: i.ModelUUID,
		Id:        i.Id,
	}
}

// BlockType values define model block type.
type BlockType string

const (
	// BlockDestroy type identifies destroy blocks.
	BlockDestroy BlockType = "BlockDestroy"

	// BlockRemove type identifies remove blocks.
	BlockRemove BlockType = "BlockRemove"

	// BlockChange type identifies change blocks.
	BlockChange BlockType = "BlockChange"
)

// ModelInfo holds the information about an model that is
// tracked by multiwatcherStore.
type ModelInfo struct {
	ModelUUID      string                 `json:"model-uuid"`
	Name           string                 `json:"name"`
	Life           Life                   `json:"life"`
	Owner          string                 `json:"owner"`
	ControllerUUID string                 `json:"controller-uuid"`
	Config         map[string]interface{} `json:"config,omitempty"`
	Status         StatusInfo             `json:"status"`
	Constraints    constraints.Value      `json:"constraints"`
}

// EntityId returns a unique identifier for an model.
func (i *ModelInfo) EntityId() EntityId {
	return EntityId{
		Kind:      "model",
		ModelUUID: i.ModelUUID,
		Id:        i.ModelUUID,
	}
}
<commit_msg>Add RemoteApplication tags<commit_after>// Copyright 2013 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package multiwatcher

import (
	"bytes"
	"encoding/json"
	"fmt"
	"time"

	"github.com/juju/errors"
	"gopkg.in/juju/charm.v6-unstable"

	"github.com/juju/juju/constraints"
	"github.com/juju/juju/instance"
	"github.com/juju/juju/status"
)

// Life describes the lifecycle state of an entity ("alive", "dying"
// or "dead").
type Life string

// EntityInfo is implemented by all entity Info types.
type EntityInfo interface {
	// EntityId returns an identifier that will uniquely
	// identify the entity within its kind
	EntityId() EntityId
}

// EntityId uniquely identifies an entity being tracked by the
// multiwatcherStore.
type EntityId struct {
	Kind      string `json:"kind"`
	ModelUUID string `json:"model-uuid"`
	Id        string `json:"id"`
}

// Delta holds details of a change to the model.
type Delta struct {
	// If Removed is true, the entity has been removed;
	// otherwise it has been created or changed.
	Removed bool `json:"removed"`
	// Entity holds data about the entity that has changed.
	Entity EntityInfo `json:"entity"`
}

// MarshalJSON implements json.Marshaler.
func (d *Delta) MarshalJSON() ([]byte, error) {
	b, err := json.Marshal(d.Entity)
	if err != nil {
		return nil, err
	}
	var buf bytes.Buffer
	buf.WriteByte('[')
	c := "change"
	if d.Removed {
		c = "remove"
	}
	fmt.Fprintf(&buf, "%q,%q,", d.Entity.EntityId().Kind, c)
	buf.Write(b)
	buf.WriteByte(']')
	return buf.Bytes(), nil
}

// UnmarshalJSON implements json.Unmarshaler.
func (d *Delta) UnmarshalJSON(data []byte) error {
	var elements []json.RawMessage
	if err := json.Unmarshal(data, &elements); err != nil {
		return err
	}
	if len(elements) != 3 {
		return fmt.Errorf(
			"Expected 3 elements in top-level of JSON but got %d",
			len(elements))
	}
	var entityKind, operation string
	if err := json.Unmarshal(elements[0], &entityKind); err != nil {
		return err
	}
	if err := json.Unmarshal(elements[1], &operation); err != nil {
		return err
	}
	if operation == "remove" {
		d.Removed = true
	} else if operation != "change" {
		return fmt.Errorf("Unexpected operation %q", operation)
	}
	switch entityKind {
	case "model":
		d.Entity = new(ModelInfo)
	case "machine":
		d.Entity = new(MachineInfo)
	case "application":
		d.Entity = new(ApplicationInfo)
	case "remoteApplication":
		d.Entity = new(RemoteApplicationInfo)
	case "unit":
		d.Entity = new(UnitInfo)
	case "relation":
		d.Entity = new(RelationInfo)
	case "annotation":
		d.Entity = new(AnnotationInfo)
	case "block":
		d.Entity = new(BlockInfo)
	case "action":
		d.Entity = new(ActionInfo)
	default:
		return errors.Errorf("Unexpected entity name %q", entityKind)
	}
	return json.Unmarshal(elements[2], &d.Entity)
}

// Address describes a network address.
type Address struct {
	Value           string `json:"value"`
	Type            string `json:"type"`
	Scope           string `json:"scope"`
	SpaceName       string `json:"space-name,omitempty"`
	SpaceProviderId string `json:"space-provider-id,omitempty"`
}

// MachineInfo holds the information about a machine
// that is tracked by multiwatcherStore.
type MachineInfo struct {
	ModelUUID                string                            `json:"model-uuid"`
	Id                       string                            `json:"id"`
	InstanceId               string                            `json:"instance-id"`
	AgentStatus              StatusInfo                        `json:"agent-status"`
	InstanceStatus           StatusInfo                        `json:"instance-status"`
	Life                     Life                              `json:"life"`
	Config                   map[string]interface{}            `json:"config,omitempty"`
	Series                   string                            `json:"series"`
	SupportedContainers      []instance.ContainerType          `json:"supported-containers"`
	SupportedContainersKnown bool                              `json:"supported-containers-known"`
	HardwareCharacteristics  *instance.HardwareCharacteristics `json:"hardware-characteristics,omitempty"`
	Jobs                     []MachineJob                      `json:"jobs"`
	Addresses                []Address                         `json:"addresses"`
	HasVote                  bool                              `json:"has-vote"`
	WantsVote                bool                              `json:"wants-vote"`
}

// EntityId returns a unique identifier for a machine across
// models.
func (i *MachineInfo) EntityId() EntityId {
	return EntityId{
		Kind:      "machine",
		ModelUUID: i.ModelUUID,
		Id:        i.Id,
	}
}

// StatusInfo holds the unit and machine status information. It is
// used by ApplicationInfo and UnitInfo.
type StatusInfo struct {
	Err     error                  `json:"err,omitempty"`
	Current status.Status          `json:"current"`
	Message string                 `json:"message"`
	Since   *time.Time             `json:"since,omitempty"`
	Version string                 `json:"version"`
	Data    map[string]interface{} `json:"data,omitempty"`
}

// NewStatusInfo return a new multiwatcher StatusInfo from a
// status StatusInfo.
func NewStatusInfo(s status.StatusInfo, err error) StatusInfo {
	return StatusInfo{
		Err:     err,
		Current: s.Status,
		Message: s.Message,
		Since:   s.Since,
		Data:    s.Data,
	}
}

// ApplicationInfo holds the information about an application that is tracked
// by multiwatcherStore.
type ApplicationInfo struct {
	ModelUUID   string                 `json:"model-uuid"`
	Name        string                 `json:"name"`
	Exposed     bool                   `json:"exposed"`
	CharmURL    string                 `json:"charm-url"`
	OwnerTag    string                 `json:"owner-tag"`
	Life        Life                   `json:"life"`
	MinUnits    int                    `json:"min-units"`
	Constraints constraints.Value      `json:"constraints"`
	Config      map[string]interface{} `json:"config,omitempty"`
	Subordinate bool                   `json:"subordinate"`
	Status      StatusInfo             `json:"status"`
}

// EntityId returns a unique identifier for an application across
// models.
func (i *ApplicationInfo) EntityId() EntityId {
	return EntityId{
		Kind:      "application",
		ModelUUID: i.ModelUUID,
		Id:        i.Name,
	}
}

// RemoteApplicationInfo holds the information about a remote application that is
// tracked by multiwatcherStore.
type RemoteApplicationInfo struct {
	ModelUUID      string     `json:"model-uuid"`
	Name           string     `json:"name"`
	ApplicationURL string     `json:"application-url"`
	Life           Life       `json:"life"`
	Status         StatusInfo `json:"status"`
}

// EntityId returns a unique identifier for a remote application across
// environments.
func (i *RemoteApplicationInfo) EntityId() EntityId {
	return EntityId{
		Kind:      "remoteApplication",
		ModelUUID: i.ModelUUID,
		Id:        i.Name,
	}
}

// Port identifies a network port number for a particular protocol.
type Port struct {
	Protocol string `json:"protocol"`
	Number   int    `json:"number"`
}

// PortRange represents a single range of ports.
type PortRange struct {
	FromPort int    `json:"from-port"`
	ToPort   int    `json:"to-port"`
	Protocol string `json:"protocol"`
}

// UnitInfo holds the information about a unit
// that is tracked by multiwatcherStore.
type UnitInfo struct {
	ModelUUID      string      `json:"model-uuid"`
	Name           string      `json:"name"`
	Application    string      `json:"application"`
	Series         string      `json:"series"`
	CharmURL       string      `json:"charm-url"`
	PublicAddress  string      `json:"public-address"`
	PrivateAddress string      `json:"private-address"`
	MachineId      string      `json:"machine-id"`
	Ports          []Port      `json:"ports"`
	PortRanges     []PortRange `json:"port-ranges"`
	Subordinate    bool        `json:"subordinate"`
	// Workload and agent state are modelled separately.
	WorkloadStatus StatusInfo `json:"workload-status"`
	AgentStatus    StatusInfo `json:"agent-status"`
}

// EntityId returns a unique identifier for a unit across
// models.
func (i *UnitInfo) EntityId() EntityId {
	return EntityId{
		Kind:      "unit",
		ModelUUID: i.ModelUUID,
		Id:        i.Name,
	}
}

// ActionInfo holds the information about a action that is tracked by
// multiwatcherStore.
type ActionInfo struct {
	ModelUUID  string                 `json:"model-uuid"`
	Id         string                 `json:"id"`
	Receiver   string                 `json:"receiver"`
	Name       string                 `json:"name"`
	Parameters map[string]interface{} `json:"parameters,omitempty"`
	Status     string                 `json:"status"`
	Message    string                 `json:"message"`
	Results    map[string]interface{} `json:"results,omitempty"`
	Enqueued   time.Time              `json:"enqueued"`
	Started    time.Time              `json:"started"`
	Completed  time.Time              `json:"completed"`
}

// EntityId returns a unique identifier for an action across
// models.
func (i *ActionInfo) EntityId() EntityId {
	return EntityId{
		Kind:      "action",
		ModelUUID: i.ModelUUID,
		Id:        i.Id,
	}
}

// RelationInfo holds the information about a relation that is tracked
// by multiwatcherStore.
type RelationInfo struct {
	ModelUUID string     `json:"model-uuid"`
	Key       string     `json:"key"`
	Id        int        `json:"id"`
	Endpoints []Endpoint `json:"endpoints"`
}

// CharmRelation is a mirror struct for charm.Relation.
type CharmRelation struct {
	Name      string `json:"name"`
	Role      string `json:"role"`
	Interface string `json:"interface"`
	Optional  bool   `json:"optional"`
	Limit     int    `json:"limit"`
	Scope     string `json:"scope"`
}

// NewCharmRelation creates a new local CharmRelation structure from  the
// charm.Relation structure. NOTE: when we update the database to not store a
// charm.Relation directly in the database, this method should take the state
// structure type.
func NewCharmRelation(cr charm.Relation) CharmRelation {
	return CharmRelation{
		Name:      cr.Name,
		Role:      string(cr.Role),
		Interface: cr.Interface,
		Optional:  cr.Optional,
		Limit:     cr.Limit,
		Scope:     string(cr.Scope),
	}
}

// Endpoint holds an application-relation pair.
type Endpoint struct {
	ApplicationName string        `json:"application-name"`
	Relation        CharmRelation `json:"relation"`
}

// EntityId returns a unique identifier for a relation across
// models.
func (i *RelationInfo) EntityId() EntityId {
	return EntityId{
		Kind:      "relation",
		ModelUUID: i.ModelUUID,
		Id:        i.Key,
	}
}

// AnnotationInfo holds the information about an annotation that is
// tracked by multiwatcherStore.
type AnnotationInfo struct {
	ModelUUID   string            `json:"model-uuid"`
	Tag         string            `json:"tag"`
	Annotations map[string]string `json:"annotations"`
}

// EntityId returns a unique identifier for an annotation across
// models.
func (i *AnnotationInfo) EntityId() EntityId {
	return EntityId{
		Kind:      "annotation",
		ModelUUID: i.ModelUUID,
		Id:        i.Tag,
	}
}

// MachineJob values define responsibilities that machines may be
// expected to fulfil.
type MachineJob string

const (
	JobHostUnits   MachineJob = "JobHostUnits"
	JobManageModel MachineJob = "JobManageModel"
)

// NeedsState returns true if the job requires a state connection.
func (job MachineJob) NeedsState() bool {
	return job == JobManageModel
}

// AnyJobNeedsState returns true if any of the provided jobs
// require a state connection.
func AnyJobNeedsState(jobs ...MachineJob) bool {
	for _, j := range jobs {
		if j.NeedsState() {
			return true
		}
	}
	return false
}

// BlockInfo holds the information about a block that is tracked by
// multiwatcherStore.
type BlockInfo struct {
	ModelUUID string    `json:"model-uuid"`
	Id        string    `json:"id"`
	Type      BlockType `json:"type"`
	Message   string    `json:"message"`
	Tag       string    `json:"tag"`
}

// EntityId returns a unique identifier for a block across
// models.
func (i *BlockInfo) EntityId() EntityId {
	return EntityId{
		Kind:      "block",
		ModelUUID: i.ModelUUID,
		Id:        i.Id,
	}
}

// BlockType values define model block type.
type BlockType string

const (
	// BlockDestroy type identifies destroy blocks.
	BlockDestroy BlockType = "BlockDestroy"

	// BlockRemove type identifies remove blocks.
	BlockRemove BlockType = "BlockRemove"

	// BlockChange type identifies change blocks.
	BlockChange BlockType = "BlockChange"
)

// ModelInfo holds the information about an model that is
// tracked by multiwatcherStore.
type ModelInfo struct {
	ModelUUID      string                 `json:"model-uuid"`
	Name           string                 `json:"name"`
	Life           Life                   `json:"life"`
	Owner          string                 `json:"owner"`
	ControllerUUID string                 `json:"controller-uuid"`
	Config         map[string]interface{} `json:"config,omitempty"`
	Status         StatusInfo             `json:"status"`
	Constraints    constraints.Value      `json:"constraints"`
}

// EntityId returns a unique identifier for an model.
func (i *ModelInfo) EntityId() EntityId {
	return EntityId{
		Kind:      "model",
		ModelUUID: i.ModelUUID,
		Id:        i.ModelUUID,
	}
}
<|endoftext|>


<commit_before>package accounts

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

	"github.com/gorilla/mux"

	"github.com/mrvdot/appengine/aeutils"
	"github.com/mrvdot/golang-utils"

	"appengine"
)

var (
	// Router instance for accounts, made public to allow for adding additional routes
	Router        *mux.Router
	SubrouterPath = "accounts"
)

// func InitRouter attaches two routes "new" and "authenticate" to a subpath
// to the http handler
// If an empty string is passed for the subpath, the default SubrouterPath is used
func InitRouter(subpath string) {
	if subpath == "" {
		subpath = SubrouterPath
	} else {
		SubrouterPath = subpath
	}
	Router = mux.NewRouter()
	ar := Router.PathPrefix(fmt.Sprintf("/%v", SubrouterPath)).Subrouter()
	ar.HandleFunc("/new", newAccount).
		Methods("POST").
		Name("CreateAccount")
	ar.HandleFunc("/authenticate", authenticate).
		Methods("POST").
		Name("Authenticate")
	http.Handle(fmt.Sprintf("/%v/", SubrouterPath), Router)
}

// func newAccount creates a new request based on the "account" parameter passed in
func newAccount(rw http.ResponseWriter, req *http.Request) {
	ctx := appengine.NewContext(req)
	out := json.NewEncoder(rw)
	response := &utils.ApiResponse{}
	name := req.FormValue("account")
	ctx.Infof("Creating new account for %v", name)
	if name == "" {
		response.Code = 400
		response.Message = "Account name must be provided"
		out.Encode(response)
		return
	}
	acct := &Account{
		Name:   name,
		Active: true,
	}
	_, err := aeutils.Save(ctx, acct)
	if err != nil {
		response.Code = 500
		response.Message = "Error saving new account: " + err.Error()
		out.Encode(response)
		return
	}
	response.Code = 200
	response.Result = acct
	out.Encode(response)
}

//func authenticate takes a request and authenticates it
func authenticate(rw http.ResponseWriter, req *http.Request) {
	ctx := appengine.NewContext(req)
	out := json.NewEncoder(rw)
	data := &utils.ApiResponse{}
	_, err := AuthenticateRequest(req)
	session, err := GetSession(ctx)
	if err != nil {
		ctx.Errorf(err.Error())
		data.Code = 403
		data.Message = err.Error()
	} else {
		data.Code = 200
		data.Data = map[string]interface{}{
			"session": session.Key,
		}
	}
	out.Encode(data)
}
<commit_msg>Updating new account to support sending json value of account<commit_after>package accounts

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

	"github.com/gorilla/mux"

	"github.com/mrvdot/appengine/aeutils"
	"github.com/mrvdot/golang-utils"

	"appengine"
)

var (
	// Router instance for accounts, made public to allow for adding additional routes
	Router        *mux.Router
	SubrouterPath = "accounts"
)

// func InitRouter attaches two routes "new" and "authenticate" to a subpath
// to the http handler
// If an empty string is passed for the subpath, the default SubrouterPath is used
func InitRouter(subpath string) {
	if subpath == "" {
		subpath = SubrouterPath
	} else {
		SubrouterPath = subpath
	}
	Router = mux.NewRouter()
	ar := Router.PathPrefix(fmt.Sprintf("/%v", SubrouterPath)).Subrouter()
	ar.HandleFunc("/new", newAccount).
		Methods("POST").
		Name("CreateAccount")
	ar.HandleFunc("/authenticate", authenticate).
		Methods("POST").
		Name("Authenticate")
	http.Handle(fmt.Sprintf("/%v/", SubrouterPath), Router)
}

// func newAccount creates a new request based on the "account" parameter passed in
func newAccount(rw http.ResponseWriter, req *http.Request) {
	ctx := appengine.NewContext(req)
	out := json.NewEncoder(rw)
	response := &utils.ApiResponse{}
	acct := &Account{}
	name := req.FormValue("account")
	if name != "" {
		acct = &Account{
			Name:   name,
			Active: true,
		}
	} else {
		dec := json.NewDecoder(req.Body)
		defer req.Body.Close()
		err := dec.Decode(acct)
		if err != nil {
			if err == io.EOF {
				response.Code = http.StatusBadRequest
				response.Message = "Account name must be provided"
			} else {
				response.Code = http.StatusInternalServerError
				response.Message = err.Error()
			}
			out.Encode(response)
			return
		}
	}
	_, err := aeutils.Save(ctx, acct)
	if err != nil {
		response.Code = http.StatusInternalServerError
		response.Message = "Error saving new account: " + err.Error()
		out.Encode(response)
		return
	}
	response.Code = 200
	response.Result = acct
	out.Encode(response)
}

//func authenticate takes a request and authenticates it
func authenticate(rw http.ResponseWriter, req *http.Request) {
	ctx := appengine.NewContext(req)
	out := json.NewEncoder(rw)
	data := &utils.ApiResponse{}
	_, err := AuthenticateRequest(req)
	session, err := GetSession(ctx)
	if err != nil {
		ctx.Errorf(err.Error())
		data.Code = 403
		data.Message = err.Error()
	} else {
		data.Code = 200
		data.Data = map[string]interface{}{
			"session": session.Key,
		}
	}
	out.Encode(data)
}
<|endoftext|>


<commit_before>package drivers

import (
	"fmt"

	"github.com/pkg/errors"

	"github.com/lxc/lxd/lxd/db"
	"github.com/lxc/lxd/lxd/device"
	deviceConfig "github.com/lxc/lxd/lxd/device/config"
	"github.com/lxc/lxd/lxd/instance"
	"github.com/lxc/lxd/lxd/instance/instancetype"
	"github.com/lxc/lxd/lxd/state"
	"github.com/lxc/lxd/shared"
	"github.com/lxc/lxd/shared/api"
)

func init() {
	// Expose load to the instance package, to avoid circular imports.
	instance.Load = load

	// Expose validDevices to the instance package, to avoid circular imports.
	instance.ValidDevices = validDevices

	// Expose create to the instance package, to avoid circular imports.
	instance.Create = create
}

// load creates the underlying instance type struct and returns it as an Instance.
func load(s *state.State, args db.InstanceArgs, profiles []api.Profile) (instance.Instance, error) {
	var inst instance.Instance
	var err error

	if args.Type == instancetype.Container {
		inst, err = lxcLoad(s, args, profiles)
	} else if args.Type == instancetype.VM {
		inst, err = qemuLoad(s, args, profiles)
	} else {
		return nil, fmt.Errorf("Invalid instance type for instance %s", args.Name)
	}

	if err != nil {
		return nil, err
	}

	return inst, nil
}

// validDevices validate instance device configs.
func validDevices(state *state.State, cluster *db.Cluster, instanceType instancetype.Type, devices deviceConfig.Devices, expanded bool) error {
	// Empty device list
	if devices == nil {
		return nil
	}

	instConf := &common{
		dbType:       instanceType,
		localDevices: devices.Clone(),
	}

	// In non-expanded validation expensive checks should be avoided.
	if expanded {
		// The devices being validated are already expanded, so just use the same
		// devices clone as we used for the main devices config.
		instConf.expandedDevices = instConf.localDevices
	}

	// Check each device individually using the device package.
	// Use instConf.localDevices so that the cloned config is passed into the driver, so it cannot modify it.
	for name, config := range instConf.localDevices {
		err := device.Validate(instConf, state, name, config)
		if err != nil {
			return errors.Wrapf(err, "Device validation failed %q", name)
		}

	}

	// Check we have a root disk if in expanded validation mode.
	if expanded {
		_, _, err := shared.GetRootDiskDevice(devices.CloneNative())
		if err != nil {
			return errors.Wrap(err, "Failed detecting root disk device")
		}
	}

	return nil
}

func create(s *state.State, args db.InstanceArgs) (instance.Instance, error) {
	if args.Type == instancetype.Container {
		return lxcCreate(s, args)
	} else if args.Type == instancetype.VM {
		return qemuCreate(s, args)
	}

	return nil, fmt.Errorf("Instance type invalid")
}
<commit_msg>lxd/instance/drivers/load: Adds project support to validDevices<commit_after>package drivers

import (
	"fmt"

	"github.com/pkg/errors"

	"github.com/lxc/lxd/lxd/db"
	"github.com/lxc/lxd/lxd/device"
	deviceConfig "github.com/lxc/lxd/lxd/device/config"
	"github.com/lxc/lxd/lxd/instance"
	"github.com/lxc/lxd/lxd/instance/instancetype"
	"github.com/lxc/lxd/lxd/state"
	"github.com/lxc/lxd/shared"
	"github.com/lxc/lxd/shared/api"
)

func init() {
	// Expose load to the instance package, to avoid circular imports.
	instance.Load = load

	// Expose validDevices to the instance package, to avoid circular imports.
	instance.ValidDevices = validDevices

	// Expose create to the instance package, to avoid circular imports.
	instance.Create = create
}

// load creates the underlying instance type struct and returns it as an Instance.
func load(s *state.State, args db.InstanceArgs, profiles []api.Profile) (instance.Instance, error) {
	var inst instance.Instance
	var err error

	if args.Type == instancetype.Container {
		inst, err = lxcLoad(s, args, profiles)
	} else if args.Type == instancetype.VM {
		inst, err = qemuLoad(s, args, profiles)
	} else {
		return nil, fmt.Errorf("Invalid instance type for instance %s", args.Name)
	}

	if err != nil {
		return nil, err
	}

	return inst, nil
}

// validDevices validate instance device configs.
func validDevices(state *state.State, cluster *db.Cluster, projectName string, instanceType instancetype.Type, devices deviceConfig.Devices, expanded bool) error {
	// Empty device list
	if devices == nil {
		return nil
	}

	instConf := &common{
		dbType:       instanceType,
		localDevices: devices.Clone(),
		project:      projectName,
	}

	// In non-expanded validation expensive checks should be avoided.
	if expanded {
		// The devices being validated are already expanded, so just use the same
		// devices clone as we used for the main devices config.
		instConf.expandedDevices = instConf.localDevices
	}

	// Check each device individually using the device package.
	// Use instConf.localDevices so that the cloned config is passed into the driver, so it cannot modify it.
	for name, config := range instConf.localDevices {
		err := device.Validate(instConf, state, name, config)
		if err != nil {
			return errors.Wrapf(err, "Device validation failed for %q", name)
		}

	}

	// Check we have a root disk if in expanded validation mode.
	if expanded {
		_, _, err := shared.GetRootDiskDevice(devices.CloneNative())
		if err != nil {
			return errors.Wrap(err, "Failed detecting root disk device")
		}
	}

	return nil
}

func create(s *state.State, args db.InstanceArgs) (instance.Instance, error) {
	if args.Type == instancetype.Container {
		return lxcCreate(s, args)
	} else if args.Type == instancetype.VM {
		return qemuCreate(s, args)
	}

	return nil, fmt.Errorf("Instance type invalid")
}
<|endoftext|>


<commit_before>package server

import (
  "net/http"
  "fmt"
)

type jsonResponse struct{
  id int
}

// Databases queries the list of all databases for a source
func (h *Service) Databases (w http.ResponseWriter, r *http.Request) {
  fmt.Print("database endpoint")

  srcID, err := paramID("id", r)
  if err != nil {
    Error(w, http.StatusUnprocessableEntity, err.Error(), h.Logger)
    return
  }

  res := jsonResponse{id: srcID}

  encodeJSON(w, http.StatusOK, res, h.Logger)
}
<commit_msg>dbs GET returns list of databases<commit_after>package server

import (
	"fmt"
	"net/http"

	"github.com/influxdata/chronograf"
)

type dbLinks struct {
	Self string `json:"self"` // Self link mapping to this resource
	RPs  string `json:"rps"`  // URL for retention policies for this database
}

type database struct {
	Name          string  `json:"name"`                  // a unique string identifier for the database
	Duration      string  `json:"duration,omitempty"`    // the duration (when creating a default retention policy)
	Replication   int32   `json:"replication,omitempty"` // the replication factor (when creating a default retention policy)
	ShardDuration string  `json:shardDuration,omitempty` // the shard duration (when creating a default retention policy)
	Links         dbLinks `json:links`                   // Links are URI locations related to the database
}

type postInfluxResponze struct {
	Results interface{} `json:"results"` // results from influx
}

// Databases queries the list of all databases for a source
func (h *Service) Databases(w http.ResponseWriter, r *http.Request) {
	id, err := paramID("id", r)
	if err != nil {
		Error(w, http.StatusUnprocessableEntity, err.Error(), h.Logger)
		return
	}

	// res := []database{}

	// move this influxdb communication code somewhere else after it's working
	// START
	ctx := r.Context()
	src, err := h.SourcesStore.Get(ctx, id)
	if err != nil {
		notFound(w, id, h.Logger)
		return
	}

	ts, err := h.TimeSeries(src)
	if err != nil {
		msg := fmt.Sprintf("Unable to connect to source %d: %v", id, err)
		Error(w, http.StatusBadRequest, msg, h.Logger)
		return
	}

	if err = ts.Connect(ctx, &src); err != nil {
		msg := fmt.Sprintf("Unable to connect to source %d: %v", id, err)
		Error(w, http.StatusBadRequest, msg, h.Logger)
		return
	}

	req := chronograf.Query{Command: "SHOW DATABASES"}

	response, err := ts.Query(ctx, req)
	if err != nil {
		if err == chronograf.ErrUpstreamTimeout {
			msg := "Timeout waiting for Influx response"
			Error(w, http.StatusRequestTimeout, msg, h.Logger)
			return
		}
		// TODO: Here I want to return the error code from influx.
		Error(w, http.StatusBadRequest, err.Error(), h.Logger)
		return
	}

	res := postInfluxResponze{
		Results: response,
	}

	//fmt.Printf("%+v\n", foo)
	// END

	encodeJSON(w, http.StatusOK, res, h.Logger)
}
<|endoftext|>


<commit_before>/*
Copyright 2015 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 generators has the generators for the client-gen utility.
package generators

import (
	"fmt"
	"path/filepath"
	"strings"

	"k8s.io/gengo/args"
	"k8s.io/gengo/generator"
	"k8s.io/gengo/namer"
	"k8s.io/gengo/types"
	clientgenargs "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/args"
	"k8s.io/kubernetes/cmd/libs/go2idl/client-gen/generators/fake"
	clientgentypes "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/types"

	"github.com/golang/glog"
)

// NameSystems returns the name system used by the generators in this package.
func NameSystems() namer.NameSystems {
	pluralExceptions := map[string]string{
		"Endpoints": "Endpoints",
	}
	return namer.NameSystems{
		"public":             namer.NewPublicNamer(0),
		"private":            namer.NewPrivateNamer(0),
		"raw":                namer.NewRawNamer("", nil),
		"publicPlural":       namer.NewPublicPluralNamer(pluralExceptions),
		"privatePlural":      namer.NewPrivatePluralNamer(pluralExceptions),
		"allLowercasePlural": namer.NewAllLowercasePluralNamer(pluralExceptions),
	}
}

// DefaultNameSystem returns the default name system for ordering the types to be
// processed by the generators in this package.
func DefaultNameSystem() string {
	return "public"
}

func generatedBy(customArgs clientgenargs.Args) string {
	if len(customArgs.CmdArgs) != 0 {
		return fmt.Sprintf("\n// This package is generated by client-gen with arguments: %s\n\n", customArgs.CmdArgs)
	}
	return fmt.Sprintf("\n// This package is generated by client-gen with the default arguments.\n\n")
}

func packageForGroup(gv clientgentypes.GroupVersion, typeList []*types.Type, packageBasePath string, apiPath string, srcTreePath string, inputPath string, boilerplate []byte, generatedBy string) generator.Package {
	outputPackagePath := strings.ToLower(filepath.Join(packageBasePath, gv.Group.NonEmpty(), gv.Version.NonEmpty()))
	return &generator.DefaultPackage{
		PackageName: strings.ToLower(gv.Version.NonEmpty()),
		PackagePath: outputPackagePath,
		HeaderText:  boilerplate,
		PackageDocumentation: []byte(
			generatedBy +
				`// This package has the automatically generated typed clients.
`),
		// GeneratorFunc returns a list of generators. Each generator makes a
		// single file.
		GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
			generators = []generator.Generator{
				// Always generate a "doc.go" file.
				generator.DefaultGen{OptionalName: "doc"},
			}
			// Since we want a file per type that we generate a client for, we
			// have to provide a function for this.
			for _, t := range typeList {
				generators = append(generators, &genClientForType{
					DefaultGen: generator.DefaultGen{
						OptionalName: strings.ToLower(c.Namers["private"].Name(t)),
					},
					outputPackage: outputPackagePath,
					group:         gv.Group.NonEmpty(),
					version:       gv.Version.String(),
					typeToMatch:   t,
					imports:       generator.NewImportTracker(),
				})
			}

			generators = append(generators, &genGroup{
				DefaultGen: generator.DefaultGen{
					OptionalName: gv.Group.NonEmpty() + "_client",
				},
				outputPackage: outputPackagePath,
				inputPacakge:  inputPath,
				group:         gv.Group.NonEmpty(),
				version:       gv.Version.String(),
				apiPath:       apiPath,
				types:         typeList,
				imports:       generator.NewImportTracker(),
			})

			expansionFileName := "generated_expansion"
			generators = append(generators, &genExpansion{
				groupPath: filepath.Join(srcTreePath, outputPackagePath),
				DefaultGen: generator.DefaultGen{
					OptionalName: expansionFileName,
				},
				types: typeList,
			})

			return generators
		},
		FilterFunc: func(c *generator.Context, t *types.Type) bool {
			return extractBoolTagOrDie("genclient", t.SecondClosestCommentLines) == true
		},
	}
}

func packageForClientset(customArgs clientgenargs.Args, typedClientBasePath string, boilerplate []byte, generatedBy string) generator.Package {
	return &generator.DefaultPackage{
		PackageName: customArgs.ClientsetName,
		PackagePath: filepath.Join(customArgs.ClientsetOutputPath, customArgs.ClientsetName),
		HeaderText:  boilerplate,
		PackageDocumentation: []byte(
			generatedBy +
				`// This package has the automatically generated clientset.
`),
		// GeneratorFunc returns a list of generators. Each generator generates a
		// single file.
		GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
			generators = []generator.Generator{
				// Always generate a "doc.go" file.
				generator.DefaultGen{OptionalName: "doc"},

				&genClientset{
					DefaultGen: generator.DefaultGen{
						OptionalName: "clientset",
					},
					groups:          customArgs.Groups,
					typedClientPath: typedClientBasePath,
					outputPackage:   customArgs.ClientsetName,
					imports:         generator.NewImportTracker(),
				},
			}
			return generators
		},
	}
}

// Packages makes the client package definition.
func Packages(context *generator.Context, arguments *args.GeneratorArgs) generator.Packages {
	boilerplate, err := arguments.LoadGoBoilerplate()
	if err != nil {
		glog.Fatalf("Failed loading boilerplate: %v", err)
	}

	customArgs, ok := arguments.CustomArgs.(clientgenargs.Args)
	if !ok {
		glog.Fatalf("cannot convert arguments.CustomArgs to clientgenargs.Args")
	}
	includedTypesOverrides := customArgs.IncludedTypesOverrides

	generatedBy := generatedBy(customArgs)

	gvToTypes := map[clientgentypes.GroupVersion][]*types.Type{}
	for gv, inputDir := range customArgs.GroupVersionToInputPath {
		p := context.Universe.Package(inputDir)
		for n, t := range p.Types {
			// filter out types which are not included in user specified overrides.
			typesOverride, ok := includedTypesOverrides[gv]
			if ok {
				found := false
				for _, typeStr := range typesOverride {
					if typeStr == n {
						found = true
						break
					}
				}
				if !found {
					continue
				}
			} else {
				// User has not specified any override for this group version.
				// filter out types which dont have genclient=true.
				if extractBoolTagOrDie("genclient", t.SecondClosestCommentLines) == false {
					continue
				}
			}
			if _, found := gvToTypes[gv]; !found {
				gvToTypes[gv] = []*types.Type{}
			}
			gvToTypes[gv] = append(gvToTypes[gv], t)
		}
	}

	var packageList []generator.Package
	typedClientBasePath := filepath.Join(customArgs.ClientsetOutputPath, customArgs.ClientsetName, "typed")

	packageList = append(packageList, packageForClientset(customArgs, typedClientBasePath, boilerplate, generatedBy))
	if customArgs.FakeClient {
		packageList = append(packageList, fake.PackageForClientset(customArgs, typedClientBasePath, boilerplate, generatedBy))
	}

	// If --clientset-only=true, we don't regenerate the individual typed clients.
	if customArgs.ClientsetOnly {
		return generator.Packages(packageList)
	}

	orderer := namer.Orderer{Namer: namer.NewPrivateNamer(0)}
	for _, group := range customArgs.Groups {
		for _, version := range group.Versions {
			gv := clientgentypes.GroupVersion{Group: group.Group, Version: version}
			types := gvToTypes[gv]
			inputPath := customArgs.GroupVersionToInputPath[gv]
			packageList = append(packageList, packageForGroup(gv, orderer.OrderTypes(types), typedClientBasePath, customArgs.ClientsetAPIPath, arguments.OutputBase, inputPath, boilerplate, generatedBy))
			if customArgs.FakeClient {
				packageList = append(packageList, fake.PackageForGroup(gv, orderer.OrderTypes(types), typedClientBasePath, arguments.OutputBase, inputPath, boilerplate, generatedBy))
			}
		}
	}

	return generator.Packages(packageList)
}
<commit_msg>Stop including full arguments list in generated clients<commit_after>/*
Copyright 2015 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 generators has the generators for the client-gen utility.
package generators

import (
	"fmt"
	"path/filepath"
	"strings"

	"k8s.io/gengo/args"
	"k8s.io/gengo/generator"
	"k8s.io/gengo/namer"
	"k8s.io/gengo/types"
	clientgenargs "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/args"
	"k8s.io/kubernetes/cmd/libs/go2idl/client-gen/generators/fake"
	clientgentypes "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/types"

	"github.com/golang/glog"
)

// NameSystems returns the name system used by the generators in this package.
func NameSystems() namer.NameSystems {
	pluralExceptions := map[string]string{
		"Endpoints": "Endpoints",
	}
	return namer.NameSystems{
		"public":             namer.NewPublicNamer(0),
		"private":            namer.NewPrivateNamer(0),
		"raw":                namer.NewRawNamer("", nil),
		"publicPlural":       namer.NewPublicPluralNamer(pluralExceptions),
		"privatePlural":      namer.NewPrivatePluralNamer(pluralExceptions),
		"allLowercasePlural": namer.NewAllLowercasePluralNamer(pluralExceptions),
	}
}

// DefaultNameSystem returns the default name system for ordering the types to be
// processed by the generators in this package.
func DefaultNameSystem() string {
	return "public"
}

func generatedBy(customArgs clientgenargs.Args) string {
	if len(customArgs.CmdArgs) != 0 {
		return fmt.Sprintf("\n// This package is generated by client-gen with custom arguments.\n\n")
	}
	return fmt.Sprintf("\n// This package is generated by client-gen with the default arguments.\n\n")
}

func packageForGroup(gv clientgentypes.GroupVersion, typeList []*types.Type, packageBasePath string, apiPath string, srcTreePath string, inputPath string, boilerplate []byte, generatedBy string) generator.Package {
	outputPackagePath := strings.ToLower(filepath.Join(packageBasePath, gv.Group.NonEmpty(), gv.Version.NonEmpty()))
	return &generator.DefaultPackage{
		PackageName: strings.ToLower(gv.Version.NonEmpty()),
		PackagePath: outputPackagePath,
		HeaderText:  boilerplate,
		PackageDocumentation: []byte(
			generatedBy +
				`// This package has the automatically generated typed clients.
`),
		// GeneratorFunc returns a list of generators. Each generator makes a
		// single file.
		GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
			generators = []generator.Generator{
				// Always generate a "doc.go" file.
				generator.DefaultGen{OptionalName: "doc"},
			}
			// Since we want a file per type that we generate a client for, we
			// have to provide a function for this.
			for _, t := range typeList {
				generators = append(generators, &genClientForType{
					DefaultGen: generator.DefaultGen{
						OptionalName: strings.ToLower(c.Namers["private"].Name(t)),
					},
					outputPackage: outputPackagePath,
					group:         gv.Group.NonEmpty(),
					version:       gv.Version.String(),
					typeToMatch:   t,
					imports:       generator.NewImportTracker(),
				})
			}

			generators = append(generators, &genGroup{
				DefaultGen: generator.DefaultGen{
					OptionalName: gv.Group.NonEmpty() + "_client",
				},
				outputPackage: outputPackagePath,
				inputPacakge:  inputPath,
				group:         gv.Group.NonEmpty(),
				version:       gv.Version.String(),
				apiPath:       apiPath,
				types:         typeList,
				imports:       generator.NewImportTracker(),
			})

			expansionFileName := "generated_expansion"
			generators = append(generators, &genExpansion{
				groupPath: filepath.Join(srcTreePath, outputPackagePath),
				DefaultGen: generator.DefaultGen{
					OptionalName: expansionFileName,
				},
				types: typeList,
			})

			return generators
		},
		FilterFunc: func(c *generator.Context, t *types.Type) bool {
			return extractBoolTagOrDie("genclient", t.SecondClosestCommentLines) == true
		},
	}
}

func packageForClientset(customArgs clientgenargs.Args, typedClientBasePath string, boilerplate []byte, generatedBy string) generator.Package {
	return &generator.DefaultPackage{
		PackageName: customArgs.ClientsetName,
		PackagePath: filepath.Join(customArgs.ClientsetOutputPath, customArgs.ClientsetName),
		HeaderText:  boilerplate,
		PackageDocumentation: []byte(
			generatedBy +
				`// This package has the automatically generated clientset.
`),
		// GeneratorFunc returns a list of generators. Each generator generates a
		// single file.
		GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
			generators = []generator.Generator{
				// Always generate a "doc.go" file.
				generator.DefaultGen{OptionalName: "doc"},

				&genClientset{
					DefaultGen: generator.DefaultGen{
						OptionalName: "clientset",
					},
					groups:          customArgs.Groups,
					typedClientPath: typedClientBasePath,
					outputPackage:   customArgs.ClientsetName,
					imports:         generator.NewImportTracker(),
				},
			}
			return generators
		},
	}
}

// Packages makes the client package definition.
func Packages(context *generator.Context, arguments *args.GeneratorArgs) generator.Packages {
	boilerplate, err := arguments.LoadGoBoilerplate()
	if err != nil {
		glog.Fatalf("Failed loading boilerplate: %v", err)
	}

	customArgs, ok := arguments.CustomArgs.(clientgenargs.Args)
	if !ok {
		glog.Fatalf("cannot convert arguments.CustomArgs to clientgenargs.Args")
	}
	includedTypesOverrides := customArgs.IncludedTypesOverrides

	generatedBy := generatedBy(customArgs)

	gvToTypes := map[clientgentypes.GroupVersion][]*types.Type{}
	for gv, inputDir := range customArgs.GroupVersionToInputPath {
		p := context.Universe.Package(inputDir)
		for n, t := range p.Types {
			// filter out types which are not included in user specified overrides.
			typesOverride, ok := includedTypesOverrides[gv]
			if ok {
				found := false
				for _, typeStr := range typesOverride {
					if typeStr == n {
						found = true
						break
					}
				}
				if !found {
					continue
				}
			} else {
				// User has not specified any override for this group version.
				// filter out types which dont have genclient=true.
				if extractBoolTagOrDie("genclient", t.SecondClosestCommentLines) == false {
					continue
				}
			}
			if _, found := gvToTypes[gv]; !found {
				gvToTypes[gv] = []*types.Type{}
			}
			gvToTypes[gv] = append(gvToTypes[gv], t)
		}
	}

	var packageList []generator.Package
	typedClientBasePath := filepath.Join(customArgs.ClientsetOutputPath, customArgs.ClientsetName, "typed")

	packageList = append(packageList, packageForClientset(customArgs, typedClientBasePath, boilerplate, generatedBy))
	if customArgs.FakeClient {
		packageList = append(packageList, fake.PackageForClientset(customArgs, typedClientBasePath, boilerplate, generatedBy))
	}

	// If --clientset-only=true, we don't regenerate the individual typed clients.
	if customArgs.ClientsetOnly {
		return generator.Packages(packageList)
	}

	orderer := namer.Orderer{Namer: namer.NewPrivateNamer(0)}
	for _, group := range customArgs.Groups {
		for _, version := range group.Versions {
			gv := clientgentypes.GroupVersion{Group: group.Group, Version: version}
			types := gvToTypes[gv]
			inputPath := customArgs.GroupVersionToInputPath[gv]
			packageList = append(packageList, packageForGroup(gv, orderer.OrderTypes(types), typedClientBasePath, customArgs.ClientsetAPIPath, arguments.OutputBase, inputPath, boilerplate, generatedBy))
			if customArgs.FakeClient {
				packageList = append(packageList, fake.PackageForGroup(gv, orderer.OrderTypes(types), typedClientBasePath, arguments.OutputBase, inputPath, boilerplate, generatedBy))
			}
		}
	}

	return generator.Packages(packageList)
}
<|endoftext|>


<commit_before>package container

import (
	"io"
	"io/ioutil"
	"runtime"
	"strings"
	"testing"

	"github.com/docker/cli/internal/test"
	"github.com/docker/cli/internal/test/testutil"
	"github.com/docker/docker/api/types"
	"github.com/docker/docker/pkg/archive"
	"github.com/gotestyourself/gotestyourself/fs"
	"github.com/gotestyourself/gotestyourself/skip"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

func TestRunCopyWithInvalidArguments(t *testing.T) {
	var testcases = []struct {
		doc         string
		options     copyOptions
		expectedErr string
	}{
		{
			doc: "copy between container",
			options: copyOptions{
				source:      "first:/path",
				destination: "second:/path",
			},
			expectedErr: "copying between containers is not supported",
		},
		{
			doc: "copy without a container",
			options: copyOptions{
				source:      "./source",
				destination: "./dest",
			},
			expectedErr: "must specify at least one container source",
		},
	}
	for _, testcase := range testcases {
		t.Run(testcase.doc, func(t *testing.T) {
			err := runCopy(test.NewFakeCli(nil), testcase.options)
			assert.EqualError(t, err, testcase.expectedErr)
		})
	}
}

func TestRunCopyFromContainerToStdout(t *testing.T) {
	tarContent := "the tar content"

	fakeClient := &fakeClient{
		containerCopyFromFunc: func(container, srcPath string) (io.ReadCloser, types.ContainerPathStat, error) {
			assert.Equal(t, "container", container)
			return ioutil.NopCloser(strings.NewReader(tarContent)), types.ContainerPathStat{}, nil
		},
	}
	options := copyOptions{source: "container:/path", destination: "-"}
	cli := test.NewFakeCli(fakeClient)
	err := runCopy(cli, options)
	require.NoError(t, err)
	assert.Equal(t, tarContent, cli.OutBuffer().String())
	assert.Equal(t, "", cli.ErrBuffer().String())
}

func TestRunCopyFromContainerToFilesystem(t *testing.T) {
	destDir := fs.NewDir(t, "cp-test",
		fs.WithFile("file1", "content\n"))
	defer destDir.Remove()

	fakeClient := &fakeClient{
		containerCopyFromFunc: func(container, srcPath string) (io.ReadCloser, types.ContainerPathStat, error) {
			assert.Equal(t, "container", container)
			readCloser, err := archive.TarWithOptions(destDir.Path(), &archive.TarOptions{})
			return readCloser, types.ContainerPathStat{}, err
		},
	}
	options := copyOptions{source: "container:/path", destination: destDir.Path()}
	cli := test.NewFakeCli(fakeClient)
	err := runCopy(cli, options)
	require.NoError(t, err)
	assert.Equal(t, "", cli.OutBuffer().String())
	assert.Equal(t, "", cli.ErrBuffer().String())

	content, err := ioutil.ReadFile(destDir.Join("file1"))
	require.NoError(t, err)
	assert.Equal(t, "content\n", string(content))
}

func TestRunCopyFromContainerToFilesystemMissingDestinationDirectory(t *testing.T) {
	destDir := fs.NewDir(t, "cp-test",
		fs.WithFile("file1", "content\n"))
	defer destDir.Remove()

	fakeClient := &fakeClient{
		containerCopyFromFunc: func(container, srcPath string) (io.ReadCloser, types.ContainerPathStat, error) {
			assert.Equal(t, "container", container)
			readCloser, err := archive.TarWithOptions(destDir.Path(), &archive.TarOptions{})
			return readCloser, types.ContainerPathStat{}, err
		},
	}

	options := copyOptions{
		source:      "container:/path",
		destination: destDir.Join("missing", "foo"),
	}
	cli := test.NewFakeCli(fakeClient)
	err := runCopy(cli, options)
	testutil.ErrorContains(t, err, destDir.Join("missing"))
}

func TestSplitCpArg(t *testing.T) {
	var testcases = []struct {
		doc               string
		path              string
		os                string
		expectedContainer string
		expectedPath      string
	}{
		{
			doc:          "absolute path with colon",
			os:           "linux",
			path:         "/abs/path:withcolon",
			expectedPath: "/abs/path:withcolon",
		},
		{
			doc:          "relative path with colon",
			path:         "./relative:path",
			expectedPath: "./relative:path",
		},
		{
			doc:          "absolute path with drive",
			os:           "windows",
			path:         `d:\abs\path`,
			expectedPath: `d:\abs\path`,
		},
		{
			doc:          "no separator",
			path:         "relative/path",
			expectedPath: "relative/path",
		},
		{
			doc:               "with separator",
			path:              "container:/opt/foo",
			expectedPath:      "/opt/foo",
			expectedContainer: "container",
		},
	}
	for _, testcase := range testcases {
		t.Run(testcase.doc, func(t *testing.T) {
			skip.IfCondition(t, testcase.os != "" && testcase.os != runtime.GOOS)

			container, path := splitCpArg(testcase.path)
			assert.Equal(t, testcase.expectedContainer, container)
			assert.Equal(t, testcase.expectedPath, path)
		})
	}
}
<commit_msg>Add more container cp tests<commit_after>package container

import (
	"io"
	"io/ioutil"
	"os"
	"runtime"
	"strings"
	"testing"

	"github.com/docker/cli/internal/test"
	"github.com/docker/cli/internal/test/testutil"
	"github.com/docker/docker/api/types"
	"github.com/docker/docker/pkg/archive"
	"github.com/gotestyourself/gotestyourself/fs"
	"github.com/gotestyourself/gotestyourself/skip"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

func TestRunCopyWithInvalidArguments(t *testing.T) {
	var testcases = []struct {
		doc         string
		options     copyOptions
		expectedErr string
	}{
		{
			doc: "copy between container",
			options: copyOptions{
				source:      "first:/path",
				destination: "second:/path",
			},
			expectedErr: "copying between containers is not supported",
		},
		{
			doc: "copy without a container",
			options: copyOptions{
				source:      "./source",
				destination: "./dest",
			},
			expectedErr: "must specify at least one container source",
		},
	}
	for _, testcase := range testcases {
		t.Run(testcase.doc, func(t *testing.T) {
			err := runCopy(test.NewFakeCli(nil), testcase.options)
			assert.EqualError(t, err, testcase.expectedErr)
		})
	}
}

func TestRunCopyFromContainerToStdout(t *testing.T) {
	tarContent := "the tar content"

	fakeClient := &fakeClient{
		containerCopyFromFunc: func(container, srcPath string) (io.ReadCloser, types.ContainerPathStat, error) {
			assert.Equal(t, "container", container)
			return ioutil.NopCloser(strings.NewReader(tarContent)), types.ContainerPathStat{}, nil
		},
	}
	options := copyOptions{source: "container:/path", destination: "-"}
	cli := test.NewFakeCli(fakeClient)
	err := runCopy(cli, options)
	require.NoError(t, err)
	assert.Equal(t, tarContent, cli.OutBuffer().String())
	assert.Equal(t, "", cli.ErrBuffer().String())
}

func TestRunCopyFromContainerToFilesystem(t *testing.T) {
	destDir := fs.NewDir(t, "cp-test",
		fs.WithFile("file1", "content\n"))
	defer destDir.Remove()

	fakeClient := &fakeClient{
		containerCopyFromFunc: func(container, srcPath string) (io.ReadCloser, types.ContainerPathStat, error) {
			assert.Equal(t, "container", container)
			readCloser, err := archive.TarWithOptions(destDir.Path(), &archive.TarOptions{})
			return readCloser, types.ContainerPathStat{}, err
		},
	}
	options := copyOptions{source: "container:/path", destination: destDir.Path()}
	cli := test.NewFakeCli(fakeClient)
	err := runCopy(cli, options)
	require.NoError(t, err)
	assert.Equal(t, "", cli.OutBuffer().String())
	assert.Equal(t, "", cli.ErrBuffer().String())

	content, err := ioutil.ReadFile(destDir.Join("file1"))
	require.NoError(t, err)
	assert.Equal(t, "content\n", string(content))
}

func TestRunCopyFromContainerToFilesystemMissingDestinationDirectory(t *testing.T) {
	destDir := fs.NewDir(t, "cp-test",
		fs.WithFile("file1", "content\n"))
	defer destDir.Remove()

	fakeClient := &fakeClient{
		containerCopyFromFunc: func(container, srcPath string) (io.ReadCloser, types.ContainerPathStat, error) {
			assert.Equal(t, "container", container)
			readCloser, err := archive.TarWithOptions(destDir.Path(), &archive.TarOptions{})
			return readCloser, types.ContainerPathStat{}, err
		},
	}

	options := copyOptions{
		source:      "container:/path",
		destination: destDir.Join("missing", "foo"),
	}
	cli := test.NewFakeCli(fakeClient)
	err := runCopy(cli, options)
	testutil.ErrorContains(t, err, destDir.Join("missing"))
}

func TestRunCopyToContainerFromFileWithTrailingSlash(t *testing.T) {
	srcFile := fs.NewFile(t, t.Name())
	defer srcFile.Remove()

	options := copyOptions{
		source:      srcFile.Path() + string(os.PathSeparator),
		destination: "container:/path",
	}
	cli := test.NewFakeCli(&fakeClient{})
	err := runCopy(cli, options)
	testutil.ErrorContains(t, err, "not a directory")
}

func TestRunCopyToContainerSourceDoesNotExist(t *testing.T) {
	options := copyOptions{
		source:      "/does/not/exist",
		destination: "container:/path",
	}
	cli := test.NewFakeCli(&fakeClient{})
	err := runCopy(cli, options)
	expected := "no such file or directory"
	if runtime.GOOS == "windows" {
		expected = "cannot find the file specified"
	}
	testutil.ErrorContains(t, err, expected)
}

func TestSplitCpArg(t *testing.T) {
	var testcases = []struct {
		doc               string
		path              string
		os                string
		expectedContainer string
		expectedPath      string
	}{
		{
			doc:          "absolute path with colon",
			os:           "linux",
			path:         "/abs/path:withcolon",
			expectedPath: "/abs/path:withcolon",
		},
		{
			doc:          "relative path with colon",
			path:         "./relative:path",
			expectedPath: "./relative:path",
		},
		{
			doc:          "absolute path with drive",
			os:           "windows",
			path:         `d:\abs\path`,
			expectedPath: `d:\abs\path`,
		},
		{
			doc:          "no separator",
			path:         "relative/path",
			expectedPath: "relative/path",
		},
		{
			doc:               "with separator",
			path:              "container:/opt/foo",
			expectedPath:      "/opt/foo",
			expectedContainer: "container",
		},
	}
	for _, testcase := range testcases {
		t.Run(testcase.doc, func(t *testing.T) {
			skip.IfCondition(t, testcase.os != "" && testcase.os != runtime.GOOS)

			container, path := splitCpArg(testcase.path)
			assert.Equal(t, testcase.expectedContainer, container)
			assert.Equal(t, testcase.expectedPath, path)
		})
	}
}
<|endoftext|>


<commit_before>package main

import (
    "fmt"
//    "os"
//    "strings"
)

func main() {
    fmt.Println("Hello World!")
}<commit_msg>made helloworld a bit fancier<commit_after>package main

import (
	"fmt"
	"os"
	"strings"
)

// This is my first ever go program. Excited to learn a new language!
func main() {
	name := "World"

	// If a name was passed, we greet that name instead.
	if len(os.Args) > 0 {
		name = strings.Join(os.Args[1:], " ")
	}

	fmt.Printf("Hello %s!\n", name)
}
<|endoftext|>


<commit_before>package stringsutil

import (
	"fmt"
	"regexp"
	"strings"
	"unicode"
	"unicode/utf8"
)

const (
	StringToLower     = "StringToLower"
	SpaceToHyphen     = "SpaceToHyphen"
	SpaceToUnderscore = "SpaceToUnderscore"
)

// PadLeft prepends a string to a base string until the string
// length is greater or equal to the desired length.
func PadLeft(str string, pad string, length int) string {
	for {
		str = pad + str
		if len(str) >= length {
			return str[0:length]
		}
	}
}

// PadRight appends a string to a base string until the string
// length is greater or equal to the desired length.
func PadRight(str string, pad string, length int) string {
	for {
		str += pad
		if len(str) > length {
			return str[0:length]
		}
	}
}

// ToLowerFirst lower cases the first letter in the string
func ToLowerFirst(s string) string {
	if s == "" {
		return ""
	}
	r, n := utf8.DecodeRuneInString(s)
	return string(unicode.ToLower(r)) + s[n:]
}

// ToUpperFirst upper cases the first letter in the string
func ToUpperFirst(s string) string {
	if s == "" {
		return ""
	}
	r, n := utf8.DecodeRuneInString(s)
	return string(unicode.ToUpper(r)) + s[n:]
}

// SliceTrimSpace removes leading and trailing spaces per
// string and also removes empty strings.
func SliceTrimSpace(slice []string) []string {
	trimmed := []string{}
	for _, part := range slice {
		part := strings.TrimSpace(part)
		if len(part) > 0 {
			trimmed = append(trimmed, part)
		}
	}
	return trimmed
}

// SplitTrimSpace splits a string and trims spaces on
// remaining elements.
func SplitTrimSpace(s, sep string) []string {
	split := strings.Split(s, sep)
	strs := []string{}
	for _, str := range split {
		strs = append(strs, strings.TrimSpace(str))
	}
	return strs
}

// SplitCondenseSpace splits a string and trims spaces on
// remaining elements, removing empty elements.
func SplitCondenseSpace(s, sep string) []string {
	split := strings.Split(s, sep)
	strs := []string{}
	for _, str := range split {
		str = strings.TrimSpace(str)
		if len(str) > 0 {
			strs = append(strs, str)
		}
	}
	return strs
}

// CondenseString trims whitespace at the ends of the string
// as well as in between.
func CondenseString(content string, join_lines bool) string {
	if join_lines {
		content = regexp.MustCompile(`\n`).ReplaceAllString(content, " ")
	}
	// Beginning
	content = regexp.MustCompile(`^\s+`).ReplaceAllString(content, "")
	// End
	content = regexp.MustCompile(`\s+$`).ReplaceAllString(content, "")
	// Middle
	content = regexp.MustCompile(`\n[\s\t\r]*\n`).ReplaceAllString(content, "\n")
	// Indentation
	content = regexp.MustCompile(`\n[\s\t\r]*`).ReplaceAllString(content, "\n")
	// Collapse
	content = regexp.MustCompile(`\s+`).ReplaceAllString(content, " ")
	return strings.TrimSpace(content)
}

// TrimSentenceLength trims a string by a max length at word boundaries.
func TrimSentenceLength(sentenceInput string, maxLength int) string {
	if len(sentenceInput) <= maxLength {
		return sentenceInput
	}
	sentenceLen := string(sentenceInput[0:maxLength]) // first350 := string(s[0:350])
	rx_end := regexp.MustCompile(`[[:punct:]][^[[:punct:]]]*$`)
	sentencePunct := rx_end.ReplaceAllString(sentenceLen, "")
	if len(sentencePunct) >= 2 {
		return sentencePunct
	}
	return sentenceLen
}

// JoinInterface joins an interface and returns a string. It takes
// a join separator, boolean to replace the join separator in the
// string parts and a separator alternate. `stripEmbeddedSep` strips
// separator string found within parts. `stripRepeatedSep` strips
// repeating separators. This flexibility is designed to support
// joining data for both CSVs and paths.
func JoinInterface(arr []interface{}, sep string, stripRepeatedSep bool, stripEmbeddedSep bool, altSep string) string {
	parts := []string{}
	rx := regexp.MustCompile(sep)
	for _, el := range arr {
		part := fmt.Sprintf("%v", el)
		if stripEmbeddedSep {
			part = rx.ReplaceAllString(part, altSep)
		}
		parts = append(parts, part)
	}
	joined := strings.Join(parts, sep)
	if stripRepeatedSep {
		joined = regexp.MustCompile(fmt.Sprintf("%s+", sep)).
			ReplaceAllString(joined, sep)
	}
	return joined
}

func FormatString(s string, options []string) string {
	for _, opt := range options {
		switch strings.TrimSpace(opt) {
		case StringToLower:
			s = strings.ToLower(s)
		case SpaceToHyphen:
			s = regexp.MustCompile(`[\s-]+`).ReplaceAllString(s, "-")
		case SpaceToUnderscore:
			s = regexp.MustCompile(`[\s_]+`).ReplaceAllString(s, "_")
		}
	}
	return s
}
<commit_msg>add stringsutil.JoinTrimSpace<commit_after>package stringsutil

import (
	"fmt"
	"regexp"
	"strings"
	"unicode"
	"unicode/utf8"
)

const (
	StringToLower     = "StringToLower"
	SpaceToHyphen     = "SpaceToHyphen"
	SpaceToUnderscore = "SpaceToUnderscore"
)

var rxSpaces = regexp.MustCompile(`\s+`)

// PadLeft prepends a string to a base string until the string
// length is greater or equal to the desired length.
func PadLeft(str string, pad string, length int) string {
	for {
		str = pad + str
		if len(str) >= length {
			return str[0:length]
		}
	}
}

// PadRight appends a string to a base string until the string
// length is greater or equal to the desired length.
func PadRight(str string, pad string, length int) string {
	for {
		str += pad
		if len(str) > length {
			return str[0:length]
		}
	}
}

// ToLowerFirst lower cases the first letter in the string
func ToLowerFirst(s string) string {
	if s == "" {
		return ""
	}
	r, n := utf8.DecodeRuneInString(s)
	return string(unicode.ToLower(r)) + s[n:]
}

// ToUpperFirst upper cases the first letter in the string
func ToUpperFirst(s string) string {
	if s == "" {
		return ""
	}
	r, n := utf8.DecodeRuneInString(s)
	return string(unicode.ToUpper(r)) + s[n:]
}

// SliceTrimSpace removes leading and trailing spaces per
// string and also removes empty strings.
func SliceTrimSpace(slice []string) []string {
	trimmed := []string{}
	for _, part := range slice {
		part := strings.TrimSpace(part)
		if len(part) > 0 {
			trimmed = append(trimmed, part)
		}
	}
	return trimmed
}

// SplitTrimSpace splits a string and trims spaces on
// remaining elements.
func SplitTrimSpace(s, sep string) []string {
	split := strings.Split(s, sep)
	strs := []string{}
	for _, str := range split {
		strs = append(strs, strings.TrimSpace(str))
	}
	return strs
}

// SplitCondenseSpace splits a string and trims spaces on
// remaining elements, removing empty elements.
func SplitCondenseSpace(s, sep string) []string {
	split := strings.Split(s, sep)
	strs := []string{}
	for _, str := range split {
		str = strings.TrimSpace(str)
		if len(str) > 0 {
			strs = append(strs, str)
		}
	}
	return strs
}

// CondenseString trims whitespace at the ends of the string
// as well as in between.
func CondenseString(content string, join_lines bool) string {
	if join_lines {
		content = regexp.MustCompile(`\n`).ReplaceAllString(content, " ")
	}
	// Beginning
	content = regexp.MustCompile(`^\s+`).ReplaceAllString(content, "")
	// End
	content = regexp.MustCompile(`\s+$`).ReplaceAllString(content, "")
	// Middle
	content = regexp.MustCompile(`\n[\s\t\r]*\n`).ReplaceAllString(content, "\n")
	// Indentation
	content = regexp.MustCompile(`\n[\s\t\r]*`).ReplaceAllString(content, "\n")
	// Collapse
	content = regexp.MustCompile(`\s+`).ReplaceAllString(content, " ")
	return strings.TrimSpace(content)
}

// TrimSentenceLength trims a string by a max length at word boundaries.
func TrimSentenceLength(sentenceInput string, maxLength int) string {
	if len(sentenceInput) <= maxLength {
		return sentenceInput
	}
	sentenceLen := string(sentenceInput[0:maxLength]) // first350 := string(s[0:350])
	rx_end := regexp.MustCompile(`[[:punct:]][^[[:punct:]]]*$`)
	sentencePunct := rx_end.ReplaceAllString(sentenceLen, "")
	if len(sentencePunct) >= 2 {
		return sentencePunct
	}
	return sentenceLen
}

func JoinTrimSpace(strs []string) string {
	return rxSpaces.ReplaceAllString(strings.Join(strs, " "), " ")
}

// JoinInterface joins an interface and returns a string. It takes
// a join separator, boolean to replace the join separator in the
// string parts and a separator alternate. `stripEmbeddedSep` strips
// separator string found within parts. `stripRepeatedSep` strips
// repeating separators. This flexibility is designed to support
// joining data for both CSVs and paths.
func JoinInterface(arr []interface{}, sep string, stripRepeatedSep bool, stripEmbeddedSep bool, altSep string) string {
	parts := []string{}
	rx := regexp.MustCompile(sep)
	for _, el := range arr {
		part := fmt.Sprintf("%v", el)
		if stripEmbeddedSep {
			part = rx.ReplaceAllString(part, altSep)
		}
		parts = append(parts, part)
	}
	joined := strings.Join(parts, sep)
	if stripRepeatedSep {
		joined = regexp.MustCompile(fmt.Sprintf("%s+", sep)).
			ReplaceAllString(joined, sep)
	}
	return joined
}

func FormatString(s string, options []string) string {
	for _, opt := range options {
		switch strings.TrimSpace(opt) {
		case StringToLower:
			s = strings.ToLower(s)
		case SpaceToHyphen:
			s = regexp.MustCompile(`[\s-]+`).ReplaceAllString(s, "-")
		case SpaceToUnderscore:
			s = regexp.MustCompile(`[\s_]+`).ReplaceAllString(s, "_")
		}
	}
	return s
}
<|endoftext|>