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

package rt

import (
	"encoding/base64"
	"time"

	"v.io/v23"
	"v.io/v23/context"
	"v.io/v23/rpc"
	"v.io/v23/security"
	"v.io/v23/verror"
	"v.io/v23/vom"

	"v.io/x/ref/lib/exec"
	"v.io/x/ref/lib/mgmt"
	vsecurity "v.io/x/ref/lib/security"
)

const pkgPath = "v.io/x/ref/option/internal/rt"

var (
	errConfigKeyNotSet = verror.Register(pkgPath+".errConfigKeyNotSet", verror.NoRetry, "{1:}{2:} {3} is not set{:_}")
)

func (rt *Runtime) initMgmt(ctx *context.T) error {
	handle, err := exec.GetChildHandle()
	if err == nil {
		// No error; fall through.
	} else if verror.ErrorID(err) == exec.ErrNoVersion.ID {
		// Do not initialize the mgmt runtime if the process has not
		// been started through the vanadium exec library by a device
		// manager.
		return nil
	} else {
		return err
	}
	parentName, err := handle.Config.Get(mgmt.ParentNameConfigKey)
	if err != nil {
		// If the ParentNameConfigKey is not set, then this process has
		// not been started by the device manager, but the parent process
		// is still a Vanadium process using the exec library so we
		// call SetReady to let it know that this child process has
		// successfully started.
		return handle.SetReady()
	}
	if ctx, err = setListenSpec(ctx, rt, handle); err != nil {
		return err
	}
	var blessings security.Blessings
	if b64blessings, err := handle.Config.Get(mgmt.AppCycleBlessingsKey); err == nil {
		vombytes, err := base64.URLEncoding.DecodeString(b64blessings)
		if err == nil {
			err = vom.Decode(vombytes, &blessings)
		}
		if err != nil {
			return err
		}
	} else {
		// AppCycleBlessingsKey is not set: The device manager was
		// compiled before the change that introduced
		// UseDeprecatedParentBlessingConfig was introduced.
		pattern, _ := handle.Config.Get(mgmt.ParentBlessingConfigKey)
		blessings = rt.GetPrincipal(ctx).BlessingStore().ForPeer(pattern)
	}
	// Arguably could use the same principal with a different blessing store
	// and blessing roots. However, at the time of this writing there wasn't
	// a particularly convenient way to do so, and this alternative scheme
	// works just as well.
	//
	// Instantiate a principal that will be used by the AppCycleManager
	// which will communicate with (both as a client and a server) only the
	// device manager.
	principal, err := vsecurity.NewPrincipal()
	if err != nil {
		return err
	}
	blessings, err = rt.GetPrincipal(ctx).Bless(principal.PublicKey(), blessings, "instance", security.UnconstrainedUse())
	if err != nil {
		return err
	}
	if err := security.AddToRoots(principal, blessings); err != nil {
		return err
	}
	if err := principal.BlessingStore().SetDefault(blessings); err != nil {
		return err
	}
	if _, err := principal.BlessingStore().Set(blessings, security.AllPrincipals); err != nil {
		return err
	}
	if ctx, err = rt.setPrincipal(ctx, principal, nil); err != nil {
		return err
	}
	// Fire up the server to receive calls from the parent and also ping the parent.
	_, server, err := rt.WithNewServer(ctx, "", v23.GetAppCycle(ctx).Remote(), nil)
	if err != nil {
		return err
	}
	if err = rt.callbackToParent(ctx, parentName, server.Status().Endpoints[0].Name()); err != nil {
		server.Stop()
		return err
	}
	return handle.SetReady()
}

func setListenSpec(ctx *context.T, rt *Runtime, handle *exec.ChildHandle) (*context.T, error) {
	protocol, err := handle.Config.Get(mgmt.ProtocolConfigKey)
	if err != nil {
		return nil, err
	}
	if protocol == "" {
		return nil, verror.New(errConfigKeyNotSet, ctx, mgmt.ProtocolConfigKey)
	}

	address, err := handle.Config.Get(mgmt.AddressConfigKey)
	if err != nil {
		return nil, err
	}
	if address == "" {
		return nil, verror.New(errConfigKeyNotSet, ctx, mgmt.AddressConfigKey)
	}
	return rt.WithListenSpec(ctx, rpc.ListenSpec{Addrs: rpc.ListenAddrs{{protocol, address}}}), nil
}

func (rt *Runtime) callbackToParent(ctx *context.T, parentName, myName string) error {
	ctx, _ = context.WithTimeout(ctx, time.Minute)
	return rt.GetClient(ctx).Call(ctx, parentName, "Set", []interface{}{mgmt.AppCycleManagerConfigKey, myName}, nil)
}
<commit_msg>runtime/mgmt: Fix TestDeviceManagerUpdateAndRevert in new rpc.<commit_after>// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package rt

import (
	"encoding/base64"
	"time"

	"v.io/v23"
	"v.io/v23/context"
	"v.io/v23/rpc"
	"v.io/v23/security"
	"v.io/v23/verror"
	"v.io/v23/vom"

	"v.io/x/ref/lib/exec"
	"v.io/x/ref/lib/mgmt"
	vsecurity "v.io/x/ref/lib/security"
)

const pkgPath = "v.io/x/ref/option/internal/rt"

var (
	errConfigKeyNotSet = verror.Register(pkgPath+".errConfigKeyNotSet", verror.NoRetry, "{1:}{2:} {3} is not set{:_}")
)

func (rt *Runtime) initMgmt(ctx *context.T) error {
	handle, err := exec.GetChildHandle()
	if err == nil {
		// No error; fall through.
	} else if verror.ErrorID(err) == exec.ErrNoVersion.ID {
		// Do not initialize the mgmt runtime if the process has not
		// been started through the vanadium exec library by a device
		// manager.
		return nil
	} else {
		return err
	}
	parentName, err := handle.Config.Get(mgmt.ParentNameConfigKey)
	if err != nil {
		// If the ParentNameConfigKey is not set, then this process has
		// not been started by the device manager, but the parent process
		// is still a Vanadium process using the exec library so we
		// call SetReady to let it know that this child process has
		// successfully started.
		return handle.SetReady()
	}
	if ctx, err = setListenSpec(ctx, rt, handle); err != nil {
		return err
	}
	var blessings security.Blessings
	if b64blessings, err := handle.Config.Get(mgmt.AppCycleBlessingsKey); err == nil {
		vombytes, err := base64.URLEncoding.DecodeString(b64blessings)
		if err == nil {
			err = vom.Decode(vombytes, &blessings)
		}
		if err != nil {
			return err
		}
	} else {
		// AppCycleBlessingsKey is not set: The device manager was
		// compiled before the change that introduced
		// UseDeprecatedParentBlessingConfig was introduced.
		pattern, _ := handle.Config.Get(mgmt.ParentBlessingConfigKey)
		blessings = rt.GetPrincipal(ctx).BlessingStore().ForPeer(pattern)
	}
	// Arguably could use the same principal with a different blessing store
	// and blessing roots. However, at the time of this writing there wasn't
	// a particularly convenient way to do so, and this alternative scheme
	// works just as well.
	//
	// Instantiate a principal that will be used by the AppCycleManager
	// which will communicate with (both as a client and a server) only the
	// device manager.
	principal, err := vsecurity.NewPrincipal()
	if err != nil {
		return err
	}
	blessings, err = rt.GetPrincipal(ctx).Bless(principal.PublicKey(), blessings, "instance", security.UnconstrainedUse())
	if err != nil {
		return err
	}
	if err := security.AddToRoots(principal, blessings); err != nil {
		return err
	}
	if err := principal.BlessingStore().SetDefault(blessings); err != nil {
		return err
	}
	if _, err := principal.BlessingStore().Set(blessings, security.AllPrincipals); err != nil {
		return err
	}
	if ctx, err = rt.WithPrincipal(ctx, principal); err != nil {
		return err
	}
	// Fire up the server to receive calls from the parent and also ping the parent.
	_, server, err := rt.WithNewServer(ctx, "", v23.GetAppCycle(ctx).Remote(), nil)
	if err != nil {
		return err
	}
	if err = rt.callbackToParent(ctx, parentName, server.Status().Endpoints[0].Name()); err != nil {
		server.Stop()
		return err
	}
	return handle.SetReady()
}

func setListenSpec(ctx *context.T, rt *Runtime, handle *exec.ChildHandle) (*context.T, error) {
	protocol, err := handle.Config.Get(mgmt.ProtocolConfigKey)
	if err != nil {
		return nil, err
	}
	if protocol == "" {
		return nil, verror.New(errConfigKeyNotSet, ctx, mgmt.ProtocolConfigKey)
	}

	address, err := handle.Config.Get(mgmt.AddressConfigKey)
	if err != nil {
		return nil, err
	}
	if address == "" {
		return nil, verror.New(errConfigKeyNotSet, ctx, mgmt.AddressConfigKey)
	}
	return rt.WithListenSpec(ctx, rpc.ListenSpec{Addrs: rpc.ListenAddrs{{protocol, address}}}), nil
}

func (rt *Runtime) callbackToParent(ctx *context.T, parentName, myName string) error {
	ctx, _ = context.WithTimeout(ctx, time.Minute)
	return rt.GetClient(ctx).Call(ctx, parentName, "Set", []interface{}{mgmt.AppCycleManagerConfigKey, myName}, nil)
}
<|endoftext|>


<commit_before>package worker

import (
	"log"
	"sync"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/sqs"
	"fmt"
)

// HandlerFunc is used to define the Handler that is run on for each message
type HandlerFunc func(msg *sqs.Message) error

func (f HandlerFunc) HandleMessage(msg *sqs.Message) error {
	return f(msg)
}

// Handler interface
type Handler interface {
	HandleMessage(msg *sqs.Message) error
}

type InvalidEventError struct {
	event string
	msg string
}
func (e *InvalidEventError) Error() string {
	return fmt.Sprintf("[Invalid Event: %s] %s", e.event, e.msg)
}

// Exported Variables
var (
	// what is the queue url we are connecting to, Defaults to empty
	QueueURL string = ""
	// The maximum number of messages to return. Amazon SQS never returns more messages
	// than this value (however, fewer messages might be returned). Valid values
	// are 1 to 10. Default is 10.
	MaxNumberOfMessage int64 = 10
	// The duration (in seconds) for which the call waits for a message to arrive
	// in the queue before returning. If a message is available, the call returns
	// sooner than WaitTimeSeconds.
	WaitTimeSecond int64 = 20
)

// Start starts the polling and will continue polling till the application is forcibly stopped
func Start(svc *sqs.SQS, h Handler) {
	for {
		log.Println("worker: Start polling")
		params := &sqs.ReceiveMessageInput{
			QueueUrl: aws.String(QueueURL), // Required
			MaxNumberOfMessages: aws.Int64(MaxNumberOfMessage),
			MessageAttributeNames: []*string{
				aws.String("All"), // Required
			},
			WaitTimeSeconds:         aws.Int64(WaitTimeSecond),
		}

		resp, err := svc.ReceiveMessage(params)
		if err != nil {
			log.Println(err)
			continue
		}
		if len(resp.Messages) > 0 {
			run(svc, h, resp.Messages)
		}
	}
}

// poll launches goroutine per received message and wait for all message to be processed
func run(svc *sqs.SQS, h Handler, messages []*sqs.Message) {
	numMessages := len(messages)
	log.Printf("worker: Received %d messages", numMessages)

	var wg sync.WaitGroup
	wg.Add(numMessages)
	for i := range messages {
		go func(m *sqs.Message) {
			// launch goroutine
			log.Println("worker: Spawned worker goroutine")
			defer wg.Done()
			if err := handleMessage(svc, m, h); err != nil {
				log.Println(err)
			}
		}(messages[i])
	}

	wg.Wait()
}

func handleMessage(svc *sqs.SQS, m *sqs.Message, h Handler) error {
	var err error
	err = h.HandleMessage(m)
	if _, ok := err.(InvalidEventError); ok {
		log.Println(err.Error())
	} else {
		return err
	}

	params := &sqs.DeleteMessageInput{
		QueueUrl:      aws.String(QueueURL), // Required
		ReceiptHandle: m.ReceiptHandle, // Required
	}
	_, err = svc.DeleteMessage(params)
	if err != nil {
		return err
	}
	log.Printf("worker: deleted message from queue: %s", aws.StringValue(m.ReceiptHandle))

	return nil
}<commit_msg>Added the Ability to create the new InvalidEventError type<commit_after>package worker

import (
	"log"
	"sync"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/sqs"
	"fmt"
)

// HandlerFunc is used to define the Handler that is run on for each message
type HandlerFunc func(msg *sqs.Message) error

func (f HandlerFunc) HandleMessage(msg *sqs.Message) error {
	return f(msg)
}

// Handler interface
type Handler interface {
	HandleMessage(msg *sqs.Message) error
}

type InvalidEventError struct {
	event string
	msg string
}
func (e *InvalidEventError) Error() string {
	return fmt.Sprintf("[Invalid Event: %s] %s", e.event, e.msg)
}

func NewInvalidEventError(event, msg string) *InvalidEventError {
	return &InvalidEventError{event: event, msg: msg}
}

// Exported Variables
var (
	// what is the queue url we are connecting to, Defaults to empty
	QueueURL string = ""
	// The maximum number of messages to return. Amazon SQS never returns more messages
	// than this value (however, fewer messages might be returned). Valid values
	// are 1 to 10. Default is 10.
	MaxNumberOfMessage int64 = 10
	// The duration (in seconds) for which the call waits for a message to arrive
	// in the queue before returning. If a message is available, the call returns
	// sooner than WaitTimeSeconds.
	WaitTimeSecond int64 = 20
)

// Start starts the polling and will continue polling till the application is forcibly stopped
func Start(svc *sqs.SQS, h Handler) {
	for {
		log.Println("worker: Start polling")
		params := &sqs.ReceiveMessageInput{
			QueueUrl: aws.String(QueueURL), // Required
			MaxNumberOfMessages: aws.Int64(MaxNumberOfMessage),
			MessageAttributeNames: []*string{
				aws.String("All"), // Required
			},
			WaitTimeSeconds:         aws.Int64(WaitTimeSecond),
		}

		resp, err := svc.ReceiveMessage(params)
		if err != nil {
			log.Println(err)
			continue
		}
		if len(resp.Messages) > 0 {
			run(svc, h, resp.Messages)
		}
	}
}

// poll launches goroutine per received message and wait for all message to be processed
func run(svc *sqs.SQS, h Handler, messages []*sqs.Message) {
	numMessages := len(messages)
	log.Printf("worker: Received %d messages", numMessages)

	var wg sync.WaitGroup
	wg.Add(numMessages)
	for i := range messages {
		go func(m *sqs.Message) {
			// launch goroutine
			log.Println("worker: Spawned worker goroutine")
			defer wg.Done()
			if err := handleMessage(svc, m, h); err != nil {
				log.Println(err)
			}
		}(messages[i])
	}

	wg.Wait()
}

func handleMessage(svc *sqs.SQS, m *sqs.Message, h Handler) error {
	var err error
	err = h.HandleMessage(m)
	if _, ok := err.(InvalidEventError); ok {
		log.Println(err.Error())
	} else {
		return err
	}

	params := &sqs.DeleteMessageInput{
		QueueUrl:      aws.String(QueueURL), // Required
		ReceiptHandle: m.ReceiptHandle, // Required
	}
	_, err = svc.DeleteMessage(params)
	if err != nil {
		return err
	}
	log.Printf("worker: deleted message from queue: %s", aws.StringValue(m.ReceiptHandle))

	return nil
}<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
)

const OPEN311_API_URI = "http://311api.cityofchicago.org/open311/v2/requests.json"

type Open311Request struct {
	service_request_id, status, service_name, service_code, agency_responsible, address string
	lat, long                                                                           float32
	requested_datetime, updated_datetime                                                string // FIXME: should these be proper time objects?
}

func main() {
	fetchRequests()
}

func fetchRequests() {
	log.Printf("fetching from %s", OPEN311_API_URI)
	resp, err := http.Get(OPEN311_API_URI)
	defer resp.Body.Close()

	if err == nil {
		log.Println("fetch succesful, reading response")
		body, err := ioutil.ReadAll(resp.Body)

		if err == nil {
			log.Println("loaded response body.")
			// parse into JSON
			var requests []map[string]interface{}
			err := json.Unmarshal(body, &requests)
			if err != nil {
				log.Fatal("error parsing JSON:", err)
			}

			for _, req := range requests {
				fmt.Println(req)
			}
		}
	} else {
		log.Fatalln("error fetching from Open311 endpoint", err)
	}
}
<commit_msg>properly unmarshal to Open311Request type<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
)

const OPEN311_API_URI = "http://311api.cityofchicago.org/open311/v2/requests.json"

type Open311Request struct {
	Lat, Long                                                                           float64
	Service_request_id, Status, Service_name, Service_code, Agency_responsible, Address string
	Requested_datetime, Updated_datetime                                                string // FIXME: should these be proper time objects?
}

func main() {
	fetchRequests()
}

func fetchRequests() {
	log.Printf("fetching from %s", OPEN311_API_URI)
	resp, err := http.Get(OPEN311_API_URI)
	defer resp.Body.Close()

	if err == nil {
		log.Println("fetch succesful, reading response")
		body, err := ioutil.ReadAll(resp.Body)

		if err == nil {
			log.Println("loaded response body.")
			// parse into JSON

			var requests []Open311Request
			err := json.Unmarshal(body, &requests)
			if err != nil {
				log.Fatal("error parsing JSON:", err)
			}

			log.Printf("received %d requests from Open311", len(requests))
			fmt.Printf("%+v", requests)
		}
	} else {
		log.Fatalln("error fetching from Open311 endpoint", err)
	}
}
<|endoftext|>


<commit_before>package static

import (
	"github.com/gin-gonic/gin"
	"net/http"
	"os"
	"path"
	"path/filepath"
	"strings"
)

type ServeFileSystem interface {
	http.FileSystem
	Exists(prefix string, path string) bool
}

func existsFile(name string) bool {
	_, err := os.Stat(name)
	return !os.IsNotExist(err)
}

type localFileSystem struct {
	fs      http.FileSystem
	root    string
	indexes bool
}

func LocalFile(root string, indexes bool) *localFileSystem {
	root, err := filepath.Abs(root)
	if err != nil {
		panic(err)
	}

	fs := http.Dir(root)
	return &localFileSystem{
		fs,
		root,
		indexes,
	}
}

func (l *localFileSystem) Open(name string) (http.File, error) {
	f, err := l.fs.Open(name)
	if err != nil {
		return nil, err
	}

	if l.indexes {
		return f, err
	} else {
		return neuteredReaddirFile{f}, nil
	}
}

func (l *localFileSystem) Exists(prefix string, filepath string) bool {

	if p := strings.TrimPrefix(filepath, prefix); len(p) < len(filepath) {
		p = path.Join(l.root, p)
		return existsFile(p)
	}
	return false
}

type neuteredReaddirFile struct {
	http.File
}

func (f neuteredReaddirFile) Readdir(count int) ([]os.FileInfo, error) {
	return nil, nil
}

// Static returns a middleware handler that serves static files in the given directory.
func Serve(prefix string, fs ServeFileSystem) gin.HandlerFunc {
	var fileserver http.Handler

	if prefix != "" {
		fileserver = http.StripPrefix(prefix, http.FileServer(fs))
	} else {
		fileserver = http.FileServer(fs)
	}

	return func(c *gin.Context) {

		if fs.Exists(prefix, c.Request.URL.Path) {
			fileserver.ServeHTTP(c.Writer, c.Request)
			c.Abort()
		} else {
			c.Next()
		}
	}
}
<commit_msg>fixbug<commit_after>package static

import (
	"github.com/gin-gonic/gin"
	"net/http"
	"os"
	"path"
	"path/filepath"
	"strings"
)

type ServeFileSystem interface {
	http.FileSystem
	Exists(prefix string, path string) bool
}

func existsFile(name string) bool {
	_, err := os.Stat(name)
	return !os.IsNotExist(err)
}

type localFileSystem struct {
	fs      http.FileSystem
	root    string
	indexes bool
}

func LocalFile(root string, indexes bool) *localFileSystem {
	root, err := filepath.Abs(root)
	if err != nil {
		panic(err)
	}

	fs := http.Dir(root)
	return &localFileSystem{
		fs,
		root,
		indexes,
	}
}

func (l *localFileSystem) Open(name string) (http.File, error) {
	f, err := l.fs.Open(name)
	if err != nil {
		return nil, err
	}

	if l.indexes {
		return f, err
	} else {
		return neuteredReaddirFile{f}, nil
	}
}

func (l *localFileSystem) Exists(prefix string, filepath string) bool {

	if p := strings.TrimPrefix(filepath, prefix); len(p) < len(filepath) {
		p = path.Join(l.root, p)
		return existsFile(p)
	}
	return false
}

type neuteredReaddirFile struct {
	http.File
}

func (f neuteredReaddirFile) Readdir(count int) ([]os.FileInfo, error) {
	return nil, nil
}

// Static returns a middleware handler that serves static files in the given directory.
func Serve(prefix string, fs ServeFileSystem) gin.HandlerFunc {
	var fileserver http.Handler

	if prefix != "" {
		fileserver = http.StripPrefix(prefix, http.FileServer(fs))
	} else {
		fileserver = http.FileServer(fs)
	}

	return func(c *gin.Context) {

		if fs.Exists(prefix, c.Request.URL.Path) {
			fileserver.ServeHTTP(c.Writer, c.Request)
		} else {
			c.Next()
		}
	}
}
<|endoftext|>


<commit_before>package k8s

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

	"github.com/servicebroker/servicebroker/k8s/service_controller/server"
	model "github.com/servicebroker/servicebroker/model/service_controller"
)

type K8sServiceStorage struct {
}

const serviceDomain string = "cncf.org"
const apiVersion string = "v1alpha1"
const brokerResource string = "servicebrokers"
const defaultUri string = "http://localhost:8080/apis/" + serviceDomain + "/" + apiVersion + "/namespaces/default/" + brokerResource

// The k8s implementation should leverage Third Party Resources
// https://github.com/kubernetes/kubernetes/blob/master/docs/design/extending-api.md

var _ server.ServiceStorage = (*K8sServiceStorage)(nil)

func CreateServiceStorage() server.ServiceStorage {
	return &K8sServiceStorage{}
}

// listSB is only used for unmarshalling the list of service brokers
// for returning to the client
type listSB struct {
	Items []*k8sServiceBroker `json:"items"`
}

func (kss *K8sServiceStorage) ListBrokers() ([]*model.ServiceBroker, error) {
	fmt.Println("listing all brokers")
	// get the ServiceBroker

	r, e := http.Get(defaultUri)
	if nil != e {
		return nil, fmt.Errorf("couldn't get the service brokers. %v, [%v]", e, r)
	}

	var lsb listSB
	e = json.NewDecoder(r.Body).Decode(&lsb)
	if nil != e { // wrong json format error
		fmt.Println("json not unmarshalled:", e, r)
		return nil, e
	}
	fmt.Println("Got", len(lsb.Items), "brokers.")
	ret := make([]*model.ServiceBroker, 0, len(lsb.Items))
	for _, v := range lsb.Items {
		ret = append(ret, v.ServiceBroker)
	}
	return ret, nil
}

func (kss *K8sServiceStorage) GetBroker(name string) (*model.ServiceBroker, error) {
	uri := defaultUri + "/" + name
	fmt.Println("uri is:", uri)
	r, e := http.Get(uri)
	if nil != e {
		return nil, fmt.Errorf("couldn't get the service broker. %v, [%v]", e, r)
	}
	defer r.Body.Close()
	var sb k8sServiceBroker
	e = json.NewDecoder(r.Body).Decode(&sb)
	if nil != e { // wrong json format error
		return nil, e
	}
	fmt.Printf("returned json: %+v\n", sb)
	return sb.ServiceBroker, nil
}

func (kss *K8sServiceStorage) GetBrokerByService(id string) (*model.ServiceBroker, error) {
	return nil, fmt.Errorf("Not implemented yet")
}

func (kss *K8sServiceStorage) GetInventory() (*model.Catalog, error) {
	return nil, fmt.Errorf("Not implemented yet")
}

type Meta struct {
	Name string `json:"name"`
}

type k8sServiceBroker struct {
	*model.ServiceBroker
	ApiVersion string `json:"apiVersion"`
	Kind       string `json:"kind"`
	Metadata   Meta   `json:"metadata"`
}

func NewK8sSB() *k8sServiceBroker {
	return &k8sServiceBroker{ApiVersion: serviceDomain + "/" + apiVersion,
		Kind: "ServiceBroker"}
}

func (kss *K8sServiceStorage) AddBroker(broker *model.ServiceBroker, catalog *model.Catalog) error {
	fmt.Println("adding broker to k8s", broker)
	// create TPR
	// tpr is
	//    kind.fqdn
	// or
	//    kind.domain.tld
	//
	// use service-broker.cncf.org
	// end up with k8s resource of ServiceBroker
	// version v1alpha1 for now
	//
	// store name/host/port/user/pass as metadata
	//
	// example yaml
	// metadata:
	//   name: service-broker.cncf.org
	//   (service)name/host/port/user/pass
	// apiVersion: extensions/v1beta1
	// kind: ThirdPartyResource
	// versions:
	// - name: v1alpha1
	ksb := NewK8sSB()
	ksb.Metadata = Meta{Name: broker.Name}
	ksb.ServiceBroker = broker

	b := new(bytes.Buffer)
	json.NewEncoder(b).Encode(&ksb)
	r, e := http.Post(defaultUri, "application/json", b)
	fmt.Sprintf("result: %v", r)
	if nil != e || 201 != r.StatusCode {
		fmt.Printf("Error creating k8s TPR [%s]...\n%v\n", e, r)
		return e
	}
	return nil
}

func (kss *K8sServiceStorage) DeleteBroker(name string) error {
	uri := defaultUri + "/" + name
	fmt.Println("uri is:", uri)

	// utter failure of an http API
	req, _ := http.NewRequest("DELETE", uri, nil)
	_, e := http.DefaultClient.Do(req)
	if nil != e {
		return fmt.Errorf("couldn't nuke %v, [%v]", name, e)
	}
	return nil
}

func (kss *K8sServiceStorage) ServiceExists(id string) bool {
	return false
}

func (kss *K8sServiceStorage) ListServices() ([]*model.ServiceInstanceData, error) {
	return nil, fmt.Errorf("Not implemented yet")
}

func (kss *K8sServiceStorage) GetService(id string) (*model.ServiceInstanceData, error) {
	return nil, fmt.Errorf("Not implemented yet")
}

func (kss *K8sServiceStorage) AddService(si *model.ServiceInstanceData) error {
	return fmt.Errorf("Not implemented yet")
}

func (kss *K8sServiceStorage) SetService(si *model.ServiceInstanceData) error {
	return fmt.Errorf("Not implemented yet")
}

func (kss *K8sServiceStorage) DeleteService(id string) error {
	return fmt.Errorf("Not implemented yet")
}

func (kss *K8sServiceStorage) ListServiceBindings() ([]*model.ServiceBinding, error) {
	return nil, fmt.Errorf("Not implemented yet")
}

func (kss *K8sServiceStorage) GetServiceBinding(id string) (*model.ServiceBinding, error) {
	return nil, fmt.Errorf("Not implemented yet")
}

func (kss *K8sServiceStorage) AddServiceBinding(binding *model.ServiceBinding, cred *model.Credential) error {
	return fmt.Errorf("Not implemented yet")
}

func (kss *K8sServiceStorage) DeleteServiceBinding(id string) error {
	return fmt.Errorf("Not implemented yet")
}
<commit_msg>switch to guid to avoid mismatch between k8s and cf<commit_after>package k8s

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

	"github.com/servicebroker/servicebroker/k8s/service_controller/server"
	model "github.com/servicebroker/servicebroker/model/service_controller"
)

type K8sServiceStorage struct {
}

const serviceDomain string = "cncf.org"
const apiVersion string = "v1alpha1"
const brokerResource string = "servicebrokers"
const defaultUri string = "http://localhost:8080/apis/" + serviceDomain + "/" + apiVersion + "/namespaces/default/" + brokerResource

// The k8s implementation should leverage Third Party Resources
// https://github.com/kubernetes/kubernetes/blob/master/docs/design/extending-api.md

var _ server.ServiceStorage = (*K8sServiceStorage)(nil)

func CreateServiceStorage() server.ServiceStorage {
	return &K8sServiceStorage{}
}

// listSB is only used for unmarshalling the list of service brokers
// for returning to the client
type listSB struct {
	Items []*k8sServiceBroker `json:"items"`
}

func (kss *K8sServiceStorage) ListBrokers() ([]*model.ServiceBroker, error) {
	fmt.Println("listing all brokers")
	// get the ServiceBroker

	r, e := http.Get(defaultUri)
	if nil != e {
		return nil, fmt.Errorf("couldn't get the service brokers. %v, [%v]", e, r)
	}

	var lsb listSB
	e = json.NewDecoder(r.Body).Decode(&lsb)
	if nil != e { // wrong json format error
		fmt.Println("json not unmarshalled:", e, r)
		return nil, e
	}
	fmt.Println("Got", len(lsb.Items), "brokers.")
	ret := make([]*model.ServiceBroker, 0, len(lsb.Items))
	for _, v := range lsb.Items {
		ret = append(ret, v.ServiceBroker)
	}
	return ret, nil
}

func (kss *K8sServiceStorage) GetBroker(name string) (*model.ServiceBroker, error) {
	uri := defaultUri + "/" + name
	fmt.Println("uri is:", uri)
	r, e := http.Get(uri)
	if nil != e {
		return nil, fmt.Errorf("couldn't get the service broker. %v, [%v]", e, r)
	}
	defer r.Body.Close()
	var sb k8sServiceBroker
	e = json.NewDecoder(r.Body).Decode(&sb)
	if nil != e { // wrong json format error
		return nil, e
	}
	fmt.Printf("returned json: %+v\n", sb)
	return sb.ServiceBroker, nil
}

func (kss *K8sServiceStorage) GetBrokerByService(id string) (*model.ServiceBroker, error) {
	return nil, fmt.Errorf("Not implemented yet")
}

func (kss *K8sServiceStorage) GetInventory() (*model.Catalog, error) {
	return nil, fmt.Errorf("Not implemented yet")
}

type Meta struct {
	Name string `json:"name"`
}

type k8sServiceBroker struct {
	*model.ServiceBroker
	ApiVersion string `json:"apiVersion"`
	Kind       string `json:"kind"`
	Metadata   Meta   `json:"metadata"`
}

func NewK8sSB() *k8sServiceBroker {
	return &k8sServiceBroker{ApiVersion: serviceDomain + "/" + apiVersion,
		Kind: "ServiceBroker"}
}

func (kss *K8sServiceStorage) AddBroker(broker *model.ServiceBroker, catalog *model.Catalog) error {
	fmt.Println("adding broker to k8s", broker)
	// create TPR
	// tpr is
	//    kind.fqdn
	// or
	//    kind.domain.tld
	//
	// use service-broker.cncf.org
	// end up with k8s resource of ServiceBroker
	// version v1alpha1 for now
	//
	// store name/host/port/user/pass as metadata
	//
	// example yaml
	// metadata:
	//   name: service-broker.cncf.org
	//   (service)name/host/port/user/pass
	// apiVersion: extensions/v1beta1
	// kind: ThirdPartyResource
	// versions:
	// - name: v1alpha1
	ksb := NewK8sSB()
	ksb.Metadata = Meta{Name: broker.GUID}
	ksb.ServiceBroker = broker

	b := new(bytes.Buffer)
	json.NewEncoder(b).Encode(&ksb)
	r, e := http.Post(defaultUri, "application/json", b)
	fmt.Sprintf("result: %v", r)
	if nil != e || 201 != r.StatusCode {
		fmt.Printf("Error creating k8s TPR [%s]...\n%v\n", e, r)
		return e
	}
	return nil
}

func (kss *K8sServiceStorage) DeleteBroker(name string) error {
	uri := defaultUri + "/" + name
	fmt.Println("uri is:", uri)

	// utter failure of an http API
	req, _ := http.NewRequest("DELETE", uri, nil)
	_, e := http.DefaultClient.Do(req)
	if nil != e {
		return fmt.Errorf("couldn't nuke %v, [%v]", name, e)
	}
	return nil
}

func (kss *K8sServiceStorage) ServiceExists(id string) bool {
	return false
}

func (kss *K8sServiceStorage) ListServices() ([]*model.ServiceInstanceData, error) {
	return nil, fmt.Errorf("Not implemented yet")
}

func (kss *K8sServiceStorage) GetService(id string) (*model.ServiceInstanceData, error) {
	return nil, fmt.Errorf("Not implemented yet")
}

func (kss *K8sServiceStorage) AddService(si *model.ServiceInstanceData) error {
	return fmt.Errorf("Not implemented yet")
}

func (kss *K8sServiceStorage) SetService(si *model.ServiceInstanceData) error {
	return fmt.Errorf("Not implemented yet")
}

func (kss *K8sServiceStorage) DeleteService(id string) error {
	return fmt.Errorf("Not implemented yet")
}

func (kss *K8sServiceStorage) ListServiceBindings() ([]*model.ServiceBinding, error) {
	return nil, fmt.Errorf("Not implemented yet")
}

func (kss *K8sServiceStorage) GetServiceBinding(id string) (*model.ServiceBinding, error) {
	return nil, fmt.Errorf("Not implemented yet")
}

func (kss *K8sServiceStorage) AddServiceBinding(binding *model.ServiceBinding, cred *model.Credential) error {
	return fmt.Errorf("Not implemented yet")
}

func (kss *K8sServiceStorage) DeleteServiceBinding(id string) error {
	return fmt.Errorf("Not implemented yet")
}
<|endoftext|>


<commit_before>package mock_godless

import (
	"fmt"
	"testing"

	"github.com/golang/mock/gomock"
	lib "github.com/johnny-morrice/godless"
)

// TODO should be okay for no where clause (return everything)
func TestRunQuerySelectSuccess(t *testing.T) {
	ctrl := gomock.NewController(t)
	defer ctrl.Finish()

	mock := NewMockNamespaceTree(ctrl)

	whereA := lib.QueryWhere{
		OpCode: lib.PREDICATE,
		Predicate: lib.QueryPredicate{
			OpCode: lib.STR_EQ,
			Literals: []string{"Hi"},
			Keys: []string{"Entry A"},
		},
	}

	whereB := lib.QueryWhere{
		OpCode: lib.PREDICATE,
		Predicate: lib.QueryPredicate{
			OpCode: lib.STR_EQ,
			Literals: []string{"Hi"},
			Keys: []string{"Entry B"},
		},
	}

	whereC := lib.QueryWhere{
		OpCode: lib.PREDICATE,
		Predicate: lib.QueryPredicate{
			OpCode: lib.STR_NEQ,
			Literals: []string{"Hello World"},
			Keys: []string{"Entry B"},
		},
	}

	whereD := lib.QueryWhere{
		OpCode: lib.PREDICATE,
		Predicate: lib.QueryPredicate{
			OpCode: lib.STR_EQ,
			Literals: []string{"Apple"},
			Keys: []string{"Entry C"},
		},
	}

	whereE := lib.QueryWhere{
		OpCode: lib.PREDICATE,
		Predicate: lib.QueryPredicate{
			OpCode: lib.STR_EQ,
			Literals: []string{"Orange"},
			Keys: []string{"Entry D"},
		},
	}

	whereF := lib.QueryWhere{
		OpCode: lib.PREDICATE,
		Predicate: lib.QueryPredicate{
			OpCode: lib.STR_EQ,
			Literals: []string{"Train"},
			Keys: []string{"Entry E"},
		},
	}

	whereG := lib.QueryWhere{
		OpCode: lib.PREDICATE,
		Predicate: lib.QueryPredicate{
			OpCode: lib.STR_EQ,
			Literals: []string{"Bus"},
			Keys: []string{"Entry E"},
		},
	}

	whereH := lib.QueryWhere{
		OpCode: lib.PREDICATE,
		Predicate: lib.QueryPredicate{
			OpCode: lib.STR_EQ,
			Literals: []string{"Boat"},
			Keys: []string{"Entry E"},
		},
	}

	whereI := lib.QueryWhere{
		OpCode: lib.PREDICATE,
		Predicate: lib.QueryPredicate{
			OpCode: lib.STR_EQ,
			IncludeRowKey: true,
			Literals: []string{"Row F0"},
		},
	}

	queries := []*lib.Query{
		// One result
		&lib.Query{
			OpCode: lib.SELECT,
			TableKey: mainTableKey,
			Select: lib.QuerySelect{
				Limit: 2,
				Where: whereA,
			},
		},
		// Multiple results
		&lib.Query{
			OpCode: lib.SELECT,
			TableKey: mainTableKey,
			Select: lib.QuerySelect{
				Limit: 2,
				Where: whereB,
			},
		},
		// STR_NEQ
		&lib.Query{
			OpCode: lib.SELECT,
			TableKey: mainTableKey,
			Select: lib.QuerySelect{
				Limit: 2,
				Where: whereC,
			},
		},
		// AND
		&lib.Query{
			OpCode: lib.SELECT,
			TableKey: mainTableKey,
			Select: lib.QuerySelect{
				Limit: 2,
				Where: lib.QueryWhere{
					OpCode: lib.AND,
					Clauses: []lib.QueryWhere{whereD, whereE},
				},
			},
		},
		// OR
		&lib.Query{
			OpCode: lib.SELECT,
			TableKey: mainTableKey,
			Select: lib.QuerySelect{
				Limit: 2,
				Where: lib.QueryWhere{
					OpCode: lib.OR,
					Clauses: []lib.QueryWhere{whereF, whereG},
				},
			},
		},
		// No results
		&lib.Query{
			OpCode: lib.SELECT,
			TableKey: mainTableKey,
			Select: lib.QuerySelect{
				Limit: 2,
				Where: whereH,
			},
		},
		// Row key
		&lib.Query{
			OpCode: lib.SELECT,
			TableKey: mainTableKey,
			Select: lib.QuerySelect{
				Limit: 2,
				Where: whereI,
			},
		},
	}

	responseA := lib.RESPONSE_OK
	responseA.Rows = rowsA()

	responseB := lib.RESPONSE_OK
	responseB.Rows = append(rowsB(), rowsC()...)

	responseC := lib.RESPONSE_OK
	responseC.Rows = rowsC()

	responseD := lib.RESPONSE_OK
	responseD.Rows = rowsD()

	responseE := lib.RESPONSE_OK
	responseE.Rows = rowsE()

	responseF := lib.RESPONSE_OK

	responseG := lib.RESPONSE_OK
	responseG.Rows = rowsF()

	expect := []lib.APIResponse{
		responseA,
		responseB,
		responseC,
		responseD,
		responseE,
		responseF,
		responseG,
	}

	if len(queries) != len(expect) {
		panic("mismatched input and expect")
	}

	mock.EXPECT().LoadTraverse(gomock.Any()).Return(nil).Do(feedNamespace).Times(len(queries))

	for i, q := range queries {
		selector := lib.MakeNamespaceTreeSelect(mock)
		q.Visit(selector)
		resp := selector.RunQuery()

		if !apiResponseEq(resp, expect[i]) {
			if resp.Rows == nil {
				t.Error("resp.Rows was nil")
			}
			if resp.Err != nil {
				t.Error("resp.Err was", resp.Err)
			}

			t.Error("Case", i, "Expected", expect[i], "but receieved", resp)
		}
	}
}

func TestRunQuerySelectInvalid(t *testing.T) {
	ctrl := gomock.NewController(t)
	defer ctrl.Finish()

	mock := NewMockNamespaceTree(ctrl)

	invalidQueries := []*lib.Query{
		// Basically wrong.
		&lib.Query{},
		&lib.Query{OpCode: lib.JOIN},
		// No limit
		&lib.Query{
			Select: lib.QuerySelect{
				Where: lib.QueryWhere{
					OpCode: lib.PREDICATE,
					Predicate: lib.QueryPredicate{
						OpCode: lib.STR_EQ,
						Literals: []string{"Hi"},
						Keys: []string{"Entry A"},
					},
				},
			},
		},
		// No where OpCode
		&lib.Query{
			Select: lib.QuerySelect{
				Limit: 1,
				Where: lib.QueryWhere{
					Predicate: lib.QueryPredicate{
						OpCode: lib.STR_EQ,
						Literals: []string{"Hi"},
						Keys: []string{"Entry A"},
					},
				},
			},
		},
		// No predicate OpCode
		&lib.Query{
			Select: lib.QuerySelect{
				Limit: 1,
				Where: lib.QueryWhere{
					OpCode: lib.PREDICATE,
					Predicate: lib.QueryPredicate{
						Literals: []string{"Hi"},
						Keys: []string{"Entry A"},
					},
				},
			},
		},
	}

	for _, q := range invalidQueries {
		selector := lib.MakeNamespaceTreeSelect(mock)
		q.Visit(selector)
		resp := selector.RunQuery()

		if resp.Msg != "error" {
			t.Error("Expected Msg error but received", resp.Msg)
		}

		if resp.Err == nil {
			t.Error("Expected response Err")
		}
	}
}

func rowsA() []lib.Row {
	return []lib.Row{
		lib.Row{
			Entries: map[string][]string {
				// TODO use user concepts to match only the Hi.
				"Entry A": []string{"Hi", "Hello"},
			},
		},
	}
}

func rowsB() []lib.Row {
	return []lib.Row{
		lib.Row{
			Entries: map[string][]string {
				"Entry B": []string{"Hi", "Hello World"},
			},
		},
	}
}

func rowsC() []lib.Row {
	return []lib.Row{
		lib.Row{
			Entries: map[string][]string {
				"Entry B": []string{"Hi", "Hello Dude"},
			},
		},
	}
}

func rowsD() []lib.Row {
	return []lib.Row{
		lib.Row{
			Entries: map[string][]string {
				"Entry C": []string{"Apple"},
				"Entry D": []string{"Orange"},
			},
		},
	}
}

func rowsE() []lib.Row {
	return []lib.Row{
		lib.Row{
			Entries: map[string][]string {
				"Entry E": []string{"Bus"},
			},
		},
		lib.Row{
			Entries: map[string][]string {
				"Entry E": []string{"Train"},
			},
		},
	}
}

func rowsF() []lib.Row {
	return []lib.Row{
		lib.Row{
			Entries: map[string][]string {
				"Entry F": []string{"This row", "rocks"},
			},
		},
	}
}

// Non matching rows.
func rowsZ() []lib.Row {
	return []lib.Row{
		lib.Row{
			Entries: map[string][]string {
				"Entry A": []string{"No", "Match"},
			},
		},
		lib.Row{
			Entries: map[string][]string {
				"Entry C": []string{"No", "Match", "Here"},
				"Entry D": []string{"Nada!"},
			},
		},
		lib.Row{
			Entries: map[string][]string {
				"Entry E": []string{"Horse"},
			},
		},
	}
}

func tableA() lib.Table {
	return mktable("A", rowsA())
}

func tableB() lib.Table {
	return mktable("B", rowsB())
}

func tableC() lib.Table {
	return mktable("C", rowsC())
}

func tableD() lib.Table {
	return mktable("D", rowsD())
}

func tableE() lib.Table {
	return mktable("E", rowsE())
}

func tableF() lib.Table {
	return mktable("F", rowsF())
}

func tableZ() lib.Table {
	return mktable("Z", rowsZ())
}

func feedNamespace(ntr lib.NamespaceTreeReader) {
	ntr.ReadNamespace(mkselectns())
}

func mkselectns() *lib.Namespace {
	namespace := lib.MakeNamespace()
	tables := []lib.Table{
		tableA(),
		tableB(),
		tableC(),
		tableD(),
		tableE(),
		tableF(),
		tableZ(),
	}

	for _, t := range tables {
		var err error
		namespace, err = namespace.JoinTable(mainTableKey, t)

		if err != nil {
			panic(err)
		}
	}

	return namespace
}

func mktable(name string, rows []lib.Row) lib.Table {
	table := lib.Table{
		Rows: map[string]lib.Row{},
	}

	for i, r := range rows {
		rowKey := fmt.Sprintf("Row %v%v", name, i)
		table.Rows[rowKey] = r
	}

	return table
}

func apiResponseEq(a, b lib.APIResponse) bool {
	if a.Msg != b.Msg {
		return false
	}

	if a.Err != b.Err {
		return false
	}

	if len(a.Rows) != len(b.Rows) {
		return false
	}

	if !rowsEq(a.Rows, b.Rows) {
		return false
	}

	return true
}

func rowsEq(a, b []lib.Row) bool {
	for _, ar := range a {
		found := false
		for _, br := range b {
			if rowEq(ar, br) {
				found = true
			}
		}
		if !found {
			return false
		}
	}

	return true
}

func rowEq(a, b lib.Row) bool {
	for ak, av := range a.Entries {
		bv, present := b.Entries[ak]

		if !present {
			return false
		}

		if !entryEq(av, bv) {
			return false
		}
	}

	return true
}

func entryEq(a, b []string) bool {
	for _, av := range a {
		found := false
		for _, bv := range b {
			if av == bv {
				found = true
			}
		}

		if !found {
			return false
		}
	}

	return true
}

const mainTableKey = "The Table"
<commit_msg>More select mocks<commit_after>package mock_godless

import (
	"fmt"
	"testing"

	"github.com/golang/mock/gomock"
	"github.com/pkg/errors"
	lib "github.com/johnny-morrice/godless"
)

func TestRunQuerySelectSuccess(t *testing.T) {
	ctrl := gomock.NewController(t)
	defer ctrl.Finish()

	mock := NewMockNamespaceTree(ctrl)

	whereA := lib.QueryWhere{
		OpCode: lib.PREDICATE,
		Predicate: lib.QueryPredicate{
			OpCode: lib.STR_EQ,
			Literals: []string{"Hi"},
			Keys: []string{"Entry A"},
		},
	}

	whereB := lib.QueryWhere{
		OpCode: lib.PREDICATE,
		Predicate: lib.QueryPredicate{
			OpCode: lib.STR_EQ,
			Literals: []string{"Hi"},
			Keys: []string{"Entry B"},
		},
	}

	whereC := lib.QueryWhere{
		OpCode: lib.PREDICATE,
		Predicate: lib.QueryPredicate{
			OpCode: lib.STR_NEQ,
			Literals: []string{"Hello World"},
			Keys: []string{"Entry B"},
		},
	}

	whereD := lib.QueryWhere{
		OpCode: lib.PREDICATE,
		Predicate: lib.QueryPredicate{
			OpCode: lib.STR_EQ,
			Literals: []string{"Apple"},
			Keys: []string{"Entry C"},
		},
	}

	whereE := lib.QueryWhere{
		OpCode: lib.PREDICATE,
		Predicate: lib.QueryPredicate{
			OpCode: lib.STR_EQ,
			Literals: []string{"Orange"},
			Keys: []string{"Entry D"},
		},
	}

	whereF := lib.QueryWhere{
		OpCode: lib.PREDICATE,
		Predicate: lib.QueryPredicate{
			OpCode: lib.STR_EQ,
			Literals: []string{"Train"},
			Keys: []string{"Entry E"},
		},
	}

	whereG := lib.QueryWhere{
		OpCode: lib.PREDICATE,
		Predicate: lib.QueryPredicate{
			OpCode: lib.STR_EQ,
			Literals: []string{"Bus"},
			Keys: []string{"Entry E"},
		},
	}

	whereH := lib.QueryWhere{
		OpCode: lib.PREDICATE,
		Predicate: lib.QueryPredicate{
			OpCode: lib.STR_EQ,
			Literals: []string{"Boat"},
			Keys: []string{"Entry E"},
		},
	}

	whereI := lib.QueryWhere{
		OpCode: lib.PREDICATE,
		Predicate: lib.QueryPredicate{
			OpCode: lib.STR_EQ,
			IncludeRowKey: true,
			Literals: []string{"Row F0"},
		},
	}

	queries := []*lib.Query{
		// One result
		&lib.Query{
			OpCode: lib.SELECT,
			TableKey: mainTableKey,
			Select: lib.QuerySelect{
				Limit: 2,
				Where: whereA,
			},
		},
		// Multiple results
		&lib.Query{
			OpCode: lib.SELECT,
			TableKey: mainTableKey,
			Select: lib.QuerySelect{
				Limit: 2,
				Where: whereB,
			},
		},
		// STR_NEQ
		&lib.Query{
			OpCode: lib.SELECT,
			TableKey: mainTableKey,
			Select: lib.QuerySelect{
				Limit: 2,
				Where: whereC,
			},
		},
		// AND
		&lib.Query{
			OpCode: lib.SELECT,
			TableKey: mainTableKey,
			Select: lib.QuerySelect{
				Limit: 2,
				Where: lib.QueryWhere{
					OpCode: lib.AND,
					Clauses: []lib.QueryWhere{whereD, whereE},
				},
			},
		},
		// OR
		&lib.Query{
			OpCode: lib.SELECT,
			TableKey: mainTableKey,
			Select: lib.QuerySelect{
				Limit: 2,
				Where: lib.QueryWhere{
					OpCode: lib.OR,
					Clauses: []lib.QueryWhere{whereF, whereG},
				},
			},
		},
		// No results
		&lib.Query{
			OpCode: lib.SELECT,
			TableKey: mainTableKey,
			Select: lib.QuerySelect{
				Limit: 2,
				Where: whereH,
			},
		},
		// Row key
		&lib.Query{
			OpCode: lib.SELECT,
			TableKey: mainTableKey,
			Select: lib.QuerySelect{
				Limit: 2,
				Where: whereI,
			},
		},
		// No where clause
		&lib.Query{
			OpCode: lib.SELECT,
			TableKey: altTableKey,
			Select: lib.QuerySelect{
				Limit: 3,
			},
		},
	}

	responseA := lib.RESPONSE_OK
	responseA.Rows = rowsA()

	responseB := lib.RESPONSE_OK
	responseB.Rows = append(rowsB(), rowsC()...)

	responseC := lib.RESPONSE_OK
	responseC.Rows = rowsC()

	responseD := lib.RESPONSE_OK
	responseD.Rows = rowsD()

	responseE := lib.RESPONSE_OK
	responseE.Rows = rowsE()

	responseF := lib.RESPONSE_OK

	responseG := lib.RESPONSE_OK
	responseG.Rows = rowsF()

	responseH := lib.RESPONSE_OK
	responseH.Rows = rowsG()

	expect := []lib.APIResponse{
		responseA,
		responseB,
		responseC,
		responseD,
		responseE,
		responseF,
		responseG,
		responseH,
	}

	if len(queries) != len(expect) {
		panic("mismatched input and expect")
	}

	mock.EXPECT().LoadTraverse(gomock.Any()).Return(nil).Do(feedNamespace).Times(len(queries))

	for i, q := range queries {
		selector := lib.MakeNamespaceTreeSelect(mock)
		q.Visit(selector)
		resp := selector.RunQuery()

		if !apiResponseEq(resp, expect[i]) {
			if resp.Rows == nil {
				t.Error("resp.Rows was nil")
			}
			if resp.Err != nil {
				t.Error("resp.Err was", resp.Err)
			}

			t.Error("Case", i, "Expected", expect[i], "but receieved", resp)
		}
	}
}

func TestRunQuerySelectFailure(t *testing.T) {
	ctrl := gomock.NewController(t)
	defer ctrl.Finish()

	mock := NewMockNamespaceTree(ctrl)

	mock.EXPECT().LoadTraverse(gomock.Any()).Return(errors.New("Expected Error"))

	failQuery := &lib.Query{
		OpCode: lib.SELECT,
		TableKey: mainTableKey,
		Select: lib.QuerySelect{
			Limit: 2,
			Where: lib.QueryWhere{
				OpCode: lib.PREDICATE,
				Predicate: lib.QueryPredicate{
					OpCode: lib.STR_EQ,
					Literals: []string{"Hi"},
					Keys: []string{"Entry A"},
				},
			},
		},
	}

	selector := lib.MakeNamespaceTreeSelect(mock)
	failQuery.Visit(selector)
	resp := selector.RunQuery()

	if resp.Msg != "error" {
		t.Error("Expected Msg error but received", resp.Msg)
	}

	if resp.Err == nil {
		t.Error("Expected response Err")
	}
}

func TestRunQuerySelectInvalid(t *testing.T) {
	ctrl := gomock.NewController(t)
	defer ctrl.Finish()

	mock := NewMockNamespaceTree(ctrl)

	invalidQueries := []*lib.Query{
		// Basically wrong.
		&lib.Query{},
		&lib.Query{OpCode: lib.JOIN},
		// No limit
		&lib.Query{
			Select: lib.QuerySelect{
				Where: lib.QueryWhere{
					OpCode: lib.PREDICATE,
					Predicate: lib.QueryPredicate{
						OpCode: lib.STR_EQ,
						Literals: []string{"Hi"},
						Keys: []string{"Entry A"},
					},
				},
			},
		},
		// No where OpCode
		&lib.Query{
			Select: lib.QuerySelect{
				Limit: 1,
				Where: lib.QueryWhere{
					Predicate: lib.QueryPredicate{
						OpCode: lib.STR_EQ,
						Literals: []string{"Hi"},
						Keys: []string{"Entry A"},
					},
				},
			},
		},
		// No predicate OpCode
		&lib.Query{
			Select: lib.QuerySelect{
				Limit: 1,
				Where: lib.QueryWhere{
					OpCode: lib.PREDICATE,
					Predicate: lib.QueryPredicate{
						Literals: []string{"Hi"},
						Keys: []string{"Entry A"},
					},
				},
			},
		},
	}

	for _, q := range invalidQueries {
		selector := lib.MakeNamespaceTreeSelect(mock)
		q.Visit(selector)
		resp := selector.RunQuery()

		if resp.Msg != "error" {
			t.Error("Expected Msg error but received", resp.Msg)
		}

		if resp.Err == nil {
			t.Error("Expected response Err")
		}
	}
}

func rowsA() []lib.Row {
	return []lib.Row{
		lib.Row{
			Entries: map[string][]string {
				// TODO use user concepts to match only the Hi.
				"Entry A": []string{"Hi", "Hello"},
			},
		},
	}
}

func rowsB() []lib.Row {
	return []lib.Row{
		lib.Row{
			Entries: map[string][]string {
				"Entry B": []string{"Hi", "Hello World"},
			},
		},
	}
}

func rowsC() []lib.Row {
	return []lib.Row{
		lib.Row{
			Entries: map[string][]string {
				"Entry B": []string{"Hi", "Hello Dude"},
			},
		},
	}
}

func rowsD() []lib.Row {
	return []lib.Row{
		lib.Row{
			Entries: map[string][]string {
				"Entry C": []string{"Apple"},
				"Entry D": []string{"Orange"},
			},
		},
	}
}

func rowsE() []lib.Row {
	return []lib.Row{
		lib.Row{
			Entries: map[string][]string {
				"Entry E": []string{"Bus"},
			},
		},
		lib.Row{
			Entries: map[string][]string {
				"Entry E": []string{"Train"},
			},
		},
	}
}

func rowsF() []lib.Row {
	return []lib.Row{
		lib.Row{
			Entries: map[string][]string {
				"Entry F": []string{"This row", "rocks"},
			},
		},
	}
}

func rowsG() []lib.Row {
	return []lib.Row{
		lib.Row{
			Entries: map[string][]string {
				"Entry Q": []string{"Hi", "Folks"},
			},
		},
		lib.Row{
			Entries: map[string][]string {
				"Entry R": []string{"Wowzer"},
			},
		},
		lib.Row{
			Entries: map[string][]string {
				"Entry S": []string{"Trumpet"},
			},
		},
	}
}

// Non matching rows.
func rowsZ() []lib.Row {
	return []lib.Row{
		lib.Row{
			Entries: map[string][]string {
				"Entry A": []string{"No", "Match"},
			},
		},
		lib.Row{
			Entries: map[string][]string {
				"Entry C": []string{"No", "Match", "Here"},
				"Entry D": []string{"Nada!"},
			},
		},
		lib.Row{
			Entries: map[string][]string {
				"Entry E": []string{"Horse"},
			},
		},
	}
}

func tableA() lib.Table {
	return mktable("A", rowsA())
}

func tableB() lib.Table {
	return mktable("B", rowsB())
}

func tableC() lib.Table {
	return mktable("C", rowsC())
}

func tableD() lib.Table {
	return mktable("D", rowsD())
}

func tableE() lib.Table {
	return mktable("E", rowsE())
}

func tableF() lib.Table {
	return mktable("F", rowsF())
}

func tableG() lib.Table {
	return mktable("G", rowsG())
}

func tableZ() lib.Table {
	return mktable("Z", rowsZ())
}

func feedNamespace(ntr lib.NamespaceTreeReader) {
	ntr.ReadNamespace(mkselectns())
}

func mkselectns() *lib.Namespace {
	namespace := lib.MakeNamespace()
	mainTables := []lib.Table{
		tableA(),
		tableB(),
		tableC(),
		tableD(),
		tableE(),
		tableF(),
		tableZ(),
	}
	altTables := []lib.Table{
		tableG(),
	}

	tables := map[string][]lib.Table{
		mainTableKey: mainTables,
		altTableKey: altTables,
	}

	for tableKey, ts := range tables {
		for _, t := range ts {
			var err error
			namespace, err = namespace.JoinTable(tableKey, t)

			if err != nil {
				panic(err)
			}
		}
	}

	return namespace
}

func mktable(name string, rows []lib.Row) lib.Table {
	table := lib.Table{
		Rows: map[string]lib.Row{},
	}

	for i, r := range rows {
		rowKey := fmt.Sprintf("Row %v%v", name, i)
		table.Rows[rowKey] = r
	}

	return table
}

func apiResponseEq(a, b lib.APIResponse) bool {
	if a.Msg != b.Msg {
		return false
	}

	if a.Err != b.Err {
		return false
	}

	if len(a.Rows) != len(b.Rows) {
		return false
	}

	if !rowsEq(a.Rows, b.Rows) {
		return false
	}

	return true
}

func rowsEq(a, b []lib.Row) bool {
	for _, ar := range a {
		found := false
		for _, br := range b {
			if rowEq(ar, br) {
				found = true
			}
		}
		if !found {
			return false
		}
	}

	return true
}

func rowEq(a, b lib.Row) bool {
	for ak, av := range a.Entries {
		bv, present := b.Entries[ak]

		if !present {
			return false
		}

		if !entryEq(av, bv) {
			return false
		}
	}

	return true
}

func entryEq(a, b []string) bool {
	for _, av := range a {
		found := false
		for _, bv := range b {
			if av == bv {
				found = true
			}
		}

		if !found {
			return false
		}
	}

	return true
}

const mainTableKey = "The Table"
const altTableKey = "Another table"
<|endoftext|>


<commit_before>package flags

import (
	"flag"
	"fmt"
	"os"

	"k8s.io/klog/v2"

	"github.com/spf13/cobra"
	"k8s.io/cli-runtime/pkg/genericclioptions"
	cmdutil "k8s.io/kubectl/pkg/cmd/util"
)

func AddFlags(cmds *cobra.Command) cmdutil.Factory {
	kubeConfigFlags := genericclioptions.NewConfigFlags(true)
	kubeConfigFlags.AddFlags(cmds.PersistentFlags())

	matchVersionKubeConfigFlags := cmdutil.NewMatchVersionFlags(kubeConfigFlags)
	matchVersionKubeConfigFlags.AddFlags(cmds.PersistentFlags())

	factory := cmdutil.NewFactory(matchVersionKubeConfigFlags)

	cmds.Flags().AddGoFlagSet(flag.CommandLine)
	flag.CommandLine.Parse([]string{})
	fakefs := flag.NewFlagSet("fake", flag.ExitOnError)
	klog.InitFlags(fakefs)
	if err := fakefs.Parse([]string{"-logtostderr=false"}); err != nil {
		fmt.Fprintf(os.Stderr, "%s\n", err)
		os.Exit(1)
	}

	return factory
}
<commit_msg>fix boilerplate<commit_after>/*
Copyright 2021 The cert-manager 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 flags

import (
	"flag"
	"fmt"
	"os"

	"k8s.io/klog/v2"

	"github.com/spf13/cobra"
	"k8s.io/cli-runtime/pkg/genericclioptions"
	cmdutil "k8s.io/kubectl/pkg/cmd/util"
)

func AddFlags(cmds *cobra.Command) cmdutil.Factory {
	kubeConfigFlags := genericclioptions.NewConfigFlags(true)
	kubeConfigFlags.AddFlags(cmds.PersistentFlags())

	matchVersionKubeConfigFlags := cmdutil.NewMatchVersionFlags(kubeConfigFlags)
	matchVersionKubeConfigFlags.AddFlags(cmds.PersistentFlags())

	factory := cmdutil.NewFactory(matchVersionKubeConfigFlags)

	cmds.Flags().AddGoFlagSet(flag.CommandLine)
	flag.CommandLine.Parse([]string{})
	fakefs := flag.NewFlagSet("fake", flag.ExitOnError)
	klog.InitFlags(fakefs)
	if err := fakefs.Parse([]string{"-logtostderr=false"}); err != nil {
		fmt.Fprintf(os.Stderr, "%s\n", err)
		os.Exit(1)
	}

	return factory
}
<|endoftext|>


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

package agent

import (
	"fmt"

	"github.com/juju/errors"

	"github.com/juju/juju/state"
	"github.com/juju/juju/worker"
)

// WorkerFactory exposes functionality for creating workers
// for an agent.
type WorkerFactory interface {
	// NewModelWorker returns a "new worker" func that may be used to
	// start a state worker for the state's model. If model workers are
	// not supported then false is returned (for "supported").
	NewModelWorker(name string, st *state.State) (newWorker func() (worker.Worker, error), supported bool)
}

var registeredWorkers = map[string]WorkerFactory{}

// RegisterWorker adds a worker factory for the named worker
// to the registry. If the name is already registered then
// errors.AlreadyExists is returned.
func RegisterWorker(name string, factory WorkerFactory) error {
	if existing, ok := registeredWorkers[name]; ok && factory != existing {
		return errors.NewAlreadyExists(nil, fmt.Sprintf("worker %q already registered", name))
	}
	registeredWorkers[name] = factory
	return nil
}
<commit_msg>Do not check for equality in RegisterWorker().<commit_after>// Copyright 2016 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package agent

import (
	"fmt"

	"github.com/juju/errors"

	"github.com/juju/juju/state"
	"github.com/juju/juju/worker"
)

// WorkerFactory exposes functionality for creating workers
// for an agent.
type WorkerFactory interface {
	// NewModelWorker returns a "new worker" func that may be used to
	// start a state worker for the state's model. If model workers are
	// not supported then false is returned (for "supported").
	NewModelWorker(name string, st *state.State) (newWorker func() (worker.Worker, error), supported bool)
}

var registeredWorkers = map[string]WorkerFactory{}

// RegisterWorker adds a worker factory for the named worker
// to the registry. If the name is already registered then
// errors.AlreadyExists is returned.
func RegisterWorker(name string, factory WorkerFactory) error {
	if _, ok := registeredWorkers[name]; ok {
		return errors.NewAlreadyExists(nil, fmt.Sprintf("worker %q already registered", name))
	}
	registeredWorkers[name] = factory
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/golang/glog"
	"github.com/spf13/cobra"
	"k8s.io/kops/upup/pkg/api"
	"k8s.io/kops/upup/pkg/fi/cloudup"
	"k8s.io/kops/upup/pkg/fi/utils"
	"k8s.io/kops/upup/pkg/kutil"
	"strings"
)

type UpdateClusterCmd struct {
	Yes          bool
	Target       string
	Models       string
	OutDir       string
	SSHPublicKey string
}

var updateCluster UpdateClusterCmd

func init() {
	cmd := &cobra.Command{
		Use:   "cluster",
		Short: "Update cluster",
		Long:  `Updates a k8s cluster.`,
		Run: func(cmd *cobra.Command, args []string) {
			err := updateCluster.Run(args)
			if err != nil {
				glog.Exitf("%v", err)
			}
		},
	}

	cmd.Flags().BoolVar(&updateCluster.Yes, "yes", false, "Actually create cloud resources")
	cmd.Flags().StringVar(&updateCluster.Target, "target", "direct", "Target - direct, terraform")
	cmd.Flags().StringVar(&updateCluster.Models, "model", "config,proto,cloudup", "Models to apply (separate multiple models with commas)")
	cmd.Flags().StringVar(&updateCluster.SSHPublicKey, "ssh-public-key", "~/.ssh/id_rsa.pub", "SSH public key to use")
	cmd.Flags().StringVar(&updateCluster.OutDir, "out", "", "Path to write any local output")
}

func (c *UpdateClusterCmd) Run(args []string) error {
	err := rootCommand.ProcessArgs(args)
	if err != nil {
		return err
	}

	isDryrun := false
	// direct requires --yes (others do not, because they don't do anything!)
	if c.Target == cloudup.TargetDirect {
		if !c.Yes {
			isDryrun = true
			c.Target = cloudup.TargetDryRun
		}
	}
	if c.Target == cloudup.TargetDryRun {
		isDryrun = true
		c.Target = cloudup.TargetDryRun
	}

	if c.OutDir == "" {
		c.OutDir = "out"
	}

	clusterRegistry, cluster, err := rootCommand.Cluster()
	if err != nil {
		return err
	}

	fullCluster, err := clusterRegistry.ReadCompletedConfig(cluster.Name)
	if err != nil {
		return err
	}

	instanceGroupRegistry, err := rootCommand.InstanceGroupRegistry()
	if err != nil {
		return err
	}

	fullInstanceGroups, err := instanceGroupRegistry.ReadAll()
	if err != nil {
		return err
	}

	if c.SSHPublicKey != "" {
		c.SSHPublicKey = utils.ExpandPath(c.SSHPublicKey)
	}

	strict := false
	err = api.DeepValidate(cluster, fullInstanceGroups, strict)
	if err != nil {
		return err
	}

	applyCmd := &cloudup.ApplyClusterCmd{
		Cluster:         fullCluster,
		InstanceGroups:  fullInstanceGroups,
		Models:          strings.Split(c.Models, ","),
		ClusterRegistry: clusterRegistry,
		Target:          c.Target,
		SSHPublicKey:    c.SSHPublicKey,
		OutDir:          c.OutDir,
		DryRun:          isDryrun,
	}
	err = applyCmd.Run()
	if err != nil {
		return err
	}

	if isDryrun {
		fmt.Printf("Must specify --yes to apply changes\n")
		return nil
	}

	// TODO: Only if not yet set?
	if !isDryrun {
		keyStore := clusterRegistry.KeyStore(cluster.Name)

		kubecfgCert, err := keyStore.FindCert("kubecfg")
		if err != nil {
			// This is only a convenience; don't error because of it
			glog.Warningf("Ignoring error trying to fetch kubecfg cert - won't export kubecfg: %v", err)
			kubecfgCert = nil
		}
		if kubecfgCert != nil {
			glog.Infof("Exporting kubecfg for cluster")
			x := &kutil.CreateKubecfg{
				ClusterName:      cluster.Name,
				KeyStore:         keyStore,
				MasterPublicName: cluster.Spec.MasterPublicName,
			}
			defer x.Close()

			err = x.WriteKubecfg()
			if err != nil {
				return err
			}
		} else {
			glog.Infof("kubecfg cert not found; won't export kubecfg")
		}
	}

	return nil
}
<commit_msg>Add update command to update parent command<commit_after>package main

import (
	"fmt"
	"github.com/golang/glog"
	"github.com/spf13/cobra"
	"k8s.io/kops/upup/pkg/api"
	"k8s.io/kops/upup/pkg/fi/cloudup"
	"k8s.io/kops/upup/pkg/fi/utils"
	"k8s.io/kops/upup/pkg/kutil"
	"strings"
)

type UpdateClusterCmd struct {
	Yes          bool
	Target       string
	Models       string
	OutDir       string
	SSHPublicKey string
}

var updateCluster UpdateClusterCmd

func init() {
	cmd := &cobra.Command{
		Use:   "cluster",
		Short: "Update cluster",
		Long:  `Updates a k8s cluster.`,
		Run: func(cmd *cobra.Command, args []string) {
			err := updateCluster.Run(args)
			if err != nil {
				glog.Exitf("%v", err)
			}
		},
	}

	updateCmd.AddCommand(cmd)

	cmd.Flags().BoolVar(&updateCluster.Yes, "yes", false, "Actually create cloud resources")
	cmd.Flags().StringVar(&updateCluster.Target, "target", "direct", "Target - direct, terraform")
	cmd.Flags().StringVar(&updateCluster.Models, "model", "config,proto,cloudup", "Models to apply (separate multiple models with commas)")
	cmd.Flags().StringVar(&updateCluster.SSHPublicKey, "ssh-public-key", "~/.ssh/id_rsa.pub", "SSH public key to use")
	cmd.Flags().StringVar(&updateCluster.OutDir, "out", "", "Path to write any local output")
}

func (c *UpdateClusterCmd) Run(args []string) error {
	err := rootCommand.ProcessArgs(args)
	if err != nil {
		return err
	}

	isDryrun := false
	// direct requires --yes (others do not, because they don't do anything!)
	if c.Target == cloudup.TargetDirect {
		if !c.Yes {
			isDryrun = true
			c.Target = cloudup.TargetDryRun
		}
	}
	if c.Target == cloudup.TargetDryRun {
		isDryrun = true
		c.Target = cloudup.TargetDryRun
	}

	if c.OutDir == "" {
		c.OutDir = "out"
	}

	clusterRegistry, cluster, err := rootCommand.Cluster()
	if err != nil {
		return err
	}

	fullCluster, err := clusterRegistry.ReadCompletedConfig(cluster.Name)
	if err != nil {
		return err
	}

	instanceGroupRegistry, err := rootCommand.InstanceGroupRegistry()
	if err != nil {
		return err
	}

	fullInstanceGroups, err := instanceGroupRegistry.ReadAll()
	if err != nil {
		return err
	}

	if c.SSHPublicKey != "" {
		c.SSHPublicKey = utils.ExpandPath(c.SSHPublicKey)
	}

	strict := false
	err = api.DeepValidate(cluster, fullInstanceGroups, strict)
	if err != nil {
		return err
	}

	applyCmd := &cloudup.ApplyClusterCmd{
		Cluster:         fullCluster,
		InstanceGroups:  fullInstanceGroups,
		Models:          strings.Split(c.Models, ","),
		ClusterRegistry: clusterRegistry,
		Target:          c.Target,
		SSHPublicKey:    c.SSHPublicKey,
		OutDir:          c.OutDir,
		DryRun:          isDryrun,
	}
	err = applyCmd.Run()
	if err != nil {
		return err
	}

	if isDryrun {
		fmt.Printf("Must specify --yes to apply changes\n")
		return nil
	}

	// TODO: Only if not yet set?
	if !isDryrun {
		keyStore := clusterRegistry.KeyStore(cluster.Name)

		kubecfgCert, err := keyStore.FindCert("kubecfg")
		if err != nil {
			// This is only a convenience; don't error because of it
			glog.Warningf("Ignoring error trying to fetch kubecfg cert - won't export kubecfg: %v", err)
			kubecfgCert = nil
		}
		if kubecfgCert != nil {
			glog.Infof("Exporting kubecfg for cluster")
			x := &kutil.CreateKubecfg{
				ClusterName:      cluster.Name,
				KeyStore:         keyStore,
				MasterPublicName: cluster.Spec.MasterPublicName,
			}
			defer x.Close()

			err = x.WriteKubecfg()
			if err != nil {
				return err
			}
		} else {
			glog.Infof("kubecfg cert not found; won't export kubecfg")
		}
	}

	return nil
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 Intel Corporation. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package main

import (
	"fmt"
	"os"
	"os/signal"
	"path"
	"strings"
	"syscall"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/defaults"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/s3"
	"github.com/dustin/go-humanize"
	"github.com/pkg/errors"
	"github.com/rcrowley/go-metrics"

	"github.com/intel-hpdd/lemur/dmplugin"
	"github.com/intel-hpdd/lemur/pkg/fsroot"
	"github.com/intel-hpdd/logging/alert"
	"github.com/intel-hpdd/logging/audit"
	"github.com/intel-hpdd/logging/debug"
)

type (
	archiveConfig struct {
		Name   string `hcl:",key"`
		ID     int
		Region string
		Bucket string
		Prefix string
	}

	archiveSet []*archiveConfig

	s3Config struct {
		NumThreads         int        `hcl:"num_threads"`
		Region             string     `hcl:"region"`
		Endpoint           string     `hcl:"endpoint"`
		AWSAccessKeyID     string     `hcl:"aws_access_key_id"`
		AWSSecretAccessKey string     `hcl:"aws_secret_access_key"`
		Archives           archiveSet `hcl:"archive"`
	}
)

// Should this be configurable?
const updateInterval = 10 * time.Second

var rate metrics.Meter

func (c *s3Config) String() string {
	return dmplugin.DisplayConfig(c)
}

func (a *archiveConfig) String() string {
	return fmt.Sprintf("%d:%s:%s/%s", a.ID, a.Region, a.Bucket, a.Prefix)
}

func (a *archiveConfig) checkValid() error {
	var errors []string

	if a.Bucket == "" {
		errors = append(errors, fmt.Sprintf("Archive %s: bucket not set", a.Name))
	}

	if a.ID < 1 {
		errors = append(errors, fmt.Sprintf("Archive %s: archive id not set", a.Name))

	}

	if len(errors) > 0 {
		return fmt.Errorf("Errors: %s", strings.Join(errors, ", "))
	}

	return nil
}

func (c *s3Config) Merge(other *s3Config) *s3Config {
	result := new(s3Config)

	result.NumThreads = c.NumThreads
	if other.NumThreads > 0 {
		result.NumThreads = other.NumThreads
	}

	result.Region = c.Region
	if other.Region != "" {
		result.Region = other.Region
	}

	result.Endpoint = c.Endpoint
	if other.Endpoint != "" {
		result.Endpoint = other.Endpoint
	}

	result.AWSAccessKeyID = c.AWSAccessKeyID
	if other.AWSAccessKeyID != "" {
		result.AWSAccessKeyID = other.AWSAccessKeyID
	}

	result.AWSSecretAccessKey = c.AWSSecretAccessKey
	if other.AWSSecretAccessKey != "" {
		result.AWSSecretAccessKey = other.AWSSecretAccessKey
	}

	result.Archives = c.Archives
	if len(other.Archives) > 0 {
		result.Archives = other.Archives
	}

	return result
}

func init() {
	rate = metrics.NewMeter()

	// if debug.Enabled() {
	go func() {
		var lastCount int64
		for {
			if lastCount != rate.Count() {
				audit.Logf("total %s (1 min/5 min/15 min/inst): %s/%s/%s/%s msg/sec\n",
					humanize.Comma(rate.Count()),
					humanize.Comma(int64(rate.Rate1())),
					humanize.Comma(int64(rate.Rate5())),
					humanize.Comma(int64(rate.Rate15())),
					humanize.Comma(int64(rate.RateMean())),
				)
				lastCount = rate.Count()
			}
			time.Sleep(10 * time.Second)
		}
	}()
	// }
}

func s3Svc(region string, endpoint string) *s3.S3 {
	// TODO: Allow more per-archive configuration options?
	cfg := aws.NewConfig().WithRegion(region).WithLogLevel(aws.LogDebug)
	if endpoint != "" {
		cfg.WithEndpoint(endpoint)
		cfg.WithS3ForcePathStyle(true)
	}
	return s3.New(session.New(cfg))
}

func getMergedConfig(plugin *dmplugin.Plugin) (*s3Config, error) {
	baseCfg := &s3Config{
		Region: "us-east-1",
	}

	var cfg s3Config
	err := dmplugin.LoadConfig(plugin.ConfigFile(), &cfg)

	if err != nil {
		return nil, fmt.Errorf("Failed to load config: %s", err)
	}

	return baseCfg.Merge(&cfg), nil
}

func checkS3Configuration(cfg *s3Config) error {
	// Check to make sure that the SDK can find some credentials
	// before continuing; otherwise there will be long timeouts and
	// mysterious failures on HSM actions.
	// Hopefully this will work for non-AWS S3 implementations as well.
	s3Creds := defaults.CredChain(aws.NewConfig().WithRegion(cfg.Region), defaults.Handlers())
	if _, err := s3Creds.Get(); err != nil {
		return errors.Wrap(err, "No S3 credentials found; cannot initialize data mover")
	}

	svc := s3Svc(cfg.Region, cfg.Endpoint)
	if _, err := svc.ListBuckets(&s3.ListBucketsInput{}); err != nil {
		return errors.Wrap(err, "Unable to list S3 buckets")
	}

	return nil
}

func main() {
	plugin, err := dmplugin.New(path.Base(os.Args[0]), func(path string) (fsroot.Client, error) {
		return fsroot.New(path)
	})
	if err != nil {
		alert.Abort(errors.Wrap(err, "failed to initialize plugin"))
	}
	defer plugin.Close()

	cfg, err := getMergedConfig(plugin)
	if err != nil {
		alert.Abort(errors.Wrap(err, "Unable to determine plugin configuration"))
	}

	debug.Printf("S3Mover configuration:\n%v", cfg)

	if len(cfg.Archives) == 0 {
		alert.Abort(errors.New("Invalid configuration: No archives defined"))
	}

	for _, archive := range cfg.Archives {
		debug.Print(archive)
		if err = archive.checkValid(); err != nil {
			alert.Abort(errors.Wrap(err, "Invalid configuration"))
		}
	}

	// Set the configured AWS credentials in the environment for use
	// by the SDK. If there are no explicitly configured credentials,
	// then the SDK will look for them in other ways
	// (e.g. ~/.aws/credentials, ec2 role, etc.).
	if cfg.AWSAccessKeyID != "" {
		os.Setenv("AWS_ACCESS_KEY_ID", cfg.AWSAccessKeyID)
	}
	if cfg.AWSSecretAccessKey != "" {
		os.Setenv("AWS_SECRET_ACCESS_KEY", cfg.AWSSecretAccessKey)
	}

	if err = checkS3Configuration(cfg); err != nil {
		alert.Abort(errors.Wrap(err, "S3 config check failed"))
	}

	// All base filesystem operations will be relative to current directory
	err = os.Chdir(plugin.Base())
	if err != nil {
		alert.Abort(errors.Wrap(err, "chdir failed"))
	}

	interruptHandler(func() {
		plugin.Stop()
	})

	for _, a := range cfg.Archives {
		// Allow each archive to set its own region, but default
		// to the region set for the plugin.
		region := cfg.Region
		if a.Region != "" {
			region = a.Region
		}
		s3Svc := s3Svc(region, cfg.Endpoint)
		plugin.AddMover(&dmplugin.Config{
			Mover:      S3Mover(s3Svc, uint32(a.ID), a.Bucket, a.Prefix),
			NumThreads: cfg.NumThreads,
			ArchiveID:  uint32(a.ID),
		})
	}

	plugin.Run()
}

func interruptHandler(once func()) {
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, syscall.SIGQUIT, syscall.SIGTERM)

	go func() {
		stopping := false
		for sig := range c {
			debug.Printf("signal received: %s", sig)
			if !stopping {
				stopping = true
				once()
			}
		}
	}()
}
<commit_msg>Remove verbose logging.<commit_after>// Copyright (c) 2016 Intel Corporation. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package main

import (
	"fmt"
	"os"
	"os/signal"
	"path"
	"strings"
	"syscall"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/defaults"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/s3"
	"github.com/dustin/go-humanize"
	"github.com/pkg/errors"
	"github.com/rcrowley/go-metrics"

	"github.com/intel-hpdd/lemur/dmplugin"
	"github.com/intel-hpdd/lemur/pkg/fsroot"
	"github.com/intel-hpdd/logging/alert"
	"github.com/intel-hpdd/logging/audit"
	"github.com/intel-hpdd/logging/debug"
)

type (
	archiveConfig struct {
		Name   string `hcl:",key"`
		ID     int
		Region string
		Bucket string
		Prefix string
	}

	archiveSet []*archiveConfig

	s3Config struct {
		NumThreads         int        `hcl:"num_threads"`
		Region             string     `hcl:"region"`
		Endpoint           string     `hcl:"endpoint"`
		AWSAccessKeyID     string     `hcl:"aws_access_key_id"`
		AWSSecretAccessKey string     `hcl:"aws_secret_access_key"`
		Archives           archiveSet `hcl:"archive"`
	}
)

// Should this be configurable?
const updateInterval = 10 * time.Second

var rate metrics.Meter

func (c *s3Config) String() string {
	return dmplugin.DisplayConfig(c)
}

func (a *archiveConfig) String() string {
	return fmt.Sprintf("%d:%s:%s/%s", a.ID, a.Region, a.Bucket, a.Prefix)
}

func (a *archiveConfig) checkValid() error {
	var errors []string

	if a.Bucket == "" {
		errors = append(errors, fmt.Sprintf("Archive %s: bucket not set", a.Name))
	}

	if a.ID < 1 {
		errors = append(errors, fmt.Sprintf("Archive %s: archive id not set", a.Name))

	}

	if len(errors) > 0 {
		return fmt.Errorf("Errors: %s", strings.Join(errors, ", "))
	}

	return nil
}

func (c *s3Config) Merge(other *s3Config) *s3Config {
	result := new(s3Config)

	result.NumThreads = c.NumThreads
	if other.NumThreads > 0 {
		result.NumThreads = other.NumThreads
	}

	result.Region = c.Region
	if other.Region != "" {
		result.Region = other.Region
	}

	result.Endpoint = c.Endpoint
	if other.Endpoint != "" {
		result.Endpoint = other.Endpoint
	}

	result.AWSAccessKeyID = c.AWSAccessKeyID
	if other.AWSAccessKeyID != "" {
		result.AWSAccessKeyID = other.AWSAccessKeyID
	}

	result.AWSSecretAccessKey = c.AWSSecretAccessKey
	if other.AWSSecretAccessKey != "" {
		result.AWSSecretAccessKey = other.AWSSecretAccessKey
	}

	result.Archives = c.Archives
	if len(other.Archives) > 0 {
		result.Archives = other.Archives
	}

	return result
}

func init() {
	rate = metrics.NewMeter()

	// if debug.Enabled() {
	go func() {
		var lastCount int64
		for {
			if lastCount != rate.Count() {
				audit.Logf("total %s (1 min/5 min/15 min/inst): %s/%s/%s/%s msg/sec\n",
					humanize.Comma(rate.Count()),
					humanize.Comma(int64(rate.Rate1())),
					humanize.Comma(int64(rate.Rate5())),
					humanize.Comma(int64(rate.Rate15())),
					humanize.Comma(int64(rate.RateMean())),
				)
				lastCount = rate.Count()
			}
			time.Sleep(10 * time.Second)
		}
	}()
	// }
}

func s3Svc(region string, endpoint string) *s3.S3 {
	// TODO: Allow more per-archive configuration options?
	cfg := aws.NewConfig().WithRegion(region)
	if endpoint != "" {
		cfg.WithEndpoint(endpoint)
		cfg.WithS3ForcePathStyle(true)
	}
	return s3.New(session.New(cfg))
}

func getMergedConfig(plugin *dmplugin.Plugin) (*s3Config, error) {
	baseCfg := &s3Config{
		Region: "us-east-1",
	}

	var cfg s3Config
	err := dmplugin.LoadConfig(plugin.ConfigFile(), &cfg)

	if err != nil {
		return nil, fmt.Errorf("Failed to load config: %s", err)
	}

	return baseCfg.Merge(&cfg), nil
}

func checkS3Configuration(cfg *s3Config) error {
	// Check to make sure that the SDK can find some credentials
	// before continuing; otherwise there will be long timeouts and
	// mysterious failures on HSM actions.
	// Hopefully this will work for non-AWS S3 implementations as well.
	s3Creds := defaults.CredChain(aws.NewConfig().WithRegion(cfg.Region), defaults.Handlers())
	if _, err := s3Creds.Get(); err != nil {
		return errors.Wrap(err, "No S3 credentials found; cannot initialize data mover")
	}

	svc := s3Svc(cfg.Region, cfg.Endpoint)
	if _, err := svc.ListBuckets(&s3.ListBucketsInput{}); err != nil {
		return errors.Wrap(err, "Unable to list S3 buckets")
	}

	return nil
}

func main() {
	plugin, err := dmplugin.New(path.Base(os.Args[0]), func(path string) (fsroot.Client, error) {
		return fsroot.New(path)
	})
	if err != nil {
		alert.Abort(errors.Wrap(err, "failed to initialize plugin"))
	}
	defer plugin.Close()

	cfg, err := getMergedConfig(plugin)
	if err != nil {
		alert.Abort(errors.Wrap(err, "Unable to determine plugin configuration"))
	}

	debug.Printf("S3Mover configuration:\n%v", cfg)

	if len(cfg.Archives) == 0 {
		alert.Abort(errors.New("Invalid configuration: No archives defined"))
	}

	for _, archive := range cfg.Archives {
		debug.Print(archive)
		if err = archive.checkValid(); err != nil {
			alert.Abort(errors.Wrap(err, "Invalid configuration"))
		}
	}

	// Set the configured AWS credentials in the environment for use
	// by the SDK. If there are no explicitly configured credentials,
	// then the SDK will look for them in other ways
	// (e.g. ~/.aws/credentials, ec2 role, etc.).
	if cfg.AWSAccessKeyID != "" {
		os.Setenv("AWS_ACCESS_KEY_ID", cfg.AWSAccessKeyID)
	}
	if cfg.AWSSecretAccessKey != "" {
		os.Setenv("AWS_SECRET_ACCESS_KEY", cfg.AWSSecretAccessKey)
	}

	if err = checkS3Configuration(cfg); err != nil {
		alert.Abort(errors.Wrap(err, "S3 config check failed"))
	}

	// All base filesystem operations will be relative to current directory
	err = os.Chdir(plugin.Base())
	if err != nil {
		alert.Abort(errors.Wrap(err, "chdir failed"))
	}

	interruptHandler(func() {
		plugin.Stop()
	})

	for _, a := range cfg.Archives {
		// Allow each archive to set its own region, but default
		// to the region set for the plugin.
		region := cfg.Region
		if a.Region != "" {
			region = a.Region
		}
		s3Svc := s3Svc(region, cfg.Endpoint)
		plugin.AddMover(&dmplugin.Config{
			Mover:      S3Mover(s3Svc, uint32(a.ID), a.Bucket, a.Prefix),
			NumThreads: cfg.NumThreads,
			ArchiveID:  uint32(a.ID),
		})
	}

	plugin.Run()
}

func interruptHandler(once func()) {
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, syscall.SIGQUIT, syscall.SIGTERM)

	go func() {
		stopping := false
		for sig := range c {
			debug.Printf("signal received: %s", sig)
			if !stopping {
				stopping = true
				once()
			}
		}
	}()
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"sort"
	"strconv"
	"strings"

	"github.com/mpreath/netcalc/pkg/network"
	"github.com/mpreath/netcalc/pkg/network/networknode"
	"github.com/mpreath/netcalc/pkg/utils"
)

type Response struct {
	Status    string      `json:"status"`
	Error     string      `json:"error,omitempty"`
	ErrorCode int         `json:"error_code,omitempty"`
	Data      interface{} `json:"data,omitempty"`
}

type NetworkInfo struct {
	NetworkAddress   string `json:"network_address"`
	Mask             string `json:"mask"`
	BroadcastAddress string `json:"broadcast_address"`
	NumberOfHosts    int    `json:"number_of_hosts"`
}

func Info(w http.ResponseWriter, r *http.Request) {

	ipAddress, err := utils.ParseAddress(r.URL.Query().Get("address"))
	if err != nil {
		writeErrorResponse(w, err)
		return
	}

	subnetMask, err := utils.ParseAddress(r.URL.Query().Get("mask"))
	if err != nil {
		writeErrorResponse(w, err)
		return
	}

	net, err := network.New(ipAddress, subnetMask)
	if err != nil {
		writeErrorResponse(w, err)
		return
	}

	info := &NetworkInfo{
		NetworkAddress:   utils.ExportAddress(net.Address),
		Mask:             utils.ExportAddress(net.Mask),
		BroadcastAddress: utils.ExportAddress(net.BroadcastAddress()),
		NumberOfHosts:    net.HostCount(),
	}

	writeJsonResponse(w, http.StatusOK, info)

}

func Subnet(w http.ResponseWriter, r *http.Request) {

	ipAddress, err := utils.ParseAddress(r.URL.Query().Get("address"))
	if err != nil {
		writeErrorResponse(w, err)
		return
	}

	subnetMask, err := utils.ParseAddress(r.URL.Query().Get("mask"))
	if err != nil {
		writeErrorResponse(w, err)
		return
	}

	hostCount, _ := strconv.Atoi(r.URL.Query().Get("hosts"))
	networkCount, _ := strconv.Atoi(r.URL.Query().Get("networks"))

	if hostCount == 0 && networkCount == 0 {
		writeErrorResponse(w, fmt.Errorf("subnet: no host or network counts provided"))
		return
	}

	net, err := network.New(ipAddress, subnetMask)
	if err != nil {
		writeErrorResponse(w, err)
		return
	}

	node := networknode.New(net)

	if hostCount > 0 {
		err = networknode.SplitToHostCount(node, hostCount)
		if err != nil {
			log.Fatal(err)
		}

	} else if networkCount > 0 {
		err = networknode.SplitToNetCount(node, networkCount)
		if err != nil {
			log.Fatal(err)
		}
	} else {
		writeErrorResponse(w, fmt.Errorf("no valid hosts or networks value provided"))
		return
	}

	writeJsonResponse(w, http.StatusOK, node.Flatten())
}

func Summarize(w http.ResponseWriter, r *http.Request) {
	var networkList []*network.Network

	err := json.NewDecoder(r.Body).Decode(&networkList)
	if err != nil {
		writeErrorResponse(w, err)
		return
	}
	summarizedNetwork, err := network.SummarizeNetworks(networkList)
	if err != nil {
		writeErrorResponse(w, err)
		return
	}

	writeJsonResponse(w, http.StatusOK, summarizedNetwork)
}

func Vlsm(w http.ResponseWriter, r *http.Request) {

	ipAddress, err := utils.ParseAddress(r.URL.Query().Get("address"))
	if err != nil {
		writeErrorResponse(w, err)
		return
	}

	subnetMask, err := utils.ParseAddress(r.URL.Query().Get("mask"))
	if err != nil {
		writeErrorResponse(w, err)
		return
	}

	net, err := network.New(ipAddress, subnetMask)
	if err != nil {
		writeErrorResponse(w, err)
		return
	}

	node := networknode.New(net)

	vlsmArgs := strings.Split(r.URL.Query().Get("vlsmList"), ",")
	var vlsmList = make([]int, len(vlsmArgs))
	for idx, val := range vlsmArgs {
		vlsmList[idx], err = strconv.Atoi(val)
		if err != nil {
			writeErrorResponse(w, err)
			return
		}
	}
	sort.Slice(vlsmList, func(i, j int) bool {
		return vlsmList[i] < vlsmList[j]
	})

	for _, vlsm := range vlsmList {
		err = networknode.SplitToVlsmCount(node, vlsm)

		if err != nil {
			writeErrorResponse(w, err)
			return
		}
	}

	writeJsonResponse(w, http.StatusOK, node.Flatten())
}

func writeJsonResponse(w http.ResponseWriter, status int, data interface{}) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(status)
	enc := json.NewEncoder(w)
	enc.SetIndent("", "  ")
	err := enc.Encode(Response{
		Status: "ok",
		Data:   data,
	})
	if err != nil {
		log.Println(err)
		return
	}
}

func writeErrorResponse(w http.ResponseWriter, err error) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusInternalServerError)
	enc := json.NewEncoder(w)
	enc.SetIndent("", "  ")
	err = enc.Encode(Response{
		Status:    "error",
		Error:     err.Error(),
		ErrorCode: http.StatusInternalServerError,
	})
	if err != nil {
		log.Println(err)
		return
	}
}
<commit_msg>refactored writing response headers<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"sort"
	"strconv"
	"strings"

	"github.com/mpreath/netcalc/pkg/network"
	"github.com/mpreath/netcalc/pkg/network/networknode"
	"github.com/mpreath/netcalc/pkg/utils"
)

type Response struct {
	Status    string      `json:"status"`
	Error     string      `json:"error,omitempty"`
	ErrorCode int         `json:"error_code,omitempty"`
	Data      interface{} `json:"data,omitempty"`
}

type NetworkInfo struct {
	NetworkAddress   string `json:"network_address"`
	Mask             string `json:"mask"`
	BroadcastAddress string `json:"broadcast_address"`
	NumberOfHosts    int    `json:"number_of_hosts"`
}

func Info(w http.ResponseWriter, r *http.Request) {

	ipAddress, err := utils.ParseAddress(r.URL.Query().Get("address"))
	if err != nil {
		writeErrorResponse(w, err)
		return
	}

	subnetMask, err := utils.ParseAddress(r.URL.Query().Get("mask"))
	if err != nil {
		writeErrorResponse(w, err)
		return
	}

	net, err := network.New(ipAddress, subnetMask)
	if err != nil {
		writeErrorResponse(w, err)
		return
	}

	info := &NetworkInfo{
		NetworkAddress:   utils.ExportAddress(net.Address),
		Mask:             utils.ExportAddress(net.Mask),
		BroadcastAddress: utils.ExportAddress(net.BroadcastAddress()),
		NumberOfHosts:    net.HostCount(),
	}

	writeJsonResponse(w, http.StatusOK, info)

}

func Subnet(w http.ResponseWriter, r *http.Request) {

	ipAddress, err := utils.ParseAddress(r.URL.Query().Get("address"))
	if err != nil {
		writeErrorResponse(w, err)
		return
	}

	subnetMask, err := utils.ParseAddress(r.URL.Query().Get("mask"))
	if err != nil {
		writeErrorResponse(w, err)
		return
	}

	hostCount, _ := strconv.Atoi(r.URL.Query().Get("hosts"))
	networkCount, _ := strconv.Atoi(r.URL.Query().Get("networks"))

	if hostCount == 0 && networkCount == 0 {
		writeErrorResponse(w, fmt.Errorf("subnet: no host or network counts provided"))
		return
	}

	net, err := network.New(ipAddress, subnetMask)
	if err != nil {
		writeErrorResponse(w, err)
		return
	}

	node := networknode.New(net)

	if hostCount > 0 {
		err = networknode.SplitToHostCount(node, hostCount)
		if err != nil {
			log.Fatal(err)
		}

	} else if networkCount > 0 {
		err = networknode.SplitToNetCount(node, networkCount)
		if err != nil {
			log.Fatal(err)
		}
	} else {
		writeErrorResponse(w, fmt.Errorf("no valid hosts or networks value provided"))
		return
	}

	writeJsonResponse(w, http.StatusOK, node.Flatten())
}

func Summarize(w http.ResponseWriter, r *http.Request) {
	var networkList []*network.Network

	err := json.NewDecoder(r.Body).Decode(&networkList)
	if err != nil {
		writeErrorResponse(w, err)
		return
	}
	summarizedNetwork, err := network.SummarizeNetworks(networkList)
	if err != nil {
		writeErrorResponse(w, err)
		return
	}

	writeJsonResponse(w, http.StatusOK, summarizedNetwork)
}

func Vlsm(w http.ResponseWriter, r *http.Request) {

	ipAddress, err := utils.ParseAddress(r.URL.Query().Get("address"))
	if err != nil {
		writeErrorResponse(w, err)
		return
	}

	subnetMask, err := utils.ParseAddress(r.URL.Query().Get("mask"))
	if err != nil {
		writeErrorResponse(w, err)
		return
	}

	net, err := network.New(ipAddress, subnetMask)
	if err != nil {
		writeErrorResponse(w, err)
		return
	}

	node := networknode.New(net)

	vlsmArgs := strings.Split(r.URL.Query().Get("vlsmList"), ",")
	var vlsmList = make([]int, len(vlsmArgs))
	for idx, val := range vlsmArgs {
		vlsmList[idx], err = strconv.Atoi(val)
		if err != nil {
			writeErrorResponse(w, err)
			return
		}
	}
	sort.Slice(vlsmList, func(i, j int) bool {
		return vlsmList[i] < vlsmList[j]
	})

	for _, vlsm := range vlsmList {
		err = networknode.SplitToVlsmCount(node, vlsm)

		if err != nil {
			writeErrorResponse(w, err)
			return
		}
	}

	writeJsonResponse(w, http.StatusOK, node.Flatten())
}

func writeJsonResponse(w http.ResponseWriter, status int, data interface{}) {
	enc := writeHeaders(w, status)
	err := enc.Encode(Response{
		Status: "ok",
		Data:   data,
	})
	if err != nil {
		log.Println(err)
		return
	}
}

func writeErrorResponse(w http.ResponseWriter, err error) {
	enc := writeHeaders(w, http.StatusInternalServerError)
	err = enc.Encode(Response{
		Status:    "error",
		Error:     err.Error(),
		ErrorCode: http.StatusInternalServerError,
	})
	if err != nil {
		log.Println(err)
		return
	}
}

func writeHeaders(w http.ResponseWriter, status int) *json.Encoder {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(status)

	enc := json.NewEncoder(w)
	enc.SetIndent("", "  ")

	return enc
}
<|endoftext|>


<commit_before>package subcmd

import (
    "net"
    "strings"
    "github.com/Lupino/periodic/driver"
    "github.com/Lupino/periodic/protocol"
    "fmt"
    "log"
    "bytes"
    "errors"
    "io"
    "os"
    "os/exec"
    "strconv"
    "time"
)

func Run(entryPoint, Func, cmd string) {
    parts := strings.SplitN(entryPoint, "://", 2)
    for {
        c, err := net.Dial(parts[0], parts[1])
        if err != nil {
            if err != io.EOF {
                log.Printf("Error: %s\n", err.Error())
            }
            log.Printf("Wait 5 second to reconnecting")
            time.Sleep(5 * time.Second)
            continue
        }
        conn := protocol.Conn{Conn: c}
        err = handleWorker(conn, Func, cmd)
        if err != nil {
            if err != io.EOF {
                log.Printf("Error: %s\n", err.Error())
            }
        }
        conn.Close()
    }
}

func handleWorker(conn protocol.Conn, Func, cmd string) (err error) {
    err = conn.Send(protocol.TYPE_WORKER.Bytes())
    if err != nil {
        return
    }
    var msgId = []byte("100")
    buf := bytes.NewBuffer(nil)
    buf.Write(msgId)
    buf.Write(protocol.NULL_CHAR)
    buf.WriteByte(byte(protocol.CAN_DO))
    buf.Write(protocol.NULL_CHAR)
    buf.WriteString(Func)
    err = conn.Send(buf.Bytes())
    if err != nil {
        return
    }

    var payload []byte
    var job driver.Job
    var jobHandle []byte
    for {
        buf = bytes.NewBuffer(nil)
        buf.Write(msgId)
        buf.Write(protocol.NULL_CHAR)
        buf.Write(protocol.GRAB_JOB.Bytes())
        err = conn.Send(buf.Bytes())
        if err != nil {
            return
        }
        payload, err = conn.Receive()
        if err != nil {
            return
        }
        job, jobHandle, err = extraJob(payload)
        realCmd := strings.Split(cmd, " ")
        realCmd = append(realCmd, job.Name)
        c := exec.Command(realCmd[0], realCmd[1:]...)
        c.Stdin = strings.NewReader(job.Args)
        var out bytes.Buffer
        c.Stdout = &out
        c.Stderr = os.Stderr
        err = c.Run()
        var schedLater int
        var fail = false
        for {
            line, err := out.ReadString([]byte("\n")[0])
            if err != nil {
                break
            }
            if strings.HasPrefix(line, "SCHED_LATER") {
                parts := strings.SplitN(line[:len(line) - 1], " ", 2)
                later := strings.Trim(parts[1], " ")
                schedLater, _ = strconv.Atoi(later)
            } else if strings.HasPrefix(line, "FAIL") {
                fail = true
            } else {
                fmt.Print(line)
            }
        }
        buf = bytes.NewBuffer(nil)
        buf.Write(msgId)
        buf.Write(protocol.NULL_CHAR)
        if err != nil || fail {
            buf.WriteByte(byte(protocol.JOB_FAIL))
        } else if schedLater > 0 {
            buf.WriteByte(byte(protocol.SCHED_LATER))
        } else {
            buf.WriteByte(byte(protocol.JOB_DONE))
        }
        buf.Write(protocol.NULL_CHAR)
        buf.Write(jobHandle)
        if schedLater > 0 {
            buf.Write(protocol.NULL_CHAR)
            buf.WriteString(strconv.Itoa(schedLater))
        }
        err = conn.Send(buf.Bytes())
        if err != nil {
            return
        }
    }
}

func extraJob(payload []byte) (job driver.Job, jobHandle []byte, err error) {
    parts := bytes.SplitN(payload, protocol.NULL_CHAR, 3)
    if len(parts) != 3 {
        err = errors.New("Invalid payload " + string(payload))
        return
    }
    job, err = driver.NewJob(parts[2])
    jobHandle = parts[1]
    return
}
<commit_msg>Fix. the protocol name<commit_after>package subcmd

import (
    "net"
    "strings"
    "github.com/Lupino/periodic/driver"
    "github.com/Lupino/periodic/protocol"
    "fmt"
    "log"
    "bytes"
    "errors"
    "io"
    "os"
    "os/exec"
    "strconv"
    "time"
)

func Run(entryPoint, Func, cmd string) {
    parts := strings.SplitN(entryPoint, "://", 2)
    for {
        c, err := net.Dial(parts[0], parts[1])
        if err != nil {
            if err != io.EOF {
                log.Printf("Error: %s\n", err.Error())
            }
            log.Printf("Wait 5 second to reconnecting")
            time.Sleep(5 * time.Second)
            continue
        }
        conn := protocol.Conn{Conn: c}
        err = handleWorker(conn, Func, cmd)
        if err != nil {
            if err != io.EOF {
                log.Printf("Error: %s\n", err.Error())
            }
        }
        conn.Close()
    }
}

func handleWorker(conn protocol.Conn, Func, cmd string) (err error) {
    err = conn.Send(protocol.TYPE_WORKER.Bytes())
    if err != nil {
        return
    }
    var msgId = []byte("100")
    buf := bytes.NewBuffer(nil)
    buf.Write(msgId)
    buf.Write(protocol.NULL_CHAR)
    buf.WriteByte(byte(protocol.CAN_DO))
    buf.Write(protocol.NULL_CHAR)
    buf.WriteString(Func)
    err = conn.Send(buf.Bytes())
    if err != nil {
        return
    }

    var payload []byte
    var job driver.Job
    var jobHandle []byte
    for {
        buf = bytes.NewBuffer(nil)
        buf.Write(msgId)
        buf.Write(protocol.NULL_CHAR)
        buf.Write(protocol.GRAB_JOB.Bytes())
        err = conn.Send(buf.Bytes())
        if err != nil {
            return
        }
        payload, err = conn.Receive()
        if err != nil {
            return
        }
        job, jobHandle, err = extraJob(payload)
        realCmd := strings.Split(cmd, " ")
        realCmd = append(realCmd, job.Name)
        c := exec.Command(realCmd[0], realCmd[1:]...)
        c.Stdin = strings.NewReader(job.Args)
        var out bytes.Buffer
        c.Stdout = &out
        c.Stderr = os.Stderr
        err = c.Run()
        var schedLater int
        var fail = false
        for {
            line, err := out.ReadString([]byte("\n")[0])
            if err != nil {
                break
            }
            if strings.HasPrefix(line, "SCHED_LATER") {
                parts := strings.SplitN(line[:len(line) - 1], " ", 2)
                later := strings.Trim(parts[1], " ")
                schedLater, _ = strconv.Atoi(later)
            } else if strings.HasPrefix(line, "FAIL") {
                fail = true
            } else {
                fmt.Print(line)
            }
        }
        buf = bytes.NewBuffer(nil)
        buf.Write(msgId)
        buf.Write(protocol.NULL_CHAR)
        if err != nil || fail {
            buf.WriteByte(byte(protocol.WORK_FAIL))
        } else if schedLater > 0 {
            buf.WriteByte(byte(protocol.SCHED_LATER))
        } else {
            buf.WriteByte(byte(protocol.WORK_DONE))
        }
        buf.Write(protocol.NULL_CHAR)
        buf.Write(jobHandle)
        if schedLater > 0 {
            buf.Write(protocol.NULL_CHAR)
            buf.WriteString(strconv.Itoa(schedLater))
        }
        err = conn.Send(buf.Bytes())
        if err != nil {
            return
        }
    }
}

func extraJob(payload []byte) (job driver.Job, jobHandle []byte, err error) {
    parts := bytes.SplitN(payload, protocol.NULL_CHAR, 3)
    if len(parts) != 3 {
        err = errors.New("Invalid payload " + string(payload))
        return
    }
    job, err = driver.NewJob(parts[2])
    jobHandle = parts[1]
    return
}
<|endoftext|>