<commit_before>package main

import (
	"bytes"
	"errors"
	"flag"
	"fmt"
	"go/ast"
	"go/doc"
	"go/format"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"unicode"
)

var (
	flagExportPath               string
	flagDefaultContext           bool
	flagExportLower              bool
	flagSkipErrorImplementStruct bool
	flagCustomContext            string
)

const help = `Export go packages to qlang modules.

Usage:
  qexport [-contexts=""] [-defctx=false] [skiperrimpl=true] [lower=false] [-outpath="./qlang"] packages

The packages for go package list or std for golang all standard packages.
`

func usage() {
	fmt.Fprintln(os.Stderr, help)
	flag.PrintDefaults()
}

func init() {
	flag.StringVar(&flagExportPath, "outpath", "./qlang", "optional set export root path")
	flag.BoolVar(&flagDefaultContext, "defctx", false, "optional use default context for build, default use all contexts.")
	flag.BoolVar(&flagExportLower, "lower", false, "optional export name is first lower")
	flag.BoolVar(&flagSkipErrorImplementStruct, "skiperrimpl", true, "optional skip error interface implement struct.")
	flag.StringVar(&flagCustomContext, "contexts", "", "optional comma-separated list of <goos>-<goarch>[-cgo] to override default contexts.")
}

func main() {
	flag.Parse()
	args := flag.Args()

	if len(args) == 0 {
		usage()
		return
	}

	if flagCustomContext != "" {
		flagDefaultContext = false
		setCustomContexts(flagCustomContext)
	}

	var outpath string
	if filepath.IsAbs(flagExportPath) {
		outpath = flagExportPath
	} else {
		dir, err := os.Getwd()
		if err != nil {
			log.Fatalln(err)
		}
		outpath = filepath.Join(dir, flagExportPath)
	}

	var pkgs []string
	if args[0] == "std" {
		out, err := exec.Command("go", "list", "-e", args[0]).Output()
		if err != nil {
			log.Fatal(err)
		}
		pkgs = strings.Fields(string(out))
	} else {
		pkgs = args
	}
	var exportd []string
	for _, pkg := range pkgs {
		err := export(pkg, outpath, true)
		if err != nil {
			log.Printf("warning skip pkg %q, error %v.\n", pkg, err)
		} else {
			exportd = append(exportd, pkg)
		}
	}
	for _, pkg := range exportd {
		log.Printf("export pkg %q success.\n", pkg)
	}
}

var (
	uint64_const_keys = []string{
		"crc64.ECMA",
		"crc64.ISO",
		"math.MaxUint64",
	}
)

func isUint64Const(key string) bool {
	for _, k := range uint64_const_keys {
		if key == k {
			return true
		}
	}
	return false
}

func export(pkg string, outpath string, skipOSArch bool) error {
	p, err := NewPackage(pkg, flagDefaultContext)
	if err != nil {
		return err
	}

	p.Parser()

	bp := p.BuildPackage()
	if bp == nil {
		return errors.New("not find build")
	}

	pkgName := bp.Name

	if bp.Name == "main" {
		return errors.New("skip main pkg")
	}

	if pkg == "unsafe" {
		return errors.New("skip unsafe pkg")
	}

	if p.CommonCount() == 0 {
		return errors.New("empty common exports")
	}

	//skip internal
	for _, path := range strings.Split(bp.ImportPath, "/") {
		if path == "internal" {
			return errors.New("skip internal pkg")
		}
	}

	var buf bytes.Buffer
	outf := func(format string, a ...interface{}) (err error) {
		_, err = buf.WriteString(fmt.Sprintf(format, a...))
		return
	}

	var hasTypeExport bool

	//write exports
	outf(`// Exports is the export table of this module.
//
var Exports = map[string]interface{}{
	"_name": "%s",
`, pkg)

	var addins []string
	//const
	if keys, _ := p.FilterCommon(Const); len(keys) > 0 {
		outf("\n")
		for _, v := range keys {
			name := toQlangName(v)
			fn := pkgName + "." + v
			if isUint64Const(fn) {
				fn = "uint64(" + fn + ")"
			}
			outf("\t%q:\t%s,\n", name, fn)
		}
	}

	//vars
	if keys, m := p.FilterCommon(Var); len(keys) > 0 {
		outf("\n")
		skeys, _ := p.FilterCommon(Struct)
		for _, v := range keys {
			mv := m[v].(*doc.Value)
			var isStructVar bool
			if typ := p.simpleValueDeclType(mv.Decl); typ != "" {
				for _, k := range skeys {
					if typ == k {
						isStructVar = true
						log.Printf("warning convert struct var to ref %s %s (%s)\n", bp.ImportPath, v, typ)
					}
				}
			}
			name := toQlangName(v)
			fn := pkgName + "." + v
			if isStructVar {
				outf("\t%q:\t&%s,\n", name, fn)
			} else {
				outf("\t%q:\t%s,\n", name, fn)
			}
		}
	}

	//funcs
	if keys, _ := p.FilterCommon(Func); len(keys) > 0 {
		outf("\n")
		for _, v := range keys {
			name := toQlangName(v)
			fn := pkgName + "." + v
			outf("\t%q:\t%s,\n", name, fn)
		}
	}

	//interface
	if keys, m := p.FilterCommon(Interface); len(keys) > 0 {
		outf("\n")
		for _, v := range keys {
			t, ok := m[v]
			if !ok {
				continue
			}
			dt, ok := t.(*doc.Type)
			if !ok {
				continue
			}
			var funcs []string
			for _, f := range dt.Funcs {
				if ast.IsExported(f.Name) {
					funcs = append(funcs, f.Name)
				}
			}
			for _, f := range funcs {
				name := toQlangName(f)
				//				if len(funcs) == 1 && strings.HasPrefix(name, "new") {
				//					name = toQlangName(v)
				//				}
				fn := pkgName + "." + f
				outf("\t%q:\t%s,\n", name, fn)
			}
		}
	}

	//structs
	if keys, m := p.FilterCommon(Struct); len(keys) > 0 {
		outf("\n")
		for _, v := range keys {
			t, ok := m[v]
			if !ok {
				continue
			}
			dt, ok := t.(*doc.Type)
			if !ok {
				continue
			}
			// exported funcs
			var funcs []string
			for _, f := range dt.Funcs {
				if ast.IsExported(f.Name) {
					funcs = append(funcs, f.Name)
				}
			}
			// check error interface implement struct
			if flagSkipErrorImplementStruct && strings.HasSuffix(v, "Error") {
				check := func(name string) bool {
					for _, f := range dt.Methods {
						if f.Name == name {
							return true
						}
					}
					return false
				}
				if check("Error") {
					log.Printf("warning skip struct %s, is error interface{} implement\n", bp.ImportPath+"."+v)
					continue
				}
			}

			//qlang.NewType(reflect.TypeOf((*http.Client)(nil)).Elem())
			//export type

			if ast.IsExported(v) {
				hasTypeExport = true
				outf("\t%q:\tqlang.NewType(reflect.TypeOf((*%s.%s)(nil)).Elem()),\n", v, pkgName, v)
			}

			for _, f := range funcs {
				name := toQlangName(f)
				fn := pkgName + "." + f
				outf("\t%q:\t%s,\n", name, fn)
			}
		}
	}

	// end exports
	outf("}")

	if len(addins) > 0 {
		for _, addin := range addins {
			outf("\n\n")
			outf(addin)
		}
	}

	var head bytes.Buffer
	outHeadf := func(format string, a ...interface{}) (err error) {
		_, err = head.WriteString(fmt.Sprintf(format, a...))
		return
	}

	//write package
	outHeadf("package %s\n", pkgName)

	//write imports
	outHeadf("import (\n")
	outHeadf("\t%q\n", pkg)
	if hasTypeExport {
		outHeadf("\t\"reflect\"\n\n")
		outHeadf("\t\"qlang.io/qlang.spec.v1\"\n")
	}
	outHeadf(")\n\n")

	// format
	data, err := format.Source(append(head.Bytes(), buf.Bytes()...))
	if err != nil {
		return err
	}

	// write file
	root := filepath.Join(outpath, pkg)
	err = os.MkdirAll(root, 0777)
	if err != nil {
		return err
	}

	file, err := os.Create(filepath.Join(root, pkgName+".go"))
	if err != nil {
		return err
	}
	defer file.Close()
	file.Write(data)

	return nil
}

func toQlangName(s string) string {
	if flagExportLower {
		if len(s) <= 1 {
			return s
		}

		if unicode.IsLower(rune(s[1])) {
			return strings.ToLower(s[0:1]) + s[1:]
		}
	}
	return s
}
<commit_msg>qexport, default to qlangstyle<commit_after>package main

import (
	"bytes"
	"errors"
	"flag"
	"fmt"
	"go/ast"
	"go/doc"
	"go/format"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"unicode"
)

var (
	flagDefaultContext           bool
	flagExportQlangStyle         bool
	flagSkipErrorImplementStruct bool
	flagCustomContext            string
	flagExportPath               string
)

const help = `Export go packages to qlang modules.

Usage:
  qexport [-contexts=""] [-defctx=false] [skiperrimpl=true] [qlangstyle=true] [-outpath="./qlang"] packages

The packages for go package list or std for golang all standard packages.
`

func usage() {
	fmt.Fprintln(os.Stderr, help)
	flag.PrintDefaults()
}

func init() {
	flag.StringVar(&flagCustomContext, "contexts", "", "optional comma-separated list of <goos>-<goarch>[-cgo] to override default contexts.")
	flag.BoolVar(&flagDefaultContext, "defctx", false, "optional use default context for build, default use all contexts.")
	flag.BoolVar(&flagExportQlangStyle, "qlangstyle", true, "optional export qlang style, lower and struct.")
	flag.BoolVar(&flagSkipErrorImplementStruct, "skiperrimpl", true, "optional skip error interface implement struct.")
	flag.StringVar(&flagExportPath, "outpath", "./qlang", "optional set export root path")
}

func main() {
	flag.Parse()
	args := flag.Args()

	if len(args) == 0 {
		usage()
		return
	}

	if flagCustomContext != "" {
		flagDefaultContext = false
		setCustomContexts(flagCustomContext)
	}

	var outpath string
	if filepath.IsAbs(flagExportPath) {
		outpath = flagExportPath
	} else {
		dir, err := os.Getwd()
		if err != nil {
			log.Fatalln(err)
		}
		outpath = filepath.Join(dir, flagExportPath)
	}

	var pkgs []string
	if args[0] == "std" {
		out, err := exec.Command("go", "list", "-e", args[0]).Output()
		if err != nil {
			log.Fatal(err)
		}
		pkgs = strings.Fields(string(out))
	} else {
		pkgs = args
	}
	var exportd []string
	for _, pkg := range pkgs {
		err := export(pkg, outpath, true)
		if err != nil {
			log.Printf("warning skip pkg %q, error %v.\n", pkg, err)
		} else {
			exportd = append(exportd, pkg)
		}
	}
	for _, pkg := range exportd {
		log.Printf("export pkg %q success.\n", pkg)
	}
}

var (
	uint64_const_keys = []string{
		"crc64.ECMA",
		"crc64.ISO",
		"math.MaxUint64",
	}
)

func isUint64Const(key string) bool {
	for _, k := range uint64_const_keys {
		if key == k {
			return true
		}
	}
	return false
}

func export(pkg string, outpath string, skipOSArch bool) error {
	p, err := NewPackage(pkg, flagDefaultContext)
	if err != nil {
		return err
	}

	p.Parser()

	bp := p.BuildPackage()
	if bp == nil {
		return errors.New("not find build")
	}

	pkgName := bp.Name

	if bp.Name == "main" {
		return errors.New("skip main pkg")
	}

	if pkg == "unsafe" {
		return errors.New("skip unsafe pkg")
	}

	if p.CommonCount() == 0 {
		return errors.New("empty common exports")
	}

	//skip internal
	for _, path := range strings.Split(bp.ImportPath, "/") {
		if path == "internal" {
			return errors.New("skip internal pkg")
		}
	}

	var buf bytes.Buffer
	outf := func(format string, a ...interface{}) (err error) {
		_, err = buf.WriteString(fmt.Sprintf(format, a...))
		return
	}

	var hasTypeExport bool

	//write exports
	outf(`// Exports is the export table of this module.
//
var Exports = map[string]interface{}{
	"_name": "%s",
`, pkg)

	var addins []string
	//const
	if keys, _ := p.FilterCommon(Const); len(keys) > 0 {
		outf("\n")
		for _, v := range keys {
			name := toQlangName(v)
			fn := pkgName + "." + v
			if isUint64Const(fn) {
				fn = "uint64(" + fn + ")"
			}
			outf("\t%q:\t%s,\n", name, fn)
		}
	}

	//vars
	if keys, m := p.FilterCommon(Var); len(keys) > 0 {
		outf("\n")
		skeys, _ := p.FilterCommon(Struct)
		for _, v := range keys {
			mv := m[v].(*doc.Value)
			var isStructVar bool
			if typ := p.simpleValueDeclType(mv.Decl); typ != "" {
				for _, k := range skeys {
					if typ == k {
						isStructVar = true
						log.Printf("warning convert struct var to ref %s %s (%s)\n", bp.ImportPath, v, typ)
					}
				}
			}
			//name := toQlangName(v)
			// TODO qlang var export is title
			name := v
			fn := pkgName + "." + v
			if isStructVar {
				outf("\t%q:\t&%s,\n", name, fn)
			} else {
				outf("\t%q:\t%s,\n", name, fn)
			}
		}
	}

	//funcs
	if keys, _ := p.FilterCommon(Func); len(keys) > 0 {
		outf("\n")
		for _, v := range keys {
			name := toQlangName(v)
			fn := pkgName + "." + v
			outf("\t%q:\t%s,\n", name, fn)
		}
	}

	//interface
	if keys, m := p.FilterCommon(Interface); len(keys) > 0 {
		outf("\n")
		for _, v := range keys {
			t, ok := m[v]
			if !ok {
				continue
			}
			dt, ok := t.(*doc.Type)
			if !ok {
				continue
			}
			var funcs []string
			for _, f := range dt.Funcs {
				if ast.IsExported(f.Name) {
					funcs = append(funcs, f.Name)
				}
			}
			for _, f := range funcs {
				name := toQlangName(f)
				if flagExportQlangStyle && len(funcs) == 1 && strings.HasPrefix(name, "new") {
					name = toQlangName(v)
				}
				fn := pkgName + "." + f
				outf("\t%q:\t%s,\n", name, fn)
			}
		}
	}

	//structs
	if keys, m := p.FilterCommon(Struct); len(keys) > 0 {
		outf("\n")
		for _, v := range keys {
			t, ok := m[v]
			if !ok {
				continue
			}
			dt, ok := t.(*doc.Type)
			if !ok {
				continue
			}
			// exported funcs
			var funcs []string
			for _, f := range dt.Funcs {
				if ast.IsExported(f.Name) {
					funcs = append(funcs, f.Name)
				}
			}
			// check error interface implement struct
			if flagSkipErrorImplementStruct && strings.HasSuffix(v, "Error") {
				check := func(name string) bool {
					for _, f := range dt.Methods {
						if f.Name == name {
							return true
						}
					}
					return false
				}
				if check("Error") {
					log.Printf("warning skip struct %s, is error interface{} implement\n", bp.ImportPath+"."+v)
					continue
				}
			}

			//qlang.NewType(reflect.TypeOf((*http.Client)(nil)).Elem())
			//export type

			if ast.IsExported(v) {
				hasTypeExport = true
				outf("\t%q:\tqlang.NewType(reflect.TypeOf((*%s.%s)(nil)).Elem()),\n", v, pkgName, v)
			}

			for _, f := range funcs {
				name := toQlangName(f)
				if flagExportQlangStyle && len(funcs) == 1 && strings.HasPrefix(name, "new") {
					name = toQlangName(v)
					// TODO qlang.NewTypeEx
					if ast.IsExported(name) {
						name = toQlangName(f)
					}
				}
				fn := pkgName + "." + f
				outf("\t%q:\t%s,\n", name, fn)
			}
		}
	}

	// end exports
	outf("}")

	if len(addins) > 0 {
		for _, addin := range addins {
			outf("\n\n")
			outf(addin)
		}
	}

	var head bytes.Buffer
	outHeadf := func(format string, a ...interface{}) (err error) {
		_, err = head.WriteString(fmt.Sprintf(format, a...))
		return
	}

	//write package
	outHeadf("package %s\n", pkgName)

	//write imports
	outHeadf("import (\n")
	outHeadf("\t%q\n", pkg)
	if hasTypeExport {
		outHeadf("\t\"reflect\"\n\n")
		outHeadf("\t\"qlang.io/qlang.spec.v1\"\n")
	}
	outHeadf(")\n\n")

	// format
	data, err := format.Source(append(head.Bytes(), buf.Bytes()...))
	if err != nil {
		return err
	}

	// write file
	root := filepath.Join(outpath, pkg)
	err = os.MkdirAll(root, 0777)
	if err != nil {
		return err
	}

	file, err := os.Create(filepath.Join(root, pkgName+".go"))
	if err != nil {
		return err
	}
	defer file.Close()
	file.Write(data)

	return nil
}

func toQlangName(s string) string {
	if flagExportQlangStyle {
		if len(s) <= 1 {
			return s
		}

		if unicode.IsLower(rune(s[1])) {
			return strings.ToLower(s[0:1]) + s[1:]
		}
	}
	return s
}
<|endoftext|>


<commit_before>/*
Copyright 2017 The Kubernetes Authors.

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

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

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

package args

import (
	"fmt"

	"github.com/spf13/pflag"
	"k8s.io/gengo/args"
)

// DefaultBasePeerDirs are the peer-dirs nearly everybody will use, i.e. those coming from
// apimachinery.
var DefaultBasePeerDirs = []string{
	"k8s.io/apimachinery/pkg/apis/meta/v1",
	"k8s.io/apimachinery/pkg/conversion",
	"k8s.io/apimachinery/pkg/runtime",
}

// CustomArgs is used by the gengo framework to pass args specific to this generator.
type CustomArgs struct {
	// Base peer dirs which nearly everybody will use, i.e. outside of Kubernetes core.
	BasePeerDirs []string

	// Custom peer dirs which are application specific. Always consider these as
	// last-ditch possibilities for conversions.
	ExtraPeerDirs []string //

	// Skipunsafe indicates whether to generate unsafe conversions to improve the efficiency
	// of these operations. The unsafe operation is a direct pointer assignment via unsafe
	// (within the allowed uses of unsafe) and is equivalent to a proposed Golang change to
	// allow structs that are identical to be assigned to each other.
	SkipUnsafe bool
}

// NewDefaults returns default arguments for the generator.
func NewDefaults() (*args.GeneratorArgs, *CustomArgs) {
	genericArgs := args.Default().WithoutDefaultFlagParsing()
	customArgs := &CustomArgs{
		BasePeerDirs: DefaultBasePeerDirs,
		SkipUnsafe:   false,
	}
	genericArgs.CustomArgs = customArgs
	genericArgs.OutputFileBaseName = "conversion_generated"
	return genericArgs, customArgs
}

// AddFlags add the generator flags to the flag set.
func (ca *CustomArgs) AddFlags(fs *pflag.FlagSet) {
	pflag.CommandLine.StringSliceVar(&ca.BasePeerDirs, "base-peer-dirs", ca.BasePeerDirs,
		"Comma-separated list of apimachinery import paths which are considered, after tag-specified peers, for conversions. Only change these if you have very good reasons.")
	pflag.CommandLine.StringSliceVar(&ca.ExtraPeerDirs, "extra-peer-dirs", ca.ExtraPeerDirs,
		"Application specific comma-separated list of import paths which are considered, after tag-specified peers and base-peer-dirs, for conversions.")
	pflag.CommandLine.BoolVar(&ca.SkipUnsafe, "skip-unsafe", ca.SkipUnsafe,
		"If true, will not generate code using unsafe pointer conversions; resulting code may be slower.")
}

// Validate checks the given arguments.
func Validate(genericArgs *args.GeneratorArgs) error {
	_ = genericArgs.CustomArgs.(*CustomArgs)

	if len(genericArgs.OutputFileBaseName) == 0 {
		return fmt.Errorf("output file base name cannot be empty")
	}

	return nil
}
<commit_msg>conversion-gen: add godocs for peer dirs<commit_after>/*
Copyright 2017 The Kubernetes Authors.

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

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

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

package args

import (
	"fmt"

	"github.com/spf13/pflag"
	"k8s.io/gengo/args"
)

// DefaultBasePeerDirs are the peer-dirs nearly everybody will use, i.e. those coming from
// apimachinery.
var DefaultBasePeerDirs = []string{
	"k8s.io/apimachinery/pkg/apis/meta/v1",
	"k8s.io/apimachinery/pkg/conversion",
	"k8s.io/apimachinery/pkg/runtime",
}

// CustomArgs is used by the gengo framework to pass args specific to this generator.
type CustomArgs struct {
	// Base peer dirs which nearly everybody will use, i.e. outside of Kubernetes core. Peer dirs
	// are declared to make the generator pick up manually written conversion funcs from external
	// packages.
	BasePeerDirs []string

	// Custom peer dirs which are application specific. Peer dirs are declared to make the
	// generator pick up manually written conversion funcs from external packages.
	ExtraPeerDirs []string

	// Skipunsafe indicates whether to generate unsafe conversions to improve the efficiency
	// of these operations. The unsafe operation is a direct pointer assignment via unsafe
	// (within the allowed uses of unsafe) and is equivalent to a proposed Golang change to
	// allow structs that are identical to be assigned to each other.
	SkipUnsafe bool
}

// NewDefaults returns default arguments for the generator.
func NewDefaults() (*args.GeneratorArgs, *CustomArgs) {
	genericArgs := args.Default().WithoutDefaultFlagParsing()
	customArgs := &CustomArgs{
		BasePeerDirs: DefaultBasePeerDirs,
		SkipUnsafe:   false,
	}
	genericArgs.CustomArgs = customArgs
	genericArgs.OutputFileBaseName = "conversion_generated"
	return genericArgs, customArgs
}

// AddFlags add the generator flags to the flag set.
func (ca *CustomArgs) AddFlags(fs *pflag.FlagSet) {
	pflag.CommandLine.StringSliceVar(&ca.BasePeerDirs, "base-peer-dirs", ca.BasePeerDirs,
		"Comma-separated list of apimachinery import paths which are considered, after tag-specified peers, for conversions. Only change these if you have very good reasons.")
	pflag.CommandLine.StringSliceVar(&ca.ExtraPeerDirs, "extra-peer-dirs", ca.ExtraPeerDirs,
		"Application specific comma-separated list of import paths which are considered, after tag-specified peers and base-peer-dirs, for conversions.")
	pflag.CommandLine.BoolVar(&ca.SkipUnsafe, "skip-unsafe", ca.SkipUnsafe,
		"If true, will not generate code using unsafe pointer conversions; resulting code may be slower.")
}

// Validate checks the given arguments.
func Validate(genericArgs *args.GeneratorArgs) error {
	_ = genericArgs.CustomArgs.(*CustomArgs)

	if len(genericArgs.OutputFileBaseName) == 0 {
		return fmt.Errorf("output file base name cannot be empty")
	}

	return nil
}
<|endoftext|>


<commit_before>package manta

import (
	"io/ioutil"
	"log"
	"path"
	"path/filepath"

	"github.com/joyent/gocommon/client"
	"github.com/joyent/gocommon/jpc"
	m "github.com/richardiux/gomanta/manta"
	"github.com/wanelo/image-server/core"
)

type MantaAdapter struct {
	Client *m.Client
}

var serverConfiguration *core.ServerConfiguration

func InitializeManta(sc *core.ServerConfiguration) *MantaAdapter {
	serverConfiguration = sc
	ma := &MantaAdapter{Client: newMantaClient()}
	ma.ensureBasePath()
	return ma
}

func newMantaClient() *m.Client {
	creds, err := jpc.CompleteCredentialsFromEnv("")
	if err != nil {
		log.Fatalf("Error reading credentials for manta: %s", err.Error())
	}

	client := client.NewClient(creds.MantaEndpoint.URL, "", creds, &m.Logger)
	return m.New(client)
}

func (ma *MantaAdapter) Upload(ic *core.ImageConfiguration) {
	source := ic.LocalResizedImagePath()
	destination := serverConfiguration.MantaResizedImagePath(ic)

	path, objectName := path.Split(destination)
	err := ma.ensureDirectory(path)
	if err != nil {
		log.Printf("Manta::sentToManta unable to create directory %s", path)
		return
	}
	object, err := ioutil.ReadFile(source)
	if err != nil {
		log.Printf("Manta::sentToManta unable to read file %s", source)
		return
	}
	err = ma.Client.PutObject(path, objectName, object)
	if err != nil {
		log.Printf("Error uploading image to manta: %s", err)
	}
}

func (ma *MantaAdapter) ensureDirectory(dir string) error {
	err := ma.createDirectory(dir)
	if err != nil {
		//  need to create sub directories
		dir2 := filepath.Dir(dir)
		dir3 := filepath.Dir(dir2)
		err = ma.createDirectory(dir3)
		if err != nil {
			return err
		}
		err = ma.createDirectory(dir2)
		if err != nil {
			return err
		}
		err = ma.createDirectory(dir)
		if err != nil {
			return err
		}
	}
	return nil
}

func (ma *MantaAdapter) ensureBasePath() {
	baseDir := serverConfiguration.MantaBasePath
	ma.createDirectory(baseDir)
}

func (ma *MantaAdapter) createDirectory(path string) error {
	err := ma.Client.PutDirectory(path)
	if err != nil {
		log.Printf("Error creating directory on manta: %s", path)
		return err
	}
	log.Printf("Created directory on manta: %s", path)
	return nil
}
<commit_msg>Manta directories can be created with new structure<commit_after>package manta

import (
	"io/ioutil"
	"log"
	"path"
	"path/filepath"

	"github.com/joyent/gocommon/client"
	"github.com/joyent/gocommon/jpc"
	m "github.com/richardiux/gomanta/manta"
	"github.com/wanelo/image-server/core"
)

type MantaAdapter struct {
	Client *m.Client
}

var serverConfiguration *core.ServerConfiguration

func InitializeManta(sc *core.ServerConfiguration) *MantaAdapter {
	serverConfiguration = sc
	ma := &MantaAdapter{Client: newMantaClient()}
	ma.ensureBasePath()
	return ma
}

func newMantaClient() *m.Client {
	creds, err := jpc.CompleteCredentialsFromEnv("")
	if err != nil {
		log.Fatalf("Error reading credentials for manta: %s", err.Error())
	}

	client := client.NewClient(creds.MantaEndpoint.URL, "", creds, &m.Logger)
	return m.New(client)
}

func (ma *MantaAdapter) Upload(ic *core.ImageConfiguration) {
	source := ic.LocalResizedImagePath()
	destination := serverConfiguration.MantaResizedImagePath(ic)

	path, objectName := path.Split(destination)
	err := ma.ensureDirectory(path)
	if err != nil {
		log.Printf("Manta::sentToManta unable to create directory %s", path)
		return
	}
	object, err := ioutil.ReadFile(source)
	if err != nil {
		log.Printf("Manta::sentToManta unable to read file %s", source)
		return
	}
	err = ma.Client.PutObject(path, objectName, object)
	if err != nil {
		log.Printf("Error uploading image to manta: %s", err)
	}
}

func (ma *MantaAdapter) ensureDirectory(dir string) error {
	err := ma.createDirectory(dir)
	if err != nil {
		//  need to create sub directories
		dir2 := filepath.Dir(dir)
		dir3 := filepath.Dir(dir2)
		dir4 := filepath.Dir(dir3)
		dir5 := filepath.Dir(dir4)
		err = ma.createDirectory(dir5)
		if err != nil {
			return err
		}
		err = ma.createDirectory(dir4)
		if err != nil {
			return err
		}
		err = ma.createDirectory(dir3)
		if err != nil {
			return err
		}
		err = ma.createDirectory(dir2)
		if err != nil {
			return err
		}
		err = ma.createDirectory(dir)
		if err != nil {
			return err
		}
	}
	return nil
}

func (ma *MantaAdapter) ensureBasePath() {
	baseDir := serverConfiguration.MantaBasePath
	ma.createDirectory(baseDir)
}

func (ma *MantaAdapter) createDirectory(path string) error {
	err := ma.Client.PutDirectory(path)
	if err != nil {
		log.Printf("Error creating directory on manta: %s", path)
		return err
	}
	log.Printf("Created directory on manta: %s", path)
	return nil
}
<|endoftext|>


<commit_before>package pod

import (
	"github.com/andyxning/eventarbiter/cmd/eventarbiter/conf"
	"github.com/andyxning/eventarbiter/handler"
	"github.com/andyxning/eventarbiter/models"
	"k8s.io/kubernetes/pkg/api"
	"strings"
)

const (
	originalPodInsufficientCPUMemoryReason = "FailedScheduling"
	PodInsufficientCPUMemoryReason         = "InsufficientCPUMemory"
)

type insufficientCPUMemory struct {
	kind             string
	reason           string
	originalReason   string
	keyWords         []string
	alertEventReason string
}

func NewInsufficientCPUMemory() models.EventHandler {
	return insufficientCPUMemory{
		kind:           "POD",
		reason:         PodInsufficientCPUMemoryReason,
		originalReason: originalPodInsufficientCPUMemoryReason,
		// TODO(andyxning): This should be replaced with more scalable reference instead of hard
		// code.
		keyWords:         []string{"insufficient cpu", "insufficient memory"},
		alertEventReason: "pod_insufficentcpumemory",
	}
}

func (icm insufficientCPUMemory) HandleEvent(sinks []models.Sink, event *api.Event) {
	if strings.ToUpper(event.InvolvedObject.Kind) == icm.kind && event.Reason == icm.reason {
		for _, keyWord := range icm.keyWords {
			if strings.Contains(strings.ToLower(event.Message), keyWord) {
				// Currently in Kubernetes 1.4.0, message for insufficient cpu is proportional with
				// the number of minion machines. This may be very large and longer information is useless.
				// So, we can just truncate it to maxMessageLength.
				// See https://gist.github.com/andyxning/8065dc35889f07073e129bb75a6e57fe for an example.
				if len(event.Message) >= maxMessageLength {
					event.Message = event.Message[:maxMessageLength]
				}

				var eventAlert = models.PodEventAlert{
					Kind:          strings.ToUpper(event.InvolvedObject.Kind),
					Name:          event.InvolvedObject.Name,
					Namespace:     event.ObjectMeta.Namespace,
					Reason:        icm.reason,
					Message:       event.Message,
					LastTimestamp: event.LastTimestamp.Local().String(),
					Environment:   conf.Conf.Environment.Value,
				}

				for _, sink := range sinks {
					sink.Sink(icm.kind, eventAlert)
				}

				break
			}
		}
	}
}

func (icm insufficientCPUMemory) AlertEventReason() string {
	return icm.alertEventReason
}

func (icm insufficientCPUMemory) Reason() string {
	return icm.reason
}

func init() {
	icm := NewInsufficientCPUMemory()
	handler.MustRegisterEventAlertReason(icm.AlertEventReason(), icm)
	handler.RegisterEventReason(icm.Reason())
}
<commit_msg>fix insufficientcpumemory reason filter<commit_after>package pod

import (
	"github.com/andyxning/eventarbiter/cmd/eventarbiter/conf"
	"github.com/andyxning/eventarbiter/handler"
	"github.com/andyxning/eventarbiter/models"
	"k8s.io/kubernetes/pkg/api"
	"strings"
	"github.com/golang/glog"
)

const (
	originalPodInsufficientCPUMemoryReason = "FailedScheduling"
	PodInsufficientCPUMemoryReason         = "InsufficientCPUMemory"
)

type insufficientCPUMemory struct {
	kind             string
	reason           string
	originalReason   string
	keyWords         []string
	alertEventReason string
}

func NewInsufficientCPUMemory() models.EventHandler {
	return insufficientCPUMemory{
		kind:           "POD",
		reason:         PodInsufficientCPUMemoryReason,
		originalReason: originalPodInsufficientCPUMemoryReason,
		// TODO(andyxning): This should be replaced with more scalable reference instead of hard
		// code.
		keyWords:         []string{"insufficient cpu", "insufficient memory"},
		alertEventReason: "pod_insufficentcpumemory",
	}
}

func (icm insufficientCPUMemory) HandleEvent(sinks []models.Sink, event *api.Event) {
	if strings.ToUpper(event.InvolvedObject.Kind) == icm.kind && event.Reason == icm.originalReason {
		for _, keyWord := range icm.keyWords {
			if strings.Contains(strings.ToLower(event.Message), keyWord) {
				// Currently in Kubernetes 1.4.0, message for insufficient cpu is proportional with
				// the number of minion machines. This may be very large and longer information is useless.
				// So, we can just truncate it to maxMessageLength.
				// See https://gist.github.com/andyxning/8065dc35889f07073e129bb75a6e57fe for an example.
				if len(event.Message) >= maxMessageLength {
					glog.Warningf("truncate event message. %s", event.Message)
					event.Message = event.Message[:maxMessageLength]
				}

				var eventAlert = models.PodEventAlert{
					Kind:          strings.ToUpper(event.InvolvedObject.Kind),
					Name:          event.InvolvedObject.Name,
					Namespace:     event.ObjectMeta.Namespace,
					Reason:        icm.reason,
					Message:       event.Message,
					LastTimestamp: event.LastTimestamp.Local().String(),
					Environment:   conf.Conf.Environment.Value,
				}

				for _, sink := range sinks {
					sink.Sink(icm.kind, eventAlert)
				}

				break
			}
		}
	}
}

func (icm insufficientCPUMemory) AlertEventReason() string {
	return icm.alertEventReason
}

func (icm insufficientCPUMemory) Reason() string {
	return icm.reason
}

func init() {
	icm := NewInsufficientCPUMemory()
	handler.MustRegisterEventAlertReason(icm.AlertEventReason(), icm)
	handler.RegisterEventReason(icm.Reason())
}
<|endoftext|>


<commit_before>package cluster

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"time"

	"github.com/google/go-querystring/query"
	"github.com/raintank/worldping-api/pkg/log"
)

//go:generate stringer -type=NodeState
type NodeState int

const (
	NodeNotReady NodeState = iota
	NodeReady
	NodeUnreachable
)

func NodeStateFromString(s string) NodeState {
	switch s {
	case "NodeNotReady":
		return NodeNotReady
	case "NodeReady":
		return NodeReady
	case "NodeUnreachable":
		return NodeUnreachable
	}
	//default
	return NodeNotReady
}

type Error struct {
	code int
	err  error
}

func NewError(code int, err error) *Error {
	return &Error{
		code: code,
		err:  err,
	}
}

// implement errors.Error interface
func (r *Error) Error() string {
	return r.err.Error()
}

// implement response.Response
func (r *Error) Code() int {
	return r.code
}

type Node struct {
	Name          string    `json:"name"`
	Version       string    `json:"version"`
	Primary       bool      `json:"primary"`
	PrimaryChange time.Time `json:"primaryChange"`
	State         NodeState `json:"state"`
	Priority      int       `json:"priority"`
	Started       time.Time `json:"started"`
	StateChange   time.Time `json:"stateChange"`
	Partitions    []int32   `json:"partitions"`
	ApiPort       int       `json:"apiPort"`
	ApiScheme     string    `json:"apiScheme"`
	Updated       time.Time `json:"updated"`
	RemoteAddr    string    `json:"remoteAddr"`
	local         bool
}

func (n Node) RemoteURL() string {
	return fmt.Sprintf("%s://%s:%d", n.ApiScheme, n.RemoteAddr, n.ApiPort)
}

func (n Node) IsReady() bool {
	return n.State == NodeReady && n.Priority <= maxPrio
}

func (n Node) IsLocal() bool {
	return n.local
}

func (n Node) Get(path string, query interface{}) ([]byte, error) {
	if query != nil {
		qstr, err := toQueryString(query)
		if err != nil {
			return nil, NewError(http.StatusInternalServerError, err)
		}
		path = path + "?" + qstr
	}

	addr := n.RemoteURL() + path
	req, err := http.NewRequest("GET", addr, nil)
	if err != nil {
		return nil, NewError(http.StatusInternalServerError, err)
	}
	rsp, err := client.Do(req)
	if err != nil {
		log.Error(3, "CLU Node: %s unreachable. %s", n.Name, err.Error())
		return nil, NewError(http.StatusServiceUnavailable, fmt.Errorf("cluster node unavailable"))
	}
	return handleResp(rsp)
}

func (n Node) Post(path string, body interface{}) ([]byte, error) {
	b, err := json.Marshal(body)
	if err != nil {
		return nil, NewError(http.StatusInternalServerError, err)
	}
	var reader *bytes.Reader
	reader = bytes.NewReader(b)
	addr := n.RemoteURL() + path
	req, err := http.NewRequest("POST", addr, reader)
	if err != nil {
		return nil, NewError(http.StatusInternalServerError, err)
	}
	req.Header.Add("Content-Type", "application/json")
	rsp, err := client.Do(req)
	if err != nil {
		log.Error(3, "CLU Node: %s unreachable. %s", n.Name, err.Error())
		return nil, NewError(http.StatusServiceUnavailable, fmt.Errorf("cluster node unavailable"))
	}
	return handleResp(rsp)
}

func handleResp(rsp *http.Response) ([]byte, error) {
	defer rsp.Body.Close()
	if rsp.StatusCode != 200 {
		return nil, NewError(rsp.StatusCode, fmt.Errorf(rsp.Status))
	}
	return ioutil.ReadAll(rsp.Body)
}

// Convert an interface{} to a urlencoded querystring
func toQueryString(q interface{}) (string, error) {
	v, err := query.Values(q)
	if err != nil {
		return "", err
	}
	return v.Encode(), nil
}
<commit_msg>remove unused node.Get()<commit_after>package cluster

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"time"

	"github.com/google/go-querystring/query"
	"github.com/raintank/worldping-api/pkg/log"
)

//go:generate stringer -type=NodeState
type NodeState int

const (
	NodeNotReady NodeState = iota
	NodeReady
	NodeUnreachable
)

func NodeStateFromString(s string) NodeState {
	switch s {
	case "NodeNotReady":
		return NodeNotReady
	case "NodeReady":
		return NodeReady
	case "NodeUnreachable":
		return NodeUnreachable
	}
	//default
	return NodeNotReady
}

type Error struct {
	code int
	err  error
}

func NewError(code int, err error) *Error {
	return &Error{
		code: code,
		err:  err,
	}
}

// implement errors.Error interface
func (r *Error) Error() string {
	return r.err.Error()
}

// implement response.Response
func (r *Error) Code() int {
	return r.code
}

type Node struct {
	Name          string    `json:"name"`
	Version       string    `json:"version"`
	Primary       bool      `json:"primary"`
	PrimaryChange time.Time `json:"primaryChange"`
	State         NodeState `json:"state"`
	Priority      int       `json:"priority"`
	Started       time.Time `json:"started"`
	StateChange   time.Time `json:"stateChange"`
	Partitions    []int32   `json:"partitions"`
	ApiPort       int       `json:"apiPort"`
	ApiScheme     string    `json:"apiScheme"`
	Updated       time.Time `json:"updated"`
	RemoteAddr    string    `json:"remoteAddr"`
	local         bool
}

func (n Node) RemoteURL() string {
	return fmt.Sprintf("%s://%s:%d", n.ApiScheme, n.RemoteAddr, n.ApiPort)
}

func (n Node) IsReady() bool {
	return n.State == NodeReady && n.Priority <= maxPrio
}

func (n Node) IsLocal() bool {
	return n.local
}

func (n Node) Post(path string, body interface{}) ([]byte, error) {
	b, err := json.Marshal(body)
	if err != nil {
		return nil, NewError(http.StatusInternalServerError, err)
	}
	var reader *bytes.Reader
	reader = bytes.NewReader(b)
	addr := n.RemoteURL() + path
	req, err := http.NewRequest("POST", addr, reader)
	if err != nil {
		return nil, NewError(http.StatusInternalServerError, err)
	}
	req.Header.Add("Content-Type", "application/json")
	rsp, err := client.Do(req)
	if err != nil {
		log.Error(3, "CLU Node: %s unreachable. %s", n.Name, err.Error())
		return nil, NewError(http.StatusServiceUnavailable, fmt.Errorf("cluster node unavailable"))
	}
	return handleResp(rsp)
}

func handleResp(rsp *http.Response) ([]byte, error) {
	defer rsp.Body.Close()
	if rsp.StatusCode != 200 {
		return nil, NewError(rsp.StatusCode, fmt.Errorf(rsp.Status))
	}
	return ioutil.ReadAll(rsp.Body)
}

// Convert an interface{} to a urlencoded querystring
func toQueryString(q interface{}) (string, error) {
	v, err := query.Values(q)
	if err != nil {
		return "", err
	}
	return v.Encode(), nil
}
<|endoftext|>


<commit_before>package main

import (
	"code.google.com/p/gorest"
	"database/sql"
	"encoding/json"
	"fmt"
	_ "github.com/lib/pq"
	"log"
	"net/http"
	"os"
)

var g_db *sql.DB

func main() {
	conf := ReadConfig()

	var err error
	g_db, err = sql.Open("postgres", fmt.Sprintf("user=%v password=%v dbname=%v sslmode=disable", conf.DbUser, conf.DbPassword, conf.DbName))

	if err != nil {
		log.Fatal(err)
	}

	gorest.RegisterService(new(StatsService))
	http.Handle("/", gorest.Handle())
	http.ListenAndServe(fmt.Sprintf(":%v", conf.HttpPort), nil)
}

//************************Define Service***************************

type StatsService struct {
	//Service level config
	gorest.RestService `root:"/" consumes:"application/json" produces:"application/json"`

	//End-Point level configs: Field names must be the same as the corresponding method names,
	// but not-exported (starts with lowercase)

	getUser gorest.EndPoint `method:"GET" path:"/users/{id:int64}" output:"User"`
	putUser gorest.EndPoint `method:"PUT" path:"/users/{id:int64}" postdata:"User"`
}

type User struct {
	Id   int64
	Name string
}

type Config struct {
	DbName     string
	DbUser     string
	DbPassword string
	HttpPort   int
}

//Handler Methods: Method names must be the same as in config, but exported (starts with uppercase)

func (serv StatsService) GetUser(id int64) User {

	var steamid int64
	var username string

	err := g_db.QueryRow("SELECT id, name FROM players WHERE id = $1", id).Scan(&steamid, &username)

	switch {
	case err == sql.ErrNoRows:
		serv.ResponseBuilder().SetResponseCode(404).Overide(true)
	case err != nil:
		log.Fatal(err)
	}

	return User{Id: steamid, Name: username}
}

func (serv StatsService) PutUser(user User, id int64) {

	if user.Id != id {
		serv.ResponseBuilder().SetResponseCode(400).Overide(true)
		return
	}

	_, err := g_db.Exec("INSERT INTO players (id, name) VALUES ($1, $2)", user.Id, user.Name)

	if err != nil {
		log.Print(err)
		serv.ResponseBuilder().SetResponseCode(500).Overide(true)
		return
	}

	serv.ResponseBuilder().SetResponseCode(201).Overide(true)
}

func ReadConfig() (config Config) {
	file, err := os.Open("conf.json")
	defer file.Close()

	if err != nil {
		log.Fatal(err)
	}

	decoder := json.NewDecoder(file)
	config = Config{}
	err = decoder.Decode(&config)

	if err != nil {
		log.Fatal(err)
	}

	return config
}
<commit_msg>Start designing API in earnest.<commit_after>package main

import (
	uuid "code.google.com/p/go-uuid/uuid"
	"code.google.com/p/gorest"
	"database/sql"
	"encoding/json"
	"fmt"
	_ "github.com/lib/pq"
	"log"
	"net/http"
	"os"
)

var g_db *sql.DB

func main() {
	conf := ReadConfig()

	var err error
	g_db, err = sql.Open("postgres", fmt.Sprintf("user=%v password=%v dbname=%v sslmode=disable", conf.DbUser, conf.DbPassword, conf.DbName))

	if err != nil {
		log.Fatal(err)
	}

	gorest.RegisterService(new(PlayersService))
	http.Handle("/", gorest.Handle())
	http.ListenAndServe(fmt.Sprintf(":%v", conf.HttpPort), nil)
}

type ServersService struct {
	gorest.RestService `root:"/s" consumes:"application/json" produces:"application/json"`

	putUser gorest.EndPoint `method:"PUT" path:"/{id:string}" postdata:"Server" output:"Server"`
}

type PlayersService struct {
	gorest.RestService `root:"/p" consumes:"application/json" produces:"application/json"`

	getUser gorest.EndPoint `method:"GET" path:"/{id:int64}" output:"Player"`
	putUser gorest.EndPoint `method:"PUT" path:"/{id:int64}" postdata:"Player"`
}

type Server struct {
	Id        string
	Name      string
	SecretKey uuid.UUID
}

type Player struct {
	Id   int64
	Name string
}

type Config struct {
	DbName     string
	DbUser     string
	DbPassword string
	HttpPort   int
}

//Handler Methods: Method names must be the same as in config, but exported (starts with uppercase)

func (serv PlayersService) GetUser(id int64) Player {

	var steamid int64
	var username string

	err := g_db.QueryRow("SELECT id, name FROM players WHERE id = $1", id).Scan(&steamid, &username)

	switch {
	case err == sql.ErrNoRows:
		serv.ResponseBuilder().SetResponseCode(404).Overide(true)
	case err != nil:
		log.Fatal(err)
	}

	return Player{Id: steamid, Name: username}
}

func (serv PlayersService) PutUser(user Player, id int64) {

	if user.Id != id {
		serv.ResponseBuilder().SetResponseCode(400).Overide(true)
		return
	}

	_, err := g_db.Exec("INSERT INTO players (id, name) VALUES ($1, $2)", user.Id, user.Name)

	if err != nil {
		log.Print(err)
		serv.ResponseBuilder().SetResponseCode(500).Overide(true)
		return
	}

	serv.ResponseBuilder().SetResponseCode(201).Overide(true)
}

func ReadConfig() (config Config) {
	file, err := os.Open("conf.json")
	defer file.Close()

	if err != nil {
		log.Fatal(err)
	}

	decoder := json.NewDecoder(file)
	config = Config{}
	err = decoder.Decode(&config)

	if err != nil {
		log.Fatal(err)
	}

	return config
}
<|endoftext|>


<commit_before>package api

import (
	"fmt"
	"strconv"
	"strings"
	"time"

	proto "github.com/appscode/api/kubernetes/v1beta1"
	"github.com/appscode/go/crypto/rand"
	. "github.com/appscode/go/encoding/json/types"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	kubeadm "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
)

type AzureCloudConfig struct {
	TenantID           string `json:"tenantId,omitempty"`
	SubscriptionID     string `json:"subscriptionId,omitempty"`
	AadClientID        string `json:"aadClientId,omitempty"`
	AadClientSecret    string `json:"aadClientSecret,omitempty"`
	ResourceGroup      string `json:"resourceGroup,omitempty"`
	Location           string `json:"location,omitempty"`
	SubnetName         string `json:"subnetName,omitempty"`
	SecurityGroupName  string `json:"securityGroupName,omitempty"`
	VnetName           string `json:"vnetName,omitempty"`
	RouteTableName     string `json:"routeTableName,omitempty"`
	StorageAccountName string `json:"storageAccountName,omitempty"`
}

type GCECloudConfig struct {
	TokenURL           string   `gcfg:"token-url"            ini:"token-url,omitempty"`
	TokenBody          string   `gcfg:"token-body"           ini:"token-body,omitempty"`
	ProjectID          string   `gcfg:"project-id"           ini:"project-id,omitempty"`
	NetworkName        string   `gcfg:"network-name"         ini:"network-name,omitempty"`
	NodeTags           []string `gcfg:"node-tags"            ini:"node-tags,omitempty,omitempty"`
	NodeInstancePrefix string   `gcfg:"node-instance-prefix" ini:"node-instance-prefix,omitempty,omitempty"`
	Multizone          bool     `gcfg:"multizone"            ini:"multizone,omitempty"`
}

type IG struct {
	SKU           string `json:"sku,omitempty"`
	Count         int64  `json:"count,omitempty"`
	SpotInstances bool   `json:"spotInstances,omitempty"`
}

type Cluster struct {
	metav1.TypeMeta   `json:",inline,omitempty,omitempty"`
	metav1.ObjectMeta `json:"metadata,omitempty,omitempty"`
	Spec              ClusterSpec   `json:"spec,omitempty,omitempty"`
	Status            ClusterStatus `json:"status,omitempty,omitempty"`
}

type Networking struct {
	PodSubnet     string `json:"podSubnet,omitempty"`
	ServiceSubnet string `json:"serviceSubnet,omitempty"`
	DNSDomain     string `json:"dnsDomain,omitempty"`

	// NEW
	NetworkProvider string `json:"networkProvider,omitempty"` // kubenet, flannel, calico, opencontrail
	// Replacing API_SERVERS https://github.com/kubernetes/kubernetes/blob/62898319dff291843e53b7839c6cde14ee5d2aa4/cluster/aws/util.sh#L1004
	DNSServerIP       string `json:"dnsServerIP,omitempty"`
	NonMasqueradeCIDR string `json:"nonMasqueradeCIDR,omitempty"`

	MasterSubnet string `json:"masterSubnet,omitempty"` // delete ?
}

type AWSSpec struct {
	// aws:TAG KubernetesCluster => clusterid
	IAMProfileMaster string `json:"iamProfileMaster,omitempty"`
	IAMProfileNode   string `json:"iamProfileNode,omitempty"`
	MasterSGName     string `json:"masterSGName,omitempty"`
	NodeSGName       string `json:"nodeSGName,omitempty"`

	VpcCIDR        string `json:"vpcCIDR,omitempty"`
	VpcCIDRBase    string `json:"vpcCIDRBase,omitempty"`
	MasterIPSuffix string `json:"masterIPSuffix,omitempty"`
	SubnetCIDR     string `json:"subnetCidr,omitempty"`
}

type GoogleSpec struct {
	// gce
	// NODE_SCOPES="${NODE_SCOPES:-compute-rw,monitoring,logging-write,storage-ro}"
	NodeScopes []string `json:"nodeScopes,omitempty"`
	// instance means either master or node
	CloudConfig *GCECloudConfig `json:"gceCloudConfig,omitempty"`
}

type AzureSpec struct {
	StorageAccountName string `json:"azureStorageAccountName,omitempty"`
	//only Azure
	InstanceImageVersion string            `json:"instanceImageVersion,omitempty"`
	CloudConfig          *AzureCloudConfig `json:"azureCloudConfig,omitempty"`
	InstanceRootPassword string            `json:"instanceRootPassword,omitempty"`
	SubnetCIDR           string            `json:"subnetCidr,omitempty"`
}

type LinodeSpec struct {
	// Azure, Linode
	InstanceRootPassword string `json:"instanceRootPassword,omitempty"`
}

type CloudSpec struct {
	CloudProvider   string `json:"cloudProvider,omitempty"`
	Project         string `json:"project,omitempty"`
	Region          string `json:"region,omitempty"`
	Zone            string `json:"ZONE,omitempty"` // master needs it for ossec
	OS              string `json:"os,omitempty"`
	Kernel          string `json:"kernel,omitempty"` // needed ?
	CloudConfigPath string `json:"cloudConfig,omitempty"`

	InstanceImage        string `json:"instanceImage,omitempty"`
	InstanceImageProject string `json:"instanceImageProject,omitempty"`

	AWS    *AWSSpec
	GCE    *GoogleSpec
	Azure  *AzureSpec
	Linode *LinodeSpec
}

type ClusterSpec struct {
	Cloud CloudSpec `json:"cloud"`

	API kubeadm.API `json:"api"`
	// move to api ?
	// 	KubeAPIserverRequestTimeout string `json:"kubeAPIserverRequestTimeout,omitempty"`
	// TerminatedPodGcThreshold    string `json:"terminatedPodGCThreshold,omitempty"`

	Etcd       kubeadm.Etcd `json:"etcd"`
	Networking Networking   `json:"networking"`

	Multizone StrToBool `json:"multizone,omitempty"`

	KubernetesVersion string `json:"kubernetesVersion,omitempty"`
	KubeadmVersion    string `json:"kubeadmVersion,omitempty"`

	// request data. This is needed to give consistent access to these values for all commands.
	DoNotDelete        bool     `json:"doNotDelete,omitempty"`
	AuthorizationModes []string `json:"authorizationModes"`

	Token    string        `json:"token"`
	TokenTTL time.Duration `json:"tokenTTL"`

	// SelfHosted enables an alpha deployment type where the apiserver, scheduler, and
	// controller manager are managed by Kubernetes itself. This option is likely to
	// become the default in the future.
	SelfHosted bool `json:"selfHosted"`

	// APIServerCertSANs sets extra Subject Alternative Names for the API Server signing cert
	APIServerCertSANs     []string `json:"apiServerCertSANs"`
	ClusterExternalDomain string   `json:"clusterExternalDomain,omitempty"`
	ClusterInternalDomain string   `json:"clusterInternalDomain,omitempty"`

	// Auto Set
	// https://github.com/kubernetes/kubernetes/blob/master/cluster/gce/util.sh#L538
	CACertName           string `json:"caCertPHID,omitempty"`
	FrontProxyCACertName string `json:"frontProxyCaCertPHID,omitempty"`
	CredentialName       string `json:"credentialName,omitempty"`

	// Cloud Config

	AllocateNodeCIDRs            bool   `json:"allocateNodeCidrs,omitempty"`
	LoggingDestination           string `json:"loggingDestination,omitempty"`
	ElasticsearchLoggingReplicas int    `json:"elasticsearchLoggingReplicas,omitempty"`
	AdmissionControl             string `json:"admissionControl,omitempty"`
	RuntimeConfig                string `json:"runtimeConfig,omitempty"`

	// Kube 1.3
	AppscodeAuthnURL string `json:"appscodeAuthnURL,omitempty"`
	AppscodeAuthzURL string `json:"appscodeAuthzURL,omitempty"`

	// Kube 1.5.4

	// config
	// Some of these parameters might be useful to expose to users to configure as they please.
	// For now, use the default value used by the Kubernetes project as the default value.

	// TODO: Download the kube binaries from GCS bucket and ignore EU data locality issues for now.

	// common

	// GCE: Use Root Field for this in GCE

	// MASTER_TAG="clusterName-master"
	// NODE_TAG="clusterName-node"

	// aws
	// NODE_SCOPES=""

	// NEW
	// enable various v1beta1 features

	AutoscalerMinNodes    int     `json:"autoscalerMinNodes,omitempty"`
	AutoscalerMaxNodes    int     `json:"autoscalerMaxNodes,omitempty"`
	TargetNodeUtilization float64 `json:"targetNodeUtilization,omitempty"`

	// only aws

	EnableClusterMonitoring string `json:"enableClusterMonitoring,omitempty"`
	EnableClusterLogging    bool   `json:"enableClusterLogging,omitempty"`
	EnableNodeLogging       bool   `json:"enableNodeLogging,omitempty"`
	EnableCustomMetrics     string `json:"enableCustomMetrics,omitempty"`
	// NEW
	EnableAPIserverBasicAudit bool   `json:"enableAPIserverBasicAudit,omitempty"`
	EnableClusterAlert        string `json:"enableClusterAlert,omitempty"`
	EnableNodeProblemDetector bool   `json:"enableNodeProblemDetector,omitempty"`
	// Kub1 1.4
	EnableRescheduler                bool `json:"enableRescheduler,omitempty"`
	EnableWebhookTokenAuthentication bool `json:"enableWebhookTokenAuthn,omitempty"`
	EnableWebhookTokenAuthorization  bool `json:"enableWebhookTokenAuthz,omitempty"`
	EnableRBACAuthorization          bool `json:"enableRbacAuthz,omitempty"`
	EnableNodePublicIP               bool `json:"enableNodePublicIP,omitempty"`
	EnableNodeAutoscaler             bool `json:"enableNodeAutoscaler,omitempty"`

	// Consolidate DNS / Master name options
	// Deprecated
	KubernetesMasterName string `json:"kubernetesMasterName,omitempty"`
	// Deprecated
	MasterInternalIP string `json:"masterInternalIp,omitempty"`
	// the master root ebs volume size (typically does not need to be very large)
	// Deprecated
	MasterDiskId string `json:"masterDiskID,omitempty"`

	// Delete since moved to InstanceGroup / Instance
	// Deprecated
	MasterDiskType string `json:"masterDiskType,omitempty"`
	// Deprecated
	MasterDiskSize int64 `json:"masterDiskSize,omitempty"`
	// Deprecated
	MasterSKU string `json:"masterSku,omitempty"`
	// If set to Elasticsearch IP, master instance will be associated with this IP.
	// If set to auto, a new Elasticsearch IP will be acquired
	// Otherwise amazon-given public ip will be used (it'll change with reboot).
	// Deprecated
	MasterReservedIP string `json:"masterReservedIp,omitempty"`
	// Deprecated
	MasterExternalIP string `json:"masterExternalIp,omitempty"`

	// the node root ebs volume size (used to house docker images)
	// Deprecated
	NodeDiskType string `json:"nodeDiskType,omitempty"`
	// Deprecated
	NodeDiskSize int64 `json:"nodeDiskSize,omitempty"`
}

type AWSStatus struct {
	MasterSGId string `json:"masterSGID,omitempty"`
	NodeSGId   string `json:"nodeSGID,omitempty"`

	VpcId         string `json:"vpcID,omitempty"`
	SubnetId      string `json:"subnetID,omitempty"`
	RouteTableId  string `json:"routeTableID,omitempty"`
	IGWId         string `json:"igwID,omitempty"`
	DHCPOptionsId string `json:"dhcpOptionsID,omitempty"`

	// only aws
	RootDeviceName string `json:"-"`
}

type CloudStatus struct {
	AWS *AWSStatus
}

type ClusterStatus struct {
	Phase            string `json:"phase,omitempty,omitempty"`
	Reason           string `json:"reason,omitempty,omitempty"`
	SSHKeyExternalID string `json:"sshKeyExternalID,omitempty"`

	Cloud CloudStatus `json:"cloud"`
}

func (cluster *Cluster) NodeCount() int64 {
	panic("Fix it!")
	return 0
}

func (cluster *Cluster) SetNodeGroups(ng []*proto.InstanceGroup) {
	panic("Fix it!")
}

func (cluster *Cluster) Delete() error {
	if cluster.Status.Phase == ClusterPhasePending || cluster.Status.Phase == ClusterPhaseFailing || cluster.Status.Phase == ClusterPhaseFailed {
		cluster.Status.Phase = ClusterPhaseFailed
	} else {
		cluster.Status.Phase = ClusterPhaseDeleted
	}
	fmt.Println("FixIt!")
	//if err := ctx.Save(); err != nil {
	//	return err
	//}

	n := rand.WithUniqSuffix(cluster.Name)
	//if _, err := ctx.Store().Engine.Update(&Kubernetes{Name: n}, &Kubernetes{PHID: ctx.PHID}); err != nil {
	//	return err
	//}
	cluster.Name = n
	return nil
}

func (cluster *Cluster) clusterIP(seq int64) string {
	octets := strings.Split(cluster.Spec.Networking.ServiceSubnet, ".")
	p, _ := strconv.ParseInt(octets[3], 10, 64)
	p = p + seq
	octets[3] = strconv.FormatInt(p, 10)
	return strings.Join(octets, ".")
}

func (cluster *Cluster) KubernetesClusterIP() string {
	return cluster.clusterIP(1)
}

// This is a onetime initializer method.
func (cluster *Cluster) APIServerURL() string {
	//if ctx.ApiServerUrl == "" {
	//	host := ctx.Extra().ExternalDomain(ctx.Name)
	//	if ctx.MasterReservedIP != "" {
	//		host = ctx.MasterReservedIP
	//	}
	return fmt.Sprintf("https://%v:6443", cluster.Spec.MasterReservedIP)
	// ctx.Logger().Infoln(fmt.Sprintf("Cluster %v 's api server url: %v\n", ctx.Name, ctx.ApiServerUrl))
	//}
}
<commit_msg>Add links to CloudConfig struct<commit_after>package api

import (
	"fmt"
	"strconv"
	"strings"
	"time"

	proto "github.com/appscode/api/kubernetes/v1beta1"
	"github.com/appscode/go/crypto/rand"
	. "github.com/appscode/go/encoding/json/types"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	kubeadm "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
)

// ref: https://github.com/kubernetes/kubernetes/blob/8b9f0ea5de2083589f3b9b289b90273556bc09c4/pkg/cloudprovider/providers/azure/azure.go#L56
type AzureCloudConfig struct {
	TenantID           string `json:"tenantId,omitempty"`
	SubscriptionID     string `json:"subscriptionId,omitempty"`
	AadClientID        string `json:"aadClientId,omitempty"`
	AadClientSecret    string `json:"aadClientSecret,omitempty"`
	ResourceGroup      string `json:"resourceGroup,omitempty"`
	Location           string `json:"location,omitempty"`
	SubnetName         string `json:"subnetName,omitempty"`
	SecurityGroupName  string `json:"securityGroupName,omitempty"`
	VnetName           string `json:"vnetName,omitempty"`
	RouteTableName     string `json:"routeTableName,omitempty"`
	StorageAccountName string `json:"storageAccountName,omitempty"`
}

// ref: https://github.com/kubernetes/kubernetes/blob/8b9f0ea5de2083589f3b9b289b90273556bc09c4/pkg/cloudprovider/providers/gce/gce.go#L228
type GCECloudConfig struct {
	TokenURL           string   `gcfg:"token-url"            ini:"token-url,omitempty"`
	TokenBody          string   `gcfg:"token-body"           ini:"token-body,omitempty"`
	ProjectID          string   `gcfg:"project-id"           ini:"project-id,omitempty"`
	NetworkName        string   `gcfg:"network-name"         ini:"network-name,omitempty"`
	NodeTags           []string `gcfg:"node-tags"            ini:"node-tags,omitempty,omitempty"`
	NodeInstancePrefix string   `gcfg:"node-instance-prefix" ini:"node-instance-prefix,omitempty,omitempty"`
	Multizone          bool     `gcfg:"multizone"            ini:"multizone,omitempty"`
}

type IG struct {
	SKU           string `json:"sku,omitempty"`
	Count         int64  `json:"count,omitempty"`
	SpotInstances bool   `json:"spotInstances,omitempty"`
}

type Cluster struct {
	metav1.TypeMeta   `json:",inline,omitempty,omitempty"`
	metav1.ObjectMeta `json:"metadata,omitempty,omitempty"`
	Spec              ClusterSpec   `json:"spec,omitempty,omitempty"`
	Status            ClusterStatus `json:"status,omitempty,omitempty"`
}

type Networking struct {
	PodSubnet     string `json:"podSubnet,omitempty"`
	ServiceSubnet string `json:"serviceSubnet,omitempty"`
	DNSDomain     string `json:"dnsDomain,omitempty"`

	// NEW
	NetworkProvider string `json:"networkProvider,omitempty"` // kubenet, flannel, calico, opencontrail
	// Replacing API_SERVERS https://github.com/kubernetes/kubernetes/blob/62898319dff291843e53b7839c6cde14ee5d2aa4/cluster/aws/util.sh#L1004
	DNSServerIP       string `json:"dnsServerIP,omitempty"`
	NonMasqueradeCIDR string `json:"nonMasqueradeCIDR,omitempty"`

	MasterSubnet string `json:"masterSubnet,omitempty"` // delete ?
}

type AWSSpec struct {
	// aws:TAG KubernetesCluster => clusterid
	IAMProfileMaster string `json:"iamProfileMaster,omitempty"`
	IAMProfileNode   string `json:"iamProfileNode,omitempty"`
	MasterSGName     string `json:"masterSGName,omitempty"`
	NodeSGName       string `json:"nodeSGName,omitempty"`

	VpcCIDR        string `json:"vpcCIDR,omitempty"`
	VpcCIDRBase    string `json:"vpcCIDRBase,omitempty"`
	MasterIPSuffix string `json:"masterIPSuffix,omitempty"`
	SubnetCIDR     string `json:"subnetCidr,omitempty"`
}

type GoogleSpec struct {
	// gce
	// NODE_SCOPES="${NODE_SCOPES:-compute-rw,monitoring,logging-write,storage-ro}"
	NodeScopes []string `json:"nodeScopes,omitempty"`
	// instance means either master or node
	CloudConfig *GCECloudConfig `json:"gceCloudConfig,omitempty"`
}

type AzureSpec struct {
	StorageAccountName string `json:"azureStorageAccountName,omitempty"`
	//only Azure
	InstanceImageVersion string            `json:"instanceImageVersion,omitempty"`
	CloudConfig          *AzureCloudConfig `json:"azureCloudConfig,omitempty"`
	InstanceRootPassword string            `json:"instanceRootPassword,omitempty"`
	SubnetCIDR           string            `json:"subnetCidr,omitempty"`
}

type LinodeSpec struct {
	// Azure, Linode
	InstanceRootPassword string `json:"instanceRootPassword,omitempty"`
}

type CloudSpec struct {
	CloudProvider   string `json:"cloudProvider,omitempty"`
	Project         string `json:"project,omitempty"`
	Region          string `json:"region,omitempty"`
	Zone            string `json:"ZONE,omitempty"` // master needs it for ossec
	OS              string `json:"os,omitempty"`
	Kernel          string `json:"kernel,omitempty"` // needed ?
	CloudConfigPath string `json:"cloudConfig,omitempty"`

	InstanceImage        string `json:"instanceImage,omitempty"`
	InstanceImageProject string `json:"instanceImageProject,omitempty"`

	AWS    *AWSSpec
	GCE    *GoogleSpec
	Azure  *AzureSpec
	Linode *LinodeSpec
}

type ClusterSpec struct {
	Cloud CloudSpec `json:"cloud"`

	API kubeadm.API `json:"api"`
	// move to api ?
	// 	KubeAPIserverRequestTimeout string `json:"kubeAPIserverRequestTimeout,omitempty"`
	// TerminatedPodGcThreshold    string `json:"terminatedPodGCThreshold,omitempty"`

	Etcd       kubeadm.Etcd `json:"etcd"`
	Networking Networking   `json:"networking"`

	Multizone StrToBool `json:"multizone,omitempty"`

	KubernetesVersion string `json:"kubernetesVersion,omitempty"`
	KubeadmVersion    string `json:"kubeadmVersion,omitempty"`

	// request data. This is needed to give consistent access to these values for all commands.
	DoNotDelete        bool     `json:"doNotDelete,omitempty"`
	AuthorizationModes []string `json:"authorizationModes"`

	Token    string        `json:"token"`
	TokenTTL time.Duration `json:"tokenTTL"`

	// SelfHosted enables an alpha deployment type where the apiserver, scheduler, and
	// controller manager are managed by Kubernetes itself. This option is likely to
	// become the default in the future.
	SelfHosted bool `json:"selfHosted"`

	// APIServerCertSANs sets extra Subject Alternative Names for the API Server signing cert
	APIServerCertSANs     []string `json:"apiServerCertSANs"`
	ClusterExternalDomain string   `json:"clusterExternalDomain,omitempty"`
	ClusterInternalDomain string   `json:"clusterInternalDomain,omitempty"`

	// Auto Set
	// https://github.com/kubernetes/kubernetes/blob/master/cluster/gce/util.sh#L538
	CACertName           string `json:"caCertPHID,omitempty"`
	FrontProxyCACertName string `json:"frontProxyCaCertPHID,omitempty"`
	CredentialName       string `json:"credentialName,omitempty"`

	// Cloud Config

	AllocateNodeCIDRs            bool   `json:"allocateNodeCidrs,omitempty"`
	LoggingDestination           string `json:"loggingDestination,omitempty"`
	ElasticsearchLoggingReplicas int    `json:"elasticsearchLoggingReplicas,omitempty"`
	AdmissionControl             string `json:"admissionControl,omitempty"`
	RuntimeConfig                string `json:"runtimeConfig,omitempty"`

	// Kube 1.3
	AppscodeAuthnURL string `json:"appscodeAuthnURL,omitempty"`
	AppscodeAuthzURL string `json:"appscodeAuthzURL,omitempty"`

	// Kube 1.5.4

	// config
	// Some of these parameters might be useful to expose to users to configure as they please.
	// For now, use the default value used by the Kubernetes project as the default value.

	// TODO: Download the kube binaries from GCS bucket and ignore EU data locality issues for now.

	// common

	// GCE: Use Root Field for this in GCE

	// MASTER_TAG="clusterName-master"
	// NODE_TAG="clusterName-node"

	// aws
	// NODE_SCOPES=""

	// NEW
	// enable various v1beta1 features

	AutoscalerMinNodes    int     `json:"autoscalerMinNodes,omitempty"`
	AutoscalerMaxNodes    int     `json:"autoscalerMaxNodes,omitempty"`
	TargetNodeUtilization float64 `json:"targetNodeUtilization,omitempty"`

	// only aws

	EnableClusterMonitoring string `json:"enableClusterMonitoring,omitempty"`
	EnableClusterLogging    bool   `json:"enableClusterLogging,omitempty"`
	EnableNodeLogging       bool   `json:"enableNodeLogging,omitempty"`
	EnableCustomMetrics     string `json:"enableCustomMetrics,omitempty"`
	// NEW
	EnableAPIserverBasicAudit bool   `json:"enableAPIserverBasicAudit,omitempty"`
	EnableClusterAlert        string `json:"enableClusterAlert,omitempty"`
	EnableNodeProblemDetector bool   `json:"enableNodeProblemDetector,omitempty"`
	// Kub1 1.4
	EnableRescheduler                bool `json:"enableRescheduler,omitempty"`
	EnableWebhookTokenAuthentication bool `json:"enableWebhookTokenAuthn,omitempty"`
	EnableWebhookTokenAuthorization  bool `json:"enableWebhookTokenAuthz,omitempty"`
	EnableRBACAuthorization          bool `json:"enableRbacAuthz,omitempty"`
	EnableNodePublicIP               bool `json:"enableNodePublicIP,omitempty"`
	EnableNodeAutoscaler             bool `json:"enableNodeAutoscaler,omitempty"`

	// Consolidate DNS / Master name options
	// Deprecated
	KubernetesMasterName string `json:"kubernetesMasterName,omitempty"`
	// Deprecated
	MasterInternalIP string `json:"masterInternalIp,omitempty"`
	// the master root ebs volume size (typically does not need to be very large)
	// Deprecated
	MasterDiskId string `json:"masterDiskID,omitempty"`

	// Delete since moved to InstanceGroup / Instance
	// Deprecated
	MasterDiskType string `json:"masterDiskType,omitempty"`
	// Deprecated
	MasterDiskSize int64 `json:"masterDiskSize,omitempty"`
	// Deprecated
	MasterSKU string `json:"masterSku,omitempty"`
	// If set to Elasticsearch IP, master instance will be associated with this IP.
	// If set to auto, a new Elasticsearch IP will be acquired
	// Otherwise amazon-given public ip will be used (it'll change with reboot).
	// Deprecated
	MasterReservedIP string `json:"masterReservedIp,omitempty"`
	// Deprecated
	MasterExternalIP string `json:"masterExternalIp,omitempty"`

	// the node root ebs volume size (used to house docker images)
	// Deprecated
	NodeDiskType string `json:"nodeDiskType,omitempty"`
	// Deprecated
	NodeDiskSize int64 `json:"nodeDiskSize,omitempty"`
}

type AWSStatus struct {
	MasterSGId string `json:"masterSGID,omitempty"`
	NodeSGId   string `json:"nodeSGID,omitempty"`

	VpcId         string `json:"vpcID,omitempty"`
	SubnetId      string `json:"subnetID,omitempty"`
	RouteTableId  string `json:"routeTableID,omitempty"`
	IGWId         string `json:"igwID,omitempty"`
	DHCPOptionsId string `json:"dhcpOptionsID,omitempty"`

	// only aws
	RootDeviceName string `json:"-"`
}

type CloudStatus struct {
	AWS *AWSStatus
}

type ClusterStatus struct {
	Phase            string `json:"phase,omitempty,omitempty"`
	Reason           string `json:"reason,omitempty,omitempty"`
	SSHKeyExternalID string `json:"sshKeyExternalID,omitempty"`

	Cloud CloudStatus `json:"cloud"`
}

func (cluster *Cluster) NodeCount() int64 {
	panic("Fix it!")
	return 0
}

func (cluster *Cluster) SetNodeGroups(ng []*proto.InstanceGroup) {
	panic("Fix it!")
}

func (cluster *Cluster) Delete() error {
	if cluster.Status.Phase == ClusterPhasePending || cluster.Status.Phase == ClusterPhaseFailing || cluster.Status.Phase == ClusterPhaseFailed {
		cluster.Status.Phase = ClusterPhaseFailed
	} else {
		cluster.Status.Phase = ClusterPhaseDeleted
	}
	fmt.Println("FixIt!")
	//if err := ctx.Save(); err != nil {
	//	return err
	//}

	n := rand.WithUniqSuffix(cluster.Name)
	//if _, err := ctx.Store().Engine.Update(&Kubernetes{Name: n}, &Kubernetes{PHID: ctx.PHID}); err != nil {
	//	return err
	//}
	cluster.Name = n
	return nil
}

func (cluster *Cluster) clusterIP(seq int64) string {
	octets := strings.Split(cluster.Spec.Networking.ServiceSubnet, ".")
	p, _ := strconv.ParseInt(octets[3], 10, 64)
	p = p + seq
	octets[3] = strconv.FormatInt(p, 10)
	return strings.Join(octets, ".")
}

func (cluster *Cluster) KubernetesClusterIP() string {
	return cluster.clusterIP(1)
}

// This is a onetime initializer method.
func (cluster *Cluster) APIServerURL() string {
	//if ctx.ApiServerUrl == "" {
	//	host := ctx.Extra().ExternalDomain(ctx.Name)
	//	if ctx.MasterReservedIP != "" {
	//		host = ctx.MasterReservedIP
	//	}
	return fmt.Sprintf("https://%v:6443", cluster.Spec.MasterReservedIP)
	// ctx.Logger().Infoln(fmt.Sprintf("Cluster %v 's api server url: %v\n", ctx.Name, ctx.ApiServerUrl))
	//}
}
<|endoftext|>


<commit_before>/**
 * Copyright 2015 @ S1N1 Team.
 * name : payment_opt
 * author : jarryliu
 * date : -- :
 * description :
 * history :
 */
package enum

var (
	PaymentOptionNames  []string = []string{"在线付款", "货到付款", "转账汇款"}
	PaymentHelpContents []string = []string{
		"请完成最后一步，点击按钮在线支付订单。",
		"请您在收到商品时候，现金支付，或使用POS机刷卡(不同地区可能不支持).",
		"请通过银行汇款至我们的银行账户后，并联系客服进行订单付款。详情点击这里查看。",
	}
)

const (
	PaymentOnlinePay      int = 1 // 线上付款
	PaymentOfflineCashPay     = 2 // 线下现金付款
	PaymentRemit          int = 3 // 转账汇款
)

// 获取支付帮助内容
//todo: 需要商户可以自定义设置
func GetPaymentHelpContent(opt int) string {
	return PaymentHelpContents[opt-1]
}
<commit_msg>commit<commit_after>/**
 * Copyright 2015 @ S1N1 Team.
 * name : payment_opt
 * author : jarryliu
 * date : -- :
 * description :
 * history :
 */
package enum

var (
	PaymentOptionNames  []string = []string{"在线付款", "货到付款", "转账汇款"}
	PaymentHelpContents []string = []string{
		"请完成最后一步，点击按钮在线支付订单。",
		"请您在收到商品时候，现金支付，或使用POS机刷卡(不同地区可能不支持).",
		"请通过银行汇款至我们的银行账户后，并联系客服进行订单付款。详情点击这里查看。",
	}
)

const (
	PaymentOnlinePay      int = 1 // 线上付款
	PaymentOfflineCashPay     = 2 // 线下现金付款
	PaymentRemit          int = 3 // 转账汇款
)

// 获取支付帮助内容
//todo: 需要商户可以自定义设置
func GetPaymentHelpContent(opt int) string {
	return PaymentHelpContents[opt-1]
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"

	"github.com/zach-klippenstein/goadb"
	"gopkg.in/alecthomas/kingpin.v2"
)

var (
	serial          = kingpin.Flag("serial", "Connect to device by serial number.").Short('s').String()
	shellCommand    = kingpin.Command("shell", "Run a shell command on the device.")
	shellCommandArg = shellCommand.Arg("command", "Command to run on device.").Strings()
	devicesCommand  = kingpin.Command("devices", "List devices.")
	devicesLongFlag = devicesCommand.Flag("long", "Include extra detail about devices.").Short('l').Bool()
)

func main() {
	var exitCode int

	switch kingpin.Parse() {
	case "devices":
		exitCode = listDevices(*devicesLongFlag)
	case "shell":
		exitCode = runShellCommand(*shellCommandArg, parseDevice())
	}

	os.Exit(exitCode)
}

func parseDevice() goadb.DeviceDescriptor {
	if *serial != "" {
		return goadb.DeviceWithSerial(*serial)
	}

	return goadb.AnyDevice()
}

func listDevices(long bool) int {
	client := goadb.NewHostClient(goadb.ClientConfig{})
	devices, err := client.ListDevices()
	if err != nil {
		fmt.Fprintln(os.Stderr, "error:", err)
	}

	for _, device := range devices {
		if long {
			fmt.Printf("%s\t\t%s\t%s\n", device.Serial, device.Product, device.Model)
		} else {
			fmt.Println(device.Serial)
		}
	}

	return 0
}

func runShellCommand(commandAndArgs []string, device goadb.DeviceDescriptor) int {
	if len(commandAndArgs) == 0 {
		fmt.Fprintln(os.Stderr, "error: no command")
		kingpin.Usage()
		return 1
	}

	command := commandAndArgs[0]
	var args []string

	if len(commandAndArgs) > 1 {
		args = commandAndArgs[1:]
	}

	client := goadb.NewDeviceClient(goadb.ClientConfig{}, device)
	output, err := client.RunCommand(command, args...)
	if err != nil {
		fmt.Fprintln(os.Stderr, "error:", err)
		return 1
	}

	fmt.Print(output)
	return 0
}
<commit_msg>[cmd/adb] Make devices -l look more like the official command's output.<commit_after>package main

import (
	"fmt"
	"os"

	"github.com/zach-klippenstein/goadb"
	"gopkg.in/alecthomas/kingpin.v2"
)

var (
	serial          = kingpin.Flag("serial", "Connect to device by serial number.").Short('s').String()
	shellCommand    = kingpin.Command("shell", "Run a shell command on the device.")
	shellCommandArg = shellCommand.Arg("command", "Command to run on device.").Strings()
	devicesCommand  = kingpin.Command("devices", "List devices.")
	devicesLongFlag = devicesCommand.Flag("long", "Include extra detail about devices.").Short('l').Bool()
)

func main() {
	var exitCode int

	switch kingpin.Parse() {
	case "devices":
		exitCode = listDevices(*devicesLongFlag)
	case "shell":
		exitCode = runShellCommand(*shellCommandArg, parseDevice())
	}

	os.Exit(exitCode)
}

func parseDevice() goadb.DeviceDescriptor {
	if *serial != "" {
		return goadb.DeviceWithSerial(*serial)
	}

	return goadb.AnyDevice()
}

func listDevices(long bool) int {
	client := goadb.NewHostClient(goadb.ClientConfig{})
	devices, err := client.ListDevices()
	if err != nil {
		fmt.Fprintln(os.Stderr, "error:", err)
	}

	for _, device := range devices {
		if long {
			if device.Usb == "" {
				fmt.Printf("%s\tproduct:%s model:%s device:%s\n",
					device.Serial, device.Product, device.Model, device.DeviceInfo)
			} else {
				fmt.Printf("%s\tusb:%s product:%s model:%s device:%s\n",
					device.Serial, device.Usb, device.Product, device.Model, device.DeviceInfo)
			}
		} else {
			fmt.Println(device.Serial)
		}
	}

	return 0
}

func runShellCommand(commandAndArgs []string, device goadb.DeviceDescriptor) int {
	if len(commandAndArgs) == 0 {
		fmt.Fprintln(os.Stderr, "error: no command")
		kingpin.Usage()
		return 1
	}

	command := commandAndArgs[0]
	var args []string

	if len(commandAndArgs) > 1 {
		args = commandAndArgs[1:]
	}

	client := goadb.NewDeviceClient(goadb.ClientConfig{}, device)
	output, err := client.RunCommand(command, args...)
	if err != nil {
		fmt.Fprintln(os.Stderr, "error:", err)
		return 1
	}

	fmt.Print(output)
	return 0
}
<|endoftext|>


<commit_before>package cmd_test

import (
	"github.com/dcwangmit01/grpc-gw-poc/cmd"

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

	"bytes"
	"io"
	"os"
)

var _ = Describe("RootCmd", func() {
	// The Ginkgo test runner takes over os.Args and fills it with its own
	// flags.  This makes the cobra command arg parsing fail because of
	// unexpected options.  Work around this.

	// Save a copy of os.Args
	var origArgs = os.Args[:]

	// A non-threadsafe buffer for capturing stdout
	var buf bytes.Buffer

	BeforeEach(func() {
		// Trim os.Args to only the first arg, which is the command itself
		os.Args = os.Args[:1]

		// set the output to both Stdout and a byteBuffer
		mw := io.MultiWriter(&buf, os.Stdout)
		cmd.RootCmd.SetOutput(mw)
	})

	AfterEach(func() {
		// Restore os.Args
		os.Args = origArgs[:]

		// restore the output to Stdout
		cmd.RootCmd.SetOutput(os.Stdout)
	})

	It("Should show rootcmd help", func() {

		// Run the command which outputs to stdout
		err := cmd.RootCmd.Execute()

		// bytes.Buffer.String() returns the contents of the unread
		// portion of the buffer as a string.
		out := buf.String()

		// process the output
		//  (?s): allows for "." to represent "\n"
		Expect(out).Should(MatchRegexp("(?s)grpc-gw-poc.*help.*keyval"))
		Expect(err).Should(BeNil())
	})

	It("Should show keyval help", func() {

		os.Args = append(os.Args, "keyval")

		// Run the command which outputs to stdout
		err := cmd.RootCmd.Execute()

		// bytes.Buffer.String() returns the contents of the unread
		// portion of the buffer as a string.
		out := buf.String()

		// process the output
		//  (?s): allows for "." to represent "\n"
		Expect(out).Should(MatchRegexp("(?s)grpc-gw-poc.*help.*keyval.*create.*read.*update.*delete"))
		Expect(err).Should(BeNil())
	})
})
<commit_msg>Finished BDD for commands showing help<commit_after>package cmd_test

import (
	"github.com/dcwangmit01/grpc-gw-poc/cmd"

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

	"bytes"
	"io"
	"os"
)

var _ = Describe("Cmd", func() {
	// The Ginkgo test runner takes over os.Args and fills it with its own
	// flags.  This makes the cobra command arg parsing fail because of
	// unexpected options.  Work around this.

	// Save a copy of os.Args
	var origArgs = os.Args[:]

	// A non-threadsafe buffer for capturing stdout
	var buf bytes.Buffer

	BeforeEach(func() {
		// Trim os.Args to only the first arg, which is the command itself
		os.Args = os.Args[:1]

		// set the output to both Stdout and a byteBuffer
		mw := io.MultiWriter(&buf, os.Stdout)
		cmd.RootCmd.SetOutput(mw)
	})

	AfterEach(func() {
		// Restore os.Args
		os.Args = origArgs[:]

		// restore the output to Stdout
		cmd.RootCmd.SetOutput(os.Stdout)
	})

	Describe("RootCmd", func() {
		Context("When run with no args", func() {
			It("Should show rootcmd help", func() {
				// Run the command which outputs to stdout
				err := cmd.RootCmd.Execute()

				// bytes.Buffer.String() returns the contents of the unread
				// portion of the buffer as a string.
				out := buf.String()

				// process the output
				//  (?s): allows for "." to represent "\n"
				Expect(out).Should(MatchRegexp("(?s)grpc-gw-poc.*help.*keyval"))
				Expect(err).Should(BeNil())
			})
		})
	})

	Describe("keyval Subcommand", func() {
		Context("When run with no args", func() {
			It("Should show keyval help", func() {
				// Set args to command
				os.Args = append(os.Args, "keyval")

				// Run the command which outputs to stdout
				err := cmd.RootCmd.Execute()

				// bytes.Buffer.String() returns the contents of the unread
				// portion of the buffer as a string.
				out := buf.String()

				// process the output
				//  (?s): allows for "." to represent "\n"
				Expect(out).Should(MatchRegexp("(?s)grpc-gw-poc.*help.*keyval.*create.*read.*update.*delete"))
				Expect(err).Should(BeNil())
			})
		})
	})
})
<|endoftext|>


<commit_before>package cmd

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"time"

	"github.com/mobingilabs/mocli/pkg/cli"
	"github.com/mobingilabs/mocli/pkg/stack"
	"github.com/mobingilabs/mocli/pkg/util"
	"github.com/spf13/cobra"
)

var describeCmd = &cobra.Command{
	Use:   "describe",
	Short: "display stack details",
	Long: `Display stack details. If you specify the '--out=[filename]' option,
make sure you provide the full path of the file. If the path has
space(s) in it, make sure to surround it with double quotes.`,
	Run: describe,
}

func init() {
	rootCmd.AddCommand(describeCmd)
	describeCmd.Flags().StringP("id", "i", "", "stack id")
	describeCmd.Flags().StringP("fmt", "f", "text", "output format (valid values: text, json)")
	describeCmd.Flags().StringP("out", "o", "", "full file path to write the output")
}

func describe(cmd *cobra.Command, args []string) {
	token, err := util.GetToken()
	if err != nil {
		util.PrintErrorAndExit("Cannot read token. See `login` for information on how to login.", 1)
	}

	id := util.GetCliStringFlag(cmd, "id")
	if id == "" {
		util.PrintErrorAndExit("Stack id cannot be empty.", 1)
	}

	c := cli.New(util.GetCliStringFlag(cmd, "api-version"))
	ep := c.RootUrl + "/alm/stack/" + fmt.Sprintf("%s", id)
	resp, body, errs := c.GetSafe(ep, fmt.Sprintf("%s", token))
	if errs != nil {
		log.Println("Error(s):", errs)
		os.Exit(1)
	}

	var stacks []stack.DescribeStack
	err = json.Unmarshal(body, &stacks)
	if err != nil {
		log.Println(err)
		var m map[string]interface{}
		err = json.Unmarshal(body, &m)
		if err != nil {
			util.PrintErrorAndExit("Internal error.", 1)
		}

		serr := util.BuildRequestError(resp, m)
		if serr != "" {
			util.PrintErrorAndExit(serr, 1)
		}
	}

	switch util.GetCliStringFlag(cmd, "fmt") {
	case "text":
		for _, s := range stacks {
			fmt.Fprintf(os.Stdout, "Stack ID       : %s\n", s.StackId)
			fmt.Fprintf(os.Stdout, "Stack name     : %s\n", s.Nickname)
			fmt.Fprintf(os.Stdout, "Stack type     : %s\n", s.Configuration.Type)
			fmt.Fprintf(os.Stdout, "Region         : %s\n", s.Configuration.Region)
			fmt.Fprintf(os.Stdout, "Architecture   : %s\n", s.Configuration.Architecture)
			fmt.Fprintf(os.Stdout, "Code           : %s\n", s.Configuration.Code)
			fmt.Fprintf(os.Stdout, "Image          : %s\n", s.Configuration.Image)
			fmt.Fprintf(os.Stdout, "Instances count: %d\n", len(s.Instances))
			for i, v := range s.Instances {
				fmt.Fprintf(os.Stdout, "  Index              : [%d]\n", i)
				fmt.Fprintf(os.Stdout, "  Instance ID        : %s\n", v.InstanceId)
				fmt.Fprintf(os.Stdout, "  Instance type      : %s\n", v.InstanceType)
				fmt.Fprintf(os.Stdout, "  Virtualization type: %s\n", v.VirtualizationType)
				fmt.Fprintf(os.Stdout, "  Public IP          : %s\n", v.PublicIpAddress)
				fmt.Fprintf(os.Stdout, "  Public DNS name    : %s\n", v.PublicDnsName)
				fmt.Fprintf(os.Stdout, "  Private IP         : %s\n", v.PrivateIpAddress)
				fmt.Fprintf(os.Stdout, "  Private DNS name   : %s\n", v.PrivateDnsName)
				fmt.Fprintf(os.Stdout, "  Architecture       : %s\n", v.Architecture)
				fmt.Fprintf(os.Stdout, "  Hypervisor         : %s\n", v.Hypervisor)
				fmt.Fprintf(os.Stdout, "  Image ID           : %s\n", v.ImageId)
				fmt.Fprintf(os.Stdout, "  Monitoring state   : %s\n", v.Monitoring.State)
				fmt.Fprintf(os.Stdout, "  State              : [%s], %s\n", v.State.Code, v.State.Name)
				fmt.Fprintf(os.Stdout, "  Availability zone  : %s\n", v.Placement.AvailabilityZone)
				fmt.Fprintf(os.Stdout, "  Root device name   : %s\n", v.RootDeviceName)
				fmt.Fprintf(os.Stdout, "  Root device type   : %s\n", v.RootDeviceType)
				fmt.Fprintf(os.Stdout, "  VPC ID             : %s\n", v.VpcId)
				fmt.Fprintf(os.Stdout, "\n")
			}

			fmt.Fprintf(os.Stdout, "Status         : %s\n", s.StackStatus)
			timestr := s.CreateTime
			t, err := time.Parse(time.RFC3339, s.CreateTime)
			if err == nil {
				timestr = t.Format(time.RFC1123)
			}

			fmt.Fprintf(os.Stdout, "Time created   : %s\n", timestr)
		}

		log.Println(fmt.Sprintf("%+v", stacks))

	case "json":
		mi, err := json.MarshalIndent(stacks, "", "  ")
		if err != nil {
			util.PrintErrorAndExit(err.Error(), 1)
		}

		// this should be a prettified JSON output
		fmt.Println(string(mi))

		f := util.GetCliStringFlag(cmd, "out")
		if f != "" {
			err = ioutil.WriteFile(f, mi, 0644)
			if err != nil {
				util.PrintErrorAndExit(err.Error(), 1)
			}

			log.Println(fmt.Sprintf("Output written to %s.", f))
		}
	}
}
<commit_msg>Remove print before recursive print cleanup.<commit_after>package cmd

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"time"

	"github.com/mobingilabs/mocli/pkg/cli"
	"github.com/mobingilabs/mocli/pkg/stack"
	"github.com/mobingilabs/mocli/pkg/util"
	"github.com/spf13/cobra"
)

var describeCmd = &cobra.Command{
	Use:   "describe",
	Short: "display stack details",
	Long: `Display stack details. If you specify the '--out=[filename]' option,
make sure you provide the full path of the file. If the path has
space(s) in it, make sure to surround it with double quotes.`,
	Run: describe,
}

func init() {
	rootCmd.AddCommand(describeCmd)
	describeCmd.Flags().StringP("id", "i", "", "stack id")
	describeCmd.Flags().StringP("fmt", "f", "text", "output format (valid values: text, json)")
	describeCmd.Flags().StringP("out", "o", "", "full file path to write the output")
}

func describe(cmd *cobra.Command, args []string) {
	token, err := util.GetToken()
	if err != nil {
		util.PrintErrorAndExit("Cannot read token. See `login` for information on how to login.", 1)
	}

	id := util.GetCliStringFlag(cmd, "id")
	if id == "" {
		util.PrintErrorAndExit("Stack id cannot be empty.", 1)
	}

	c := cli.New(util.GetCliStringFlag(cmd, "api-version"))
	ep := c.RootUrl + "/alm/stack/" + fmt.Sprintf("%s", id)
	resp, body, errs := c.GetSafe(ep, fmt.Sprintf("%s", token))
	if errs != nil {
		log.Println("Error(s):", errs)
		os.Exit(1)
	}

	var stacks []stack.DescribeStack
	err = json.Unmarshal(body, &stacks)
	if err != nil {
		log.Println(err)
		var m map[string]interface{}
		err = json.Unmarshal(body, &m)
		if err != nil {
			util.PrintErrorAndExit("Internal error.", 1)
		}

		serr := util.BuildRequestError(resp, m)
		if serr != "" {
			util.PrintErrorAndExit(serr, 1)
		}
	}

	switch util.GetCliStringFlag(cmd, "fmt") {
	case "text":
		for _, s := range stacks {
			fmt.Fprintf(os.Stdout, "Stack ID       : %s\n", s.StackId)
			fmt.Fprintf(os.Stdout, "Stack name     : %s\n", s.Nickname)
			fmt.Fprintf(os.Stdout, "Stack type     : %s\n", s.Configuration.Type)
			fmt.Fprintf(os.Stdout, "Region         : %s\n", s.Configuration.Region)
			fmt.Fprintf(os.Stdout, "Architecture   : %s\n", s.Configuration.Architecture)
			fmt.Fprintf(os.Stdout, "Code           : %s\n", s.Configuration.Code)
			fmt.Fprintf(os.Stdout, "Image          : %s\n", s.Configuration.Image)
			fmt.Fprintf(os.Stdout, "Instances count: %d\n", len(s.Instances))
			for i, v := range s.Instances {
				fmt.Fprintf(os.Stdout, "  Index              : [%d]\n", i)
				fmt.Fprintf(os.Stdout, "  Instance ID        : %s\n", v.InstanceId)
				fmt.Fprintf(os.Stdout, "  Instance type      : %s\n", v.InstanceType)
				fmt.Fprintf(os.Stdout, "  Virtualization type: %s\n", v.VirtualizationType)
				fmt.Fprintf(os.Stdout, "  Public IP          : %s\n", v.PublicIpAddress)
				fmt.Fprintf(os.Stdout, "  Public DNS name    : %s\n", v.PublicDnsName)
				fmt.Fprintf(os.Stdout, "  Private IP         : %s\n", v.PrivateIpAddress)
				fmt.Fprintf(os.Stdout, "  Private DNS name   : %s\n", v.PrivateDnsName)
				fmt.Fprintf(os.Stdout, "  Architecture       : %s\n", v.Architecture)
				fmt.Fprintf(os.Stdout, "  Hypervisor         : %s\n", v.Hypervisor)
				fmt.Fprintf(os.Stdout, "  Image ID           : %s\n", v.ImageId)
				fmt.Fprintf(os.Stdout, "  Monitoring state   : %s\n", v.Monitoring.State)
				fmt.Fprintf(os.Stdout, "  State              : [%s], %s\n", v.State.Code, v.State.Name)
				fmt.Fprintf(os.Stdout, "  Availability zone  : %s\n", v.Placement.AvailabilityZone)
				fmt.Fprintf(os.Stdout, "  Root device name   : %s\n", v.RootDeviceName)
				fmt.Fprintf(os.Stdout, "  Root device type   : %s\n", v.RootDeviceType)
				fmt.Fprintf(os.Stdout, "  VPC ID             : %s\n", v.VpcId)
				fmt.Fprintf(os.Stdout, "\n")
			}

			fmt.Fprintf(os.Stdout, "Status         : %s\n", s.StackStatus)
			timestr := s.CreateTime
			t, err := time.Parse(time.RFC3339, s.CreateTime)
			if err == nil {
				timestr = t.Format(time.RFC1123)
			}

			fmt.Fprintf(os.Stdout, "Time created   : %s\n", timestr)
		}

		// log.Println(fmt.Sprintf("%+v", stacks))

	case "json":
		mi, err := json.MarshalIndent(stacks, "", "  ")
		if err != nil {
			util.PrintErrorAndExit(err.Error(), 1)
		}

		// this should be a prettified JSON output
		fmt.Println(string(mi))

		f := util.GetCliStringFlag(cmd, "out")
		if f != "" {
			err = ioutil.WriteFile(f, mi, 0644)
			if err != nil {
				util.PrintErrorAndExit(err.Error(), 1)
			}

			log.Println(fmt.Sprintf("Output written to %s.", f))
		}
	}
}
<|endoftext|>


<commit_before>package cmd

import (
	"encoding/json"
	"errors"
	"fmt"
	"strings"

	"github.com/mbtproject/mbt/lib"
	"gopkg.in/spf13/cobra.v0"
)

var (
	formatAsJson bool
)

func init() {
	describePrCmd.Flags().StringVar(&src, "src", "", "source branch")
	describePrCmd.Flags().StringVar(&dst, "dst", "", "destination branch")

	describeIntersectionCmd.Flags().StringVar(&kind, "kind", "", "kind of input for first and second args (available options are 'branch' and 'commit')")
	describeIntersectionCmd.Flags().StringVar(&first, "first", "", "first item")
	describeIntersectionCmd.Flags().StringVar(&second, "second", "", "second item")

	describeCmd.PersistentFlags().BoolVar(&formatAsJson, "json", false, "format output as json")
	describeCmd.AddCommand(describeCommitCmd)
	describeCmd.AddCommand(describeBranchCmd)
	describeCmd.AddCommand(describePrCmd)
	describeCmd.AddCommand(describeIntersectionCmd)

	RootCmd.AddCommand(describeCmd)
}

var describeCmd = &cobra.Command{
	Use:   "describe",
	Short: "Describes the manifest of a repo",
}

var describeBranchCmd = &cobra.Command{
	Use:   "branch <branch>",
	Short: "Describes the manifest for the given branch",
	RunE: func(cmd *cobra.Command, args []string) error {
		branch := "master"
		if len(args) > 0 {
			branch = args[0]
		}
		m, err := lib.ManifestByBranch(in, branch)
		if err != nil {
			return handle(err)
		}

		output(m.Applications)
		return nil
	},
}

var describePrCmd = &cobra.Command{
	Use:   "pr --src <branch> --dst <branch>",
	Short: "Describes the manifest for a given pr",
	RunE: func(cmd *cobra.Command, args []string) error {
		if src == "" {
			return errors.New("requires source")
		}

		if dst == "" {
			return errors.New("requires dest")
		}

		m, err := lib.ManifestByPr(in, src, dst)
		if err != nil {
			return handle(err)
		}

		output(m.Applications)

		return nil
	},
}

var describeCommitCmd = &cobra.Command{
	Use:   "commit <sha>",
	Short: "Describes the manifest for a given commit",
	RunE: func(cmd *cobra.Command, args []string) error {
		if len(args) == 0 {
			return errors.New("requires the commit sha")
		}

		commit := args[0]

		m, err := lib.ManifestBySha(in, commit)
		if err != nil {
			return handle(err)
		}

		output(m.Applications)

		return nil
	},
}

var describeIntersectionCmd = &cobra.Command{
	Use:   "intersection --kind <branch|commit> --first <first> --second <second>",
	Short: "Describes the intersection between two trees",
	RunE: func(cmd *cobra.Command, args []string) error {
		if kind == "" {
			return errors.New("requires the kind argument")
		}

		if first == "" {
			return errors.New("requires the first argument")
		}

		if second == "" {
			return errors.New("requires the second argument")
		}

		var apps lib.Applications
		var err error

		switch kind {
		case "branch":
			apps, err = lib.IntersectionByBranch(in, first, second)
		case "commit":
			apps, err = lib.IntersectionByCommit(in, first, second)
		default:
			err = errors.New("not a valid kind - available options are 'branch' and 'commit'")
		}

		if err != nil {
			return handle(err)
		}

		return handle(output(apps))
	},
}

const columnWidth = 30

func formatRow(args ...interface{}) string {
	padded := make([]interface{}, len(args))
	for i, a := range args {
		requiredPadding := columnWidth - len(a.(string))
		if requiredPadding > 0 {
			padded[i] = fmt.Sprintf("%s%s", a, strings.Join(make([]string, requiredPadding), " "))
		} else {
			padded[i] = a
		}
	}
	return fmt.Sprintf("%s\t\t%s\t\t%s\n", padded...)
}

func output(apps lib.Applications) error {
	if formatAsJson {
		v := make(map[string]interface{})
		for _, a := range apps {
			v["Name"] = a.Name()
			v["Path"] = a.Path()
			v["Version"] = a.Version()
			v["Properties"] = a.Properties()
		}
		buff, err := json.MarshalIndent(v, "", "  ")
		if err != nil {
			return err
		}
		fmt.Println(string(buff))
	} else {
		fmt.Print(formatRow("NAME", "PATH", "VERSION"))
		for _, a := range apps {
			fmt.Printf(formatRow(a.Name(), a.Path(), a.Version()))
		}
	}

	return nil
}
<commit_msg>Fixed missing apps issue in json output<commit_after>package cmd

import (
	"encoding/json"
	"errors"
	"fmt"
	"strings"

	"github.com/mbtproject/mbt/lib"
	"gopkg.in/spf13/cobra.v0"
)

var (
	formatAsJson bool
)

func init() {
	describePrCmd.Flags().StringVar(&src, "src", "", "source branch")
	describePrCmd.Flags().StringVar(&dst, "dst", "", "destination branch")

	describeIntersectionCmd.Flags().StringVar(&kind, "kind", "", "kind of input for first and second args (available options are 'branch' and 'commit')")
	describeIntersectionCmd.Flags().StringVar(&first, "first", "", "first item")
	describeIntersectionCmd.Flags().StringVar(&second, "second", "", "second item")

	describeCmd.PersistentFlags().BoolVar(&formatAsJson, "json", false, "format output as json")
	describeCmd.AddCommand(describeCommitCmd)
	describeCmd.AddCommand(describeBranchCmd)
	describeCmd.AddCommand(describePrCmd)
	describeCmd.AddCommand(describeIntersectionCmd)

	RootCmd.AddCommand(describeCmd)
}

var describeCmd = &cobra.Command{
	Use:   "describe",
	Short: "Describes the manifest of a repo",
}

var describeBranchCmd = &cobra.Command{
	Use:   "branch <branch>",
	Short: "Describes the manifest for the given branch",
	RunE: func(cmd *cobra.Command, args []string) error {
		branch := "master"
		if len(args) > 0 {
			branch = args[0]
		}
		m, err := lib.ManifestByBranch(in, branch)
		if err != nil {
			return handle(err)
		}

		output(m.Applications)
		return nil
	},
}

var describePrCmd = &cobra.Command{
	Use:   "pr --src <branch> --dst <branch>",
	Short: "Describes the manifest for a given pr",
	RunE: func(cmd *cobra.Command, args []string) error {
		if src == "" {
			return errors.New("requires source")
		}

		if dst == "" {
			return errors.New("requires dest")
		}

		m, err := lib.ManifestByPr(in, src, dst)
		if err != nil {
			return handle(err)
		}

		output(m.Applications)

		return nil
	},
}

var describeCommitCmd = &cobra.Command{
	Use:   "commit <sha>",
	Short: "Describes the manifest for a given commit",
	RunE: func(cmd *cobra.Command, args []string) error {
		if len(args) == 0 {
			return errors.New("requires the commit sha")
		}

		commit := args[0]

		m, err := lib.ManifestBySha(in, commit)
		if err != nil {
			return handle(err)
		}

		output(m.Applications)

		return nil
	},
}

var describeIntersectionCmd = &cobra.Command{
	Use:   "intersection --kind <branch|commit> --first <first> --second <second>",
	Short: "Describes the intersection between two trees",
	RunE: func(cmd *cobra.Command, args []string) error {
		if kind == "" {
			return errors.New("requires the kind argument")
		}

		if first == "" {
			return errors.New("requires the first argument")
		}

		if second == "" {
			return errors.New("requires the second argument")
		}

		var apps lib.Applications
		var err error

		switch kind {
		case "branch":
			apps, err = lib.IntersectionByBranch(in, first, second)
		case "commit":
			apps, err = lib.IntersectionByCommit(in, first, second)
		default:
			err = errors.New("not a valid kind - available options are 'branch' and 'commit'")
		}

		if err != nil {
			return handle(err)
		}

		return handle(output(apps))
	},
}

const columnWidth = 30

func formatRow(args ...interface{}) string {
	padded := make([]interface{}, len(args))
	for i, a := range args {
		requiredPadding := columnWidth - len(a.(string))
		if requiredPadding > 0 {
			padded[i] = fmt.Sprintf("%s%s", a, strings.Join(make([]string, requiredPadding), " "))
		} else {
			padded[i] = a
		}
	}
	return fmt.Sprintf("%s\t\t%s\t\t%s\n", padded...)
}

func output(apps lib.Applications) error {
	if formatAsJson {
		m := make(map[string]map[string]interface{})
		for _, a := range apps {
			v := make(map[string]interface{})
			v["Name"] = a.Name()
			v["Path"] = a.Path()
			v["Version"] = a.Version()
			v["Properties"] = a.Properties()
			m[a.Name()] = v
		}
		buff, err := json.MarshalIndent(m, "", "  ")
		if err != nil {
			return err
		}
		fmt.Println(string(buff))
	} else {
		fmt.Print(formatRow("NAME", "PATH", "VERSION"))
		for _, a := range apps {
			fmt.Printf(formatRow(a.Name(), a.Path(), a.Version()))
		}
	}

	return nil
}
<|endoftext|>