<commit_before>/*
Copyright 2018 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 commands

import (
	"fmt"
	"io"
	"strconv"
	"strings"

	"github.com/spf13/cobra"
	"k8s.io/apimachinery/pkg/util/validation/field"

	"k8s.io/kops/cmd/kops/util"
	api "k8s.io/kops/pkg/apis/kops"
	"k8s.io/kops/pkg/featureflag"
)

type SetClusterOptions struct {
	Fields      []string
	ClusterName string
}

// RunSetCluster implements the set cluster command logic
func RunSetCluster(f *util.Factory, cmd *cobra.Command, out io.Writer, options *SetClusterOptions) error {
	if !featureflag.SpecOverrideFlag.Enabled() {
		return fmt.Errorf("set cluster command is current feature gated; set `export KOPS_FEATURE_FLAGS=SpecOverrideFlag`")
	}

	if options.ClusterName == "" {
		return field.Required(field.NewPath("ClusterName"), "Cluster name is required")
	}

	clientset, err := f.Clientset()
	if err != nil {
		return err
	}

	cluster, err := clientset.GetCluster(options.ClusterName)
	if err != nil {
		return err
	}

	instanceGroups, err := ReadAllInstanceGroups(clientset, cluster)
	if err != nil {
		return err
	}

	if err := SetClusterFields(options.Fields, cluster, instanceGroups); err != nil {
		return err
	}

	if err := UpdateCluster(clientset, cluster, instanceGroups); err != nil {
		return err
	}

	return nil
}

// SetClusterFields sets field values in the cluster
func SetClusterFields(fields []string, cluster *api.Cluster, instanceGroups []*api.InstanceGroup) error {
	for _, field := range fields {
		kv := strings.SplitN(field, "=", 2)
		if len(kv) != 2 {
			return fmt.Errorf("unhandled field: %q", field)
		}

		// For now we have hard-code the values we want to support; we'll get test coverage and then do this properly...
		switch kv[0] {
		case "spec.kubelet.authorizationMode":
			cluster.Spec.Kubelet.AuthorizationMode = kv[1]
		case "spec.kubelet.authenticationTokenWebhook":
			v, err := strconv.ParseBool(kv[1])
			if err != nil {
				return fmt.Errorf("unknown boolean value: %q", kv[1])
			}
			cluster.Spec.Kubelet.AuthenticationTokenWebhook = &v
		case "cluster.spec.nodePortAccess":
			cluster.Spec.NodePortAccess = append(cluster.Spec.NodePortAccess, kv[1])
		case "spec.kubernetesVersion":
			cluster.Spec.KubernetesVersion = kv[1]
		case "spec.masterPublicName":
			cluster.Spec.masterPublicName = kv[1]
		case "cluster.spec.etcdClusters[*].enableEtcdTLS":
			v, err := strconv.ParseBool(kv[1])
			if err != nil {
				return fmt.Errorf("unknown boolean value: %q", kv[1])
			}
			for _, c := range cluster.Spec.EtcdClusters {
				c.EnableEtcdTLS = v
			}
		case "cluster.spec.etcdClusters[*].enableTLSAuth":
			v, err := strconv.ParseBool(kv[1])
			if err != nil {
				return fmt.Errorf("unknown boolean value: %q", kv[1])
			}
			for _, c := range cluster.Spec.EtcdClusters {
				c.EnableTLSAuth = v
			}
		case "cluster.spec.etcdClusters[*].version":
			for _, c := range cluster.Spec.EtcdClusters {
				c.Version = kv[1]
			}
		case "cluster.spec.etcdClusters[*].provider":
			p, err := toEtcdProviderType(kv[1])
			if err != nil {
				return err
			}
			for _, etcd := range cluster.Spec.EtcdClusters {
				etcd.Provider = p
			}
		case "cluster.spec.etcdClusters[*].manager.image":
			for _, etcd := range cluster.Spec.EtcdClusters {
				if etcd.Manager == nil {
					etcd.Manager = &api.EtcdManagerSpec{}
				}
				etcd.Manager.Image = kv[1]
			}
		default:
			return fmt.Errorf("unhandled field: %q", field)
		}
	}
	return nil
}

func toEtcdProviderType(in string) (api.EtcdProviderType, error) {
	s := strings.ToLower(in)
	switch s {
	case "legacy":
		return api.EtcdProviderTypeLegacy, nil
	case "manager":
		return api.EtcdProviderTypeManager, nil
	default:
		return api.EtcdProviderTypeManager, fmt.Errorf("unknown etcd provider type %q", in)
	}
}
<commit_msg>fixes typo - s/(Spec.)m(asterPublicName)/$1M$2/<commit_after>/*
Copyright 2018 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 commands

import (
	"fmt"
	"io"
	"strconv"
	"strings"

	"github.com/spf13/cobra"
	"k8s.io/apimachinery/pkg/util/validation/field"

	"k8s.io/kops/cmd/kops/util"
	api "k8s.io/kops/pkg/apis/kops"
	"k8s.io/kops/pkg/featureflag"
)

type SetClusterOptions struct {
	Fields      []string
	ClusterName string
}

// RunSetCluster implements the set cluster command logic
func RunSetCluster(f *util.Factory, cmd *cobra.Command, out io.Writer, options *SetClusterOptions) error {
	if !featureflag.SpecOverrideFlag.Enabled() {
		return fmt.Errorf("set cluster command is current feature gated; set `export KOPS_FEATURE_FLAGS=SpecOverrideFlag`")
	}

	if options.ClusterName == "" {
		return field.Required(field.NewPath("ClusterName"), "Cluster name is required")
	}

	clientset, err := f.Clientset()
	if err != nil {
		return err
	}

	cluster, err := clientset.GetCluster(options.ClusterName)
	if err != nil {
		return err
	}

	instanceGroups, err := ReadAllInstanceGroups(clientset, cluster)
	if err != nil {
		return err
	}

	if err := SetClusterFields(options.Fields, cluster, instanceGroups); err != nil {
		return err
	}

	if err := UpdateCluster(clientset, cluster, instanceGroups); err != nil {
		return err
	}

	return nil
}

// SetClusterFields sets field values in the cluster
func SetClusterFields(fields []string, cluster *api.Cluster, instanceGroups []*api.InstanceGroup) error {
	for _, field := range fields {
		kv := strings.SplitN(field, "=", 2)
		if len(kv) != 2 {
			return fmt.Errorf("unhandled field: %q", field)
		}

		// For now we have hard-code the values we want to support; we'll get test coverage and then do this properly...
		switch kv[0] {
		case "spec.kubelet.authorizationMode":
			cluster.Spec.Kubelet.AuthorizationMode = kv[1]
		case "spec.kubelet.authenticationTokenWebhook":
			v, err := strconv.ParseBool(kv[1])
			if err != nil {
				return fmt.Errorf("unknown boolean value: %q", kv[1])
			}
			cluster.Spec.Kubelet.AuthenticationTokenWebhook = &v
		case "cluster.spec.nodePortAccess":
			cluster.Spec.NodePortAccess = append(cluster.Spec.NodePortAccess, kv[1])
		case "spec.kubernetesVersion":
			cluster.Spec.KubernetesVersion = kv[1]
		case "spec.masterPublicName":
			cluster.Spec.MasterPublicName = kv[1]
		case "cluster.spec.etcdClusters[*].enableEtcdTLS":
			v, err := strconv.ParseBool(kv[1])
			if err != nil {
				return fmt.Errorf("unknown boolean value: %q", kv[1])
			}
			for _, c := range cluster.Spec.EtcdClusters {
				c.EnableEtcdTLS = v
			}
		case "cluster.spec.etcdClusters[*].enableTLSAuth":
			v, err := strconv.ParseBool(kv[1])
			if err != nil {
				return fmt.Errorf("unknown boolean value: %q", kv[1])
			}
			for _, c := range cluster.Spec.EtcdClusters {
				c.EnableTLSAuth = v
			}
		case "cluster.spec.etcdClusters[*].version":
			for _, c := range cluster.Spec.EtcdClusters {
				c.Version = kv[1]
			}
		case "cluster.spec.etcdClusters[*].provider":
			p, err := toEtcdProviderType(kv[1])
			if err != nil {
				return err
			}
			for _, etcd := range cluster.Spec.EtcdClusters {
				etcd.Provider = p
			}
		case "cluster.spec.etcdClusters[*].manager.image":
			for _, etcd := range cluster.Spec.EtcdClusters {
				if etcd.Manager == nil {
					etcd.Manager = &api.EtcdManagerSpec{}
				}
				etcd.Manager.Image = kv[1]
			}
		default:
			return fmt.Errorf("unhandled field: %q", field)
		}
	}
	return nil
}

func toEtcdProviderType(in string) (api.EtcdProviderType, error) {
	s := strings.ToLower(in)
	switch s {
	case "legacy":
		return api.EtcdProviderTypeLegacy, nil
	case "manager":
		return api.EtcdProviderTypeManager, nil
	default:
		return api.EtcdProviderTypeManager, fmt.Errorf("unknown etcd provider type %q", in)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"flag"
	"fmt"
	"io"
	"log"
	"os"
	"runtime/pprof"

	"github.com/dim13/golyb"
	"github.com/dim13/golyb/dynamic"
	"github.com/dim13/golyb/optimize"
	"github.com/dim13/golyb/static"
)

type Storage string

func (s *Storage) Set(v string) error {
	if v == "static" || v == "dynamic" {
		*s = Storage(v)
		return nil
	}
	return errors.New("unknown tape type")
}

func (s Storage) String() string {
	return string(s)
}

func (s Storage) Usage() string {
	return "Tape type: static or dynamic"
}

func (s Storage) New(r io.Reader, w io.Writer) golyb.Storage {
	switch s {
	case "static":
		return static.New(r, w)
	case "dynamic":
		return dynamic.New(r, w)
	}
	return nil
}

var (
	file    = flag.String("file", "", "Source file (required)")
	in      = flag.String("in", "", "Input file")
	out     = flag.String("out", "", "Output file or /dev/null")
	profile = flag.String("profile", "", "Write CPU profile to file")
	dump    = flag.Bool("dump", false, "Dump AST and terminate")
	noop    = flag.Bool("noop", false, "Disable optimization")
	show    = flag.Bool("show", false, "Dump tape cells")
	storage = Storage("static")
)

func init() {
	flag.Var(&storage, "tape", storage.Usage())
	flag.Parse()
}

func main() {
	if *profile != "" {
		f, err := os.Create(*profile)
		if err != nil {
			log.Fatal(err)
		}
		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	}

	program, err := golyb.ParseFile(*file)
	if err != nil {
		log.Fatal(err)
	}

	if !*noop {
		program = optimize.All(program)
	}

	if *dump {
		fmt.Print(program)
		return
	}

	var r io.Reader
	if *in != "" && *in != "-" {
		r, err = os.Open(*in)
		if err != nil {
			log.Fatal(err)
		}
	}

	var w io.Writer
	if *out != "" && *out != "-" {
		w, err = os.Create(*out)
		if err != nil {
			log.Fatal(err)
		}
	}

	tape := storage.New(r, w)
	program.Execute(tape)

	if *show {
		fmt.Println(tape)
	}
}
<commit_msg>PrintStack<commit_after>package main

import (
	"errors"
	"flag"
	"fmt"
	"io"
	"log"
	"os"
	"runtime/debug"
	"runtime/pprof"

	"github.com/dim13/golyb"
	"github.com/dim13/golyb/dynamic"
	"github.com/dim13/golyb/optimize"
	"github.com/dim13/golyb/static"
)

type Storage string

func (s *Storage) Set(v string) error {
	if v == "static" || v == "dynamic" {
		*s = Storage(v)
		return nil
	}
	return errors.New("unknown tape type")
}

func (s Storage) String() string {
	return string(s)
}

func (s Storage) Usage() string {
	return "Tape type: static or dynamic"
}

func (s Storage) New(r io.Reader, w io.Writer) golyb.Storage {
	switch s {
	case "static":
		return static.New(r, w)
	case "dynamic":
		return dynamic.New(r, w)
	}
	return nil
}

var (
	file    = flag.String("file", "", "Source file (required)")
	in      = flag.String("in", "", "Input file")
	out     = flag.String("out", "", "Output file or /dev/null")
	profile = flag.String("profile", "", "Write CPU profile to file")
	dump    = flag.Bool("dump", false, "Dump AST and terminate")
	noop    = flag.Bool("noop", false, "Disable optimization")
	show    = flag.Bool("show", false, "Dump tape cells")
	storage = Storage("static")
)

func init() {
	flag.Var(&storage, "tape", storage.Usage())
	flag.Parse()
}

func main() {
	if *profile != "" {
		f, err := os.Create(*profile)
		if err != nil {
			log.Fatal(err)
		}
		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	}

	program, err := golyb.ParseFile(*file)
	if err != nil {
		log.Fatal(err)
	}

	if !*noop {
		program = optimize.All(program)
	}

	if *dump {
		fmt.Print(program)
		return
	}

	var r io.Reader
	if *in != "" && *in != "-" {
		r, err = os.Open(*in)
		if err != nil {
			log.Fatal(err)
		}
	}

	var w io.Writer
	if *out != "" && *out != "-" {
		w, err = os.Create(*out)
		if err != nil {
			log.Fatal(err)
		}
	}

	tape := storage.New(r, w)
	defer stacktrace()
	program.Execute(tape)

	if *show {
		fmt.Println(tape)
	}
}

func stacktrace() {
	if r := recover(); r != nil {
		debug.PrintStack()
		log.Fatal(r)
	}
}
<|endoftext|>


<commit_before>package template

import (
	"encoding/json"
	"fmt"
	"sort"

	"golang.org/x/text/language"

	"github.com/iawaknahc/gomessageformat"
	"github.com/skygeario/skygear-server/pkg/core/config"
	"github.com/skygeario/skygear-server/pkg/core/intl"
)

type ResolveOptions struct {
	Key string
}

type resolveResult struct {
	Spec         Spec
	TemplateBody string
	// Translations is key -> tag -> translation.
	// For example,
	// {
	//   "key1": {
	//     "": "Hello",
	//     "en": "Hello",
	//     "en-US": "Hi!",
	//     "zh": "你好"
	//   }
	// }
	Translations map[string]map[string]string
}

type NewEngineOptions struct {
	EnableFileLoader bool
	EnableDataLoader bool
	AssetGearLoader  *AssetGearLoader
	TemplateItems    []config.TemplateItem
}

type Loader interface {
	Load(string) (string, error)
}

// Engine resolves and renders templates.
type Engine struct {
	loader                Loader
	TemplateSpecs         map[config.TemplateItemType]Spec
	templateItems         []config.TemplateItem
	preferredLanguageTags []string
	validatorOptions      []ValidatorOption
}

func NewEngine(opts NewEngineOptions) *Engine {
	uriLoader := NewURILoader(opts.AssetGearLoader)
	uriLoader.EnableFileLoader = opts.EnableFileLoader
	uriLoader.EnableDataLoader = opts.EnableDataLoader
	return &Engine{
		loader:        uriLoader,
		templateItems: opts.TemplateItems,
		TemplateSpecs: map[config.TemplateItemType]Spec{},
	}
}

// Clone clones e.
func (e *Engine) Clone() *Engine {
	// A simply struct copy is enough here because we assume
	// Register calls are made only during engine creation.
	newEngine := *e
	return &newEngine
}

// WithPreferredLanguageTags returns a new engine with the given tags.
// This function offers greater flexibility on configuring preferred languages because
// This information may not be available at the creation of the engine.
func (e *Engine) WithPreferredLanguageTags(tags []string) *Engine {
	newEngine := e.Clone()
	newEngine.preferredLanguageTags = tags
	return newEngine
}

// WithValidatorOptions returns a new engine with the givan validator options.
func (e *Engine) WithValidatorOptions(opts ...ValidatorOption) *Engine {
	newEngine := e.Clone()
	newEngine.validatorOptions = opts
	return newEngine
}

// Register registers spec with e.
func (e *Engine) Register(spec Spec) {
	e.TemplateSpecs[spec.Type] = spec
}

func (e *Engine) RenderTemplate(templateType config.TemplateItemType, context map[string]interface{}, resolveOptions ResolveOptions) (out string, err error) {
	result, err := e.resolveTemplate(templateType, resolveOptions)
	if err != nil {
		return
	}

	renderOptions := RenderOptions{
		Name:          string(templateType),
		TemplateBody:  result.TemplateBody,
		Defines:       result.Spec.Defines,
		Context:       context,
		ValidatorOpts: e.validatorOptions,
	}

	if result.Spec.Translation != "" {
		renderOptions.Funcs = map[string]interface{}{
			"localize": makeLocalize(
				e.preferredLanguageTags,
				result.Translations,
			),
		}
	}

	renderFunc := RenderTextTemplate
	if result.Spec.IsHTML {
		renderFunc = RenderHTMLTemplate
	}

	return renderFunc(renderOptions)
}

func (e *Engine) resolveTemplate(templateType config.TemplateItemType, options ResolveOptions) (result *resolveResult, err error) {
	spec, ok := e.TemplateSpecs[templateType]
	if !ok {
		panic("template: unregistered template type: " + templateType)
	}

	// Resolve the template body
	// Take the default value by default
	templateBody := spec.Default
	templateItem, err := e.resolveTemplateItem(spec, options.Key)
	if err != nil {
		// No template item can be resolved. Fallback to default.
		err = nil
	} else {
		templateBody, err = e.loader.Load(templateItem.URI)
		if err != nil {
			return
		}
	}

	// Resolve the translations, if any
	var translations map[string]map[string]string
	if spec.Translation != "" {
		translations, err = e.resolveTranslations(spec.Translation)
		if err != nil {
			return
		}
	}

	result = &resolveResult{
		TemplateBody: templateBody,
		Spec:         spec,
		Translations: translations,
	}
	return
}

func (e *Engine) resolveTemplateItem(spec Spec, key string) (templateItem *config.TemplateItem, err error) {
	input := e.templateItems
	var output []config.TemplateItem

	// The first step is to find out templates with the target type.
	for _, item := range input {
		if item.Type == spec.Type {
			i := item
			output = append(output, i)
		}
	}
	input = output
	output = nil

	// The second step is to find out templates with the target key, if key is specified
	if spec.IsKeyed && key != "" {
		for _, item := range input {
			if item.Key == key {
				i := item
				output = append(output, i)
			}
		}
		input = output
	}

	// We have either have a list of templates of different language tags or an empty list.
	if len(input) <= 0 {
		err = &errNotFound{name: string(spec.Type)}
		return
	}

	// We have a list of templates of different language tags.
	// The first item in tags is used as fallback.
	// So we have sort the templates so that template with empty
	// language tag comes first.
	//
	// language.Make("") is "und"
	sort.Slice(input, func(i, j int) bool {
		return input[i].LanguageTag < input[j].LanguageTag
	})

	supportedTags := make([]language.Tag, len(input))
	for i, item := range input {
		supportedTags[i] = language.Make(item.LanguageTag)
	}
	matcher := language.NewMatcher(supportedTags)

	preferredTags := make([]language.Tag, len(e.preferredLanguageTags))
	for i, tagStr := range e.preferredLanguageTags {
		preferredTags[i] = language.Make(tagStr)
	}

	_, idx, _ := matcher.Match(preferredTags...)

	return &input[idx], nil
}

func (e *Engine) resolveTranslations(templateType config.TemplateItemType) (translations map[string]map[string]string, err error) {
	spec, ok := e.TemplateSpecs[templateType]
	if !ok {
		panic("template: unregistered template type: " + templateType)
	}

	translations = map[string]map[string]string{}

	// Load the default translation
	defaultTranslation, err := loadTranslation(spec.Default)
	if err != nil {
		return
	}
	insertTranslation(translations, "", defaultTranslation)

	// Find out all items
	var items []config.TemplateItem
	for _, item := range e.templateItems {
		if item.Type == spec.Type {
			i := item
			items = append(items, i)
		}
	}

	// Load all provided translations
	for _, item := range items {
		var jsonStr string
		jsonStr, err = e.loader.Load(item.URI)
		if err != nil {
			return
		}
		var translation map[string]string
		translation, err = loadTranslation(jsonStr)
		if err != nil {
			return
		}
		insertTranslation(translations, item.LanguageTag, translation)
	}

	return
}

func makeLocalize(preferredLanguageTags []string, translations map[string]map[string]string) func(key string, args ...interface{}) (string, error) {
	return func(key string, args ...interface{}) (out string, err error) {
		m, ok := translations[key]
		if !ok {
			err = fmt.Errorf("translation key not found: %s", key)
			return
		}

		tag, pattern := intl.Localize(preferredLanguageTags, m)

		out, err = messageformat.FormatPositional(tag, pattern, args...)
		if err != nil {
			return
		}

		return
	}
}

func loadTranslation(jsonStr string) (translation map[string]string, err error) {
	var jsonObj map[string]interface{}
	err = json.Unmarshal([]byte(jsonStr), &jsonObj)
	if err != nil {
		err = fmt.Errorf("expected translation file to be JSON: %w", err)
		return
	}

	translation = map[string]string{}
	for key, val := range jsonObj {
		s, ok := val.(string)
		if !ok {
			err = fmt.Errorf("expected translation value to be string: %s %T", key, val)
			return
		}
		translation[key] = s
	}
	return
}

func insertTranslation(translations map[string]map[string]string, tag string, translation map[string]string) {
	for key, val := range translation {
		m, ok := translations[key]
		if !ok {
			translations[key] = map[string]string{}
			m = translations[key]
		}
		m[tag] = val
	}
}
<commit_msg>Extract loadTemplateBody<commit_after>package template

import (
	"encoding/json"
	"fmt"
	"sort"

	"golang.org/x/text/language"

	"github.com/iawaknahc/gomessageformat"
	"github.com/skygeario/skygear-server/pkg/core/config"
	"github.com/skygeario/skygear-server/pkg/core/intl"
)

type ResolveOptions struct {
	Key string
}

type resolveResult struct {
	Spec         Spec
	TemplateBody string
	// Translations is key -> tag -> translation.
	// For example,
	// {
	//   "key1": {
	//     "": "Hello",
	//     "en": "Hello",
	//     "en-US": "Hi!",
	//     "zh": "你好"
	//   }
	// }
	Translations map[string]map[string]string
}

type NewEngineOptions struct {
	EnableFileLoader bool
	EnableDataLoader bool
	AssetGearLoader  *AssetGearLoader
	TemplateItems    []config.TemplateItem
}

type Loader interface {
	Load(string) (string, error)
}

// Engine resolves and renders templates.
type Engine struct {
	loader                Loader
	TemplateSpecs         map[config.TemplateItemType]Spec
	templateItems         []config.TemplateItem
	preferredLanguageTags []string
	validatorOptions      []ValidatorOption
}

func NewEngine(opts NewEngineOptions) *Engine {
	uriLoader := NewURILoader(opts.AssetGearLoader)
	uriLoader.EnableFileLoader = opts.EnableFileLoader
	uriLoader.EnableDataLoader = opts.EnableDataLoader
	return &Engine{
		loader:        uriLoader,
		templateItems: opts.TemplateItems,
		TemplateSpecs: map[config.TemplateItemType]Spec{},
	}
}

// Clone clones e.
func (e *Engine) Clone() *Engine {
	// A simply struct copy is enough here because we assume
	// Register calls are made only during engine creation.
	newEngine := *e
	return &newEngine
}

// WithPreferredLanguageTags returns a new engine with the given tags.
// This function offers greater flexibility on configuring preferred languages because
// This information may not be available at the creation of the engine.
func (e *Engine) WithPreferredLanguageTags(tags []string) *Engine {
	newEngine := e.Clone()
	newEngine.preferredLanguageTags = tags
	return newEngine
}

// WithValidatorOptions returns a new engine with the givan validator options.
func (e *Engine) WithValidatorOptions(opts ...ValidatorOption) *Engine {
	newEngine := e.Clone()
	newEngine.validatorOptions = opts
	return newEngine
}

// Register registers spec with e.
func (e *Engine) Register(spec Spec) {
	e.TemplateSpecs[spec.Type] = spec
}

func (e *Engine) RenderTemplate(templateType config.TemplateItemType, context map[string]interface{}, resolveOptions ResolveOptions) (out string, err error) {
	result, err := e.resolveTemplate(templateType, resolveOptions)
	if err != nil {
		return
	}

	renderOptions := RenderOptions{
		Name:          string(templateType),
		TemplateBody:  result.TemplateBody,
		Defines:       result.Spec.Defines,
		Context:       context,
		ValidatorOpts: e.validatorOptions,
	}

	if result.Spec.Translation != "" {
		renderOptions.Funcs = map[string]interface{}{
			"localize": makeLocalize(
				e.preferredLanguageTags,
				result.Translations,
			),
		}
	}

	renderFunc := RenderTextTemplate
	if result.Spec.IsHTML {
		renderFunc = RenderHTMLTemplate
	}

	return renderFunc(renderOptions)
}

func (e *Engine) resolveTemplate(templateType config.TemplateItemType, options ResolveOptions) (result *resolveResult, err error) {
	spec, ok := e.TemplateSpecs[templateType]
	if !ok {
		panic("template: unregistered template type: " + templateType)
	}

	templateBody, err := e.loadTemplateBody(spec, options.Key)
	if err != nil {
		return
	}

	// Resolve the translations, if any
	var translations map[string]map[string]string
	if spec.Translation != "" {
		translations, err = e.resolveTranslations(spec.Translation)
		if err != nil {
			return
		}
	}

	result = &resolveResult{
		Spec:         spec,
		TemplateBody: templateBody,
		Translations: translations,
	}

	return
}

func (e *Engine) loadTemplateBody(spec Spec, key string) (templateBody string, err error) {
	// Take the default value by default
	templateBody = spec.Default
	templateItem, err := e.resolveTemplateItem(spec, key)
	if err != nil {
		// No template item can be resolved. Fallback to default.
		err = nil
	} else {
		templateBody, err = e.loader.Load(templateItem.URI)
		if err != nil {
			return
		}
	}
	return
}

func (e *Engine) resolveTemplateItem(spec Spec, key string) (templateItem *config.TemplateItem, err error) {
	input := e.templateItems
	var output []config.TemplateItem

	// The first step is to find out templates with the target type.
	for _, item := range input {
		if item.Type == spec.Type {
			i := item
			output = append(output, i)
		}
	}
	input = output
	output = nil

	// The second step is to find out templates with the target key, if key is specified
	if spec.IsKeyed && key != "" {
		for _, item := range input {
			if item.Key == key {
				i := item
				output = append(output, i)
			}
		}
		input = output
	}

	// We have either have a list of templates of different language tags or an empty list.
	if len(input) <= 0 {
		err = &errNotFound{name: string(spec.Type)}
		return
	}

	// We have a list of templates of different language tags.
	// The first item in tags is used as fallback.
	// So we have sort the templates so that template with empty
	// language tag comes first.
	//
	// language.Make("") is "und"
	sort.Slice(input, func(i, j int) bool {
		return input[i].LanguageTag < input[j].LanguageTag
	})

	supportedTags := make([]language.Tag, len(input))
	for i, item := range input {
		supportedTags[i] = language.Make(item.LanguageTag)
	}
	matcher := language.NewMatcher(supportedTags)

	preferredTags := make([]language.Tag, len(e.preferredLanguageTags))
	for i, tagStr := range e.preferredLanguageTags {
		preferredTags[i] = language.Make(tagStr)
	}

	_, idx, _ := matcher.Match(preferredTags...)

	return &input[idx], nil
}

func (e *Engine) resolveTranslations(templateType config.TemplateItemType) (translations map[string]map[string]string, err error) {
	spec, ok := e.TemplateSpecs[templateType]
	if !ok {
		panic("template: unregistered template type: " + templateType)
	}

	translations = map[string]map[string]string{}

	// Load the default translation
	defaultTranslation, err := loadTranslation(spec.Default)
	if err != nil {
		return
	}
	insertTranslation(translations, "", defaultTranslation)

	// Find out all items
	var items []config.TemplateItem
	for _, item := range e.templateItems {
		if item.Type == spec.Type {
			i := item
			items = append(items, i)
		}
	}

	// Load all provided translations
	for _, item := range items {
		var jsonStr string
		jsonStr, err = e.loader.Load(item.URI)
		if err != nil {
			return
		}
		var translation map[string]string
		translation, err = loadTranslation(jsonStr)
		if err != nil {
			return
		}
		insertTranslation(translations, item.LanguageTag, translation)
	}

	return
}

func makeLocalize(preferredLanguageTags []string, translations map[string]map[string]string) func(key string, args ...interface{}) (string, error) {
	return func(key string, args ...interface{}) (out string, err error) {
		m, ok := translations[key]
		if !ok {
			err = fmt.Errorf("translation key not found: %s", key)
			return
		}

		tag, pattern := intl.Localize(preferredLanguageTags, m)

		out, err = messageformat.FormatPositional(tag, pattern, args...)
		if err != nil {
			return
		}

		return
	}
}

func loadTranslation(jsonStr string) (translation map[string]string, err error) {
	var jsonObj map[string]interface{}
	err = json.Unmarshal([]byte(jsonStr), &jsonObj)
	if err != nil {
		err = fmt.Errorf("expected translation file to be JSON: %w", err)
		return
	}

	translation = map[string]string{}
	for key, val := range jsonObj {
		s, ok := val.(string)
		if !ok {
			err = fmt.Errorf("expected translation value to be string: %s %T", key, val)
			return
		}
		translation[key] = s
	}
	return
}

func insertTranslation(translations map[string]map[string]string, tag string, translation map[string]string) {
	for key, val := range translation {
		m, ok := translations[key]
		if !ok {
			translations[key] = map[string]string{}
			m = translations[key]
		}
		m[tag] = val
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2019 The Kubernetes Authors All rights reserved.

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

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

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

package oci

import (
	"encoding/json"
	"os/exec"
	"strings"
	"time"

	"github.com/pkg/errors"
)

// SysInfo Info represents common system Information between docker and podman that minikube cares
type SysInfo struct {
	CPUs        int    // CPUs is Number of CPUs
	TotalMemory int64  // TotalMemory Total available ram
	OSType      string // container's OsType (windows or linux)
}

var cachedSysInfo *SysInfo
var cachedSysInfoErr *error

// CachedDaemonInfo will run and return a docker/podman info only once per minikube run time. to avoid performance
func CachedDaemonInfo(ociBin string) (SysInfo, error) {
	if cachedSysInfo == nil { // if cached daemon info has error, try to get a new one
		si, err := DaemonInfo(ociBin)
		cachedSysInfo = &si
		cachedSysInfoErr = &err
	}
	if cachedSysInfoErr == nil {
		return *cachedSysInfo, nil
	}
	return *cachedSysInfo, *cachedSysInfoErr
}

// DaemonInfo returns common docker/podman daemon system info that minikube cares about
func DaemonInfo(ociBin string) (SysInfo, error) {
	if ociBin == Podman {
		p, err := podmanSystemInfo()
		cachedSysInfo = &SysInfo{CPUs: p.Host.Cpus, TotalMemory: p.Host.MemTotal, OSType: p.Host.Os}
		return *cachedSysInfo, err
	}
	d, err := dockerSystemInfo()
	cachedSysInfo = &SysInfo{CPUs: d.NCPU, TotalMemory: d.MemTotal, OSType: d.OSType}
	return *cachedSysInfo, err
}

// dockerSysInfo represents the output of docker system info --format '{{json .}}'
type dockerSysInfo struct {
	ID                string      `json:"ID"`
	Containers        int         `json:"Containers"`
	ContainersRunning int         `json:"ContainersRunning"`
	ContainersPaused  int         `json:"ContainersPaused"`
	ContainersStopped int         `json:"ContainersStopped"`
	Images            int         `json:"Images"`
	Driver            string      `json:"Driver"`
	DriverStatus      [][]string  `json:"DriverStatus"`
	SystemStatus      interface{} `json:"SystemStatus"`
	Plugins           struct {
		Volume        []string    `json:"Volume"`
		Network       []string    `json:"Network"`
		Authorization interface{} `json:"Authorization"`
		Log           []string    `json:"Log"`
	} `json:"Plugins"`
	MemoryLimit        bool      `json:"MemoryLimit"`
	SwapLimit          bool      `json:"SwapLimit"`
	KernelMemory       bool      `json:"KernelMemory"`
	KernelMemoryTCP    bool      `json:"KernelMemoryTCP"`
	CPUCfsPeriod       bool      `json:"CpuCfsPeriod"`
	CPUCfsQuota        bool      `json:"CpuCfsQuota"`
	CPUShares          bool      `json:"CPUShares"`
	CPUSet             bool      `json:"CPUSet"`
	PidsLimit          bool      `json:"PidsLimit"`
	IPv4Forwarding     bool      `json:"IPv4Forwarding"`
	BridgeNfIptables   bool      `json:"BridgeNfIptables"`
	BridgeNfIP6Tables  bool      `json:"BridgeNfIp6tables"`
	Debug              bool      `json:"Debug"`
	NFd                int       `json:"NFd"`
	OomKillDisable     bool      `json:"OomKillDisable"`
	NGoroutines        int       `json:"NGoroutines"`
	SystemTime         time.Time `json:"SystemTime"`
	LoggingDriver      string    `json:"LoggingDriver"`
	CgroupDriver       string    `json:"CgroupDriver"`
	NEventsListener    int       `json:"NEventsListener"`
	KernelVersion      string    `json:"KernelVersion"`
	OperatingSystem    string    `json:"OperatingSystem"`
	OSType             string    `json:"OSType"`
	Architecture       string    `json:"Architecture"`
	IndexServerAddress string    `json:"IndexServerAddress"`
	RegistryConfig     struct {
		AllowNondistributableArtifactsCIDRs     []interface{} `json:"AllowNondistributableArtifactsCIDRs"`
		AllowNondistributableArtifactsHostnames []interface{} `json:"AllowNondistributableArtifactsHostnames"`
		InsecureRegistryCIDRs                   []string      `json:"InsecureRegistryCIDRs"`
		IndexConfigs                            struct {
			DockerIo struct {
				Name     string        `json:"Name"`
				Mirrors  []interface{} `json:"Mirrors"`
				Secure   bool          `json:"Secure"`
				Official bool          `json:"Official"`
			} `json:"docker.io"`
		} `json:"IndexConfigs"`
		Mirrors []interface{} `json:"Mirrors"`
	} `json:"RegistryConfig"`
	NCPU              int           `json:"NCPU"`
	MemTotal          int64         `json:"MemTotal"`
	GenericResources  interface{}   `json:"GenericResources"`
	DockerRootDir     string        `json:"DockerRootDir"`
	HTTPProxy         string        `json:"HttpProxy"`
	HTTPSProxy        string        `json:"HttpsProxy"`
	NoProxy           string        `json:"NoProxy"`
	Name              string        `json:"Name"`
	Labels            []interface{} `json:"Labels"`
	ExperimentalBuild bool          `json:"ExperimentalBuild"`
	ServerVersion     string        `json:"ServerVersion"`
	ClusterStore      string        `json:"ClusterStore"`
	ClusterAdvertise  string        `json:"ClusterAdvertise"`
	Runtimes          struct {
		Runc struct {
			Path string `json:"path"`
		} `json:"runc"`
	} `json:"Runtimes"`
	DefaultRuntime string `json:"DefaultRuntime"`
	Swarm          struct {
		NodeID           string      `json:"NodeID"`
		NodeAddr         string      `json:"NodeAddr"`
		LocalNodeState   string      `json:"LocalNodeState"`
		ControlAvailable bool        `json:"ControlAvailable"`
		Error            string      `json:"Error"`
		RemoteManagers   interface{} `json:"RemoteManagers"`
	} `json:"Swarm"`
	LiveRestoreEnabled bool   `json:"LiveRestoreEnabled"`
	Isolation          string `json:"Isolation"`
	InitBinary         string `json:"InitBinary"`
	ContainerdCommit   struct {
		ID       string `json:"ID"`
		Expected string `json:"Expected"`
	} `json:"ContainerdCommit"`
	RuncCommit struct {
		ID       string `json:"ID"`
		Expected string `json:"Expected"`
	} `json:"RuncCommit"`
	InitCommit struct {
		ID       string `json:"ID"`
		Expected string `json:"Expected"`
	} `json:"InitCommit"`
	SecurityOptions []string    `json:"SecurityOptions"`
	ProductLicense  string      `json:"ProductLicense"`
	Warnings        interface{} `json:"Warnings"`
	ClientInfo      struct {
		Debug    bool          `json:"Debug"`
		Plugins  []interface{} `json:"Plugins"`
		Warnings interface{}   `json:"Warnings"`
	} `json:"ClientInfo"`
}

// podmanSysInfo represents the output of podman system info --format '{{json .}}'
type podmanSysInfo struct {
	Host struct {
		BuildahVersion string `json:"BuildahVersion"`
		CgroupVersion  string `json:"CgroupVersion"`
		Conmon         struct {
			Package string `json:"package"`
			Path    string `json:"path"`
			Version string `json:"version"`
		} `json:"Conmon"`
		Distribution struct {
			Distribution string `json:"distribution"`
			Version      string `json:"version"`
		} `json:"Distribution"`
		MemFree    int   `json:"MemFree"`
		MemTotal   int64 `json:"MemTotal"`
		OCIRuntime struct {
			Name    string `json:"name"`
			Package string `json:"package"`
			Path    string `json:"path"`
			Version string `json:"version"`
		} `json:"OCIRuntime"`
		SwapFree    int    `json:"SwapFree"`
		SwapTotal   int    `json:"SwapTotal"`
		Arch        string `json:"arch"`
		Cpus        int    `json:"cpus"`
		Eventlogger string `json:"eventlogger"`
		Hostname    string `json:"hostname"`
		Kernel      string `json:"kernel"`
		Os          string `json:"os"`
		Rootless    bool   `json:"rootless"`
		Uptime      string `json:"uptime"`
	} `json:"host"`
	Registries struct {
		Search []string `json:"search"`
	} `json:"registries"`
	Store struct {
		ConfigFile     string `json:"ConfigFile"`
		ContainerStore struct {
			Number int `json:"number"`
		} `json:"ContainerStore"`
		GraphDriverName string `json:"GraphDriverName"`
		GraphOptions    struct {
		} `json:"GraphOptions"`
		GraphRoot   string `json:"GraphRoot"`
		GraphStatus struct {
			BackingFilesystem string `json:"Backing Filesystem"`
			NativeOverlayDiff string `json:"Native Overlay Diff"`
			SupportsDType     string `json:"Supports d_type"`
			UsingMetacopy     string `json:"Using metacopy"`
		} `json:"GraphStatus"`
		ImageStore struct {
			Number int `json:"number"`
		} `json:"ImageStore"`
		RunRoot    string `json:"RunRoot"`
		VolumePath string `json:"VolumePath"`
	} `json:"store"`
}

// dockerSystemInfo returns docker system info --format '{{json .}}'
func dockerSystemInfo() (dockerSysInfo, error) {
	var ds dockerSysInfo
	rr, err := runCmd(exec.Command(Docker, "system", "info", "--format", "{{json .}}"))
	if err != nil {
		return ds, errors.Wrap(err, "get docker system info")
	}

	if err := json.Unmarshal([]byte(strings.TrimSpace(rr.Stdout.String())), &ds); err != nil {
		return ds, errors.Wrapf(err, "unmarshal docker system info")
	}

	return ds, nil
}

// podmanSysInfo returns podman system info --format '{{json .}}'
func podmanSystemInfo() (podmanSysInfo, error) {
	var ps podmanSysInfo
	rr, err := runCmd(exec.Command(Podman, "system", "info", "--format", "json"))
	if err != nil {
		return ps, errors.Wrap(err, "get podman system info")
	}

	if err := json.Unmarshal([]byte(strings.TrimSpace(rr.Stdout.String())), &ps); err != nil {
		return ps, errors.Wrapf(err, "unmarshal podman system info")
	}
	return ps, nil
}
<commit_msg>remvoe comment<commit_after>/*
Copyright 2019 The Kubernetes Authors All rights reserved.

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

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

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

package oci

import (
	"encoding/json"
	"os/exec"
	"strings"
	"time"

	"github.com/pkg/errors"
)

// SysInfo Info represents common system Information between docker and podman that minikube cares
type SysInfo struct {
	CPUs        int    // CPUs is Number of CPUs
	TotalMemory int64  // TotalMemory Total available ram
	OSType      string // container's OsType (windows or linux)
}

var cachedSysInfo *SysInfo
var cachedSysInfoErr *error

// CachedDaemonInfo will run and return a docker/podman info only once per minikube run time. to avoid performance
func CachedDaemonInfo(ociBin string) (SysInfo, error) {
	if cachedSysInfo == nil {
		si, err := DaemonInfo(ociBin)
		cachedSysInfo = &si
		cachedSysInfoErr = &err
	}
	if cachedSysInfoErr == nil {
		return *cachedSysInfo, nil
	}
	return *cachedSysInfo, *cachedSysInfoErr
}

// DaemonInfo returns common docker/podman daemon system info that minikube cares about
func DaemonInfo(ociBin string) (SysInfo, error) {
	if ociBin == Podman {
		p, err := podmanSystemInfo()
		cachedSysInfo = &SysInfo{CPUs: p.Host.Cpus, TotalMemory: p.Host.MemTotal, OSType: p.Host.Os}
		return *cachedSysInfo, err
	}
	d, err := dockerSystemInfo()
	cachedSysInfo = &SysInfo{CPUs: d.NCPU, TotalMemory: d.MemTotal, OSType: d.OSType}
	return *cachedSysInfo, err
}

// dockerSysInfo represents the output of docker system info --format '{{json .}}'
type dockerSysInfo struct {
	ID                string      `json:"ID"`
	Containers        int         `json:"Containers"`
	ContainersRunning int         `json:"ContainersRunning"`
	ContainersPaused  int         `json:"ContainersPaused"`
	ContainersStopped int         `json:"ContainersStopped"`
	Images            int         `json:"Images"`
	Driver            string      `json:"Driver"`
	DriverStatus      [][]string  `json:"DriverStatus"`
	SystemStatus      interface{} `json:"SystemStatus"`
	Plugins           struct {
		Volume        []string    `json:"Volume"`
		Network       []string    `json:"Network"`
		Authorization interface{} `json:"Authorization"`
		Log           []string    `json:"Log"`
	} `json:"Plugins"`
	MemoryLimit        bool      `json:"MemoryLimit"`
	SwapLimit          bool      `json:"SwapLimit"`
	KernelMemory       bool      `json:"KernelMemory"`
	KernelMemoryTCP    bool      `json:"KernelMemoryTCP"`
	CPUCfsPeriod       bool      `json:"CpuCfsPeriod"`
	CPUCfsQuota        bool      `json:"CpuCfsQuota"`
	CPUShares          bool      `json:"CPUShares"`
	CPUSet             bool      `json:"CPUSet"`
	PidsLimit          bool      `json:"PidsLimit"`
	IPv4Forwarding     bool      `json:"IPv4Forwarding"`
	BridgeNfIptables   bool      `json:"BridgeNfIptables"`
	BridgeNfIP6Tables  bool      `json:"BridgeNfIp6tables"`
	Debug              bool      `json:"Debug"`
	NFd                int       `json:"NFd"`
	OomKillDisable     bool      `json:"OomKillDisable"`
	NGoroutines        int       `json:"NGoroutines"`
	SystemTime         time.Time `json:"SystemTime"`
	LoggingDriver      string    `json:"LoggingDriver"`
	CgroupDriver       string    `json:"CgroupDriver"`
	NEventsListener    int       `json:"NEventsListener"`
	KernelVersion      string    `json:"KernelVersion"`
	OperatingSystem    string    `json:"OperatingSystem"`
	OSType             string    `json:"OSType"`
	Architecture       string    `json:"Architecture"`
	IndexServerAddress string    `json:"IndexServerAddress"`
	RegistryConfig     struct {
		AllowNondistributableArtifactsCIDRs     []interface{} `json:"AllowNondistributableArtifactsCIDRs"`
		AllowNondistributableArtifactsHostnames []interface{} `json:"AllowNondistributableArtifactsHostnames"`
		InsecureRegistryCIDRs                   []string      `json:"InsecureRegistryCIDRs"`
		IndexConfigs                            struct {
			DockerIo struct {
				Name     string        `json:"Name"`
				Mirrors  []interface{} `json:"Mirrors"`
				Secure   bool          `json:"Secure"`
				Official bool          `json:"Official"`
			} `json:"docker.io"`
		} `json:"IndexConfigs"`
		Mirrors []interface{} `json:"Mirrors"`
	} `json:"RegistryConfig"`
	NCPU              int           `json:"NCPU"`
	MemTotal          int64         `json:"MemTotal"`
	GenericResources  interface{}   `json:"GenericResources"`
	DockerRootDir     string        `json:"DockerRootDir"`
	HTTPProxy         string        `json:"HttpProxy"`
	HTTPSProxy        string        `json:"HttpsProxy"`
	NoProxy           string        `json:"NoProxy"`
	Name              string        `json:"Name"`
	Labels            []interface{} `json:"Labels"`
	ExperimentalBuild bool          `json:"ExperimentalBuild"`
	ServerVersion     string        `json:"ServerVersion"`
	ClusterStore      string        `json:"ClusterStore"`
	ClusterAdvertise  string        `json:"ClusterAdvertise"`
	Runtimes          struct {
		Runc struct {
			Path string `json:"path"`
		} `json:"runc"`
	} `json:"Runtimes"`
	DefaultRuntime string `json:"DefaultRuntime"`
	Swarm          struct {
		NodeID           string      `json:"NodeID"`
		NodeAddr         string      `json:"NodeAddr"`
		LocalNodeState   string      `json:"LocalNodeState"`
		ControlAvailable bool        `json:"ControlAvailable"`
		Error            string      `json:"Error"`
		RemoteManagers   interface{} `json:"RemoteManagers"`
	} `json:"Swarm"`
	LiveRestoreEnabled bool   `json:"LiveRestoreEnabled"`
	Isolation          string `json:"Isolation"`
	InitBinary         string `json:"InitBinary"`
	ContainerdCommit   struct {
		ID       string `json:"ID"`
		Expected string `json:"Expected"`
	} `json:"ContainerdCommit"`
	RuncCommit struct {
		ID       string `json:"ID"`
		Expected string `json:"Expected"`
	} `json:"RuncCommit"`
	InitCommit struct {
		ID       string `json:"ID"`
		Expected string `json:"Expected"`
	} `json:"InitCommit"`
	SecurityOptions []string    `json:"SecurityOptions"`
	ProductLicense  string      `json:"ProductLicense"`
	Warnings        interface{} `json:"Warnings"`
	ClientInfo      struct {
		Debug    bool          `json:"Debug"`
		Plugins  []interface{} `json:"Plugins"`
		Warnings interface{}   `json:"Warnings"`
	} `json:"ClientInfo"`
}

// podmanSysInfo represents the output of podman system info --format '{{json .}}'
type podmanSysInfo struct {
	Host struct {
		BuildahVersion string `json:"BuildahVersion"`
		CgroupVersion  string `json:"CgroupVersion"`
		Conmon         struct {
			Package string `json:"package"`
			Path    string `json:"path"`
			Version string `json:"version"`
		} `json:"Conmon"`
		Distribution struct {
			Distribution string `json:"distribution"`
			Version      string `json:"version"`
		} `json:"Distribution"`
		MemFree    int   `json:"MemFree"`
		MemTotal   int64 `json:"MemTotal"`
		OCIRuntime struct {
			Name    string `json:"name"`
			Package string `json:"package"`
			Path    string `json:"path"`
			Version string `json:"version"`
		} `json:"OCIRuntime"`
		SwapFree    int    `json:"SwapFree"`
		SwapTotal   int    `json:"SwapTotal"`
		Arch        string `json:"arch"`
		Cpus        int    `json:"cpus"`
		Eventlogger string `json:"eventlogger"`
		Hostname    string `json:"hostname"`
		Kernel      string `json:"kernel"`
		Os          string `json:"os"`
		Rootless    bool   `json:"rootless"`
		Uptime      string `json:"uptime"`
	} `json:"host"`
	Registries struct {
		Search []string `json:"search"`
	} `json:"registries"`
	Store struct {
		ConfigFile     string `json:"ConfigFile"`
		ContainerStore struct {
			Number int `json:"number"`
		} `json:"ContainerStore"`
		GraphDriverName string `json:"GraphDriverName"`
		GraphOptions    struct {
		} `json:"GraphOptions"`
		GraphRoot   string `json:"GraphRoot"`
		GraphStatus struct {
			BackingFilesystem string `json:"Backing Filesystem"`
			NativeOverlayDiff string `json:"Native Overlay Diff"`
			SupportsDType     string `json:"Supports d_type"`
			UsingMetacopy     string `json:"Using metacopy"`
		} `json:"GraphStatus"`
		ImageStore struct {
			Number int `json:"number"`
		} `json:"ImageStore"`
		RunRoot    string `json:"RunRoot"`
		VolumePath string `json:"VolumePath"`
	} `json:"store"`
}

// dockerSystemInfo returns docker system info --format '{{json .}}'
func dockerSystemInfo() (dockerSysInfo, error) {
	var ds dockerSysInfo
	rr, err := runCmd(exec.Command(Docker, "system", "info", "--format", "{{json .}}"))
	if err != nil {
		return ds, errors.Wrap(err, "get docker system info")
	}

	if err := json.Unmarshal([]byte(strings.TrimSpace(rr.Stdout.String())), &ds); err != nil {
		return ds, errors.Wrapf(err, "unmarshal docker system info")
	}

	return ds, nil
}

// podmanSysInfo returns podman system info --format '{{json .}}'
func podmanSystemInfo() (podmanSysInfo, error) {
	var ps podmanSysInfo
	rr, err := runCmd(exec.Command(Podman, "system", "info", "--format", "json"))
	if err != nil {
		return ps, errors.Wrap(err, "get podman system info")
	}

	if err := json.Unmarshal([]byte(strings.TrimSpace(rr.Stdout.String())), &ps); err != nil {
		return ps, errors.Wrapf(err, "unmarshal podman system info")
	}
	return ps, nil
}
<|endoftext|>


<commit_before>/*
Copyright 2019 The Kubernetes Authors All rights reserved.

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

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

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

package oci

import (
	"encoding/json"
	"os/exec"
	"strings"
	"time"

	"github.com/pkg/errors"
)

// SysInfo Info represents common system Information between docker and podman that minikube cares
type SysInfo struct {
	CPUs        int    // CPUs is Number of CPUs
	TotalMemory int64  // TotalMemory Total available ram
	OSType      string // container's OsType (windows or linux)
}

var cachedSysInfo *SysInfo
var cachedSysInfoErr *error

// CachedDaemonInfo will run and return a docker/podman info only once per minikube run time. to avoid performance
func CachedDaemonInfo(ociBin string) (SysInfo, error) {
	var err error
	if cachedSysInfo == nil {
		si, err := DaemonInfo(ociBin)
		cachedSysInfo = &si
		cachedSysInfoErr = &err
		return *cachedSysInfo, err
	}
	return *cachedSysInfo, *cachedSysInfoErr
}

// DaemonInfo returns common docker/podman daemon system info that minikube cares about
func DaemonInfo(ociBin string) (SysInfo, error) {
	if ociBin == Podman {
		p, err := podmanSystemInfo()
		cachedSysInfo.CPUs = p.Host.Cpus
		cachedSysInfo.TotalMemory = p.Host.MemTotal
		cachedSysInfo.OSType = p.Host.Os
		return *cachedSysInfo, err
	}
	d, err := dockerSystemInfo()
	cachedSysInfo.CPUs = d.NCPU
	cachedSysInfo.TotalMemory = d.MemTotal
	cachedSysInfo.OSType = d.OSType
	return *cachedSysInfo, err
}

// dockerSysInfo represents the output of docker system info --format '{{json .}}'
type dockerSysInfo struct {
	ID                string      `json:"ID"`
	Containers        int         `json:"Containers"`
	ContainersRunning int         `json:"ContainersRunning"`
	ContainersPaused  int         `json:"ContainersPaused"`
	ContainersStopped int         `json:"ContainersStopped"`
	Images            int         `json:"Images"`
	Driver            string      `json:"Driver"`
	DriverStatus      [][]string  `json:"DriverStatus"`
	SystemStatus      interface{} `json:"SystemStatus"`
	Plugins           struct {
		Volume        []string    `json:"Volume"`
		Network       []string    `json:"Network"`
		Authorization interface{} `json:"Authorization"`
		Log           []string    `json:"Log"`
	} `json:"Plugins"`
	MemoryLimit        bool      `json:"MemoryLimit"`
	SwapLimit          bool      `json:"SwapLimit"`
	KernelMemory       bool      `json:"KernelMemory"`
	KernelMemoryTCP    bool      `json:"KernelMemoryTCP"`
	CPUCfsPeriod       bool      `json:"CpuCfsPeriod"`
	CPUCfsQuota        bool      `json:"CpuCfsQuota"`
	CPUShares          bool      `json:"CPUShares"`
	CPUSet             bool      `json:"CPUSet"`
	PidsLimit          bool      `json:"PidsLimit"`
	IPv4Forwarding     bool      `json:"IPv4Forwarding"`
	BridgeNfIptables   bool      `json:"BridgeNfIptables"`
	BridgeNfIP6Tables  bool      `json:"BridgeNfIp6tables"`
	Debug              bool      `json:"Debug"`
	NFd                int       `json:"NFd"`
	OomKillDisable     bool      `json:"OomKillDisable"`
	NGoroutines        int       `json:"NGoroutines"`
	SystemTime         time.Time `json:"SystemTime"`
	LoggingDriver      string    `json:"LoggingDriver"`
	CgroupDriver       string    `json:"CgroupDriver"`
	NEventsListener    int       `json:"NEventsListener"`
	KernelVersion      string    `json:"KernelVersion"`
	OperatingSystem    string    `json:"OperatingSystem"`
	OSType             string    `json:"OSType"`
	Architecture       string    `json:"Architecture"`
	IndexServerAddress string    `json:"IndexServerAddress"`
	RegistryConfig     struct {
		AllowNondistributableArtifactsCIDRs     []interface{} `json:"AllowNondistributableArtifactsCIDRs"`
		AllowNondistributableArtifactsHostnames []interface{} `json:"AllowNondistributableArtifactsHostnames"`
		InsecureRegistryCIDRs                   []string      `json:"InsecureRegistryCIDRs"`
		IndexConfigs                            struct {
			DockerIo struct {
				Name     string        `json:"Name"`
				Mirrors  []interface{} `json:"Mirrors"`
				Secure   bool          `json:"Secure"`
				Official bool          `json:"Official"`
			} `json:"docker.io"`
		} `json:"IndexConfigs"`
		Mirrors []interface{} `json:"Mirrors"`
	} `json:"RegistryConfig"`
	NCPU              int           `json:"NCPU"`
	MemTotal          int64         `json:"MemTotal"`
	GenericResources  interface{}   `json:"GenericResources"`
	DockerRootDir     string        `json:"DockerRootDir"`
	HTTPProxy         string        `json:"HttpProxy"`
	HTTPSProxy        string        `json:"HttpsProxy"`
	NoProxy           string        `json:"NoProxy"`
	Name              string        `json:"Name"`
	Labels            []interface{} `json:"Labels"`
	ExperimentalBuild bool          `json:"ExperimentalBuild"`
	ServerVersion     string        `json:"ServerVersion"`
	ClusterStore      string        `json:"ClusterStore"`
	ClusterAdvertise  string        `json:"ClusterAdvertise"`
	Runtimes          struct {
		Runc struct {
			Path string `json:"path"`
		} `json:"runc"`
	} `json:"Runtimes"`
	DefaultRuntime string `json:"DefaultRuntime"`
	Swarm          struct {
		NodeID           string      `json:"NodeID"`
		NodeAddr         string      `json:"NodeAddr"`
		LocalNodeState   string      `json:"LocalNodeState"`
		ControlAvailable bool        `json:"ControlAvailable"`
		Error            string      `json:"Error"`
		RemoteManagers   interface{} `json:"RemoteManagers"`
	} `json:"Swarm"`
	LiveRestoreEnabled bool   `json:"LiveRestoreEnabled"`
	Isolation          string `json:"Isolation"`
	InitBinary         string `json:"InitBinary"`
	ContainerdCommit   struct {
		ID       string `json:"ID"`
		Expected string `json:"Expected"`
	} `json:"ContainerdCommit"`
	RuncCommit struct {
		ID       string `json:"ID"`
		Expected string `json:"Expected"`
	} `json:"RuncCommit"`
	InitCommit struct {
		ID       string `json:"ID"`
		Expected string `json:"Expected"`
	} `json:"InitCommit"`
	SecurityOptions []string    `json:"SecurityOptions"`
	ProductLicense  string      `json:"ProductLicense"`
	Warnings        interface{} `json:"Warnings"`
	ClientInfo      struct {
		Debug    bool          `json:"Debug"`
		Plugins  []interface{} `json:"Plugins"`
		Warnings interface{}   `json:"Warnings"`
	} `json:"ClientInfo"`
}

// podmanSysInfo represents the output of podman system info --format '{{json .}}'
type podmanSysInfo struct {
	Host struct {
		BuildahVersion string `json:"BuildahVersion"`
		CgroupVersion  string `json:"CgroupVersion"`
		Conmon         struct {
			Package string `json:"package"`
			Path    string `json:"path"`
			Version string `json:"version"`
		} `json:"Conmon"`
		Distribution struct {
			Distribution string `json:"distribution"`
			Version      string `json:"version"`
		} `json:"Distribution"`
		MemFree    int   `json:"MemFree"`
		MemTotal   int64 `json:"MemTotal"`
		OCIRuntime struct {
			Name    string `json:"name"`
			Package string `json:"package"`
			Path    string `json:"path"`
			Version string `json:"version"`
		} `json:"OCIRuntime"`
		SwapFree    int    `json:"SwapFree"`
		SwapTotal   int    `json:"SwapTotal"`
		Arch        string `json:"arch"`
		Cpus        int    `json:"cpus"`
		Eventlogger string `json:"eventlogger"`
		Hostname    string `json:"hostname"`
		Kernel      string `json:"kernel"`
		Os          string `json:"os"`
		Rootless    bool   `json:"rootless"`
		Uptime      string `json:"uptime"`
	} `json:"host"`
	Registries struct {
		Search []string `json:"search"`
	} `json:"registries"`
	Store struct {
		ConfigFile     string `json:"ConfigFile"`
		ContainerStore struct {
			Number int `json:"number"`
		} `json:"ContainerStore"`
		GraphDriverName string `json:"GraphDriverName"`
		GraphOptions    struct {
		} `json:"GraphOptions"`
		GraphRoot   string `json:"GraphRoot"`
		GraphStatus struct {
			BackingFilesystem string `json:"Backing Filesystem"`
			NativeOverlayDiff string `json:"Native Overlay Diff"`
			SupportsDType     string `json:"Supports d_type"`
			UsingMetacopy     string `json:"Using metacopy"`
		} `json:"GraphStatus"`
		ImageStore struct {
			Number int `json:"number"`
		} `json:"ImageStore"`
		RunRoot    string `json:"RunRoot"`
		VolumePath string `json:"VolumePath"`
	} `json:"store"`
}

// dockerSystemInfo returns docker system info --format '{{json .}}'
func dockerSystemInfo() (dockerSysInfo, error) {
	var ds dockerSysInfo
	rr, err := runCmd(exec.Command(Docker, "system", "info", "--format", "{{json .}}"))
	if err != nil {
		return ds, errors.Wrap(err, "get docker system info")
	}

	if err := json.Unmarshal([]byte(strings.TrimSpace(rr.Stdout.String())), &ds); err != nil {
		return ds, errors.Wrapf(err, "unmarshal docker system info")
	}

	return ds, nil
}

// podmanSysInfo returns podman system info --format '{{json .}}'
func podmanSystemInfo() (podmanSysInfo, error) {
	var ps podmanSysInfo
	rr, err := runCmd(exec.Command(Podman, "system", "info", "--format", "json"))
	if err != nil {
		return ps, errors.Wrap(err, "get podman system info")
	}

	if err := json.Unmarshal([]byte(strings.TrimSpace(rr.Stdout.String())), &ps); err != nil {
		return ps, errors.Wrapf(err, "unmarshal podman system info")
	}
	return ps, nil
}
<commit_msg>remove duplicate return statement<commit_after>/*
Copyright 2019 The Kubernetes Authors All rights reserved.

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

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

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

package oci

import (
	"encoding/json"
	"os/exec"
	"strings"
	"time"

	"github.com/pkg/errors"
)

// SysInfo Info represents common system Information between docker and podman that minikube cares
type SysInfo struct {
	CPUs        int    // CPUs is Number of CPUs
	TotalMemory int64  // TotalMemory Total available ram
	OSType      string // container's OsType (windows or linux)
}

var cachedSysInfo *SysInfo
var cachedSysInfoErr *error

// CachedDaemonInfo will run and return a docker/podman info only once per minikube run time. to avoid performance
func CachedDaemonInfo(ociBin string) (SysInfo, error) {
	if cachedSysInfo == nil {
		si, err := DaemonInfo(ociBin)
		cachedSysInfo = &si
		cachedSysInfoErr = &err
	}
	return *cachedSysInfo, *cachedSysInfoErr
}

// DaemonInfo returns common docker/podman daemon system info that minikube cares about
func DaemonInfo(ociBin string) (SysInfo, error) {
	if ociBin == Podman {
		p, err := podmanSystemInfo()
		cachedSysInfo.CPUs = p.Host.Cpus
		cachedSysInfo.TotalMemory = p.Host.MemTotal
		cachedSysInfo.OSType = p.Host.Os
		return *cachedSysInfo, err
	}
	d, err := dockerSystemInfo()
	cachedSysInfo.CPUs = d.NCPU
	cachedSysInfo.TotalMemory = d.MemTotal
	cachedSysInfo.OSType = d.OSType
	return *cachedSysInfo, err
}

// dockerSysInfo represents the output of docker system info --format '{{json .}}'
type dockerSysInfo struct {
	ID                string      `json:"ID"`
	Containers        int         `json:"Containers"`
	ContainersRunning int         `json:"ContainersRunning"`
	ContainersPaused  int         `json:"ContainersPaused"`
	ContainersStopped int         `json:"ContainersStopped"`
	Images            int         `json:"Images"`
	Driver            string      `json:"Driver"`
	DriverStatus      [][]string  `json:"DriverStatus"`
	SystemStatus      interface{} `json:"SystemStatus"`
	Plugins           struct {
		Volume        []string    `json:"Volume"`
		Network       []string    `json:"Network"`
		Authorization interface{} `json:"Authorization"`
		Log           []string    `json:"Log"`
	} `json:"Plugins"`
	MemoryLimit        bool      `json:"MemoryLimit"`
	SwapLimit          bool      `json:"SwapLimit"`
	KernelMemory       bool      `json:"KernelMemory"`
	KernelMemoryTCP    bool      `json:"KernelMemoryTCP"`
	CPUCfsPeriod       bool      `json:"CpuCfsPeriod"`
	CPUCfsQuota        bool      `json:"CpuCfsQuota"`
	CPUShares          bool      `json:"CPUShares"`
	CPUSet             bool      `json:"CPUSet"`
	PidsLimit          bool      `json:"PidsLimit"`
	IPv4Forwarding     bool      `json:"IPv4Forwarding"`
	BridgeNfIptables   bool      `json:"BridgeNfIptables"`
	BridgeNfIP6Tables  bool      `json:"BridgeNfIp6tables"`
	Debug              bool      `json:"Debug"`
	NFd                int       `json:"NFd"`
	OomKillDisable     bool      `json:"OomKillDisable"`
	NGoroutines        int       `json:"NGoroutines"`
	SystemTime         time.Time `json:"SystemTime"`
	LoggingDriver      string    `json:"LoggingDriver"`
	CgroupDriver       string    `json:"CgroupDriver"`
	NEventsListener    int       `json:"NEventsListener"`
	KernelVersion      string    `json:"KernelVersion"`
	OperatingSystem    string    `json:"OperatingSystem"`
	OSType             string    `json:"OSType"`
	Architecture       string    `json:"Architecture"`
	IndexServerAddress string    `json:"IndexServerAddress"`
	RegistryConfig     struct {
		AllowNondistributableArtifactsCIDRs     []interface{} `json:"AllowNondistributableArtifactsCIDRs"`
		AllowNondistributableArtifactsHostnames []interface{} `json:"AllowNondistributableArtifactsHostnames"`
		InsecureRegistryCIDRs                   []string      `json:"InsecureRegistryCIDRs"`
		IndexConfigs                            struct {
			DockerIo struct {
				Name     string        `json:"Name"`
				Mirrors  []interface{} `json:"Mirrors"`
				Secure   bool          `json:"Secure"`
				Official bool          `json:"Official"`
			} `json:"docker.io"`
		} `json:"IndexConfigs"`
		Mirrors []interface{} `json:"Mirrors"`
	} `json:"RegistryConfig"`
	NCPU              int           `json:"NCPU"`
	MemTotal          int64         `json:"MemTotal"`
	GenericResources  interface{}   `json:"GenericResources"`
	DockerRootDir     string        `json:"DockerRootDir"`
	HTTPProxy         string        `json:"HttpProxy"`
	HTTPSProxy        string        `json:"HttpsProxy"`
	NoProxy           string        `json:"NoProxy"`
	Name              string        `json:"Name"`
	Labels            []interface{} `json:"Labels"`
	ExperimentalBuild bool          `json:"ExperimentalBuild"`
	ServerVersion     string        `json:"ServerVersion"`
	ClusterStore      string        `json:"ClusterStore"`
	ClusterAdvertise  string        `json:"ClusterAdvertise"`
	Runtimes          struct {
		Runc struct {
			Path string `json:"path"`
		} `json:"runc"`
	} `json:"Runtimes"`
	DefaultRuntime string `json:"DefaultRuntime"`
	Swarm          struct {
		NodeID           string      `json:"NodeID"`
		NodeAddr         string      `json:"NodeAddr"`
		LocalNodeState   string      `json:"LocalNodeState"`
		ControlAvailable bool        `json:"ControlAvailable"`
		Error            string      `json:"Error"`
		RemoteManagers   interface{} `json:"RemoteManagers"`
	} `json:"Swarm"`
	LiveRestoreEnabled bool   `json:"LiveRestoreEnabled"`
	Isolation          string `json:"Isolation"`
	InitBinary         string `json:"InitBinary"`
	ContainerdCommit   struct {
		ID       string `json:"ID"`
		Expected string `json:"Expected"`
	} `json:"ContainerdCommit"`
	RuncCommit struct {
		ID       string `json:"ID"`
		Expected string `json:"Expected"`
	} `json:"RuncCommit"`
	InitCommit struct {
		ID       string `json:"ID"`
		Expected string `json:"Expected"`
	} `json:"InitCommit"`
	SecurityOptions []string    `json:"SecurityOptions"`
	ProductLicense  string      `json:"ProductLicense"`
	Warnings        interface{} `json:"Warnings"`
	ClientInfo      struct {
		Debug    bool          `json:"Debug"`
		Plugins  []interface{} `json:"Plugins"`
		Warnings interface{}   `json:"Warnings"`
	} `json:"ClientInfo"`
}

// podmanSysInfo represents the output of podman system info --format '{{json .}}'
type podmanSysInfo struct {
	Host struct {
		BuildahVersion string `json:"BuildahVersion"`
		CgroupVersion  string `json:"CgroupVersion"`
		Conmon         struct {
			Package string `json:"package"`
			Path    string `json:"path"`
			Version string `json:"version"`
		} `json:"Conmon"`
		Distribution struct {
			Distribution string `json:"distribution"`
			Version      string `json:"version"`
		} `json:"Distribution"`
		MemFree    int   `json:"MemFree"`
		MemTotal   int64 `json:"MemTotal"`
		OCIRuntime struct {
			Name    string `json:"name"`
			Package string `json:"package"`
			Path    string `json:"path"`
			Version string `json:"version"`
		} `json:"OCIRuntime"`
		SwapFree    int    `json:"SwapFree"`
		SwapTotal   int    `json:"SwapTotal"`
		Arch        string `json:"arch"`
		Cpus        int    `json:"cpus"`
		Eventlogger string `json:"eventlogger"`
		Hostname    string `json:"hostname"`
		Kernel      string `json:"kernel"`
		Os          string `json:"os"`
		Rootless    bool   `json:"rootless"`
		Uptime      string `json:"uptime"`
	} `json:"host"`
	Registries struct {
		Search []string `json:"search"`
	} `json:"registries"`
	Store struct {
		ConfigFile     string `json:"ConfigFile"`
		ContainerStore struct {
			Number int `json:"number"`
		} `json:"ContainerStore"`
		GraphDriverName string `json:"GraphDriverName"`
		GraphOptions    struct {
		} `json:"GraphOptions"`
		GraphRoot   string `json:"GraphRoot"`
		GraphStatus struct {
			BackingFilesystem string `json:"Backing Filesystem"`
			NativeOverlayDiff string `json:"Native Overlay Diff"`
			SupportsDType     string `json:"Supports d_type"`
			UsingMetacopy     string `json:"Using metacopy"`
		} `json:"GraphStatus"`
		ImageStore struct {
			Number int `json:"number"`
		} `json:"ImageStore"`
		RunRoot    string `json:"RunRoot"`
		VolumePath string `json:"VolumePath"`
	} `json:"store"`
}

// dockerSystemInfo returns docker system info --format '{{json .}}'
func dockerSystemInfo() (dockerSysInfo, error) {
	var ds dockerSysInfo
	rr, err := runCmd(exec.Command(Docker, "system", "info", "--format", "{{json .}}"))
	if err != nil {
		return ds, errors.Wrap(err, "get docker system info")
	}

	if err := json.Unmarshal([]byte(strings.TrimSpace(rr.Stdout.String())), &ds); err != nil {
		return ds, errors.Wrapf(err, "unmarshal docker system info")
	}

	return ds, nil
}

// podmanSysInfo returns podman system info --format '{{json .}}'
func podmanSystemInfo() (podmanSysInfo, error) {
	var ps podmanSysInfo
	rr, err := runCmd(exec.Command(Podman, "system", "info", "--format", "json"))
	if err != nil {
		return ps, errors.Wrap(err, "get podman system info")
	}

	if err := json.Unmarshal([]byte(strings.TrimSpace(rr.Stdout.String())), &ps); err != nil {
		return ps, errors.Wrapf(err, "unmarshal podman system info")
	}
	return ps, nil
}
<|endoftext|>


<commit_before>/*
Copyright 2016 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 master

import (
	"k8s.io/kubernetes/pkg/api/rest"
	"k8s.io/kubernetes/pkg/apis/batch"
	batchapiv1 "k8s.io/kubernetes/pkg/apis/batch/v1"
	batchapiv2alpha1 "k8s.io/kubernetes/pkg/apis/batch/v2alpha1"
	"k8s.io/kubernetes/pkg/genericapiserver"
	jobetcd "k8s.io/kubernetes/pkg/registry/job/etcd"
)

type BatchRESTStorageProvider struct{}

var _ RESTStorageProvider = &BatchRESTStorageProvider{}

func (p BatchRESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) {
	apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(batch.GroupName)

	if apiResourceConfigSource.AnyResourcesForVersionEnabled(batchapiv2alpha1.SchemeGroupVersion) {
		apiGroupInfo.VersionedResourcesStorageMap[batchapiv2alpha1.SchemeGroupVersion.Version] = p.v2alpha1Storage(apiResourceConfigSource, restOptionsGetter)
		apiGroupInfo.GroupMeta.GroupVersion = batchapiv2alpha1.SchemeGroupVersion
	}
	if apiResourceConfigSource.AnyResourcesForVersionEnabled(batchapiv1.SchemeGroupVersion) {
		apiGroupInfo.VersionedResourcesStorageMap[batchapiv1.SchemeGroupVersion.Version] = p.v1Storage(apiResourceConfigSource, restOptionsGetter)
		apiGroupInfo.GroupMeta.GroupVersion = batchapiv1.SchemeGroupVersion
	}

	return apiGroupInfo, true
}

func (p BatchRESTStorageProvider) v1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter RESTOptionsGetter) map[string]rest.Storage {
	version := batchapiv1.SchemeGroupVersion

	storage := map[string]rest.Storage{}
	if apiResourceConfigSource.ResourceEnabled(version.WithResource("jobs")) {
		jobsStorage, jobsStatusStorage := jobetcd.NewREST(restOptionsGetter(batch.Resource("jobs")))
		storage["jobs"] = jobsStorage
		storage["jobs/status"] = jobsStatusStorage
	}
	return storage
}

func (p BatchRESTStorageProvider) v2alpha1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter RESTOptionsGetter) map[string]rest.Storage {
	version := batchapiv2alpha1.SchemeGroupVersion

	storage := map[string]rest.Storage{}
	if apiResourceConfigSource.ResourceEnabled(version.WithResource("jobs")) {
		jobsStorage, jobsStatusStorage := jobetcd.NewREST(restOptionsGetter(batch.Resource("jobs")))
		storage["jobs"] = jobsStorage
		storage["jobs/status"] = jobsStatusStorage
	}
	return storage
}
<commit_msg>ScheduledJob storage leftovers<commit_after>/*
Copyright 2016 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 master

import (
	"k8s.io/kubernetes/pkg/api/rest"
	"k8s.io/kubernetes/pkg/apis/batch"
	batchapiv1 "k8s.io/kubernetes/pkg/apis/batch/v1"
	batchapiv2alpha1 "k8s.io/kubernetes/pkg/apis/batch/v2alpha1"
	"k8s.io/kubernetes/pkg/genericapiserver"
	jobetcd "k8s.io/kubernetes/pkg/registry/job/etcd"
	scheduledjobetcd "k8s.io/kubernetes/pkg/registry/scheduledjob/etcd"
)

type BatchRESTStorageProvider struct{}

var _ RESTStorageProvider = &BatchRESTStorageProvider{}

func (p BatchRESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) {
	apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(batch.GroupName)

	if apiResourceConfigSource.AnyResourcesForVersionEnabled(batchapiv2alpha1.SchemeGroupVersion) {
		apiGroupInfo.VersionedResourcesStorageMap[batchapiv2alpha1.SchemeGroupVersion.Version] = p.v2alpha1Storage(apiResourceConfigSource, restOptionsGetter)
		apiGroupInfo.GroupMeta.GroupVersion = batchapiv2alpha1.SchemeGroupVersion
	}
	if apiResourceConfigSource.AnyResourcesForVersionEnabled(batchapiv1.SchemeGroupVersion) {
		apiGroupInfo.VersionedResourcesStorageMap[batchapiv1.SchemeGroupVersion.Version] = p.v1Storage(apiResourceConfigSource, restOptionsGetter)
		apiGroupInfo.GroupMeta.GroupVersion = batchapiv1.SchemeGroupVersion
	}

	return apiGroupInfo, true
}

func (p BatchRESTStorageProvider) v1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter RESTOptionsGetter) map[string]rest.Storage {
	version := batchapiv1.SchemeGroupVersion

	storage := map[string]rest.Storage{}
	if apiResourceConfigSource.ResourceEnabled(version.WithResource("jobs")) {
		jobsStorage, jobsStatusStorage := jobetcd.NewREST(restOptionsGetter(batch.Resource("jobs")))
		storage["jobs"] = jobsStorage
		storage["jobs/status"] = jobsStatusStorage
	}
	return storage
}

func (p BatchRESTStorageProvider) v2alpha1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter RESTOptionsGetter) map[string]rest.Storage {
	version := batchapiv2alpha1.SchemeGroupVersion

	storage := map[string]rest.Storage{}
	if apiResourceConfigSource.ResourceEnabled(version.WithResource("jobs")) {
		jobsStorage, jobsStatusStorage := jobetcd.NewREST(restOptionsGetter(batch.Resource("jobs")))
		storage["jobs"] = jobsStorage
		storage["jobs/status"] = jobsStatusStorage
	}
	if apiResourceConfigSource.ResourceEnabled(version.WithResource("scheduledjobs")) {
		scheduledJobsStorage, scheduledJobsStatusStorage := scheduledjobetcd.NewREST(restOptionsGetter(batch.Resource("scheduledjobs")))
		storage["scheduledjobs"] = scheduledJobsStorage
		storage["scheduledjobs/status"] = scheduledJobsStatusStorage
	}
	return storage
}
<|endoftext|>


<commit_before>/*
The syslog package provides a syslog client.

Unlike the core log/syslog package it uses the newer rfc5424 syslog protocol,
reliably reconnects on failure, and supports TLS encrypted TCP connections.
*/
package syslog

import (
	"crypto/tls"
	"crypto/x509"
	_ "crypto/sha512"
	"fmt"
	"io"
	"net"
	"time"
)

// A net.Conn with added reconnection logic
type conn struct {
	netConn net.Conn
	errors  chan error
}

// watch watches the connection for error, sends detected error to c.errors
func (c *conn) watch() {
	for {
		data := make([]byte, 1)
		_, err := c.netConn.Read(data)
		if err != nil {
			c.netConn.Close()
			c.errors <- err
			return
		}
	}
}

// reconnectNeeded determines if a reconnect is needed by checking for a
// message on the readErrors channel
func (c *conn) reconnectNeeded() bool {
	if c == nil {
		return true
	}
	select {
	case <-c.errors:
		return true
	default:
		return false
	}
}

// dial connects to the server and set up a watching goroutine
func dial(network, raddr string, rootCAs *x509.CertPool, connectTimeout time.Duration) (*conn, error) {
	var netConn net.Conn
	var err error

	switch network {
	case "tls":
		var config *tls.Config
		if rootCAs != nil {
			config = &tls.Config{RootCAs: rootCAs}
		}
		dialer := &net.Dialer{
			Timeout : connectTimeout,
		}
		netConn, err = tls.DialWithDialer(dialer, "tcp", raddr, config)
	case "udp", "tcp":
		netConn, err = net.DialTimeout(network, raddr, connectTimeout)
	default:
		return nil, fmt.Errorf("Network protocol %s not supported", network)
	}
	if err != nil {
		return nil, err
	} else {
		c := &conn{netConn, make(chan error)}
		go c.watch()
		return c, nil
	}
}

// A Logger is a connection to a syslog server. It reconnects on error.
// Clients log by sending a Packet to the logger.Packets channel.
type Logger struct {
	conn           *conn
	Packets        chan Packet
	Errors         chan error
	ClientHostname string

	network string
	raddr   string
	rootCAs *x509.CertPool
	connectTimeout time.Duration
	writeTimeout time.Duration
}

// Dial connects to the syslog server at raddr, using the optional certBundle,
// and launches a goroutine to watch logger.Packets for messages to log.
func Dial(clientHostname, network, raddr string, rootCAs *x509.CertPool, connectTimeout time.Duration, writeTimeout time.Duration) (*Logger, error) {
	// dial once, just to make sure the network is working
	conn, err := dial(network, raddr, rootCAs, connectTimeout)

	logger := &Logger{
		ClientHostname: clientHostname,
		network:        network,
		raddr:          raddr,
		rootCAs:        rootCAs,
		Packets:        make(chan Packet, 100),
		Errors:         make(chan error, 0),
		connectTimeout: connectTimeout,
		writeTimeout:	writeTimeout,
		conn:           conn,
	}
	go logger.writeLoop()
	return logger, err
}

// Connect to the server, retrying every 10 seconds until successful.
func (l *Logger) connect() {
	for {
		c, err := dial(l.network, l.raddr, l.rootCAs, l.connectTimeout)
		if err == nil {
			l.conn = c
			return
		} else {
			l.handleError(err)
			time.Sleep(10 * time.Second)
		}
	}
	panic("unreachable")
}

// Send an error to the Error channel, but don't block if nothing is listening
func (l *Logger) handleError(err error) {
	select {
	case l.Errors <- err:
	default:
	}
}

// Write a packet, reconnecting if needed. It is not safe to call this
// method concurrently.
func (l *Logger) writePacket(p Packet) {
	var err error
	for {
		if l.conn.reconnectNeeded() {
			l.connect()
		}

		deadline := time.Now().Add(l.writeTimeout)
		switch l.conn.netConn.(type) {
		case *net.TCPConn, *tls.Conn:
			l.conn.netConn.SetWriteDeadline(deadline)
			_, err = io.WriteString(l.conn.netConn, p.Generate(0)+"\n")
		case *net.UDPConn:
			l.conn.netConn.SetWriteDeadline(deadline)
			_, err = io.WriteString(l.conn.netConn, p.Generate(1024))
		default:
			panic(fmt.Errorf("Network protocol %s not supported", l.network))
		}
		if err == nil {
			return
		} else {
			l.handleError(err)
			time.Sleep(10 * time.Second)
		}
	}
}

// writeloop writes any packets recieved on l.Packets() to the syslog server.
func (l *Logger) writeLoop() {
	for p := range l.Packets {
		l.writePacket(p)
	}
}
<commit_msg>TCP has a limit of 100 KB<commit_after>/*
The syslog package provides a syslog client.

Unlike the core log/syslog package it uses the newer rfc5424 syslog protocol,
reliably reconnects on failure, and supports TLS encrypted TCP connections.
*/
package syslog

import (
	"crypto/tls"
	"crypto/x509"
	_ "crypto/sha512"
	"fmt"
	"io"
	"net"
	"time"
)

// A net.Conn with added reconnection logic
type conn struct {
	netConn net.Conn
	errors  chan error
}

// watch watches the connection for error, sends detected error to c.errors
func (c *conn) watch() {
	for {
		data := make([]byte, 1)
		_, err := c.netConn.Read(data)
		if err != nil {
			c.netConn.Close()
			c.errors <- err
			return
		}
	}
}

// reconnectNeeded determines if a reconnect is needed by checking for a
// message on the readErrors channel
func (c *conn) reconnectNeeded() bool {
	if c == nil {
		return true
	}
	select {
	case <-c.errors:
		return true
	default:
		return false
	}
}

// dial connects to the server and set up a watching goroutine
func dial(network, raddr string, rootCAs *x509.CertPool, connectTimeout time.Duration) (*conn, error) {
	var netConn net.Conn
	var err error

	switch network {
	case "tls":
		var config *tls.Config
		if rootCAs != nil {
			config = &tls.Config{RootCAs: rootCAs}
		}
		dialer := &net.Dialer{
			Timeout : connectTimeout,
		}
		netConn, err = tls.DialWithDialer(dialer, "tcp", raddr, config)
	case "udp", "tcp":
		netConn, err = net.DialTimeout(network, raddr, connectTimeout)
	default:
		return nil, fmt.Errorf("Network protocol %s not supported", network)
	}
	if err != nil {
		return nil, err
	} else {
		c := &conn{netConn, make(chan error)}
		go c.watch()
		return c, nil
	}
}

// A Logger is a connection to a syslog server. It reconnects on error.
// Clients log by sending a Packet to the logger.Packets channel.
type Logger struct {
	conn           *conn
	Packets        chan Packet
	Errors         chan error
	ClientHostname string

	network string
	raddr   string
	rootCAs *x509.CertPool
	connectTimeout time.Duration
	writeTimeout time.Duration
}

// Dial connects to the syslog server at raddr, using the optional certBundle,
// and launches a goroutine to watch logger.Packets for messages to log.
func Dial(clientHostname, network, raddr string, rootCAs *x509.CertPool, connectTimeout time.Duration, writeTimeout time.Duration) (*Logger, error) {
	// dial once, just to make sure the network is working
	conn, err := dial(network, raddr, rootCAs, connectTimeout)

	logger := &Logger{
		ClientHostname: clientHostname,
		network:        network,
		raddr:          raddr,
		rootCAs:        rootCAs,
		Packets:        make(chan Packet, 100),
		Errors:         make(chan error, 0),
		connectTimeout: connectTimeout,
		writeTimeout:	writeTimeout,
		conn:           conn,
	}
	go logger.writeLoop()
	return logger, err
}

// Connect to the server, retrying every 10 seconds until successful.
func (l *Logger) connect() {
	for {
		c, err := dial(l.network, l.raddr, l.rootCAs, l.connectTimeout)
		if err == nil {
			l.conn = c
			return
		} else {
			l.handleError(err)
			time.Sleep(10 * time.Second)
		}
	}
	panic("unreachable")
}

// Send an error to the Error channel, but don't block if nothing is listening
func (l *Logger) handleError(err error) {
	select {
	case l.Errors <- err:
	default:
	}
}

// Write a packet, reconnecting if needed. It is not safe to call this
// method concurrently.
func (l *Logger) writePacket(p Packet) {
	var err error
	for {
		if l.conn.reconnectNeeded() {
			l.connect()
		}

		deadline := time.Now().Add(l.writeTimeout)
		switch l.conn.netConn.(type) {
		case *net.TCPConn, *tls.Conn:
			l.conn.netConn.SetWriteDeadline(deadline)
			_, err = io.WriteString(l.conn.netConn, p.Generate(102400)+"\n")
		case *net.UDPConn:
			l.conn.netConn.SetWriteDeadline(deadline)
			_, err = io.WriteString(l.conn.netConn, p.Generate(1024))
		default:
			panic(fmt.Errorf("Network protocol %s not supported", l.network))
		}
		if err == nil {
			return
		} else {
			l.handleError(err)
			time.Sleep(10 * time.Second)
		}
	}
}

// writeloop writes any packets recieved on l.Packets() to the syslog server.
func (l *Logger) writeLoop() {
	for p := range l.Packets {
		l.writePacket(p)
	}
}
<|endoftext|>


<commit_before>// Copyright (c) 2016, Daniel Martí <mvdan@mvdan.cc>
// See LICENSE for licensing information

package main

import (
	"bufio"
	"bytes"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"

	"github.com/mvdan/sh"
)

var (
	write  = flag.Bool("w", false, "write result to file instead of stdout")
	list   = flag.Bool("l", false, "list files whose formatting differs from shfmt's")
	indent = flag.Int("i", 0, "indent: 0 for tabs (default), >0 for number of spaces")
)

var config sh.PrintConfig

func main() {
	flag.Parse()
	config.Spaces = *indent
	if flag.NArg() == 0 {
		if err := formatStdin(); err != nil {
			fmt.Fprintln(os.Stderr, err)
			os.Exit(1)
		}
		return
	}
	anyErr := false
	for _, path := range flag.Args() {
		if err := work(path); err != nil {
			anyErr = true
			fmt.Fprintln(os.Stderr, err)
		}
	}
	if anyErr {
		os.Exit(1)
	}
}

func formatStdin() error {
	if *write || *list {
		return fmt.Errorf("-w and -l can only be used on files")
	}
	prog, err := sh.Parse(os.Stdin, "", sh.ParseComments)
	if err != nil {
		return err
	}
	return config.Fprint(os.Stdout, prog)
}

var (
	hidden    = regexp.MustCompile(`^\.[^/.]`)
	shellFile = regexp.MustCompile(`^.*\.(sh|bash)$`)
)

func work(path string) error {
	info, err := os.Stat(path)
	if err != nil {
		return err
	}
	if !info.IsDir() {
		return formatPath(path)
	}
	return filepath.Walk(path, func(path string, info os.FileInfo, err error) error {
		if hidden.MatchString(path) {
			return filepath.SkipDir
		}
		if info.IsDir() || !shellFile.MatchString(path) {
			return nil
		}
		return formatPath(path)
	})
}

func empty(f *os.File) error {
	if err := f.Truncate(0); err != nil {
		return err
	}
	_, err := f.Seek(0, 0)
	return err
}

func formatPath(path string) error {
	f, err := os.OpenFile(path, os.O_RDWR, 0)
	if err != nil {
		return err
	}
	prog, err := sh.Parse(f, path, sh.ParseComments)
	if err != nil {
		return err
	}
	var orig string
	if *list {
		if _, err := f.Seek(0, 0); err != nil {
			return err
		}
		b, err := ioutil.ReadAll(f)
		if err != nil {
			return err
		}
		orig = string(b)
	}
	switch {
	case *list && *write:
		var buf bytes.Buffer
		if err := config.Fprint(&buf, prog); err != nil {
			return err
		}
		if buf.String() != orig {
			fmt.Println(path)
		}
		if err := empty(f); err != nil {
			return err
		}
		_, err := io.Copy(f, &buf)
		if err != nil {
			return err
		}
		return f.Close()
	case *write:
		if err := empty(f); err != nil {
			return err
		}
		w := bufio.NewWriter(f)
		if err := config.Fprint(w, prog); err != nil {
			return err
		}
		if err := w.Flush(); err != nil {
			return err
		}
		return f.Close()
	case *list:
		var buf bytes.Buffer
		if err := config.Fprint(&buf, prog); err != nil {
			return err
		}
		if buf.String() != orig {
			fmt.Println(path)
		}
		f.Close()
	default:
		f.Close()
		return config.Fprint(os.Stdout, prog)
	}
	return nil
}
<commit_msg>shfmt: open file in read-write only with -w<commit_after>// Copyright (c) 2016, Daniel Martí <mvdan@mvdan.cc>
// See LICENSE for licensing information

package main

import (
	"bufio"
	"bytes"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"

	"github.com/mvdan/sh"
)

var (
	write  = flag.Bool("w", false, "write result to file instead of stdout")
	list   = flag.Bool("l", false, "list files whose formatting differs from shfmt's")
	indent = flag.Int("i", 0, "indent: 0 for tabs (default), >0 for number of spaces")
)

var config sh.PrintConfig

func main() {
	flag.Parse()
	config.Spaces = *indent
	if flag.NArg() == 0 {
		if err := formatStdin(); err != nil {
			fmt.Fprintln(os.Stderr, err)
			os.Exit(1)
		}
		return
	}
	anyErr := false
	for _, path := range flag.Args() {
		if err := work(path); err != nil {
			anyErr = true
			fmt.Fprintln(os.Stderr, err)
		}
	}
	if anyErr {
		os.Exit(1)
	}
}

func formatStdin() error {
	if *write || *list {
		return fmt.Errorf("-w and -l can only be used on files")
	}
	prog, err := sh.Parse(os.Stdin, "", sh.ParseComments)
	if err != nil {
		return err
	}
	return config.Fprint(os.Stdout, prog)
}

var (
	hidden    = regexp.MustCompile(`^\.[^/.]`)
	shellFile = regexp.MustCompile(`^.*\.(sh|bash)$`)
)

func work(path string) error {
	info, err := os.Stat(path)
	if err != nil {
		return err
	}
	if !info.IsDir() {
		return formatPath(path)
	}
	return filepath.Walk(path, func(path string, info os.FileInfo, err error) error {
		if hidden.MatchString(path) {
			return filepath.SkipDir
		}
		if info.IsDir() || !shellFile.MatchString(path) {
			return nil
		}
		return formatPath(path)
	})
}

func empty(f *os.File) error {
	if err := f.Truncate(0); err != nil {
		return err
	}
	_, err := f.Seek(0, 0)
	return err
}

func formatPath(path string) error {
	mode := os.O_RDONLY
	if *write {
		mode = os.O_RDWR
	}
	f, err := os.OpenFile(path, mode, 0)
	if err != nil {
		return err
	}
	prog, err := sh.Parse(f, path, sh.ParseComments)
	if err != nil {
		return err
	}
	var orig string
	if *list {
		if _, err := f.Seek(0, 0); err != nil {
			return err
		}
		b, err := ioutil.ReadAll(f)
		if err != nil {
			return err
		}
		orig = string(b)
	}
	switch {
	case *list && *write:
		var buf bytes.Buffer
		if err := config.Fprint(&buf, prog); err != nil {
			return err
		}
		if buf.String() != orig {
			fmt.Println(path)
		}
		if err := empty(f); err != nil {
			return err
		}
		_, err := io.Copy(f, &buf)
		if err != nil {
			return err
		}
		return f.Close()
	case *write:
		if err := empty(f); err != nil {
			return err
		}
		w := bufio.NewWriter(f)
		if err := config.Fprint(w, prog); err != nil {
			return err
		}
		if err := w.Flush(); err != nil {
			return err
		}
		return f.Close()
	case *list:
		var buf bytes.Buffer
		if err := config.Fprint(&buf, prog); err != nil {
			return err
		}
		if buf.String() != orig {
			fmt.Println(path)
		}
		f.Close()
	default:
		f.Close()
		return config.Fprint(os.Stdout, prog)
	}
	return nil
}
<|endoftext|>


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

package main

import (
	"github.com/globocom/tsuru/cmd"
	"github.com/globocom/tsuru/cmd/tsuru-base"
	"os"
)

const (
	version = "0.8.4"
	header  = "Supported-Tsuru"
)

func buildManager(name string) *cmd.Manager {
	m := cmd.BuildBaseManager(name, version, header)
	m.Register(&tsuru.AppRun{})
	m.Register(&tsuru.AppInfo{})
	m.Register(AppCreate{})
	m.Register(&AppRemove{})
	m.Register(&UnitAdd{})
	m.Register(&UnitRemove{})
	m.Register(tsuru.AppList{})
	m.Register(&tsuru.AppLog{})
	m.Register(&tsuru.AppGrant{})
	m.Register(&tsuru.AppRevoke{})
	m.Register(&tsuru.AppRestart{})
	m.Register(&tsuru.SetCName{})
	m.Register(&tsuru.UnsetCName{})
	m.Register(&tsuru.EnvGet{})
	m.Register(&tsuru.EnvSet{})
	m.Register(&tsuru.EnvUnset{})
	m.Register(&KeyAdd{})
	m.Register(&KeyRemove{})
	m.Register(tsuru.ServiceList{})
	m.Register(tsuru.ServiceAdd{})
	m.Register(tsuru.ServiceRemove{})
	m.Register(tsuru.ServiceDoc{})
	m.Register(tsuru.ServiceInfo{})
	m.Register(tsuru.ServiceInstanceStatus{})
	m.Register(&tsuru.ServiceBind{})
	m.Register(&tsuru.ServiceUnbind{})
	m.Register(platformList{})
	m.Register(swap{})
	return m
}

func main() {
	name := cmd.ExtractProgramName(os.Args[0])
	manager := buildManager(name)
	manager.Run(os.Args[1:])
}
<commit_msg>cmd/tsuru: version 0.8.5<commit_after>// Copyright 2013 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"github.com/globocom/tsuru/cmd"
	"github.com/globocom/tsuru/cmd/tsuru-base"
	"os"
)

const (
	version = "0.8.5"
	header  = "Supported-Tsuru"
)

func buildManager(name string) *cmd.Manager {
	m := cmd.BuildBaseManager(name, version, header)
	m.Register(&tsuru.AppRun{})
	m.Register(&tsuru.AppInfo{})
	m.Register(AppCreate{})
	m.Register(&AppRemove{})
	m.Register(&UnitAdd{})
	m.Register(&UnitRemove{})
	m.Register(tsuru.AppList{})
	m.Register(&tsuru.AppLog{})
	m.Register(&tsuru.AppGrant{})
	m.Register(&tsuru.AppRevoke{})
	m.Register(&tsuru.AppRestart{})
	m.Register(&tsuru.SetCName{})
	m.Register(&tsuru.UnsetCName{})
	m.Register(&tsuru.EnvGet{})
	m.Register(&tsuru.EnvSet{})
	m.Register(&tsuru.EnvUnset{})
	m.Register(&KeyAdd{})
	m.Register(&KeyRemove{})
	m.Register(tsuru.ServiceList{})
	m.Register(tsuru.ServiceAdd{})
	m.Register(tsuru.ServiceRemove{})
	m.Register(tsuru.ServiceDoc{})
	m.Register(tsuru.ServiceInfo{})
	m.Register(tsuru.ServiceInstanceStatus{})
	m.Register(&tsuru.ServiceBind{})
	m.Register(&tsuru.ServiceUnbind{})
	m.Register(platformList{})
	m.Register(swap{})
	return m
}

func main() {
	name := cmd.ExtractProgramName(os.Args[0])
	manager := buildManager(name)
	manager.Run(os.Args[1:])
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io"
	"sync"
)

var subTaskChan chan *subTask

func init() {
	subTaskChan = make(chan *subTask)
}

type TaskExecutor interface {
	Execute(errChan chan<- error) []*Env
}

type ConcurrentActions struct {
	Actions             []*ActionSpec `json:"actions"`
	ProceedWhenNoUpdate bool          `json:"proceed-when-no-update"`
}

type TaskSpec struct {
	ConcurrentActions []*ConcurrentActions `json:"concurrent-actions"`
	InitEnv           *Env                 `json:"env,omitempty"`
	Plugins           []*PluginSpec        `json:"plugins,omitempty"`
	Finalizers        []*TaskFinalizerSpec `json:"finally,omitempty"`
}

func (self *TaskSpec) GetWorker(rr ResponseReader) (exec TaskExecutor, err error) {
	ret := new(worker)

	if rr == nil {
		plugins := self.Plugins
		if len(plugins) == 0 {
			plugins = []*PluginSpec{
				&PluginSpec{
					Name:   "http",
					Params: nil,
				},
			}
		}
		rr, err = NewPluginChain(plugins)
		if err != nil {
			return
		}
		ret.closer = rr
	}

	ret.rr = rr
	ret.spec = self
	ret.subTaskChan = subTaskChan
	exec = ret
	return
}

func StartWorkers(n int) {
	if n <= 0 {
		n = 2
	}
	for i := 0; i < n; i++ {
		go subTaskExecutor(subTaskChan)
	}
}

func StopAllWorkers() {
	close(subTaskChan)
	subTaskChan = make(chan *subTask)
}

type worker struct {
	subTaskChan chan<- *subTask
	spec        *TaskSpec
	rr          ResponseReader
	closer      io.Closer
}

type subTaskResult struct {
	err     error
	updates []*Env
}

type subTask struct {
	action  *Action
	env     *Env
	resChan chan<- *subTaskResult
}

func subTaskExecutor(taskChan <-chan *subTask) {
	for st := range taskChan {
		updates, err := st.action.Perform(st.env)
		res := new(subTaskResult)
		res.updates = updates
		res.err = err
		st.resChan <- res
	}
}

func (self *worker) Execute(errChan chan<- error) []*Env {
	if self.closer != nil {
		defer self.closer.Close()
	}
	envs := make([]*Env, 1)
	envs[0] = self.spec.InitEnv
	if envs[0].IsEmpty() {
		envs[0] = EmptyEnv()
	}
	var nilEnvs [1]*Env
	nilEnvs[0] = EmptyEnv()

	for _, concurrentActions := range self.spec.ConcurrentActions {
		nrActions := len(concurrentActions.Actions)
		if nrActions == 0 {
			continue
		}
		resChan := make(chan *subTaskResult)
		updates := make([]*Env, 0, nrActions*2)
		var wg sync.WaitGroup
		wg.Add(1)
		// reaper function
		go func(n int) {
			defer wg.Done()
			for i := 0; i < n; i++ {
				res := <-resChan
				if res.err != nil {
					errChan <- res.err
					continue
				}
				updates = append(updates, res.updates...)
			}
		}(nrActions * len(envs))

		for _, env := range envs {
			for _, spec := range concurrentActions.Actions {
				action, err := spec.GetAction(self.rr)
				if err != nil {
					res := new(subTaskResult)
					res.err = fmt.Errorf("Action %v is invalid: %v", spec.Tag, err)
					resChan <- res
					continue
				}
				st := new(subTask)
				st.action = action
				st.env = env
				st.resChan = resChan
				self.subTaskChan <- st
			}
		}
		wg.Wait()
		if len(updates) == 0 && !concurrentActions.ProceedWhenNoUpdate {
			break
		}
		forks := make([]*Env, 0, len(envs)*len(updates))
		for _, env := range envs {
			f := env.Fork(updates...)
			forks = append(forks, f...)
		}
		envs = uniqEnvs(forks...)
		if len(envs) == 0 {
			envs = nilEnvs[:]
		}
	}
	return envs
}
<commit_msg>rename in json<commit_after>package main

import (
	"fmt"
	"io"
	"sync"
)

var subTaskChan chan *subTask

func init() {
	subTaskChan = make(chan *subTask)
}

type TaskExecutor interface {
	Execute(errChan chan<- error) []*Env
}

type ConcurrentActions struct {
	Actions             []*ActionSpec `json:"concurrent-actions"`
	ProceedWhenNoUpdate bool          `json:"proceed-when-no-update,omitempty"`
}

type TaskSpec struct {
	ConcurrentActions []*ConcurrentActions `json:"action-seq"`
	InitEnv           *Env                 `json:"env,omitempty"`
	Plugins           []*PluginSpec        `json:"plugins,omitempty"`
	Finalizers        []*TaskFinalizerSpec `json:"finally,omitempty"`
}

func (self *TaskSpec) GetWorker(rr ResponseReader) (exec TaskExecutor, err error) {
	ret := new(worker)

	if rr == nil {
		plugins := self.Plugins
		if len(plugins) == 0 {
			plugins = []*PluginSpec{
				&PluginSpec{
					Name:   "http",
					Params: nil,
				},
			}
		}
		rr, err = NewPluginChain(plugins)
		if err != nil {
			return
		}
		ret.closer = rr
	}

	ret.rr = rr
	ret.spec = self
	ret.subTaskChan = subTaskChan
	exec = ret
	return
}

func StartWorkers(n int) {
	if n <= 0 {
		n = 2
	}
	for i := 0; i < n; i++ {
		go subTaskExecutor(subTaskChan)
	}
}

func StopAllWorkers() {
	close(subTaskChan)
	subTaskChan = make(chan *subTask)
}

type worker struct {
	subTaskChan chan<- *subTask
	spec        *TaskSpec
	rr          ResponseReader
	closer      io.Closer
}

type subTaskResult struct {
	err     error
	updates []*Env
}

type subTask struct {
	action  *Action
	env     *Env
	resChan chan<- *subTaskResult
}

func subTaskExecutor(taskChan <-chan *subTask) {
	for st := range taskChan {
		updates, err := st.action.Perform(st.env)
		res := new(subTaskResult)
		res.updates = updates
		res.err = err
		st.resChan <- res
	}
}

func (self *worker) Execute(errChan chan<- error) []*Env {
	if self.closer != nil {
		defer self.closer.Close()
	}
	envs := make([]*Env, 1)
	envs[0] = self.spec.InitEnv
	if envs[0].IsEmpty() {
		envs[0] = EmptyEnv()
	}
	var nilEnvs [1]*Env
	nilEnvs[0] = EmptyEnv()

	for _, concurrentActions := range self.spec.ConcurrentActions {
		nrActions := len(concurrentActions.Actions)
		if nrActions == 0 {
			continue
		}
		resChan := make(chan *subTaskResult)
		updates := make([]*Env, 0, nrActions*2)
		var wg sync.WaitGroup
		wg.Add(1)
		// reaper function
		go func(n int) {
			defer wg.Done()
			for i := 0; i < n; i++ {
				res := <-resChan
				if res.err != nil {
					errChan <- res.err
					continue
				}
				updates = append(updates, res.updates...)
			}
		}(nrActions * len(envs))

		for _, env := range envs {
			for _, spec := range concurrentActions.Actions {
				action, err := spec.GetAction(self.rr)
				if err != nil {
					res := new(subTaskResult)
					res.err = fmt.Errorf("Action %v is invalid: %v", spec.Tag, err)
					resChan <- res
					continue
				}
				st := new(subTask)
				st.action = action
				st.env = env
				st.resChan = resChan
				self.subTaskChan <- st
			}
		}
		wg.Wait()
		if len(updates) == 0 && !concurrentActions.ProceedWhenNoUpdate {
			break
		}
		forks := make([]*Env, 0, len(envs)*len(updates))
		for _, env := range envs {
			f := env.Fork(updates...)
			forks = append(forks, f...)
		}
		envs = uniqEnvs(forks...)
		if len(envs) == 0 {
			envs = nilEnvs[:]
		}
	}
	return envs
}
<|endoftext|>