<commit_before>/*
Copyright 2014 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 algorithmprovider

import (
	"sort"
	"strings"

	utilfeature "k8s.io/apiserver/pkg/util/feature"
	"k8s.io/klog/v2"
	"k8s.io/kubernetes/pkg/features"
	schedulerapi "k8s.io/kubernetes/pkg/scheduler/apis/config"
	"k8s.io/kubernetes/pkg/scheduler/framework/plugins/defaultbinder"
	"k8s.io/kubernetes/pkg/scheduler/framework/plugins/defaultpreemption"
	"k8s.io/kubernetes/pkg/scheduler/framework/plugins/imagelocality"
	"k8s.io/kubernetes/pkg/scheduler/framework/plugins/interpodaffinity"
	"k8s.io/kubernetes/pkg/scheduler/framework/plugins/nodeaffinity"
	"k8s.io/kubernetes/pkg/scheduler/framework/plugins/nodename"
	"k8s.io/kubernetes/pkg/scheduler/framework/plugins/nodeports"
	"k8s.io/kubernetes/pkg/scheduler/framework/plugins/nodepreferavoidpods"
	"k8s.io/kubernetes/pkg/scheduler/framework/plugins/noderesources"
	"k8s.io/kubernetes/pkg/scheduler/framework/plugins/nodeunschedulable"
	"k8s.io/kubernetes/pkg/scheduler/framework/plugins/nodevolumelimits"
	"k8s.io/kubernetes/pkg/scheduler/framework/plugins/podtopologyspread"
	"k8s.io/kubernetes/pkg/scheduler/framework/plugins/queuesort"
	"k8s.io/kubernetes/pkg/scheduler/framework/plugins/selectorspread"
	"k8s.io/kubernetes/pkg/scheduler/framework/plugins/tainttoleration"
	"k8s.io/kubernetes/pkg/scheduler/framework/plugins/volumebinding"
	"k8s.io/kubernetes/pkg/scheduler/framework/plugins/volumerestrictions"
	"k8s.io/kubernetes/pkg/scheduler/framework/plugins/volumezone"
)

// ClusterAutoscalerProvider defines the default autoscaler provider
const ClusterAutoscalerProvider = "ClusterAutoscalerProvider"

// Registry is a collection of all available algorithm providers.
type Registry map[string]*schedulerapi.Plugins

// NewRegistry returns an algorithm provider registry instance.
func NewRegistry() Registry {
	defaultConfig := getDefaultConfig()
	applyFeatureGates(defaultConfig)

	caConfig := getClusterAutoscalerConfig()
	applyFeatureGates(caConfig)

	return Registry{
		schedulerapi.SchedulerDefaultProviderName: defaultConfig,
		ClusterAutoscalerProvider:                 caConfig,
	}
}

// ListAlgorithmProviders lists registered algorithm providers.
func ListAlgorithmProviders() string {
	r := NewRegistry()
	var providers []string
	for k := range r {
		providers = append(providers, k)
	}
	sort.Strings(providers)
	return strings.Join(providers, " | ")
}

func getDefaultConfig() *schedulerapi.Plugins {
	return &schedulerapi.Plugins{
		QueueSort: &schedulerapi.PluginSet{
			Enabled: []schedulerapi.Plugin{
				{Name: queuesort.Name},
			},
		},
		PreFilter: &schedulerapi.PluginSet{
			Enabled: []schedulerapi.Plugin{
				{Name: noderesources.FitName},
				{Name: nodeports.Name},
				{Name: podtopologyspread.Name},
				{Name: interpodaffinity.Name},
				{Name: volumebinding.Name},
			},
		},
		Filter: &schedulerapi.PluginSet{
			Enabled: []schedulerapi.Plugin{
				{Name: nodeunschedulable.Name},
				{Name: noderesources.FitName},
				{Name: nodename.Name},
				{Name: nodeports.Name},
				{Name: nodeaffinity.Name},
				{Name: volumerestrictions.Name},
				{Name: tainttoleration.Name},
				{Name: nodevolumelimits.EBSName},
				{Name: nodevolumelimits.GCEPDName},
				{Name: nodevolumelimits.CSIName},
				{Name: nodevolumelimits.AzureDiskName},
				{Name: volumebinding.Name},
				{Name: volumezone.Name},
				{Name: podtopologyspread.Name},
				{Name: interpodaffinity.Name},
			},
		},
		PostFilter: &schedulerapi.PluginSet{
			Enabled: []schedulerapi.Plugin{
				{Name: defaultpreemption.Name},
			},
		},
		PreScore: &schedulerapi.PluginSet{
			Enabled: []schedulerapi.Plugin{
				{Name: interpodaffinity.Name},
				{Name: podtopologyspread.Name},
				{Name: tainttoleration.Name},
			},
		},
		Score: &schedulerapi.PluginSet{
			Enabled: []schedulerapi.Plugin{
				{Name: noderesources.BalancedAllocationName, Weight: 1},
				{Name: imagelocality.Name, Weight: 1},
				{Name: interpodaffinity.Name, Weight: 1},
				{Name: noderesources.LeastAllocatedName, Weight: 1},
				{Name: nodeaffinity.Name, Weight: 1},
				{Name: nodepreferavoidpods.Name, Weight: 10000},
				// Weight is doubled because:
				// - This is a score coming from user preference.
				// - It makes its signal comparable to NodeResourcesLeastAllocated.
				{Name: podtopologyspread.Name, Weight: 2},
				{Name: tainttoleration.Name, Weight: 1},
			},
		},
		Reserve: &schedulerapi.PluginSet{
			Enabled: []schedulerapi.Plugin{
				{Name: volumebinding.Name},
			},
		},
		PreBind: &schedulerapi.PluginSet{
			Enabled: []schedulerapi.Plugin{
				{Name: volumebinding.Name},
			},
		},
		Bind: &schedulerapi.PluginSet{
			Enabled: []schedulerapi.Plugin{
				{Name: defaultbinder.Name},
			},
		},
	}
}

func getClusterAutoscalerConfig() *schedulerapi.Plugins {
	caConfig := getDefaultConfig()
	// Replace least with most requested.
	for i := range caConfig.Score.Enabled {
		if caConfig.Score.Enabled[i].Name == noderesources.LeastAllocatedName {
			caConfig.Score.Enabled[i].Name = noderesources.MostAllocatedName
		}
	}
	return caConfig
}

func applyFeatureGates(config *schedulerapi.Plugins) {
	if !utilfeature.DefaultFeatureGate.Enabled(features.DefaultPodTopologySpread) {
		// When feature is enabled, the default spreading is done by
		// PodTopologySpread plugin, which is enabled by default.
		klog.Infof("Registering SelectorSpread plugin")
		s := schedulerapi.Plugin{Name: selectorspread.Name}
		config.PreScore.Enabled = append(config.PreScore.Enabled, s)
		s.Weight = 1
		config.Score.Enabled = append(config.Score.Enabled, s)
	}
}
<commit_msg>Seperate registry and feature gates<commit_after>/*
Copyright 2014 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 algorithmprovider

import (
	"fmt"

	utilfeature "k8s.io/apiserver/pkg/util/feature"
	"k8s.io/klog/v2"
	"k8s.io/kubernetes/pkg/features"
	schedulerapi "k8s.io/kubernetes/pkg/scheduler/apis/config"
	"k8s.io/kubernetes/pkg/scheduler/framework/plugins/defaultbinder"
	"k8s.io/kubernetes/pkg/scheduler/framework/plugins/defaultpreemption"
	"k8s.io/kubernetes/pkg/scheduler/framework/plugins/imagelocality"
	"k8s.io/kubernetes/pkg/scheduler/framework/plugins/interpodaffinity"
	"k8s.io/kubernetes/pkg/scheduler/framework/plugins/nodeaffinity"
	"k8s.io/kubernetes/pkg/scheduler/framework/plugins/nodename"
	"k8s.io/kubernetes/pkg/scheduler/framework/plugins/nodeports"
	"k8s.io/kubernetes/pkg/scheduler/framework/plugins/nodepreferavoidpods"
	"k8s.io/kubernetes/pkg/scheduler/framework/plugins/noderesources"
	"k8s.io/kubernetes/pkg/scheduler/framework/plugins/nodeunschedulable"
	"k8s.io/kubernetes/pkg/scheduler/framework/plugins/nodevolumelimits"
	"k8s.io/kubernetes/pkg/scheduler/framework/plugins/podtopologyspread"
	"k8s.io/kubernetes/pkg/scheduler/framework/plugins/queuesort"
	"k8s.io/kubernetes/pkg/scheduler/framework/plugins/selectorspread"
	"k8s.io/kubernetes/pkg/scheduler/framework/plugins/tainttoleration"
	"k8s.io/kubernetes/pkg/scheduler/framework/plugins/volumebinding"
	"k8s.io/kubernetes/pkg/scheduler/framework/plugins/volumerestrictions"
	"k8s.io/kubernetes/pkg/scheduler/framework/plugins/volumezone"
)

// ClusterAutoscalerProvider defines the default autoscaler provider
const ClusterAutoscalerProvider = "ClusterAutoscalerProvider"

// Registry is a collection of all available algorithm providers.
type Registry map[string]*schedulerapi.Plugins

// NewRegistry returns an algorithm provider registry instance.
func NewRegistry() Registry {
	defaultConfig := getDefaultConfig()
	applyFeatureGates(defaultConfig)

	caConfig := getClusterAutoscalerConfig()
	applyFeatureGates(caConfig)

	return Registry{
		schedulerapi.SchedulerDefaultProviderName: defaultConfig,
		ClusterAutoscalerProvider:                 caConfig,
	}
}

// ListAlgorithmProviders lists registered algorithm providers.
func ListAlgorithmProviders() string {
	return fmt.Sprintf("%s | %s", ClusterAutoscalerProvider, schedulerapi.SchedulerDefaultProviderName)
}

func getDefaultConfig() *schedulerapi.Plugins {
	return &schedulerapi.Plugins{
		QueueSort: &schedulerapi.PluginSet{
			Enabled: []schedulerapi.Plugin{
				{Name: queuesort.Name},
			},
		},
		PreFilter: &schedulerapi.PluginSet{
			Enabled: []schedulerapi.Plugin{
				{Name: noderesources.FitName},
				{Name: nodeports.Name},
				{Name: podtopologyspread.Name},
				{Name: interpodaffinity.Name},
				{Name: volumebinding.Name},
			},
		},
		Filter: &schedulerapi.PluginSet{
			Enabled: []schedulerapi.Plugin{
				{Name: nodeunschedulable.Name},
				{Name: noderesources.FitName},
				{Name: nodename.Name},
				{Name: nodeports.Name},
				{Name: nodeaffinity.Name},
				{Name: volumerestrictions.Name},
				{Name: tainttoleration.Name},
				{Name: nodevolumelimits.EBSName},
				{Name: nodevolumelimits.GCEPDName},
				{Name: nodevolumelimits.CSIName},
				{Name: nodevolumelimits.AzureDiskName},
				{Name: volumebinding.Name},
				{Name: volumezone.Name},
				{Name: podtopologyspread.Name},
				{Name: interpodaffinity.Name},
			},
		},
		PostFilter: &schedulerapi.PluginSet{
			Enabled: []schedulerapi.Plugin{
				{Name: defaultpreemption.Name},
			},
		},
		PreScore: &schedulerapi.PluginSet{
			Enabled: []schedulerapi.Plugin{
				{Name: interpodaffinity.Name},
				{Name: podtopologyspread.Name},
				{Name: tainttoleration.Name},
			},
		},
		Score: &schedulerapi.PluginSet{
			Enabled: []schedulerapi.Plugin{
				{Name: noderesources.BalancedAllocationName, Weight: 1},
				{Name: imagelocality.Name, Weight: 1},
				{Name: interpodaffinity.Name, Weight: 1},
				{Name: noderesources.LeastAllocatedName, Weight: 1},
				{Name: nodeaffinity.Name, Weight: 1},
				{Name: nodepreferavoidpods.Name, Weight: 10000},
				// Weight is doubled because:
				// - This is a score coming from user preference.
				// - It makes its signal comparable to NodeResourcesLeastAllocated.
				{Name: podtopologyspread.Name, Weight: 2},
				{Name: tainttoleration.Name, Weight: 1},
			},
		},
		Reserve: &schedulerapi.PluginSet{
			Enabled: []schedulerapi.Plugin{
				{Name: volumebinding.Name},
			},
		},
		PreBind: &schedulerapi.PluginSet{
			Enabled: []schedulerapi.Plugin{
				{Name: volumebinding.Name},
			},
		},
		Bind: &schedulerapi.PluginSet{
			Enabled: []schedulerapi.Plugin{
				{Name: defaultbinder.Name},
			},
		},
	}
}

func getClusterAutoscalerConfig() *schedulerapi.Plugins {
	caConfig := getDefaultConfig()
	// Replace least with most requested.
	for i := range caConfig.Score.Enabled {
		if caConfig.Score.Enabled[i].Name == noderesources.LeastAllocatedName {
			caConfig.Score.Enabled[i].Name = noderesources.MostAllocatedName
		}
	}
	return caConfig
}

func applyFeatureGates(config *schedulerapi.Plugins) {
	if !utilfeature.DefaultFeatureGate.Enabled(features.DefaultPodTopologySpread) {
		// When feature is enabled, the default spreading is done by
		// PodTopologySpread plugin, which is enabled by default.
		klog.Infof("Registering SelectorSpread plugin")
		s := schedulerapi.Plugin{Name: selectorspread.Name}
		config.PreScore.Enabled = append(config.PreScore.Enabled, s)
		s.Weight = 1
		config.Score.Enabled = append(config.Score.Enabled, s)
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2019 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package queue

import (
	"sync"
	"time"

	ktypes "k8s.io/apimachinery/pkg/types"
)

// PodBackoffMap is a structure that stores backoff related information for pods
type PodBackoffMap struct {
	// lock for performing actions on this PodBackoffMap
	lock sync.Mutex
	// initial backoff duration
	initialDuration time.Duration
	// maximal backoff duration
	maxDuration time.Duration
	// map for pod -> number of attempts for this pod
	podAttempts map[ktypes.NamespacedName]int
	// map for pod -> lastUpdateTime pod of this pod
	podLastUpdateTime map[ktypes.NamespacedName]time.Time
}

// NewPodBackoffMap creates a PodBackoffMap with initial duration and max duration.
func NewPodBackoffMap(initialDuration, maxDuration time.Duration) *PodBackoffMap {
	return &PodBackoffMap{
		initialDuration:   initialDuration,
		maxDuration:       maxDuration,
		podAttempts:       make(map[ktypes.NamespacedName]int),
		podLastUpdateTime: make(map[ktypes.NamespacedName]time.Time),
	}
}

// GetBackoffTime returns the time that nsPod completes backoff
func (pbm *PodBackoffMap) GetBackoffTime(nsPod ktypes.NamespacedName) (time.Time, bool) {
	pbm.lock.Lock()
	defer pbm.lock.Unlock()
	if _, found := pbm.podAttempts[nsPod]; found == false {
		return time.Time{}, false
	}
	lastUpdateTime := pbm.podLastUpdateTime[nsPod]
	backoffDuration := pbm.calculateBackoffDuration(nsPod)
	backoffTime := lastUpdateTime.Add(backoffDuration)
	return backoffTime, true
}

// TryBackoffAndWait tries to perform backoff for a non-preempting pod.
// it is invoked from factory.go if util.PodPriorityEnabled() returns false.
func (pbm *PodBackoffMap) TryBackoffAndWait(nsPod ktypes.NamespacedName, stop <-chan struct{}) bool {
	pbm.lock.Lock()
	defer pbm.lock.Unlock()
	backoffDuration := pbm.calculateBackoffDuration(nsPod)
	select {
	case <-time.After(backoffDuration):
		return true
	case <-stop:
		return false
	}
}

// calculateBackoffDuration is a helper function for calculating the backoffDuration
// based on the number of attempts the pod has made.
func (pbm *PodBackoffMap) calculateBackoffDuration(nsPod ktypes.NamespacedName) time.Duration {
	backoffDuration := pbm.initialDuration
	if _, found := pbm.podAttempts[nsPod]; found {
		for i := 1; i < pbm.podAttempts[nsPod]; i++ {
			backoffDuration = backoffDuration * 2
			if backoffDuration > pbm.maxDuration {
				return pbm.maxDuration
			}
		}
	}
	return backoffDuration
}

// clearPodBackoff removes all tracking information for nsPod.
// Lock is supposed to be acquired by caller.
func (pbm *PodBackoffMap) clearPodBackoff(nsPod ktypes.NamespacedName) {
	delete(pbm.podAttempts, nsPod)
	delete(pbm.podLastUpdateTime, nsPod)
}

// ClearPodBackoff is the thread safe version of clearPodBackoff
func (pbm *PodBackoffMap) ClearPodBackoff(nsPod ktypes.NamespacedName) {
	pbm.lock.Lock()
	pbm.clearPodBackoff(nsPod)
	pbm.lock.Unlock()
}

// CleanupPodsCompletesBackingoff execute garbage collection on the pod backoff,
// i.e, it will remove a pod from the PodBackoffMap if
// lastUpdateTime + maxBackoffDuration is before the current timestamp
func (pbm *PodBackoffMap) CleanupPodsCompletesBackingoff() {
	pbm.lock.Lock()
	defer pbm.lock.Unlock()
	for pod, value := range pbm.podLastUpdateTime {
		if value.Add(pbm.maxDuration).Before(time.Now()) {
			pbm.clearPodBackoff(pod)
		}
	}
}

// BackoffPod updates the lastUpdateTime for an nsPod,
// and increases its numberOfAttempts by 1
func (pbm *PodBackoffMap) BackoffPod(nsPod ktypes.NamespacedName) {
	pbm.lock.Lock()
	pbm.podLastUpdateTime[nsPod] = time.Now()
	pbm.podAttempts[nsPod]++
	pbm.lock.Unlock()
}
<commit_msg>Change Mutex to RWMutex for pod backoff<commit_after>/*
Copyright 2019 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package queue

import (
	"sync"
	"time"

	ktypes "k8s.io/apimachinery/pkg/types"
)

// PodBackoffMap is a structure that stores backoff related information for pods
type PodBackoffMap struct {
	// lock for performing actions on this PodBackoffMap
	lock sync.RWMutex
	// initial backoff duration
	initialDuration time.Duration
	// maximal backoff duration
	maxDuration time.Duration
	// map for pod -> number of attempts for this pod
	podAttempts map[ktypes.NamespacedName]int
	// map for pod -> lastUpdateTime pod of this pod
	podLastUpdateTime map[ktypes.NamespacedName]time.Time
}

// NewPodBackoffMap creates a PodBackoffMap with initial duration and max duration.
func NewPodBackoffMap(initialDuration, maxDuration time.Duration) *PodBackoffMap {
	return &PodBackoffMap{
		initialDuration:   initialDuration,
		maxDuration:       maxDuration,
		podAttempts:       make(map[ktypes.NamespacedName]int),
		podLastUpdateTime: make(map[ktypes.NamespacedName]time.Time),
	}
}

// GetBackoffTime returns the time that nsPod completes backoff
func (pbm *PodBackoffMap) GetBackoffTime(nsPod ktypes.NamespacedName) (time.Time, bool) {
	pbm.lock.RLock()
	defer pbm.lock.RUnlock()
	if _, found := pbm.podAttempts[nsPod]; found == false {
		return time.Time{}, false
	}
	lastUpdateTime := pbm.podLastUpdateTime[nsPod]
	backoffDuration := pbm.calculateBackoffDuration(nsPod)
	backoffTime := lastUpdateTime.Add(backoffDuration)
	return backoffTime, true
}

// TryBackoffAndWait tries to perform backoff for a non-preempting pod.
// it is invoked from factory.go if util.PodPriorityEnabled() returns false.
func (pbm *PodBackoffMap) TryBackoffAndWait(nsPod ktypes.NamespacedName, stop <-chan struct{}) bool {
	pbm.lock.RLock()
	defer pbm.lock.RUnlock()
	backoffDuration := pbm.calculateBackoffDuration(nsPod)
	select {
	case <-time.After(backoffDuration):
		return true
	case <-stop:
		return false
	}
}

// calculateBackoffDuration is a helper function for calculating the backoffDuration
// based on the number of attempts the pod has made.
func (pbm *PodBackoffMap) calculateBackoffDuration(nsPod ktypes.NamespacedName) time.Duration {
	backoffDuration := pbm.initialDuration
	if _, found := pbm.podAttempts[nsPod]; found {
		for i := 1; i < pbm.podAttempts[nsPod]; i++ {
			backoffDuration = backoffDuration * 2
			if backoffDuration > pbm.maxDuration {
				return pbm.maxDuration
			}
		}
	}
	return backoffDuration
}

// clearPodBackoff removes all tracking information for nsPod.
// Lock is supposed to be acquired by caller.
func (pbm *PodBackoffMap) clearPodBackoff(nsPod ktypes.NamespacedName) {
	delete(pbm.podAttempts, nsPod)
	delete(pbm.podLastUpdateTime, nsPod)
}

// ClearPodBackoff is the thread safe version of clearPodBackoff
func (pbm *PodBackoffMap) ClearPodBackoff(nsPod ktypes.NamespacedName) {
	pbm.lock.Lock()
	pbm.clearPodBackoff(nsPod)
	pbm.lock.Unlock()
}

// CleanupPodsCompletesBackingoff execute garbage collection on the pod backoff,
// i.e, it will remove a pod from the PodBackoffMap if
// lastUpdateTime + maxBackoffDuration is before the current timestamp
func (pbm *PodBackoffMap) CleanupPodsCompletesBackingoff() {
	pbm.lock.Lock()
	defer pbm.lock.Unlock()
	for pod, value := range pbm.podLastUpdateTime {
		if value.Add(pbm.maxDuration).Before(time.Now()) {
			pbm.clearPodBackoff(pod)
		}
	}
}

// BackoffPod updates the lastUpdateTime for an nsPod,
// and increases its numberOfAttempts by 1
func (pbm *PodBackoffMap) BackoffPod(nsPod ktypes.NamespacedName) {
	pbm.lock.Lock()
	pbm.podLastUpdateTime[nsPod] = time.Now()
	pbm.podAttempts[nsPod]++
	pbm.lock.Unlock()
}
<|endoftext|>


<commit_before>// Libcontainer provides a native Go implementation for creating containers
// with namespaces, cgroups, capabilities, and filesystem access controls.
// It allows you to manage the lifecycle of the container performing additional operations
// after the container is created.
package libcontainer

import (
	"os"
	"time"

	"github.com/opencontainers/runc/libcontainer/configs"
)

// The status of a container.
type Status int

const (
	// The container exists but has not been run yet
	Created Status = iota

	// The container exists and is running.
	Running

	// The container exists, it is in the process of being paused.
	Pausing

	// The container exists, but all its processes are paused.
	Paused

	// The container exists, but its state is saved on disk
	Checkpointed

	// The container does not exist.
	Destroyed
)

func (s Status) String() string {
	switch s {
	case Created:
		return "created"
	case Running:
		return "running"
	case Pausing:
		return "pausing"
	case Paused:
		return "paused"
	case Checkpointed:
		return "checkpointed"
	case Destroyed:
		return "destroyed"
	default:
		return "unknown"
	}
}

// BaseState represents the platform agnostic pieces relating to a
// running container's state
type BaseState struct {
	// ID is the container ID.
	ID string `json:"id"`

	// InitProcessPid is the init process id in the parent namespace.
	InitProcessPid int `json:"init_process_pid"`

	// InitProcessStartTime is the init process start time in clock cycles since boot time.
	InitProcessStartTime string `json:"init_process_start"`

	// Created is the unix timestamp for the creation time of the container in UTC
	Created time.Time `json:"created"`

	// Config is the container's configuration.
	Config configs.Config `json:"config"`
}

// A libcontainer container object.
//
// Each container is thread-safe within the same process. Since a container can
// be destroyed by a separate process, any function may return that the container
// was not found. BaseContainer includes methods that are platform agnostic.
type BaseContainer interface {
	// Returns the ID of the container
	ID() string

	// Returns the current status of the container.
	//
	// errors:
	// ContainerDestroyed - Container no longer exists,
	// Systemerror - System error.
	Status() (Status, error)

	// State returns the current container's state information.
	//
	// errors:
	// Systemerror - System error.
	State() (*State, error)

	// Returns the current config of the container.
	Config() configs.Config

	// Returns the PIDs inside this container. The PIDs are in the namespace of the calling process.
	//
	// errors:
	// ContainerDestroyed - Container no longer exists,
	// Systemerror - System error.
	//
	// Some of the returned PIDs may no longer refer to processes in the Container, unless
	// the Container state is PAUSED in which case every PID in the slice is valid.
	Processes() ([]int, error)

	// Returns statistics for the container.
	//
	// errors:
	// ContainerDestroyed - Container no longer exists,
	// Systemerror - System error.
	Stats() (*Stats, error)

	// Set resources of container as configured
	//
	// We can use this to change resources when containers are running.
	//
	// errors:
	// Systemerror - System error.
	Set(config configs.Config) error

	// Start a process inside the container. Returns error if process fails to
	// start. You can track process lifecycle with passed Process structure.
	//
	// errors:
	// ContainerDestroyed - Container no longer exists,
	// ConfigInvalid - config is invalid,
	// ContainerPaused - Container is paused,
	// Systemerror - System error.
	Start(process *Process) (err error)

	// Destroys the container after killing all running processes.
	//
	// Any event registrations are removed before the container is destroyed.
	// No error is returned if the container is already destroyed.
	//
	// errors:
	// Systemerror - System error.
	Destroy() error

	// Signal sends the provided signal code to the container's initial process.
	//
	// errors:
	// Systemerror - System error.
	Signal(s os.Signal) error
}
<commit_msg>Eliminating checkpoint state in container<commit_after>// Libcontainer provides a native Go implementation for creating containers
// with namespaces, cgroups, capabilities, and filesystem access controls.
// It allows you to manage the lifecycle of the container performing additional operations
// after the container is created.
package libcontainer

import (
	"os"
	"time"

	"github.com/opencontainers/runc/libcontainer/configs"
)

// The status of a container.
type Status int

const (
	// The container exists but has not been run yet
	Created Status = iota

	// The container exists and is running.
	Running

	// The container exists, it is in the process of being paused.
	Pausing

	// The container exists, but all its processes are paused.
	Paused

	// The container does not exist.
	Destroyed
)

func (s Status) String() string {
	switch s {
	case Created:
		return "created"
	case Running:
		return "running"
	case Pausing:
		return "pausing"
	case Paused:
		return "paused"
	case Destroyed:
		return "destroyed"
	default:
		return "unknown"
	}
}

// BaseState represents the platform agnostic pieces relating to a
// running container's state
type BaseState struct {
	// ID is the container ID.
	ID string `json:"id"`

	// InitProcessPid is the init process id in the parent namespace.
	InitProcessPid int `json:"init_process_pid"`

	// InitProcessStartTime is the init process start time in clock cycles since boot time.
	InitProcessStartTime string `json:"init_process_start"`

	// Created is the unix timestamp for the creation time of the container in UTC
	Created time.Time `json:"created"`

	// Config is the container's configuration.
	Config configs.Config `json:"config"`
}

// A libcontainer container object.
//
// Each container is thread-safe within the same process. Since a container can
// be destroyed by a separate process, any function may return that the container
// was not found. BaseContainer includes methods that are platform agnostic.
type BaseContainer interface {
	// Returns the ID of the container
	ID() string

	// Returns the current status of the container.
	//
	// errors:
	// ContainerDestroyed - Container no longer exists,
	// Systemerror - System error.
	Status() (Status, error)

	// State returns the current container's state information.
	//
	// errors:
	// Systemerror - System error.
	State() (*State, error)

	// Returns the current config of the container.
	Config() configs.Config

	// Returns the PIDs inside this container. The PIDs are in the namespace of the calling process.
	//
	// errors:
	// ContainerDestroyed - Container no longer exists,
	// Systemerror - System error.
	//
	// Some of the returned PIDs may no longer refer to processes in the Container, unless
	// the Container state is PAUSED in which case every PID in the slice is valid.
	Processes() ([]int, error)

	// Returns statistics for the container.
	//
	// errors:
	// ContainerDestroyed - Container no longer exists,
	// Systemerror - System error.
	Stats() (*Stats, error)

	// Set resources of container as configured
	//
	// We can use this to change resources when containers are running.
	//
	// errors:
	// Systemerror - System error.
	Set(config configs.Config) error

	// Start a process inside the container. Returns error if process fails to
	// start. You can track process lifecycle with passed Process structure.
	//
	// errors:
	// ContainerDestroyed - Container no longer exists,
	// ConfigInvalid - config is invalid,
	// ContainerPaused - Container is paused,
	// Systemerror - System error.
	Start(process *Process) (err error)

	// Destroys the container after killing all running processes.
	//
	// Any event registrations are removed before the container is destroyed.
	// No error is returned if the container is already destroyed.
	//
	// errors:
	// Systemerror - System error.
	Destroy() error

	// Signal sends the provided signal code to the container's initial process.
	//
	// errors:
	// Systemerror - System error.
	Signal(s os.Signal) error
}
<|endoftext|>


<commit_before>// Copyright 2018 Keybase Inc. All rights reserved.
// Use of this source code is governed by a BSD
// license that can be found in the LICENSE file.

package libkbfs

import (
	"github.com/keybase/go-codec/codec"
	"github.com/keybase/kbfs/kbfsmd"
)

// PrevRevisionAndCount track the MD version of a previous revision of
// a dir entry, and how many revisions ago that was from the current
// revision.
type PrevRevisionAndCount struct {
	Revision kbfsmd.Revision `codec:"r"`
	Count    uint8           `codec:"c"`

	codec.UnknownFieldSetHandler
}

// minPrevRevisionSlotCounts defines the "min count" of each
// corresponding entry in a `PrevRevisions` slice.  The length of
// `minPrevRevisionSlotCounts` is the max length of a `PrevRevisions`
// slice.
var minPrevRevisionSlotCounts = [...]uint8{1, 5, 20, 50, 100}

// PrevRevisions tracks several previous versions of a file in order
// of descending revision number, starting with the most recent.
type PrevRevisions []PrevRevisionAndCount

// addRevision returns a copy of `pr` with a new immediately-previous
// revision added, with the existing entries moved or overwritten to
// accomodate the new entry, and with increased counts.  Any existing
// revisions smaller than or equal to minRev will be removed.
func (pr PrevRevisions) addRevision(
	r, minRev kbfsmd.Revision) (ret PrevRevisions) {
	newLength := len(pr)
	if newLength < len(minPrevRevisionSlotCounts) {
		newLength++
	}
	ret = make(PrevRevisions, newLength)
	copy(ret, pr)
	earliestGoodSlot := 0
	numDropped := 0

	// First we eliminate any revisions in the current list that don't
	// make sense anymore, either because they're greater or equal to
	// `r`, or they're smaller or equal to `minRev` (and thus have
	// been GC'd).  For example:
	//
	// pr = [27, 25, 15, 10, 5] (revision numbers only)
	// r  = 27
	// minRev = 11
	//
	// After this next block, we should have:
	//
	// ret = [0, 25, 15, 0, 0]
	// earliestGoodSlot = 1
	// numDropped = 2
	//
	// Then the next block of code will trim it appropriately.
	for i, prc := range ret {
		if prc.Count == 255 {
			// This should never happen, as the largest max count is
			// approximated by the sum of all the min slots.  Test of
			// this hypothesis is at
			// https://play.golang.org/p/ltVzr1PH-MG, which shows a
			// max count of 178 seen over 100,000 revisions.
			panic("Previous revision count is about to overflow")
		} else if prc.Revision >= r {
			if numDropped > 0 {
				panic("Revision too large after dropping one")
			}
			// The revision number is bigger than expected (e.g. it
			// was made on an unmerged branch)
			ret[i] = PrevRevisionAndCount{
				Revision: kbfsmd.RevisionUninitialized,
				Count:    0,
			}
			earliestGoodSlot = i + 1
			continue
		} else if prc.Revision <= minRev {
			// This revision is too old (or is empty), so remove it.
			ret[i] = PrevRevisionAndCount{
				Revision: kbfsmd.RevisionUninitialized,
				Count:    0,
			}
			numDropped++
			continue
		} else if numDropped > 0 {
			panic("Once we've dropped one, we should drop all the rest")
		}
		// `minRev` < `prc.Revision` < `r`, so we keep it in the new
		// slice and increment its count.
		ret[i].Count++
	}

	// Cut out the revisions that are newer than `r` (e.g., because
	// they are from an unmerged branch).
	//
	// Continuing the example above, this code will leave us with:
	//
	// ret = [25, 15, 0, 0]
	if earliestGoodSlot > 0 {
		ret = ret[earliestGoodSlot:]
	}

	// Drop revisions off the end that are too old, but leave an empty
	// slot available at the end for shifting everything over and
	// putting `r` in slot 0.
	//
	// Continuing the example above, this code will leave us with:
	//
	// ret = [25, 15, 0]
	if numDropped == len(ret) {
		// Leave the first slot available for overwriting.
		ret = ret[:1]
	} else if numDropped > 1 {
		ret = ret[:len(ret)-(numDropped-1)]
	}

	// Starting at the end, shift revisions to the right if either a)
	// they satisfy the count of the slot to the right, or b) that
	// slot is already empty.
	//
	// Continuing the example above, this code will leave us with:
	//
	// ret = [0, 25, 15]
	for i := len(ret) - 1; i >= 1; i-- {
		// Check if we can shift over the entry in slot i-1.
		if ret[i].Count == 0 || ret[i-1].Count >= minPrevRevisionSlotCounts[i] {
			ret[i], ret[i-1] = ret[i-1], PrevRevisionAndCount{
				Revision: kbfsmd.RevisionUninitialized,
				Count:    0,
			}
		}
	}

	// Finally, overwrite whatever's left in the first slot with `r`
	// and a count of 1.
	//
	// Continuing the example above, this code will leave us with:
	//
	// ret = [27, 25, 15]
	ret[0] = PrevRevisionAndCount{
		Revision: r,
		Count:    1,
	}
	return ret
}
<commit_msg>prev_revisions: space out revisions more evenly<commit_after>// Copyright 2018 Keybase Inc. All rights reserved.
// Use of this source code is governed by a BSD
// license that can be found in the LICENSE file.

package libkbfs

import (
	"github.com/keybase/go-codec/codec"
	"github.com/keybase/kbfs/kbfsmd"
)

// PrevRevisionAndCount track the MD version of a previous revision of
// a dir entry, and how many revisions ago that was from the current
// revision.
type PrevRevisionAndCount struct {
	Revision kbfsmd.Revision `codec:"r"`
	Count    uint8           `codec:"c"`

	codec.UnknownFieldSetHandler
}

// minPrevRevisionSlotCounts defines the "min count" of each
// corresponding entry in a `PrevRevisions` slice.  The length of
// `minPrevRevisionSlotCounts` is the max length of a `PrevRevisions`
// slice.
var minPrevRevisionSlotCounts = [...]uint8{1, 5, 10, 25, 100}

// PrevRevisions tracks several previous versions of a file in order
// of descending revision number, starting with the most recent.
type PrevRevisions []PrevRevisionAndCount

// addRevision returns a copy of `pr` with a new immediately-previous
// revision added, with the existing entries moved or overwritten to
// accomodate the new entry, and with increased counts.  Any existing
// revisions smaller than or equal to minRev will be removed.
func (pr PrevRevisions) addRevision(
	r, minRev kbfsmd.Revision) (ret PrevRevisions) {
	newLength := len(pr)
	if newLength < len(minPrevRevisionSlotCounts) {
		newLength++
	}
	ret = make(PrevRevisions, newLength)
	copy(ret, pr)
	earliestGoodSlot := 0
	numDropped := 0

	// First we eliminate any revisions in the current list that don't
	// make sense anymore, either because they're greater or equal to
	// `r`, or they're smaller or equal to `minRev` (and thus have
	// been GC'd).  For example:
	//
	// pr = [27, 25, 15, 10, 5] (revision numbers only)
	// r  = 27
	// minRev = 11
	//
	// After this next block, we should have:
	//
	// ret = [0, 25, 15, 0, 0]
	// earliestGoodSlot = 1
	// numDropped = 2
	//
	// Then the next block of code will trim it appropriately.
	for i, prc := range ret {
		if prc.Count == 255 {
			// This should never happen, as the largest max count is
			// approximated by the sum of all the min slots.  Test of
			// this hypothesis is at
			// https://play.golang.org/p/ltVzr1PH-MG, which shows a
			// max count of 178 seen over 100,000 revisions.
			panic("Previous revision count is about to overflow")
		} else if prc.Revision >= r {
			if numDropped > 0 {
				panic("Revision too large after dropping one")
			}
			// The revision number is bigger than expected (e.g. it
			// was made on an unmerged branch)
			ret[i] = PrevRevisionAndCount{
				Revision: kbfsmd.RevisionUninitialized,
				Count:    0,
			}
			earliestGoodSlot = i + 1
			continue
		} else if prc.Revision <= minRev {
			// This revision is too old (or is empty), so remove it.
			ret[i] = PrevRevisionAndCount{
				Revision: kbfsmd.RevisionUninitialized,
				Count:    0,
			}
			numDropped++
			continue
		} else if numDropped > 0 {
			panic("Once we've dropped one, we should drop all the rest")
		}
		// `minRev` < `prc.Revision` < `r`, so we keep it in the new
		// slice and increment its count.
		ret[i].Count++
	}

	// Cut out the revisions that are newer than `r` (e.g., because
	// they are from an unmerged branch).
	//
	// Continuing the example above, this code will leave us with:
	//
	// ret = [25, 15, 0, 0]
	if earliestGoodSlot > 0 {
		ret = ret[earliestGoodSlot:]
	}

	// Drop revisions off the end that are too old, but leave an empty
	// slot available at the end for shifting everything over and
	// putting `r` in slot 0.
	//
	// Continuing the example above, this code will leave us with:
	//
	// ret = [25, 15, 0]
	if numDropped == len(ret) {
		// Leave the first slot available for overwriting.
		ret = ret[:1]
	} else if numDropped > 1 {
		ret = ret[:len(ret)-(numDropped-1)]
	}

	// Starting at the end, shift revisions to the right if either a)
	// that slot is already empty or b) they satisfy the count of the
	// slot to the right.  If a revision is not going to shifted, but
	// it is too close (in terms of count) to the revision on its
	// right, just drop it and let the other revisions slide over --
	// this makes sure we have a nicely-spaced set of revision numbers
	// even when the total number of revisions for the entry is small.
	//
	// Continuing the example above, this code will leave us with:
	//
	// ret = [0, 25, 15]
	for i := len(ret) - 1; i >= 1; i-- {
		// Check if we can shift over the entry in slot i-1.
		minCount := minPrevRevisionSlotCounts[i]
		if ret[i].Count == 0 || ret[i-1].Count >= minCount {
			ret[i], ret[i-1] = ret[i-1], PrevRevisionAndCount{
				Revision: kbfsmd.RevisionUninitialized,
				Count:    0,
			}
		} else if ret[i].Count-ret[i-1].Count < minCount/5 {
			// This revision is not being shifted, but it's
			// uncomfortablely close to its neighbor on the right, so
			// just drop it.
			ret[i-1] = PrevRevisionAndCount{
				Revision: kbfsmd.RevisionUninitialized,
				Count:    0,
			}
		}
	}

	// Finally, overwrite whatever's left in the first slot with `r`
	// and a count of 1.
	//
	// Continuing the example above, this code will leave us with:
	//
	// ret = [27, 25, 15]
	ret[0] = PrevRevisionAndCount{
		Revision: r,
		Count:    1,
	}
	return ret
}
<|endoftext|>


<commit_before>package glukit

import (
	"appengine"
	"appengine/user"
	"encoding/json"
	"fmt"
	"github.com/alexandre-normand/glukit/app/apimodel"
	"github.com/alexandre-normand/glukit/app/engine"
	"github.com/alexandre-normand/glukit/app/model"
	"github.com/alexandre-normand/glukit/app/store"
	"github.com/alexandre-normand/glukit/app/util"
	"github.com/alexandre-normand/glukit/lib/github.com/grd/stat"
	"net/http"
	"sort"
	"strconv"
	"time"
)

// Represents a DataResponse with an array of DataSeries and some metadata
type DataResponse struct {
	FirstName string       `json:"firstName"`
	LastName  string       `json:"lastName"`
	Data      []DataSeries `json:"data"`
	Picture   string       `json:"picture"`
	LastSync  time.Time    `json:"lastSync"`
}

// Represents a generic DataSeries structure with a series of DataPoints
type DataSeries struct {
	Name string               `json:"name"`
	Data []apimodel.DataPoint `json:"data"`
	Type string               `json:"type"`
}

const (
	QUERY_PARAM_LIMIT = "limit"
	QUERY_PARAM_FROM  = "from"
	QUERY_PARAM_TO    = "to"
)

// content renders the most recent day's worth of data as json for the active user
func personalData(writer http.ResponseWriter, request *http.Request) {
	context := appengine.NewContext(request)
	user := user.Current(context)

	mostRecentWeekAsJson(writer, request, user.Email)
}

// demoContent renders the most recent day's worth of data as json for the demo user
func demoContent(writer http.ResponseWriter, request *http.Request) {
	mostRecentWeekAsJson(writer, request, DEMO_EMAIL)
}

// mostRecentWeekAsJson retrieves the most recent day's week worth of data for the user identified by
// the given email address and writes to the response writer as json
func mostRecentWeekAsJson(writer http.ResponseWriter, request *http.Request, email string) {
	context := appengine.NewContext(request)
	glukitUser, _, upperBound, err := store.GetUserData(context, email)
	lowerBound := util.GetEndOfDayBoundaryBefore(upperBound).Add(model.DEFAULT_LOOKBACK_PERIOD)

	if err != nil && err == store.ErrNoImportedDataFound {
		context.Debugf("No imported data found for user [%s]", email)
		http.Error(writer, err.Error(), 204)
	} else if err != nil {
		util.Propagate(err)
	} else {
		reads, err := store.GetGlucoseReads(context, email, lowerBound, upperBound)
		if err != nil {
			util.Propagate(err)
		}
		injections, err := store.GetInjections(context, email, lowerBound, upperBound)
		if err != nil {
			util.Propagate(err)
		}
		carbs, err := store.GetMeals(context, email, lowerBound, upperBound)
		if err != nil {
			util.Propagate(err)
		}
		exercises, err := store.GetExercises(context, email, lowerBound, upperBound)
		if err != nil {
			util.Propagate(err)
		}

		value := writer.Header()
		value.Add("Content-type", "application/json")

		response := DataResponse{FirstName: glukitUser.FirstName, LastName: glukitUser.LastName, Data: generateDataSeriesFromData(reads, injections, carbs, exercises), Picture: glukitUser.PictureUrl, LastSync: glukitUser.MostRecentRead.GetTime()}
		writeAsJson(writer, response)
	}
}

// find the steady sailor and retrieve his most recent day's worth of data.
func steadySailorData(writer http.ResponseWriter, request *http.Request) {
	context := appengine.NewContext(request)
	user := user.Current(context)

	steadySailorDataForEmail(writer, request, user.Email)
}

// find the steady sailor for the demo user and retrieve his most recent day's worth of data.
func demoSteadySailorData(writer http.ResponseWriter, request *http.Request) {
	steadySailorDataForEmail(writer, request, DEMO_EMAIL)
}

// find the steady sailor and retrieve his most recent day's worth of data.
func steadySailorDataForEmail(writer http.ResponseWriter, request *http.Request, recipientEmail string) {
	context := appengine.NewContext(request)
	steadySailor, _, upperBound, err := store.FindSteadySailor(context, recipientEmail)

	lowerBound := upperBound.Add(model.DEFAULT_LOOKBACK_PERIOD)
	if err != nil && err == store.ErrNoSteadySailorMatchFound {
		context.Debugf("No steady sailor match found for user [%s]", recipientEmail)
		http.Error(writer, err.Error(), 204)
	} else if err != nil {
		util.Propagate(err)
	} else {
		reads, err := store.GetGlucoseReads(context, steadySailor.Email, lowerBound, upperBound)
		if err != nil {
			util.Propagate(err)
		}

		value := writer.Header()
		value.Add("Content-type", "application/json")

		response := DataResponse{FirstName: steadySailor.FirstName, LastName: steadySailor.LastName, Data: generateDataSeriesFromData(reads, nil, nil, nil), Picture: steadySailor.PictureUrl, LastSync: steadySailor.MostRecentRead.GetTime()}
		writeAsJson(writer, response)
	}
}

// writeAsJson writes a DataResponse with its set of GlucoseReads, Injections, Meals and Exercises as json. This is what is called from the javascript
// front-end to get the data.
func writeAsJson(writer http.ResponseWriter, response DataResponse) {
	enc := json.NewEncoder(writer)
	enc.Encode(response)
}

func generateDataSeriesFromData(reads []apimodel.GlucoseRead, injections []apimodel.Injection, carbs []apimodel.Meal, exercises []apimodel.Exercise) (dataSeries []DataSeries) {
	data := make([]DataSeries, 1)

	data[0] = DataSeries{"GlucoseReads", apimodel.GlucoseReadSlice(reads).ToDataPointSlice(), "GlucoseReads"}
	var userEvents []apimodel.DataPoint
	if injections != nil {
		userEvents = apimodel.MergeDataPointArrays(userEvents, apimodel.InjectionSlice(injections).ToDataPointSlice(reads))
	}

	if carbs != nil {
		userEvents = apimodel.MergeDataPointArrays(userEvents, apimodel.MealSlice(carbs).ToDataPointSlice(reads))
	}

	// TODO: clean up exercise from all the app or restore it. We won't be using it at the moment as we don't think the exercise data
	// from the dexcom is good enough
	// if exercises != nil {
	// 	userEvents = apimodel.MergeDataPointArrays(userEvents, apimodel.ExerciseSlice(exercises).ToDataPointSlice(reads))
	// }

	sort.Sort(apimodel.DataPointSlice(userEvents))

	data = append(data, DataSeries{"UserEvents", userEvents, "UserEvents"})

	return data
}

// dashboard renders the dashboard statistics as json
func dashboard(writer http.ResponseWriter, request *http.Request) {
	context := appengine.NewContext(request)
	user := user.Current(context)

	dashboardDataForUser(writer, request, user.Email)
}

// demodashboard renders the dashboard statistics as json for the demo user
func demoDashboard(writer http.ResponseWriter, request *http.Request) {
	dashboardDataForUser(writer, request, DEMO_EMAIL)
}

// dashboardDataForUser retrieves reads and generates dashboard statistics from them
func dashboardDataForUser(writer http.ResponseWriter, request *http.Request, email string) {
	context := appengine.NewContext(request)

	userProfile, _, upperBound, err := store.GetUserData(context, email)
	lowerBound := util.GetEndOfDayBoundaryBefore(upperBound).Add(time.Duration(-1*24) * time.Hour)

	if err != nil && err == store.ErrNoImportedDataFound {
		context.Debugf("No imported data found for user [%s]", email)
		http.Error(writer, err.Error(), 204)
	} else if err != nil {
		util.Propagate(err)
	} else {
		reads, err := store.GetGlucoseReads(context, email, lowerBound, upperBound)
		if err != nil {
			util.Propagate(err)
		}

		writeDashboardDataAsJson(writer, request, reads, userProfile)
	}
}

// writedashboardDataAsJson calculates dashboard statistics from an array of GlucoseReads and writes it
// as json
func writeDashboardDataAsJson(writer http.ResponseWriter, request *http.Request, reads []apimodel.GlucoseRead, userProfile *model.GlukitUser) {
	context := appengine.NewContext(request)
	value := writer.Header()
	value.Add("Content-type", "application/json")

	var dashboardData model.DashboardData
	if len(reads) > 0 {
		sort.Sort(model.ReadStatsSlice(reads))
		dashboardData.FirstName = userProfile.FirstName
		dashboardData.LastName = userProfile.LastName
		dashboardData.Picture = userProfile.PictureUrl
		dashboardData.LastSync = userProfile.MostRecentRead.GetTime()
		dashboardData.Average = stat.Mean(model.ReadStatsSlice(reads))
		dashboardData.High, _ = stat.Max(model.ReadStatsSlice(reads))
		dashboardData.Low, _ = stat.Min(model.ReadStatsSlice(reads))
		dashboardData.Median = stat.MedianFromSortedData(model.ReadStatsSlice(reads))
		dashboardData.Score = engine.CalculateUserFacingScore(userProfile.MostRecentScore)
		dashboardData.ScoreDetails = userProfile.MostRecentScore
		dashboardData.JoinedOn = userProfile.AccountCreated
		context.Debugf("Calculated user score of [%d] from internal score of [%d]", dashboardData.Score, userProfile.MostRecentScore.Value)
	}

	enc := json.NewEncoder(writer)
	enc.Encode(dashboardData)
}

func glukitScores(writer http.ResponseWriter, request *http.Request) {
	context := appengine.NewContext(request)
	user := user.Current(context)

	glukitScoresForEmail(writer, request, user.Email)
}

func glukitScoresForDemo(writer http.ResponseWriter, request *http.Request) {
	glukitScoresForEmail(writer, request, DEMO_EMAIL)
}

// glukitScoresForEmail is the endpoint to retrieve a list of glukitscores.
func glukitScoresForEmail(writer http.ResponseWriter, request *http.Request, email string) {
	context := appengine.NewContext(request)

	limit := request.FormValue(QUERY_PARAM_LIMIT)
	fromTimestamp := request.FormValue(QUERY_PARAM_FROM)
	toTimestamp := request.FormValue(QUERY_PARAM_TO)

	// The request must include at least one of from/to/limit to be considered valid
	// as leaving it too open would could open the door for costly queries
	if len(limit) == 0 && len(fromTimestamp) == 0 && len(toTimestamp) == 0 {
		http.Error(writer, fmt.Sprintf("Query must specify at least one of: %s, %s or %s.",
			QUERY_PARAM_LIMIT, QUERY_PARAM_FROM, QUERY_PARAM_TO), 400)
		return
	}

	var scanQuery store.GlukitScoreScanQuery
	if len(limit) > 0 {
		if limitValue, err := strconv.ParseInt(limit, 10, 32); err != nil {
			http.Error(writer, fmt.Sprintf("Invalid value for %s: [%v].", QUERY_PARAM_LIMIT, err), 400)
			return
		} else {
			limitVal := int(limitValue)
			scanQuery.Limit = &limitVal
		}
	}

	if len(fromTimestamp) > 0 {
		if fromValue, err := strconv.ParseInt(fromTimestamp, 10, 64); err != nil {
			http.Error(writer, fmt.Sprintf("Invalid value for %s: [%v].", QUERY_PARAM_FROM, err), 400)
			return
		} else {
			fromTime := time.Unix(fromValue, 0)
			scanQuery.From = &fromTime
		}
	}

	if len(toTimestamp) > 0 {
		if toValue, err := strconv.ParseInt(toTimestamp, 10, 64); err != nil {
			http.Error(writer, fmt.Sprintf("Invalid value for %s: [%v].", QUERY_PARAM_TO, err), 400)
			return
		} else {
			toTime := time.Unix(toValue, 0)
			scanQuery.To = &toTime
		}
	}

	glukitScores, err := store.GetGlukitScores(context, email, scanQuery)
	if err != nil {
		util.Propagate(err)
	}

	if len(glukitScores) < 1 {
		http.Error(writer, "No glukit scores calculated yet.", 204)
		return
	}

	value := writer.Header()
	value.Add("Content-type", "application/json")

	enc := json.NewEncoder(writer)
	enc.Encode(glukitScores)

}
<commit_msg>Fix Steady Sailor Not Having Enough Data to Cover for a Partial Day of Data Showing.<commit_after>package glukit

import (
	"appengine"
	"appengine/user"
	"encoding/json"
	"fmt"
	"github.com/alexandre-normand/glukit/app/apimodel"
	"github.com/alexandre-normand/glukit/app/engine"
	"github.com/alexandre-normand/glukit/app/model"
	"github.com/alexandre-normand/glukit/app/store"
	"github.com/alexandre-normand/glukit/app/util"
	"github.com/alexandre-normand/glukit/lib/github.com/grd/stat"
	"net/http"
	"sort"
	"strconv"
	"time"
)

// Represents a DataResponse with an array of DataSeries and some metadata
type DataResponse struct {
	FirstName string       `json:"firstName"`
	LastName  string       `json:"lastName"`
	Data      []DataSeries `json:"data"`
	Picture   string       `json:"picture"`
	LastSync  time.Time    `json:"lastSync"`
}

// Represents a generic DataSeries structure with a series of DataPoints
type DataSeries struct {
	Name string               `json:"name"`
	Data []apimodel.DataPoint `json:"data"`
	Type string               `json:"type"`
}

const (
	QUERY_PARAM_LIMIT = "limit"
	QUERY_PARAM_FROM  = "from"
	QUERY_PARAM_TO    = "to"
)

// content renders the most recent day's worth of data as json for the active user
func personalData(writer http.ResponseWriter, request *http.Request) {
	context := appengine.NewContext(request)
	user := user.Current(context)

	mostRecentWeekAsJson(writer, request, user.Email)
}

// demoContent renders the most recent day's worth of data as json for the demo user
func demoContent(writer http.ResponseWriter, request *http.Request) {
	mostRecentWeekAsJson(writer, request, DEMO_EMAIL)
}

// mostRecentWeekAsJson retrieves the most recent day's week worth of data for the user identified by
// the given email address and writes to the response writer as json
func mostRecentWeekAsJson(writer http.ResponseWriter, request *http.Request, email string) {
	context := appengine.NewContext(request)
	glukitUser, _, upperBound, err := store.GetUserData(context, email)
	lowerBound := util.GetEndOfDayBoundaryBefore(upperBound).Add(model.DEFAULT_LOOKBACK_PERIOD)

	if err != nil && err == store.ErrNoImportedDataFound {
		context.Debugf("No imported data found for user [%s]", email)
		http.Error(writer, err.Error(), 204)
	} else if err != nil {
		util.Propagate(err)
	} else {
		reads, err := store.GetGlucoseReads(context, email, lowerBound, upperBound)
		if err != nil {
			util.Propagate(err)
		}
		injections, err := store.GetInjections(context, email, lowerBound, upperBound)
		if err != nil {
			util.Propagate(err)
		}
		carbs, err := store.GetMeals(context, email, lowerBound, upperBound)
		if err != nil {
			util.Propagate(err)
		}
		exercises, err := store.GetExercises(context, email, lowerBound, upperBound)
		if err != nil {
			util.Propagate(err)
		}

		value := writer.Header()
		value.Add("Content-type", "application/json")

		response := DataResponse{FirstName: glukitUser.FirstName, LastName: glukitUser.LastName, Data: generateDataSeriesFromData(reads, injections, carbs, exercises), Picture: glukitUser.PictureUrl, LastSync: glukitUser.MostRecentRead.GetTime()}
		writeAsJson(writer, response)
	}
}

// find the steady sailor and retrieve his most recent day's worth of data.
func steadySailorData(writer http.ResponseWriter, request *http.Request) {
	context := appengine.NewContext(request)
	user := user.Current(context)

	steadySailorDataForEmail(writer, request, user.Email)
}

// find the steady sailor for the demo user and retrieve his most recent day's worth of data.
func demoSteadySailorData(writer http.ResponseWriter, request *http.Request) {
	steadySailorDataForEmail(writer, request, DEMO_EMAIL)
}

// find the steady sailor and retrieve his most recent day's worth of data.
func steadySailorDataForEmail(writer http.ResponseWriter, request *http.Request, recipientEmail string) {
	context := appengine.NewContext(request)
	steadySailor, _, upperBound, err := store.FindSteadySailor(context, recipientEmail)

	// Overscan by a day so that we have enough data to cover for a partial day of the user's data
	lowerBound := upperBound.Add(model.DEFAULT_LOOKBACK_PERIOD + time.Duration(-24)*time.Hour)
	if err != nil && err == store.ErrNoSteadySailorMatchFound {
		context.Debugf("No steady sailor match found for user [%s]", recipientEmail)
		http.Error(writer, err.Error(), 204)
	} else if err != nil {
		util.Propagate(err)
	} else {
		reads, err := store.GetGlucoseReads(context, steadySailor.Email, lowerBound, upperBound)
		if err != nil {
			util.Propagate(err)
		}

		value := writer.Header()
		value.Add("Content-type", "application/json")

		response := DataResponse{FirstName: steadySailor.FirstName, LastName: steadySailor.LastName, Data: generateDataSeriesFromData(reads, nil, nil, nil), Picture: steadySailor.PictureUrl, LastSync: steadySailor.MostRecentRead.GetTime()}
		writeAsJson(writer, response)
	}
}

// writeAsJson writes a DataResponse with its set of GlucoseReads, Injections, Meals and Exercises as json. This is what is called from the javascript
// front-end to get the data.
func writeAsJson(writer http.ResponseWriter, response DataResponse) {
	enc := json.NewEncoder(writer)
	enc.Encode(response)
}

func generateDataSeriesFromData(reads []apimodel.GlucoseRead, injections []apimodel.Injection, carbs []apimodel.Meal, exercises []apimodel.Exercise) (dataSeries []DataSeries) {
	data := make([]DataSeries, 1)

	data[0] = DataSeries{"GlucoseReads", apimodel.GlucoseReadSlice(reads).ToDataPointSlice(), "GlucoseReads"}
	var userEvents []apimodel.DataPoint
	if injections != nil {
		userEvents = apimodel.MergeDataPointArrays(userEvents, apimodel.InjectionSlice(injections).ToDataPointSlice(reads))
	}

	if carbs != nil {
		userEvents = apimodel.MergeDataPointArrays(userEvents, apimodel.MealSlice(carbs).ToDataPointSlice(reads))
	}

	// TODO: clean up exercise from all the app or restore it. We won't be using it at the moment as we don't think the exercise data
	// from the dexcom is good enough
	// if exercises != nil {
	// 	userEvents = apimodel.MergeDataPointArrays(userEvents, apimodel.ExerciseSlice(exercises).ToDataPointSlice(reads))
	// }

	sort.Sort(apimodel.DataPointSlice(userEvents))

	data = append(data, DataSeries{"UserEvents", userEvents, "UserEvents"})

	return data
}

// dashboard renders the dashboard statistics as json
func dashboard(writer http.ResponseWriter, request *http.Request) {
	context := appengine.NewContext(request)
	user := user.Current(context)

	dashboardDataForUser(writer, request, user.Email)
}

// demodashboard renders the dashboard statistics as json for the demo user
func demoDashboard(writer http.ResponseWriter, request *http.Request) {
	dashboardDataForUser(writer, request, DEMO_EMAIL)
}

// dashboardDataForUser retrieves reads and generates dashboard statistics from them
func dashboardDataForUser(writer http.ResponseWriter, request *http.Request, email string) {
	context := appengine.NewContext(request)

	userProfile, _, upperBound, err := store.GetUserData(context, email)
	lowerBound := util.GetEndOfDayBoundaryBefore(upperBound).Add(time.Duration(-1*24) * time.Hour)

	if err != nil && err == store.ErrNoImportedDataFound {
		context.Debugf("No imported data found for user [%s]", email)
		http.Error(writer, err.Error(), 204)
	} else if err != nil {
		util.Propagate(err)
	} else {
		reads, err := store.GetGlucoseReads(context, email, lowerBound, upperBound)
		if err != nil {
			util.Propagate(err)
		}

		writeDashboardDataAsJson(writer, request, reads, userProfile)
	}
}

// writedashboardDataAsJson calculates dashboard statistics from an array of GlucoseReads and writes it
// as json
func writeDashboardDataAsJson(writer http.ResponseWriter, request *http.Request, reads []apimodel.GlucoseRead, userProfile *model.GlukitUser) {
	context := appengine.NewContext(request)
	value := writer.Header()
	value.Add("Content-type", "application/json")

	var dashboardData model.DashboardData
	if len(reads) > 0 {
		sort.Sort(model.ReadStatsSlice(reads))
		dashboardData.FirstName = userProfile.FirstName
		dashboardData.LastName = userProfile.LastName
		dashboardData.Picture = userProfile.PictureUrl
		dashboardData.LastSync = userProfile.MostRecentRead.GetTime()
		dashboardData.Average = stat.Mean(model.ReadStatsSlice(reads))
		dashboardData.High, _ = stat.Max(model.ReadStatsSlice(reads))
		dashboardData.Low, _ = stat.Min(model.ReadStatsSlice(reads))
		dashboardData.Median = stat.MedianFromSortedData(model.ReadStatsSlice(reads))
		dashboardData.Score = engine.CalculateUserFacingScore(userProfile.MostRecentScore)
		dashboardData.ScoreDetails = userProfile.MostRecentScore
		dashboardData.JoinedOn = userProfile.AccountCreated
		context.Debugf("Calculated user score of [%d] from internal score of [%d]", dashboardData.Score, userProfile.MostRecentScore.Value)
	}

	enc := json.NewEncoder(writer)
	enc.Encode(dashboardData)
}

func glukitScores(writer http.ResponseWriter, request *http.Request) {
	context := appengine.NewContext(request)
	user := user.Current(context)

	glukitScoresForEmail(writer, request, user.Email)
}

func glukitScoresForDemo(writer http.ResponseWriter, request *http.Request) {
	glukitScoresForEmail(writer, request, DEMO_EMAIL)
}

// glukitScoresForEmail is the endpoint to retrieve a list of glukitscores.
func glukitScoresForEmail(writer http.ResponseWriter, request *http.Request, email string) {
	context := appengine.NewContext(request)

	limit := request.FormValue(QUERY_PARAM_LIMIT)
	fromTimestamp := request.FormValue(QUERY_PARAM_FROM)
	toTimestamp := request.FormValue(QUERY_PARAM_TO)

	// The request must include at least one of from/to/limit to be considered valid
	// as leaving it too open would could open the door for costly queries
	if len(limit) == 0 && len(fromTimestamp) == 0 && len(toTimestamp) == 0 {
		http.Error(writer, fmt.Sprintf("Query must specify at least one of: %s, %s or %s.",
			QUERY_PARAM_LIMIT, QUERY_PARAM_FROM, QUERY_PARAM_TO), 400)
		return
	}

	var scanQuery store.GlukitScoreScanQuery
	if len(limit) > 0 {
		if limitValue, err := strconv.ParseInt(limit, 10, 32); err != nil {
			http.Error(writer, fmt.Sprintf("Invalid value for %s: [%v].", QUERY_PARAM_LIMIT, err), 400)
			return
		} else {
			limitVal := int(limitValue)
			scanQuery.Limit = &limitVal
		}
	}

	if len(fromTimestamp) > 0 {
		if fromValue, err := strconv.ParseInt(fromTimestamp, 10, 64); err != nil {
			http.Error(writer, fmt.Sprintf("Invalid value for %s: [%v].", QUERY_PARAM_FROM, err), 400)
			return
		} else {
			fromTime := time.Unix(fromValue, 0)
			scanQuery.From = &fromTime
		}
	}

	if len(toTimestamp) > 0 {
		if toValue, err := strconv.ParseInt(toTimestamp, 10, 64); err != nil {
			http.Error(writer, fmt.Sprintf("Invalid value for %s: [%v].", QUERY_PARAM_TO, err), 400)
			return
		} else {
			toTime := time.Unix(toValue, 0)
			scanQuery.To = &toTime
		}
	}

	glukitScores, err := store.GetGlukitScores(context, email, scanQuery)
	if err != nil {
		util.Propagate(err)
	}

	if len(glukitScores) < 1 {
		http.Error(writer, "No glukit scores calculated yet.", 204)
		return
	}

	value := writer.Header()
	value.Add("Content-type", "application/json")

	enc := json.NewEncoder(writer)
	enc.Encode(glukitScores)

}
<|endoftext|>


<commit_before>package gaestatic

import (
	"strings"
	"os"
	"fmt"
	"strconv"
	"io"
	"net/http"
	"google.golang.org/appengine/file"
	"html/template"
	"bytes"
)

const PLIST_TEMPLATE string = `
<?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
        <dict>
            <key>items</key>
            <array>
                <dict>
                    <key>assets</key>
                    <array>
                        {{if .IpaUrl}}
                        <dict>
                            <key>kind</key>
                            <string>software-package</string>
                            <key>url</key>
                            <string>{{.IpaUrl}}</string>
                        </dict>
                        {{end}}
                        {{if .DisplayImageUrl}}
                        <dict>
                            <key>kind</key>
                            <string>display-image</string>
                            <key>url</key>
                            <string>{{.DisplayImageUrl}}</string>
                        </dict>
                        {{end}}
                        {{if .FullSizeImageUrl}}
                        <dict>
                            <key>kind</key>
                            <string>full-size-image</string>
                            <key>url</key>
                            <string>{{.FullSizeImageUrl}}</string>
                        </dict>
                        {{end}}
                    </array>
                    <key>metadata</key>
                    <dict>
                        {{if .BundleIdentifer}}
                        <key>bundle-identifier</key>
                        <string>{{.BundleIdentifer}}</string>
                        {{end}}
                        {{if .BundleVersion}}
                        <key>bundle-version</key>
                        <string>{{.BundleVersion}}</string>
                        <key>kind</key>
                        {{end}}
                        {{if .Title}}
                        <string>software</string>
                        <key>title</key>
                        <string>{{.Title}}</string>
                        {{end}}
                    </dict>
                </dict>
            </array>
        </dict>
    </plist>
`

type PlistTemplateParams struct {
	// eg. https://example.com/apps/ios/sample.ipa
	IpaUrl string
	// eg. https://example.com/apps/ios/image.png
	DisplayImageUrl string
	// eg. https://example.com/apps/ios/full-image.png
	FullSizeImageUrl string
	// eg. com.example.sample
	BundleIdentifer string
	// eg. 1.0
	BundleVersion string
	// eg. Sample App
	Title string
}

/**
 * Dynamic Plist Handler
 */
func plistHandler(w http.ResponseWriter, r *http.Request) bool {
	var filePath string

	fileConfig := config.FileConfig

	isDone := true

	config := GetAppConfig()
	if config == nil {
		// Internal Server Errror
		w.WriteHeader(500)
		w.Write([]byte("No Config"))
		return isDone
	}

	filePath = strings.Replace(r.URL.Path, config.PubDir, fileConfig.PubPath, -1)

	params := PlistTemplateParams{}

	params.BundleIdentifer = "com.example.sample"

	tmpl, err := template.New("plist").Parse(PLIST_TEMPLATE)

	if err != nil {
		// Not Found
		w.WriteHeader(501)
		w.Write([]byte(fmt.Sprintf("plist template is invalid.")))
		return isDone
	}

	writer := new(bytes.Buffer)
	err	= tmpl.Execute(writer, params)

	var contentLength string
	if err != nil {
		// Forbidden : サイズ取得失敗
		w.WriteHeader(403)
		w.Write([]byte(fmt.Sprintf("plist params is invalid.")))
		return isDone
	} else {
		contentLength = strconv.FormatInt(int64(writer.Len()), 10)
	}
	contentLength = contentLength + "bytes"

	contentType := GetContentType(filePath)
	if contentType != "" {
		w.Header().Set("Content-Type", contentType)
	}
	w.Write(writer.Bytes())
	isDone = true
	return isDone
}
<commit_msg>dynamic plist : snapshot<commit_after>package gaestatic

import (
	"strings"
	"fmt"
	"strconv"
	"net/http"
	"html/template"
	"bytes"
)

const PLIST_TEMPLATE string = `
<?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
        <dict>
            <key>items</key>
            <array>
                <dict>
                    <key>assets</key>
                    <array>
                        {{if .IpaUrl}}
                        <dict>
                            <key>kind</key>
                            <string>software-package</string>
                            <key>url</key>
                            <string>{{.IpaUrl}}</string>
                        </dict>
                        {{end}}
                        {{if .DisplayImageUrl}}
                        <dict>
                            <key>kind</key>
                            <string>display-image</string>
                            <key>url</key>
                            <string>{{.DisplayImageUrl}}</string>
                        </dict>
                        {{end}}
                        {{if .FullSizeImageUrl}}
                        <dict>
                            <key>kind</key>
                            <string>full-size-image</string>
                            <key>url</key>
                            <string>{{.FullSizeImageUrl}}</string>
                        </dict>
                        {{end}}
                    </array>
                    <key>metadata</key>
                    <dict>
                        {{if .BundleIdentifer}}
                        <key>bundle-identifier</key>
                        <string>{{.BundleIdentifer}}</string>
                        {{end}}
                        {{if .BundleVersion}}
                        <key>bundle-version</key>
                        <string>{{.BundleVersion}}</string>
                        <key>kind</key>
                        {{end}}
                        {{if .Title}}
                        <string>software</string>
                        <key>title</key>
                        <string>{{.Title}}</string>
                        {{end}}
                    </dict>
                </dict>
            </array>
        </dict>
    </plist>
`

type PlistTemplateParams struct {
	// eg. https://example.com/apps/ios/sample.ipa
	IpaUrl string
	// eg. https://example.com/apps/ios/image.png
	DisplayImageUrl string
	// eg. https://example.com/apps/ios/full-image.png
	FullSizeImageUrl string
	// eg. com.example.sample
	BundleIdentifer string
	// eg. 1.0
	BundleVersion string
	// eg. Sample App
	Title string
}

/**
 * Dynamic Plist Handler
 */
func plistHandler(w http.ResponseWriter, r *http.Request) bool {
	var filePath string

	fileConfig := config.FileConfig

	isDone := true

	config := GetAppConfig()
	if config == nil {
		// Internal Server Errror
		w.WriteHeader(500)
		w.Write([]byte("No Config"))
		return isDone
	}

	filePath = strings.Replace(r.URL.Path, config.PubDir, fileConfig.PubPath, -1)

	params := PlistTemplateParams{}

	params.BundleIdentifer = "com.example.sample"

	tmpl, err := template.New("plist").Parse(PLIST_TEMPLATE)

	if err != nil {
		// Not Found
		w.WriteHeader(501)
		w.Write([]byte(fmt.Sprintf("plist template is invalid.")))
		return isDone
	}

	writer := new(bytes.Buffer)
	err	= tmpl.Execute(writer, params)

	var contentLength string
	if err != nil {
		// Forbidden : サイズ取得失敗
		w.WriteHeader(403)
		w.Write([]byte(fmt.Sprintf("plist params is invalid.")))
		return isDone
	} else {
		contentLength = strconv.FormatInt(int64(writer.Len()), 10)
	}
	contentLength = contentLength + "bytes"

	contentType := GetContentType(filePath)
	if contentType != "" {
		w.Header().Set("Content-Type", contentType)
	}
	w.Write(writer.Bytes())
	isDone = true
	return isDone
}
<|endoftext|>


<commit_before>// +build ignore

// Enumerate unique keys from key/values found in the whois responses.
// To use: go run enumerate.go

package main

import (
	"bufio"
	"flag"
	"fmt"
	"os"
	"regexp"

	"github.com/domainr/whois"
	"github.com/domainr/whoistest"
)

func main() {
	flag.Parse()
	if err := main1(); err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}

func main1() error {
	fns, err := whoistest.ResponseFiles()
	if err != nil {
		return err
	}
	for _, fn := range fns {
		res, err := whois.ReadMIMEFile(fn)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error reading response file %s: %s\n", fn, err)
			continue
		}
		if res.MediaType != "text/plain" {
			continue
		}
		scan(res)
	}
	return nil
}

var (
	reEmptyLine      = regexp.MustCompile(`^\s*$`)
	reElement   = regexp.MustCompile(`^\s*([^\:]*\S)\s*\:\s*(.*\S)\s*$`)
	reElementB = regexp.MustCompile(`^\s*\[([^\]]+)\]\s*(.*\S)\s*$`)

	jpNotice = `^\[ .+ \]$`
	deNotice = `^% .*$`
	updated  = `^<<<.+>>>$`
	reNotice   = regexp.MustCompile(jpNotice + "|" + deNotice + "|" + updated)
)

func scan(res *whois.Response) {
	r, err := res.Reader()
	if err != nil {
		return
	}
	line := 0
	s := bufio.NewScanner(r)
	for s.Scan() {
		line++
		text := s.Text()

		if reEmptyLine.MatchString(text) {
			fmt.Printf("% 4d  EMPTY\n", line)
			continue
		}

		if m := reNotice.FindStringSubmatch(text); m != nil {
			fmt.Printf("% 4d  %- 20s  %s\n", line, "NOTICE", m[0])
			continue
		}

		if m := reElementB.FindStringSubmatch(text); m != nil {
			fmt.Printf("% 4d  %- 20s  %- 30s %s\n", line, "B ELEMENT", m[1], m[2])
			continue
		}

		if m := reElement.FindStringSubmatch(text); m != nil {
			fmt.Printf("% 4d  %- 20s  %- 30s %s\n", line, "ELEMENT", m[1], m[2])
			continue
		}

		fmt.Fprintf(os.Stderr, "% 4d  %- 20s  %s\n", line, "UNKNOWN", text)
	}
	fmt.Printf("\n")
}
<commit_msg>Element -> KeyValue<commit_after>// +build ignore

// Enumerate unique keys from key/values found in the whois responses.
// To use: go run enumerate.go

package main

import (
	"bufio"
	"flag"
	"fmt"
	"os"
	"regexp"

	"github.com/domainr/whois"
	"github.com/domainr/whoistest"
)

func main() {
	flag.Parse()
	if err := main1(); err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}

func main1() error {
	fns, err := whoistest.ResponseFiles()
	if err != nil {
		return err
	}
	for _, fn := range fns {
		res, err := whois.ReadMIMEFile(fn)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error reading response file %s: %s\n", fn, err)
			continue
		}
		if res.MediaType != "text/plain" {
			continue
		}
		scan(res)
	}
	return nil
}

var (
	reEmptyLine   = regexp.MustCompile(`^\s*$`)
	reKeyValue    = regexp.MustCompile(`^\s*([^\:]*\S)\s*\:\s*(.*\S)\s*$`)
	reAltKeyValue = regexp.MustCompile(`^\s*\[([^\]]+)\]\s*(.*\S)\s*$`)
	jpNotice      = `^\[ .+ \]$`
	deNotice      = `^% .*$`
	updated       = `^<<<.+>>>$`
	reNotice      = regexp.MustCompile(jpNotice + "|" + deNotice + "|" + updated)
)

func scan(res *whois.Response) {
	r, err := res.Reader()
	if err != nil {
		return
	}
	line := 0
	s := bufio.NewScanner(r)
	for s.Scan() {
		line++
		text := s.Text()

		if reEmptyLine.MatchString(text) {
			fmt.Printf("% 4d  EMPTY\n", line)
			continue
		}

		if m := reNotice.FindStringSubmatch(text); m != nil {
			fmt.Printf("% 4d  %- 20s  %s\n", line, "NOTICE", m[0])
			continue
		}

		if m := reAltKeyValue.FindStringSubmatch(text); m != nil {
			fmt.Printf("% 4d  %- 20s  %- 30s %s\n", line, "ALT_KEY_VALUE", m[1], m[2])
			continue
		}

		if m := reKeyValue.FindStringSubmatch(text); m != nil {
			fmt.Printf("% 4d  %- 20s  %- 30s %s\n", line, "KEY_VALUE", m[1], m[2])
			continue
		}

		fmt.Fprintf(os.Stderr, "% 4d  %- 20s  %s\n", line, "UNKNOWN", text)
	}
	fmt.Printf("\n")
}
<|endoftext|>


<commit_before>// +build ignore

// Enumerate unique keys from key/values found in the whois responses.
// To use: go run enumerate.go

package main

import (
	"bufio"
	"flag"
	"fmt"
	"os"
	"regexp"
	"sort"
	"strings"

	"github.com/domainr/whois"
	"github.com/domainr/whoistest"
	"github.com/wsxiaoys/terminal/color"
)

var (
	keys = make(map[string]string)
)

func main() {
	flag.Parse()
	if err := main1(); err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}

func main1() error {
	wd, err := os.Getwd()
	if err != nil {
		return err
	}
	wd = wd + "/"

	fns, err := whoistest.ResponseFiles()
	if err != nil {
		return err
	}

	for _, fn := range fns {
		res, err := whois.ReadMIMEFile(fn)
		if err != nil {
			color.Fprintf(os.Stderr, "@{|r}Error reading response file %s: %s\n", fn, err)
			continue
		}
		if res.MediaType != "text/plain" {
			continue
		}
		color.Printf("@{|g}%s\n", strings.TrimPrefix(fn, wd))
		scan(res)
	}

	sorted := make([]string, 0, len(keys))
	for k, _ := range keys {
		sorted = append(sorted, k)
	}
	sort.Strings(sorted)

	for _, k := range sorted {
		color.Printf("@{|c}%- 40s  @{|.}%s\n", k, keys[k])
	}
	color.Printf("@{|w}%d unique keys found\n", len(keys))

	return nil
}

var (
	reEmptyLine   = regexp.MustCompile(`^\s*$`)
	reKey         = `([^,a-z\:\],][^\:\]]{0,39}\S|[a-z-]{3,40})`
	reBareKey     = regexp.MustCompile(`^\s*` + reKey + `\s*\:\s*$`)
	reKeyValue    = regexp.MustCompile(`^\s*` + reKey + `\s*\:\s*(.*\S)\s*$`)
	reAltKey      = regexp.MustCompile(`^\s*\[` + reKey + `\]\s*$`)
	reAltKeyValue = regexp.MustCompile(`^\s*\[` + reKey + `\]\s*(.*\S)\s*$`)
	reBareValue   = regexp.MustCompile(`^      \s+(.*\S)\s*$`)
	reNotice      = regexp.MustCompile(strings.Join([]string{
		`^%`,                // whois.de, whois.registro.br
		`^# `,               // whois.kr
		`^\[ .+ \]$`,        // whois.jprs.jp
		`^>>>.+<<<$`,        // Database last updated...
		`^[^\:]+https?\://`, // Line with an URL
		`^NOTE: |^NOTICE: |^TERMS OF USE: `,
	}, "|"))
)

func scan(res *whois.Response) {
	r, err := res.Reader()
	if err != nil {
		return
	}
	line := 0
	s := bufio.NewScanner(r)
	for s.Scan() {
		line++
		color.Printf("@{|.}% 4d  ", line)

		// Get next line
		text := s.Text()

		// Notices and empty lines
		if reEmptyLine.MatchString(text) {
			color.Printf("@{|w}EMPTY\n")
			continue
		}
		if m := reNotice.FindStringSubmatch(text); m != nil {
			color.Printf("@{|w}%- 16s  %s\n", "NOTICE", text)
			continue
		}

		// Keys and values
		if m := reAltKeyValue.FindStringSubmatch(text); m != nil {
			addKey(m[1], res.Host)
			color.Printf("@{|w}%- 16s  @{c}%- 40s @{w}%s\n", "ALT_KEY_VALUE", m[1], m[2])
			continue
		}
		if m := reAltKey.FindStringSubmatch(text); m != nil {
			addKey(m[1], res.Host)
			color.Printf("@{|w}%- 16s  @{c}%s\n", "BARE_ALT_KEY", m[1])
			continue
		}
		if m := reKeyValue.FindStringSubmatch(text); m != nil {
			addKey(m[1], res.Host)
			color.Printf("@{|w}%- 16s  @{c}%- 40s @{w}%s\n", "KEY_VALUE", m[1], m[2])
			continue
		}
		if m := reBareKey.FindStringSubmatch(text); m != nil {
			addKey(m[1], res.Host)
			color.Printf("@{|w}%- 16s  @{c}%s\n", "BARE_KEY", m[1])
			continue
		}
		if m := reBareValue.FindStringSubmatch(text); m != nil {
			color.Printf("@{|w}%- 16s  @{c}%- 40s @{w}%s\n", "BARE_VALUE", "", m[1])
			continue
		}

		// Unknown
		color.Printf("@{|.}%- 16s  @{|.}%s\n", "UNKNOWN", text)
	}

	fmt.Printf("\n")
}

func addKey(k, host string) string {
	k = transformKey(k)
	if _, ok := keys[k]; !ok {
		keys[k] = host
	} else if !strings.Contains(keys[k], host) {
		keys[k] = keys[k] + "  " + host
	}
	return k
}

var (
	reStrip = regexp.MustCompile(`[[:punct:]]`)
	reSpace = regexp.MustCompile(`\s+`)
)

func transformKey(k string) string {
	k = strings.ToUpper(k)
	k = reStrip.ReplaceAllLiteralString(k, " ")
	k = strings.TrimSpace(k)
	k = reSpace.ReplaceAllLiteralString(k, "_")
	return k
}
<commit_msg>bracketed [Keys] have no leading whitespace<commit_after>// +build ignore

// Enumerate unique keys from key/values found in the whois responses.
// To use: go run enumerate.go

package main

import (
	"bufio"
	"flag"
	"fmt"
	"os"
	"regexp"
	"sort"
	"strings"

	"github.com/domainr/whois"
	"github.com/domainr/whoistest"
	"github.com/wsxiaoys/terminal/color"
)

var (
	keys = make(map[string]string)
)

func main() {
	flag.Parse()
	if err := main1(); err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}

func main1() error {
	wd, err := os.Getwd()
	if err != nil {
		return err
	}
	wd = wd + "/"

	fns, err := whoistest.ResponseFiles()
	if err != nil {
		return err
	}

	for _, fn := range fns {
		res, err := whois.ReadMIMEFile(fn)
		if err != nil {
			color.Fprintf(os.Stderr, "@{|r}Error reading response file %s: %s\n", fn, err)
			continue
		}
		if res.MediaType != "text/plain" {
			continue
		}
		color.Printf("@{|g}%s\n", strings.TrimPrefix(fn, wd))
		scan(res)
	}

	sorted := make([]string, 0, len(keys))
	for k, _ := range keys {
		sorted = append(sorted, k)
	}
	sort.Strings(sorted)

	for _, k := range sorted {
		color.Printf("@{|c}%- 40s  @{|.}%s\n", k, keys[k])
	}
	color.Printf("@{|w}%d unique keys found\n", len(keys))

	return nil
}

var (
	reEmptyLine   = regexp.MustCompile(`^\s*$`)
	reKey         = `([^,a-z\:\],][^\:\]]{0,39}\S|[a-z-]{3,40})`
	reBareKey     = regexp.MustCompile(`^\s*` + reKey + `\s*\:\s*$`)
	reKeyValue    = regexp.MustCompile(`^\s*` + reKey + `\s*\:\s*(.*\S)\s*$`)
	reAltKey      = regexp.MustCompile(`^\[` + reKey + `\]\s*$`)
	reAltKeyValue = regexp.MustCompile(`^\[` + reKey + `\]\s*(.*\S)\s*$`)
	reBareValue   = regexp.MustCompile(`^      \s+(.*\S)\s*$`)
	reNotice      = regexp.MustCompile(strings.Join([]string{
		`^%`,                // whois.de, whois.registro.br
		`^# `,               // whois.kr
		`^\[ .+ \]$`,        // whois.jprs.jp
		`^>>>.+<<<$`,        // Database last updated...
		`^[^\:]+https?\://`, // Line with an URL
		`^NOTE: |^NOTICE: |^TERMS OF USE: `,
	}, "|"))
)

func scan(res *whois.Response) {
	r, err := res.Reader()
	if err != nil {
		return
	}
	line := 0
	s := bufio.NewScanner(r)
	for s.Scan() {
		line++
		color.Printf("@{|.}% 4d  ", line)

		// Get next line
		text := s.Text()

		// Notices and empty lines
		if reEmptyLine.MatchString(text) {
			color.Printf("@{|w}EMPTY\n")
			continue
		}
		if m := reNotice.FindStringSubmatch(text); m != nil {
			color.Printf("@{|w}%- 16s  %s\n", "NOTICE", text)
			continue
		}

		// Keys and values
		if m := reAltKeyValue.FindStringSubmatch(text); m != nil {
			addKey(m[1], res.Host)
			color.Printf("@{|w}%- 16s  @{c}%- 40s @{w}%s\n", "ALT_KEY_VALUE", m[1], m[2])
			continue
		}
		if m := reAltKey.FindStringSubmatch(text); m != nil {
			addKey(m[1], res.Host)
			color.Printf("@{|w}%- 16s  @{c}%s\n", "BARE_ALT_KEY", m[1])
			continue
		}
		if m := reKeyValue.FindStringSubmatch(text); m != nil {
			addKey(m[1], res.Host)
			color.Printf("@{|w}%- 16s  @{c}%- 40s @{w}%s\n", "KEY_VALUE", m[1], m[2])
			continue
		}
		if m := reBareKey.FindStringSubmatch(text); m != nil {
			addKey(m[1], res.Host)
			color.Printf("@{|w}%- 16s  @{c}%s\n", "BARE_KEY", m[1])
			continue
		}
		if m := reBareValue.FindStringSubmatch(text); m != nil {
			color.Printf("@{|w}%- 16s  @{c}%- 40s @{w}%s\n", "BARE_VALUE", "", m[1])
			continue
		}

		// Unknown
		color.Printf("@{|.}%- 16s  @{|.}%s\n", "UNKNOWN", text)
	}

	fmt.Printf("\n")
}

func addKey(k, host string) string {
	k = transformKey(k)
	if _, ok := keys[k]; !ok {
		keys[k] = host
	} else if !strings.Contains(keys[k], host) {
		keys[k] = keys[k] + "  " + host
	}
	return k
}

var (
	reStrip = regexp.MustCompile(`[[:punct:]]`)
	reSpace = regexp.MustCompile(`\s+`)
)

func transformKey(k string) string {
	k = strings.ToUpper(k)
	k = reStrip.ReplaceAllLiteralString(k, " ")
	k = strings.TrimSpace(k)
	k = reSpace.ReplaceAllLiteralString(k, "_")
	return k
}
<|endoftext|>


<commit_before>package main

import (
	"gform"
	"syscall"
	"w32"
)

const IDR_PNG1 = 100

func onpaint(arg *gform.EventArg) {
	if data, ok := arg.Data().(*gform.PaintEventData); ok {
		if bmp, err := gform.NewBitmapFromResource(
			gform.GetAppInstance(),
			w32.MakeIntResource(IDR_PNG1),
			syscall.StringToUTF16Ptr("PNG"),
			gform.RGB(255, 0, 0)); err == nil {
			data.Canvas.DrawBitmap(bmp, 10, 10)
			bmp.Dispose()
		} else {
			println(err.Error())
		}
	}
}

func main() {
	gform.Init()

	mf := gform.NewForm(nil)
	mf.SetSize(300, 200)
	mf.Center()

	mf.OnPaint().Bind(onpaint)

	mf.Show()

	gform.RunMainLoop()
}
<commit_msg>Update import path of gform and w32.<commit_after>package main

import (
	"syscall"
	"github.com/AllenDang/gform"
	"github.com/AllenDang/w32"
)

const IDR_PNG1 = 100

func onpaint(arg *gform.EventArg) {
	if data, ok := arg.Data().(*gform.PaintEventData); ok {
		if bmp, err := gform.NewBitmapFromResource(
			gform.GetAppInstance(),
			w32.MakeIntResource(IDR_PNG1),
			syscall.StringToUTF16Ptr("PNG"),
			gform.RGB(255, 0, 0)); err == nil {
			data.Canvas.DrawBitmap(bmp, 10, 10)
			bmp.Dispose()
		} else {
			println(err.Error())
		}
	}
}

func main() {
	gform.Init()

	mf := gform.NewForm(nil)
	mf.SetSize(300, 200)
	mf.Center()

	mf.OnPaint().Bind(onpaint)

	mf.Show()

	gform.RunMainLoop()
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"net/http"
	"os"

	"github.com/gorilla/mux"
	restlog "github.com/jroimartin/gorest/handlers/log"
	"github.com/jroimartin/gorest/server"
)

func main() {
	s := server.NewServer("localhost:8080")

	logger := log.New(os.Stdout, "[SERVER] ", log.LstdFlags)
	logHandler := server.M(restlog.NewLogHandler(logger,
		"{{.Req.RemoteAddr}} - {{.Req.Method}} {{.Req.RequestURI}}"))

	s.Route("/hello/{name}", server.H(http.HandlerFunc(helloHandler)), logHandler)
	s.Route("/test", server.H(http.HandlerFunc(testHandler)), logHandler)

	log.Fatalln(s.ListenAndServe())
}

func helloHandler(rw http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	fmt.Fprintln(rw, "Hello,", vars["name"])
}

func testHandler(rw http.ResponseWriter, r *http.Request) {
	rw.WriteHeader(http.StatusUnauthorized)
	fmt.Fprintln(rw, "401 unauthorized")
}
<commit_msg>Simplify example "simple.go"<commit_after>package main

import (
	"fmt"
	"log"
	"net/http"
	"os"

	"github.com/gorilla/mux"
	restlog "github.com/jroimartin/gorest/handlers/log"
	"github.com/jroimartin/gorest/server"
)

func main() {
	s := server.NewServer("localhost:8080")

	logger := log.New(os.Stdout, "[SERVER] ", log.LstdFlags)
	logHandler := server.M(restlog.NewLogHandler(logger,
		"{{.Req.RemoteAddr}} - {{.Req.Method}} {{.Req.RequestURI}}"))

	s.Route("/hello/{name}", server.H(http.HandlerFunc(helloHandler)), logHandler)

	log.Fatalln(s.ListenAndServe())
}

func helloHandler(rw http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	fmt.Fprintln(rw, "Hello,", vars["name"])
}
<|endoftext|>


<commit_before>// Package endpoints provides lookups for all AWS service endpoints.
package endpoints

import "strings"

type override struct {
	Service string
	Region  string
	URI     string
}

var overrides []override

// Lookup returns the endpoint for the given service in the given region plus
// any overrides for the service name and region.
func Lookup(service, region string) (uri, newService, newRegion string) {
	if override := findOverride(service, region); override != nil {
		return override.URI, override.Service, override.Region
	}

	switch service {

	case "cloudfront":

		if !strings.HasPrefix(region, "cn-") {
			return format("https://cloudfront.amazonaws.com", service, region), service, "us-east-1"
		}

	case "dynamodb":

		if region == "local" {
			return format("http://localhost:8000", service, region), "dynamodb", "us-east-1"
		}

	case "elasticmapreduce":

		if strings.HasPrefix(region, "cn-") {
			return format("https://elasticmapreduce.cn-north-1.amazonaws.com.cn", service, region), service, region
		}

		if region == "eu-central-1" {
			return format("https://elasticmapreduce.eu-central-1.amazonaws.com", service, region), service, region
		}

		if region == "us-east-1" {
			return format("https://elasticmapreduce.us-east-1.amazonaws.com", service, region), service, region
		}

		if region != "" {
			return format("https://{region}.elasticmapreduce.amazonaws.com", service, region), service, region
		}

	case "iam":

		if strings.HasPrefix(region, "cn-") {
			return format("https://{service}.cn-north-1.amazonaws.com.cn", service, region), service, region
		}

		if strings.HasPrefix(region, "us-gov") {
			return format("https://{service}.us-gov.amazonaws.com", service, region), service, region
		}

		return format("https://iam.amazonaws.com", service, region), service, "us-east-1"

	case "importexport":

		if !strings.HasPrefix(region, "cn-") {
			return format("https://importexport.amazonaws.com", service, region), service, region
		}

	case "rds":

		if region == "us-east-1" {
			return format("https://rds.amazonaws.com", service, region), service, region
		}

	case "route53":

		if !strings.HasPrefix(region, "cn-") {
			return format("https://route53.amazonaws.com", service, region), service, region
		}

	case "s3":

		if region == "us-east-1" || region == "" {
			return format("{scheme}://s3.amazonaws.com", service, region), service, "us-east-1"
		}

		if strings.HasPrefix(region, "cn-") {
			return format("{scheme}://{service}.{region}.amazonaws.com.cn", service, region), service, region
		}

		if region == "us-east-1" || region == "ap-northeast-1" || region == "sa-east-1" || region == "ap-southeast-1" || region == "ap-southeast-2" || region == "us-west-2" || region == "us-west-1" || region == "eu-west-1" || region == "us-gov-west-1" || region == "fips-us-gov-west-1" {
			return format("{scheme}://{service}-{region}.amazonaws.com", service, region), service, region
		}

		if region != "" {
			return format("{scheme}://{service}.{region}.amazonaws.com", service, region), service, region
		}

	case "sdb":

		if region == "us-east-1" {
			return format("https://sdb.amazonaws.com", service, region), service, region
		}

	case "sqs":

		if region == "us-east-1" {
			return format("https://queue.amazonaws.com", service, region), service, region
		}

		if strings.HasPrefix(region, "cn-") {
			return format("https://{region}.queue.amazonaws.com.cn", service, region), service, region
		}

		if region != "" {
			return format("https://{region}.queue.amazonaws.com", service, region), service, region
		}

	case "sts":

		if strings.HasPrefix(region, "cn-") {
			return format("{scheme}://{service}.cn-north-1.amazonaws.com.cn", service, region), service, region
		}

		if strings.HasPrefix(region, "us-gov") {
			return format("https://{service}.{region}.amazonaws.com", service, region), service, region
		}

		return format("https://sts.amazonaws.com", service, region), service, "us-east-1"

	}

	if strings.HasPrefix(region, "cn-") {
		return format("{scheme}://{service}.{region}.amazonaws.com.cn", service, region), service, region
	}

	if region != "" {
		return format("{scheme}://{service}.{region}.amazonaws.com", service, region), service, region
	}

	panic("unknown endpoint for " + service + " in " + region)
}

/*
AddOverride overrides the endpoint for a specific service, using either an
existing region name or a fake one (e.g. "test-1").
This allows developers to use local mock AWS services when they're
writing tests for their Go code that uses aws-go.

		endpoints.AddOverride("EC2", "test-1", "http://localhost:3000")

		// This EC2 client uses the override as service endpoint.
		cli := ec2.New(credentials, "test-1", nil)

*/
func AddOverride(service, region, uri string) {
	overrides = append(overrides, override{service, region, uri})
}

func format(uri, service, region string) string {
	uri = strings.Replace(uri, "{scheme}", "https", -1)
	uri = strings.Replace(uri, "{service}", service, -1)
	uri = strings.Replace(uri, "{region}", region, -1)
	return uri
}

func findOverride(service, region string) *override {
	for _, override := range overrides {
		if strings.ToUpper(override.Service) == strings.ToUpper(service) && override.Region == region {
			return &override
		}
	}

	return nil
}
<commit_msg>Revert "Add support for service endpoint overrides"<commit_after>// Package endpoints provides lookups for all AWS service endpoints.
package endpoints

import (
	"strings"
)

// Lookup returns the endpoint for the given service in the given region plus
// any overrides for the service name and region.
func Lookup(service, region string) (uri, newService, newRegion string) {
	switch service {

	case "cloudfront":

		if !strings.HasPrefix(region, "cn-") {
			return format("https://cloudfront.amazonaws.com", service, region), service, "us-east-1"
		}

	case "dynamodb":

		if region == "local" {
			return format("http://localhost:8000", service, region), "dynamodb", "us-east-1"
		}

	case "elasticmapreduce":

		if strings.HasPrefix(region, "cn-") {
			return format("https://elasticmapreduce.cn-north-1.amazonaws.com.cn", service, region), service, region
		}

		if region == "eu-central-1" {
			return format("https://elasticmapreduce.eu-central-1.amazonaws.com", service, region), service, region
		}

		if region == "us-east-1" {
			return format("https://elasticmapreduce.us-east-1.amazonaws.com", service, region), service, region
		}

		if region != "" {
			return format("https://{region}.elasticmapreduce.amazonaws.com", service, region), service, region
		}

	case "iam":

		if strings.HasPrefix(region, "cn-") {
			return format("https://{service}.cn-north-1.amazonaws.com.cn", service, region), service, region
		}

		if strings.HasPrefix(region, "us-gov") {
			return format("https://{service}.us-gov.amazonaws.com", service, region), service, region
		}

		return format("https://iam.amazonaws.com", service, region), service, "us-east-1"

	case "importexport":

		if !strings.HasPrefix(region, "cn-") {
			return format("https://importexport.amazonaws.com", service, region), service, region
		}

	case "rds":

		if region == "us-east-1" {
			return format("https://rds.amazonaws.com", service, region), service, region
		}

	case "route53":

		if !strings.HasPrefix(region, "cn-") {
			return format("https://route53.amazonaws.com", service, region), service, region
		}

	case "s3":

		if region == "us-east-1" || region == "" {
			return format("{scheme}://s3.amazonaws.com", service, region), service, "us-east-1"
		}

		if strings.HasPrefix(region, "cn-") {
			return format("{scheme}://{service}.{region}.amazonaws.com.cn", service, region), service, region
		}

		if region == "us-east-1" || region == "ap-northeast-1" || region == "sa-east-1" || region == "ap-southeast-1" || region == "ap-southeast-2" || region == "us-west-2" || region == "us-west-1" || region == "eu-west-1" || region == "us-gov-west-1" || region == "fips-us-gov-west-1" {
			return format("{scheme}://{service}-{region}.amazonaws.com", service, region), service, region
		}

		if region != "" {
			return format("{scheme}://{service}.{region}.amazonaws.com", service, region), service, region
		}

	case "sdb":

		if region == "us-east-1" {
			return format("https://sdb.amazonaws.com", service, region), service, region
		}

	case "sqs":

		if region == "us-east-1" {
			return format("https://queue.amazonaws.com", service, region), service, region
		}

		if strings.HasPrefix(region, "cn-") {
			return format("https://{region}.queue.amazonaws.com.cn", service, region), service, region
		}

		if region != "" {
			return format("https://{region}.queue.amazonaws.com", service, region), service, region
		}

	case "sts":

		if strings.HasPrefix(region, "cn-") {
			return format("{scheme}://{service}.cn-north-1.amazonaws.com.cn", service, region), service, region
		}

		if strings.HasPrefix(region, "us-gov") {
			return format("https://{service}.{region}.amazonaws.com", service, region), service, region
		}

		return format("https://sts.amazonaws.com", service, region), service, "us-east-1"

	}

	if strings.HasPrefix(region, "cn-") {
		return format("{scheme}://{service}.{region}.amazonaws.com.cn", service, region), service, region
	}

	if region != "" {
		return format("{scheme}://{service}.{region}.amazonaws.com", service, region), service, region
	}

	panic("unknown endpoint for " + service + " in " + region)
}

func format(uri, service, region string) string {
	uri = strings.Replace(uri, "{scheme}", "https", -1)
	uri = strings.Replace(uri, "{service}", service, -1)
	uri = strings.Replace(uri, "{region}", region, -1)
	return uri
}
<|endoftext|>


<commit_before>package generator

import (
	"testing"

	_ "github.com/kr/pretty"
	"github.com/mhamrah/gql/parser"
	"github.com/stretchr/testify/assert"
)

const simpleSchema = `
	schema {
		query: MyQueryRootType
		mutation: MyMutationRootType
	}

	type MyQueryRootType {
		someField: String
	}

	type MyMutationRootType {
		setSomeField(to: String): String
	}
`

const defaultSchema = `
	type Query {
		someField: String
	}`

func TestGenerateDefaultSchema(t *testing.T) {
	ast, err := parser.ParseString(defaultSchema)

	assert.NoError(t, err)
	assert.NotNil(t, ast)

	result, err := Generate(&ast.Schema, "test")
	assert.NoError(t, err)
	assert.NotNil(t, result)
}
<commit_msg>rename genrator<commit_after><|endoftext|>


<commit_before>package builds

import (
	"fmt"

	g "github.com/onsi/ginkgo"
	o "github.com/onsi/gomega"

	exutil "github.com/openshift/origin/test/extended/util"
)

var _ = g.Describe("[builds] build have source revision metadata", func() {
	defer g.GinkgoRecover()
	var (
		buildFixture = exutil.FixturePath("..", "extended", "fixtures", "test-build-revision.json")
		oc           = exutil.NewCLI("cli-build-revision", exutil.KubeConfigPath())
	)

	g.JustBeforeEach(func() {
		g.By("waiting for builder service account")
		err := exutil.WaitForBuilderAccount(oc.KubeREST().ServiceAccounts(oc.Namespace()))
		o.Expect(err).NotTo(o.HaveOccurred())
		oc.Run("create").Args("-f", buildFixture).Execute()
	})

	g.Describe("started build", func() {
		g.It("should contain source revision information", func() {
			g.By("starting the build with --wait flag")
			out, err := oc.Run("start-build").Args("sample-build", "--wait").Output()
			o.Expect(err).NotTo(o.HaveOccurred())

			g.By(fmt.Sprintf("verifying the build %q status", out))
			build, err := oc.REST().Builds(oc.Namespace()).Get(out)
			o.Expect(err).NotTo(o.HaveOccurred())
			o.Expect(build.Spec.Revision).NotTo(o.BeNil())
			o.Expect(build.Spec.Revision.Git).NotTo(o.BeNil())
			o.Expect(build.Spec.Revision.Git.Commit).NotTo(o.BeEmpty())
			o.Expect(build.Spec.Revision.Git.Author.Name).NotTo(o.BeEmpty())
			o.Expect(build.Spec.Revision.Git.Committer.Name).NotTo(o.BeEmpty())
			o.Expect(build.Spec.Revision.Git.Message).NotTo(o.BeEmpty())
		})
	})
})
<commit_msg>hardcode build name to expect instead of getting it from start-build output<commit_after>package builds

import (
	"fmt"

	g "github.com/onsi/ginkgo"
	o "github.com/onsi/gomega"

	exutil "github.com/openshift/origin/test/extended/util"
)

var _ = g.Describe("[builds] build have source revision metadata", func() {
	defer g.GinkgoRecover()
	var (
		buildFixture = exutil.FixturePath("..", "extended", "fixtures", "test-build-revision.json")
		oc           = exutil.NewCLI("cli-build-revision", exutil.KubeConfigPath())
	)

	g.JustBeforeEach(func() {
		g.By("waiting for builder service account")
		err := exutil.WaitForBuilderAccount(oc.KubeREST().ServiceAccounts(oc.Namespace()))
		o.Expect(err).NotTo(o.HaveOccurred())
		oc.Run("create").Args("-f", buildFixture).Execute()
	})

	g.Describe("started build", func() {
		g.It("should contain source revision information", func() {
			g.By("starting the build with --wait flag")
			err := oc.Run("start-build").Args("sample-build", "--wait").Execute()
			o.Expect(err).NotTo(o.HaveOccurred())

			g.By(fmt.Sprintf("verifying the build %q status", "sample-build-1"))
			build, err := oc.REST().Builds(oc.Namespace()).Get("sample-build-1")
			o.Expect(err).NotTo(o.HaveOccurred())
			o.Expect(build.Spec.Revision).NotTo(o.BeNil())
			o.Expect(build.Spec.Revision.Git).NotTo(o.BeNil())
			o.Expect(build.Spec.Revision.Git.Commit).NotTo(o.BeEmpty())
			o.Expect(build.Spec.Revision.Git.Author.Name).NotTo(o.BeEmpty())
			o.Expect(build.Spec.Revision.Git.Committer.Name).NotTo(o.BeEmpty())
			o.Expect(build.Spec.Revision.Git.Message).NotTo(o.BeEmpty())
		})
	})
})
<|endoftext|>