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

package table

/*  Filename:    test.go
 *  Author:      Bryan Matsuo <bmatsuo@soe.ucsc.edu>
 *  Created:     Fri Dec  9 08:58:18 PST 2011
 *  Description:
 */

import (
	"testing"
	"reflect"
	"strings"
	"regexp"
	"os"
)

// Non-nil values returned by the Test method will cause the table test that
// called Test to fail. A FatalError retured by Test stops the table test.
type T interface {
	Test() os.Error // Execute the test described by the object.
}

// These types act on strings values of uncaught panics inside Test() the
// type's test method.  Acceptable value types are substrings,
// *regexp.Regexp, or func(string) os.Error objects.
type PanicExpectation interface{}

func acceptablePanicExpectation(exp PanicExpectation) os.Error {
	switch exp.(type) {
	case nil:
		return Error("nil PanicExpectation")
	case string, *regexp.Regexp, func(string) os.Error:
		return nil
	}
	return Errorf("unacceptable PanicExpectation type %s", reflect.TypeOf(exp))
}

func applyPanicExpectation(exp PanicExpectation, pstr string) (err os.Error) {
	switch exp.(type) {
	case *regexp.Regexp:
		r := exp.(*regexp.Regexp)
		if !r.MatchString(pstr) {
			err = Fatalf("unexpected panic (doesn't match %v): %s", r, pstr)
		}
	case string:
		if strings.Index(pstr, exp.(string)) < 0 {
			err = Fatalf("unexpected panic (doesn't contain %#v): %s", exp, pstr)
		}
	case func(string) os.Error:
		if err := exp.(func(string) os.Error)(pstr); err != nil {
			err = Fatalf("panic callback error: %s", err)
		}
	}
	return
}

type indexedError struct {
	index int
	Err   os.Error
}

func (err indexedError) String() string { return err.Err.String() }

func applyPanicExpectations(exps []PanicExpectation, pstr string) (err os.Error) {
	var errs []indexedError
	for i, exp := range exps {
		if e := applyPanicExpectation(exp, pstr); e != nil {
			errs = append(errs, indexedError{i, e})
		}
	}
	if len(errs) > 0 {
		if e := errs[0]; len(errs) == 1 {
			err = Fatalf("PanicExpectation %d failure: %v", e.index, e)
			return
		}
		err = Fatal("PanicExpectation failure")
		for _, e := range errs {
			err = Fatalf("%s\n\texpectation %d: %v", err, e.index, e)
		}
	}
	return
}

type TPanics interface {
	T // TPanics is a TType.
	Panics() []PanicExpectation
}

func getTPanicsExpectations(test TPanics) (exps []PanicExpectation, err os.Error) {
	if test == nil {
		return nil, Error("nil test")
	}
	exps = test.Panics()
	for i, exp := range exps {
		if err = acceptablePanicExpectation(exp); err == nil {
			err = Errorf("PanicExpectation %d type error: %v", i, err)
			return
		}
	}
	return
}

type TBefore interface {
	T        // TBefore is a T type.
	Before() // Callback executed before the Test method.
}

type TAfter interface {
	T       // TAfter is a T type.
	After() // Callback executed after the Test method.
}

type TBeforeAfter interface {
	T        // TBeforeAfter is a T type.
	Before() // TBeforeAfter is a TBefore type.
	After()  // TBeforeAfter is a TAfter type.
}

// Cast an element as a T, or create an os.Error describing the failure.
func mustT(t *testing.T, name string, elem interface{}) (T, os.Error) {
	switch elem.(type) {
	case nil:
		return nil, os.NewError(fatalstrf(name, "nil slice element"))
	case T:
	default:
		errf := "element does not implement table.T %v"
		return nil, os.NewError(fatalstrf(name, errf, reflect.TypeOf(elem)))
	}
	return elem.(T), nil
}

// Execute t's Test method. If t is a TBefore type execute t.Before() prior to
// t.Test(). If t is a TAfter type, execute t.After() after t.Test() returns.
// Handles runtimes panics resulting from any of these callback.
func tTest(t T) (err os.Error) {
	place := "before"
	defer func() {
		if e := recover(); e != nil {
			err = Errorf("panic %s test; %v", place, e)
		}
	}()
	switch t.(type) {
	case TBeforeAfter:
		t.(TBefore).Before()
		defer t.(TAfter).After()
	case TBefore:
		t.(TBefore).Before()
	case TAfter:
		defer t.(TAfter).After()
	}
	place = "during"
	defer func() { place = "after" }()
	defer func() {
		panicv := recover()
		switch t.(type) {
		case TPanics:
			exps, err := getTPanicsExpectations(t.(TPanics))
			if err != nil {
				err = Errorf("error retrieving PanicExpectations: %v", err)
			} else if hasexp := len(exps) > 0; panicv != nil {
				if hasexp {
					err = applyPanicExpectations(exps, sprint(panicv))
				} else {
					err = Errorf("unexpected panic: %v", panicv)
				}
			} else {
				if hasexp {
					err = Errorf("test did not panic as expected %v", exps)
				}
			}
			return
		}
		if panicv != nil {
			err = Errorf("panic: %v", panicv)
		}
	}()
	err = t.Test()
	return
}
<commit_msg>Add small description of TPanics' Panics method.<commit_after>// Copyright 2011, Bryan Matsuo. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package table

/*  Filename:    test.go
 *  Author:      Bryan Matsuo <bmatsuo@soe.ucsc.edu>
 *  Created:     Fri Dec  9 08:58:18 PST 2011
 *  Description:
 */

import (
	"testing"
	"reflect"
	"strings"
	"regexp"
	"os"
)

// Non-nil values returned by the Test method will cause the table test that
// called Test to fail. A FatalError retured by Test stops the table test.
type T interface {
	Test() os.Error // Execute the test described by the object.
}

// These types act on strings values of uncaught panics inside Test() the
// type's test method.  Acceptable value types are substrings,
// *regexp.Regexp, or func(string) os.Error objects.
type PanicExpectation interface{}

func acceptablePanicExpectation(exp PanicExpectation) os.Error {
	switch exp.(type) {
	case nil:
		return Error("nil PanicExpectation")
	case string, *regexp.Regexp, func(string) os.Error:
		return nil
	}
	return Errorf("unacceptable PanicExpectation type %s", reflect.TypeOf(exp))
}

func applyPanicExpectation(exp PanicExpectation, pstr string) (err os.Error) {
	switch exp.(type) {
	case *regexp.Regexp:
		r := exp.(*regexp.Regexp)
		if !r.MatchString(pstr) {
			err = Fatalf("unexpected panic (doesn't match %v): %s", r, pstr)
		}
	case string:
		if strings.Index(pstr, exp.(string)) < 0 {
			err = Fatalf("unexpected panic (doesn't contain %#v): %s", exp, pstr)
		}
	case func(string) os.Error:
		if err := exp.(func(string) os.Error)(pstr); err != nil {
			err = Fatalf("panic callback error: %s", err)
		}
	}
	return
}

type indexedError struct {
	index int
	Err   os.Error
}

func (err indexedError) String() string { return err.Err.String() }

func applyPanicExpectations(exps []PanicExpectation, pstr string) (err os.Error) {
	var errs []indexedError
	for i, exp := range exps {
		if e := applyPanicExpectation(exp, pstr); e != nil {
			errs = append(errs, indexedError{i, e})
		}
	}
	if len(errs) > 0 {
		if e := errs[0]; len(errs) == 1 {
			err = Fatalf("PanicExpectation %d failure: %v", e.index, e)
			return
		}
		err = Fatal("PanicExpectation failure")
		for _, e := range errs {
			err = Fatalf("%s\n\texpectation %d: %v", err, e.index, e)
		}
	}
	return
}

type TPanics interface {
	T                           // TPanics is a TType.
	Panics() []PanicExpectation // TPanics when non-nil, certain panics expected.
}

func getTPanicsExpectations(test TPanics) (exps []PanicExpectation, err os.Error) {
	if test == nil {
		return nil, Error("nil test")
	}
	exps = test.Panics()
	for i, exp := range exps {
		if err = acceptablePanicExpectation(exp); err == nil {
			err = Errorf("PanicExpectation %d type error: %v", i, err)
			return
		}
	}
	return
}

type TBefore interface {
	T        // TBefore is a T type.
	Before() // Callback executed before the Test method.
}

type TAfter interface {
	T       // TAfter is a T type.
	After() // Callback executed after the Test method.
}

type TBeforeAfter interface {
	T        // TBeforeAfter is a T type.
	Before() // TBeforeAfter is a TBefore type.
	After()  // TBeforeAfter is a TAfter type.
}

// Cast an element as a T, or create an os.Error describing the failure.
func mustT(t *testing.T, name string, elem interface{}) (T, os.Error) {
	switch elem.(type) {
	case nil:
		return nil, os.NewError(fatalstrf(name, "nil slice element"))
	case T:
	default:
		errf := "element does not implement table.T %v"
		return nil, os.NewError(fatalstrf(name, errf, reflect.TypeOf(elem)))
	}
	return elem.(T), nil
}

// Execute t's Test method. If t is a TBefore type execute t.Before() prior to
// t.Test(). If t is a TAfter type, execute t.After() after t.Test() returns.
// Handles runtimes panics resulting from any of these callback.
func tTest(t T) (err os.Error) {
	place := "before"
	defer func() {
		if e := recover(); e != nil {
			err = Errorf("panic %s test; %v", place, e)
		}
	}()
	switch t.(type) {
	case TBeforeAfter:
		t.(TBefore).Before()
		defer t.(TAfter).After()
	case TBefore:
		t.(TBefore).Before()
	case TAfter:
		defer t.(TAfter).After()
	}
	place = "during"
	defer func() { place = "after" }()
	defer func() {
		panicv := recover()
		switch t.(type) {
		case TPanics:
			exps, err := getTPanicsExpectations(t.(TPanics))
			if err != nil {
				err = Errorf("error retrieving PanicExpectations: %v", err)
			} else if hasexp := len(exps) > 0; panicv != nil {
				if hasexp {
					err = applyPanicExpectations(exps, sprint(panicv))
				} else {
					err = Errorf("unexpected panic: %v", panicv)
				}
			} else {
				if hasexp {
					err = Errorf("test did not panic as expected %v", exps)
				}
			}
			return
		}
		if panicv != nil {
			err = Errorf("panic: %v", panicv)
		}
	}()
	err = t.Test()
	return
}
<|endoftext|>


<commit_before>// Copyright 2011 Andrew Scherkus
//
// 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 id3

import (
	"bufio"
	"fmt"
)

type v22Parser struct {
	reader *bufio.Reader
}

type v22Frame struct {
	id   string
	size int32
}

func newID3v22Parser(reader *bufio.Reader) id3Parser {
	parser := new(v22Parser)
	parser.reader = reader
	return parser
}

func (parser *v22Parser) HasFrame() bool {
	data, err := parser.reader.Peek(3)
	if err != nil {
		return false
	}

	for _, c := range data {
		if (c < 'A' || c > 'Z') && (c < '0' || c > '9') {
			return false
		}
	}
	return true
}

func (parser *v22Parser) ReadFrame(file *File) {
	frame := new(v22Frame)

	id := readBytes(parser.reader, 3)
	frame.id = string(id)

	size := readBytes(parser.reader, 3)
	frame.size = int32(size[0])<<16 | int32(size[1])<<8 | int32(size[2])

	switch frame.id {
	case "TAL":
		file.Album = readString(parser.reader, int(frame.size))
	case "TRK":
		file.Track = readString(parser.reader, int(frame.size))
	case "TP1":
		file.Artist = readString(parser.reader, int(frame.size))
	case "TT2":
		file.Name = readString(parser.reader, int(frame.size))
	case "TYE":
		file.Year = readString(parser.reader, int(frame.size))
	case "TPA":
		file.Disc = readString(parser.reader, int(frame.size))
	case "TCO":
		file.Genre = readGenre(parser.reader, int(frame.size))

	// Skip these frame types.
	case "CM1": // ???
		fallthrough
	case "COM": // Comment
		fallthrough
	case "IPP": // ???
		fallthrough
	case "PCS": // ???
		fallthrough
	case "PIC": // Picture
		fallthrough
	case "TCM": // Composer
		fallthrough
	case "TCT": // ???
		fallthrough
	case "TDR": // ???
		fallthrough
	case "TEN": // Encoded by
		fallthrough
	case "TID": // ???
		fallthrough
	case "TP2": // Band/Orchestra/Accompaniment
		fallthrough
	case "TT1": // Content group description
		fallthrough
	case "UFI": // Unique file identifier
		fallthrough
	case "ULT": // Unsychronized lyrics/text transcription
		fallthrough
	case "WFD": // ???
		skipBytes(parser.reader, int(frame.size))
		break
	default:
		panic(fmt.Sprintf("Unrecognized frame ID: %s, size=%d\n", frame.id, frame.size))
	}
}
<commit_msg>Added TSS to v2 parser.<commit_after>// Copyright 2011 Andrew Scherkus
//
// 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 id3

import (
	"bufio"
	"fmt"
)

type v22Parser struct {
	reader *bufio.Reader
}

type v22Frame struct {
	id   string
	size int32
}

func newID3v22Parser(reader *bufio.Reader) id3Parser {
	parser := new(v22Parser)
	parser.reader = reader
	return parser
}

func (parser *v22Parser) HasFrame() bool {
	data, err := parser.reader.Peek(3)
	if err != nil {
		return false
	}

	for _, c := range data {
		if (c < 'A' || c > 'Z') && (c < '0' || c > '9') {
			return false
		}
	}
	return true
}

func (parser *v22Parser) ReadFrame(file *File) {
	frame := new(v22Frame)

	id := readBytes(parser.reader, 3)
	frame.id = string(id)

	size := readBytes(parser.reader, 3)
	frame.size = int32(size[0])<<16 | int32(size[1])<<8 | int32(size[2])

	switch frame.id {
	case "TAL":
		file.Album = readString(parser.reader, int(frame.size))
	case "TRK":
		file.Track = readString(parser.reader, int(frame.size))
	case "TP1":
		file.Artist = readString(parser.reader, int(frame.size))
	case "TT2":
		file.Name = readString(parser.reader, int(frame.size))
	case "TYE":
		file.Year = readString(parser.reader, int(frame.size))
	case "TPA":
		file.Disc = readString(parser.reader, int(frame.size))
	case "TCO":
		file.Genre = readGenre(parser.reader, int(frame.size))

	// Skip these frame types.
	case "CM1": // ???
		fallthrough
	case "COM": // Comment
		fallthrough
	case "IPP": // ???
		fallthrough
	case "PCS": // ???
		fallthrough
	case "PIC": // Picture
		fallthrough
	case "TCM": // Composer
		fallthrough
	case "TCT": // ???
		fallthrough
	case "TDR": // ???
		fallthrough
	case "TEN": // Encoded by
		fallthrough
	case "TID": // ???
		fallthrough
	case "TP2": // Band/Orchestra/Accompaniment
		fallthrough
	case "TSS": // Software/hardware and settings used for encoding
		fallthrough
	case "TT1": // Content group description
		fallthrough
	case "UFI": // Unique file identifier
		fallthrough
	case "ULT": // Unsychronized lyrics/text transcription
		fallthrough
	case "WFD": // ???
		skipBytes(parser.reader, int(frame.size))
		break
	default:
		panic(fmt.Sprintf("Unrecognized frame ID: %s, size=%d\n", frame.id, frame.size))
	}
}
<|endoftext|>


<commit_before>// +build linux darwin freebsd

package tail

import (
	"os"
)

func OpenFile(name string) (file *os.File, err error) {
	return os.Open(name)
}
<commit_msg>add netbsd<commit_after>// +build linux darwin freebsd netbsd

package tail

import (
	"os"
)

func OpenFile(name string) (file *os.File, err error) {
	return os.Open(name)
}
<|endoftext|>


<commit_before>// +build task

package main

import (
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
)

func sourceDir() (dir string, ok bool) {
	_, file, _, ok := runtime.Caller(1)
	if !ok {
		return "", ok
	}
	dir = filepath.Dir(file)

	// if the last segment is "task", strip that out; allows
	// segregating task files in a subdir
	parent, taskDir := filepath.Split(dir)
	if taskDir == "task" {
		dir = parent
	}

	return dir, ok
}

func goBuild(src string, action string, args ...string) error {
	cmd := exec.Command(
		"go", action,
		"-v",
	)
	cmd.Args = append(cmd.Args, args...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	if err := cmd.Run(); err != nil {
		return err
	}
	return nil
}

func gitVersion() (string, error) {
	cmd := exec.Command(
		"git", "describe",
		"--match", "release/*",
		"--dirty=-edited",
	)
	cmd.Stderr = os.Stderr
	buf, err := cmd.Output()
	if err != nil {
		return "", err
	}
	return string(buf), nil
}

func main() {
	log.SetFlags(0)
	log.SetPrefix("# ")
	src, ok := sourceDir()
	if !ok {
		log.Fatal("cannot determine source directory")
	}
	err := os.Chdir(src)
	if err != nil {
		log.Fatalf("cannot change to source directory: %v", err)
	}

	log.Print("build bazil")
	version, err := gitVersion()
	if err != nil {
		log.Fatalf("git describe: %v", err)
	}
	err = goBuild(src, "build", "-v",
		"-ldflags", "-X bazil.org/bazil/version.Version="+version,
		"bazil.org/bazil",
	)
	if err != nil {
		log.Fatalf("go build of bazil: %v", err)
	}
}
<commit_msg>task: Coding style<commit_after>// +build task

package main

import (
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
)

func sourceDir() (dir string, ok bool) {
	_, file, _, ok := runtime.Caller(1)
	if !ok {
		return "", ok
	}
	dir = filepath.Dir(file)

	// if the last segment is "task", strip that out; allows
	// segregating task files in a subdir
	parent, taskDir := filepath.Split(dir)
	if taskDir == "task" {
		dir = parent
	}

	return dir, ok
}

func goBuild(src string, action string, args ...string) error {
	cmd := exec.Command(
		"go", action,
		"-v",
	)
	cmd.Args = append(cmd.Args, args...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	if err := cmd.Run(); err != nil {
		return err
	}
	return nil
}

func gitVersion() (string, error) {
	cmd := exec.Command(
		"git", "describe",
		"--match", "release/*",
		"--dirty=-edited",
	)
	cmd.Stderr = os.Stderr
	buf, err := cmd.Output()
	if err != nil {
		return "", err
	}
	return string(buf), nil
}

func main() {
	log.SetFlags(0)
	log.SetPrefix("# ")
	src, ok := sourceDir()
	if !ok {
		log.Fatal("cannot determine source directory")
	}
	if err := os.Chdir(src); err != nil {
		log.Fatalf("cannot change to source directory: %v", err)
	}

	log.Print("build bazil")
	version, err := gitVersion()
	if err != nil {
		log.Fatalf("git describe: %v", err)
	}

	if err := goBuild(src, "build", "-v",
		"-ldflags", "-X bazil.org/bazil/version.Version="+version,
		"bazil.org/bazil",
	); err != nil {
		log.Fatalf("go build of bazil: %v", err)
	}
}
<|endoftext|>


<commit_before>package softlayer

import (
	"fmt"
	"log"
	"strconv"

	"github.com/hashicorp/terraform/helper/schema"
	"github.ibm.com/riethm/gopherlayer.git/datatypes"
	"github.ibm.com/riethm/gopherlayer.git/filter"
	"github.ibm.com/riethm/gopherlayer.git/services"
	"github.ibm.com/riethm/gopherlayer.git/session"
	"github.ibm.com/riethm/gopherlayer.git/sl"
)

func resourceSoftLayerLocalLoadBalancerService() *schema.Resource {
	return &schema.Resource{
		Create:   resourceSoftLayerLocalLoadBalancerServiceCreate,
		Read:     resourceSoftLayerLocalLoadBalancerServiceRead,
		Update:   resourceSoftLayerLocalLoadBalancerServiceUpdate,
		Delete:   resourceSoftLayerLocalLoadBalancerServiceDelete,
		Exists:   resourceSoftLayerLocalLoadBalancerServiceExists,
		Importer: &schema.ResourceImporter{},

		Schema: map[string]*schema.Schema{
			"service_group_id": &schema.Schema{
				Type:     schema.TypeInt,
				Required: true,
				ForceNew: true,
			},
			"ip_address_id": &schema.Schema{
				Type:     schema.TypeInt,
				Required: true,
			},
			"port": &schema.Schema{
				Type:     schema.TypeInt,
				Required: true,
			},
			"enabled": &schema.Schema{
				Type:     schema.TypeBool,
				Required: true,
			},
			"health_check_type": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
			},
			"weight": &schema.Schema{
				Type:     schema.TypeInt,
				Required: true,
			},
		},
	}
}

func resourceSoftLayerLocalLoadBalancerServiceCreate(d *schema.ResourceData, meta interface{}) error {
	sess := meta.(*session.Session)

	// SoftLayer Local LBs consist of a multi-level hierarchy of types.
	// (virtualIpAddress -> []virtualServer -> []serviceGroup -> []service)

	// Using the service group ID provided in the config, find the IDs of the
	// respective virtualServer and virtualIpAddress
	sgID := d.Get("service_group_id").(int)
	serviceGroup, err := services.GetNetworkApplicationDeliveryControllerLoadBalancerServiceGroupService(sess).
		Id(sgID).
		Mask("id,routingMethodId,routingTypeId,virtualServer[id,allocation,port,virtualIpAddress[id]]").
		GetObject()

	if err != nil {
		return fmt.Errorf("Error retrieving load balancer service group from SoftLayer, %s", err)
	}

	// Store the IDs for later use
	vsID := *serviceGroup.VirtualServer.Id
	vipID := *serviceGroup.VirtualServer.VirtualIpAddress.Id

	// Convert the health check type name to an ID
	healthCheckTypeId, err := getHealthCheckTypeId(sess, d.Get("health_check_type").(string))
	if err != nil {
		return err
	}

	// The API only exposes edit capability at the root of the tree (virtualIpAddress),
	// so need to send the full structure from the root down to the node to be added or
	// modified
	vip := datatypes.Network_Application_Delivery_Controller_LoadBalancer_VirtualIpAddress{

		VirtualServers: []datatypes.Network_Application_Delivery_Controller_LoadBalancer_VirtualServer{{
			Id:         &vsID,
			Allocation: serviceGroup.VirtualServer.Allocation,
			Port:       serviceGroup.VirtualServer.Port,

			ServiceGroups: []datatypes.Network_Application_Delivery_Controller_LoadBalancer_Service_Group{{
				Id:              &sgID,
				RoutingMethodId: serviceGroup.RoutingMethodId,
				RoutingTypeId:   serviceGroup.RoutingTypeId,

				Services: []datatypes.Network_Application_Delivery_Controller_LoadBalancer_Service{{
					Enabled:     sl.Int(1),
					Port:        sl.Int(d.Get("port").(int)),
					IpAddressId: sl.Int(d.Get("ip_address_id").(int)),

					HealthChecks: []datatypes.Network_Application_Delivery_Controller_LoadBalancer_Health_Check{{
						HealthCheckTypeId: &healthCheckTypeId,
					}},

					GroupReferences: []datatypes.Network_Application_Delivery_Controller_LoadBalancer_Service_Group_CrossReference{{
						Weight: sl.Int(d.Get("weight").(int)),
					}},
				}},
			}},
		}},
	}

	log.Printf("[INFO] Creating load balancer service")

	success, err := services.GetNetworkApplicationDeliveryControllerLoadBalancerVirtualIpAddressService(sess).
		Id(vipID).
		EditObject(&vip)

	if err != nil {
		return fmt.Errorf("Error creating load balancer service: %s", err)
	}

	if !success {
		return fmt.Errorf("Error creating load balancer service")
	}

	// Retrieve the newly created object, to obtain its ID
	svcs, err := services.GetNetworkApplicationDeliveryControllerLoadBalancerServiceGroupService(sess).
		Id(sgID).
		Mask("services[id],port,ipAddressId]").
		Filter(filter.New(
			filter.Path("port").Eq(d.Get("port")),
			filter.Path("ipAddressId").Eq(d.Get("ip_address_id"))).Build()).
		GetServices()

	if err != nil || len(svcs) == 0 {
		return fmt.Errorf("Error retrieving load balancer: %s", err)
	}

	d.SetId(strconv.Itoa(*svcs[0].Id))

	log.Printf("[INFO] Load Balancer Service ID: %s", d.Id())

	return resourceSoftLayerLocalLoadBalancerServiceRead(d, meta)
}

func resourceSoftLayerLocalLoadBalancerServiceUpdate(d *schema.ResourceData, meta interface{}) error {
	sess := meta.(*session.Session)

	// Using the ID stored in the config, find the IDs of the respective
	// serviceGroup, virtualServer and virtualIpAddress
	svcID, _ := strconv.Atoi(d.Id())
	svc, err := services.GetNetworkApplicationDeliveryControllerLoadBalancerServiceService(sess).
		Id(svcID).
		Mask("id,serviceGroup[id,routingTypeId,routingMethodId,virtualServer[id,,allocation,port,virtualIpAddress[id]]]").
		GetObject()

	if err != nil {
		return fmt.Errorf("Error retrieving load balancer service group from SoftLayer, %s", err)
	}

	// Store the IDs for later use
	sgID := *svc.ServiceGroup.Id
	vsID := *svc.ServiceGroup.VirtualServer.Id
	vipID := *svc.ServiceGroup.VirtualServer.VirtualIpAddress.Id

	// Convert the health check type name to an ID
	healthCheckTypeId, err := getHealthCheckTypeId(sess, d.Get("health_check_type").(string))
	if err != nil {
		return err
	}

	// The API only exposes edit capability at the root of the tree (virtualIpAddress),
	// so need to send the full structure from the root down to the node to be added or
	// modified
	vip := datatypes.Network_Application_Delivery_Controller_LoadBalancer_VirtualIpAddress{

		VirtualServers: []datatypes.Network_Application_Delivery_Controller_LoadBalancer_VirtualServer{{
			Id:         &vsID,
			Allocation: svc.ServiceGroup.VirtualServer.Allocation,
			Port:       svc.ServiceGroup.VirtualServer.Port,

			ServiceGroups: []datatypes.Network_Application_Delivery_Controller_LoadBalancer_Service_Group{{
				Id:              &sgID,
				RoutingMethodId: svc.ServiceGroup.RoutingMethodId,
				RoutingTypeId:   svc.ServiceGroup.RoutingTypeId,

				Services: []datatypes.Network_Application_Delivery_Controller_LoadBalancer_Service{{
					Id:          &svcID,
					Enabled:     sl.Int(1),
					Port:        sl.Int(d.Get("port").(int)),
					IpAddressId: sl.Int(d.Get("ip_address_id").(int)),

					HealthChecks: []datatypes.Network_Application_Delivery_Controller_LoadBalancer_Health_Check{{
						HealthCheckTypeId: &healthCheckTypeId,
					}},

					GroupReferences: []datatypes.Network_Application_Delivery_Controller_LoadBalancer_Service_Group_CrossReference{{
						Weight: sl.Int(d.Get("weight").(int)),
					}},
				}},
			}},
		}},
	}

	log.Printf("[INFO] Updating load balancer service")

	success, err := services.GetNetworkApplicationDeliveryControllerLoadBalancerVirtualIpAddressService(sess).
		Id(vipID).
		EditObject(&vip)

	if err != nil {
		return fmt.Errorf("Error updating load balancer service: %s", err)
	}

	if !success {
		return fmt.Errorf("Error updating load balancer service")
	}

	return resourceSoftLayerLocalLoadBalancerServiceRead(d, meta)
}

func resourceSoftLayerLocalLoadBalancerServiceRead(d *schema.ResourceData, meta interface{}) error {
	sess := meta.(*session.Session)

	svcID, _ := strconv.Atoi(d.Id())

	svc, err := services.GetNetworkApplicationDeliveryControllerLoadBalancerServiceService(sess).
		Id(svcID).
		Mask("ipAddressId,port,healthChecks[type[keyname]],groupReferences[weight]").
		GetObject()

	if err != nil {
		return fmt.Errorf("Error retrieving service: %s", err)
	}

	d.Set("ip_address_id", *svc.IpAddressId)
	d.Set("port", *svc.Port)
	d.Set("health_check_type", *svc.HealthChecks[0].Type.Keyname)
	d.Set("weight", *svc.GroupReferences[0].Weight)

	return nil
}

func resourceSoftLayerLocalLoadBalancerServiceDelete(d *schema.ResourceData, meta interface{}) error {
	sess := meta.(*session.Session)

	svcID, _ := strconv.Atoi(d.Id())
	success, err := services.GetNetworkApplicationDeliveryControllerLoadBalancerServiceService(sess).
		Id(svcID).
		DeleteObject()

	if err != nil {
		return fmt.Errorf("Error deleting service group: %s", err)
	}

	if !success {
		return fmt.Errorf("Error deleting service group")
	}

	return nil
}

func resourceSoftLayerLocalLoadBalancerServiceExists(d *schema.ResourceData, meta interface{}) (bool, error) {
	sess := meta.(*session.Session)

	svcID, _ := strconv.Atoi(d.Id())

	_, err := services.GetNetworkApplicationDeliveryControllerLoadBalancerServiceService(sess).
		Id(svcID).
		Mask("id").
		GetObject()

	if err != nil {
		return false, err
	}

	return true, nil
}

func getHealthCheckTypeId(sess *session.Session, healthCheckTypeName string) (int, error) {
	healthCheckTypes, err := services.GetNetworkApplicationDeliveryControllerLoadBalancerHealthCheckTypeService(sess).
		Mask("id").
		Filter(filter.Build(
			filter.Path("keyname").Eq(healthCheckTypeName))).
		Limit(1).
		GetAllObjects()

	if err != nil {
		return -1, err
	}

	if len(healthCheckTypes) < 1 {
		return -1, fmt.Errorf("Invalid health check type: %s", healthCheckTypeName)
	}

	return *healthCheckTypes[0].Id, nil
}
<commit_msg>Fix object mask<commit_after>package softlayer

import (
	"fmt"
	"log"
	"strconv"

	"github.com/hashicorp/terraform/helper/schema"
	"github.ibm.com/riethm/gopherlayer.git/datatypes"
	"github.ibm.com/riethm/gopherlayer.git/filter"
	"github.ibm.com/riethm/gopherlayer.git/services"
	"github.ibm.com/riethm/gopherlayer.git/session"
	"github.ibm.com/riethm/gopherlayer.git/sl"
)

func resourceSoftLayerLocalLoadBalancerService() *schema.Resource {
	return &schema.Resource{
		Create:   resourceSoftLayerLocalLoadBalancerServiceCreate,
		Read:     resourceSoftLayerLocalLoadBalancerServiceRead,
		Update:   resourceSoftLayerLocalLoadBalancerServiceUpdate,
		Delete:   resourceSoftLayerLocalLoadBalancerServiceDelete,
		Exists:   resourceSoftLayerLocalLoadBalancerServiceExists,
		Importer: &schema.ResourceImporter{},

		Schema: map[string]*schema.Schema{
			"service_group_id": &schema.Schema{
				Type:     schema.TypeInt,
				Required: true,
				ForceNew: true,
			},
			"ip_address_id": &schema.Schema{
				Type:     schema.TypeInt,
				Required: true,
			},
			"port": &schema.Schema{
				Type:     schema.TypeInt,
				Required: true,
			},
			"enabled": &schema.Schema{
				Type:     schema.TypeBool,
				Required: true,
			},
			"health_check_type": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
			},
			"weight": &schema.Schema{
				Type:     schema.TypeInt,
				Required: true,
			},
		},
	}
}

func resourceSoftLayerLocalLoadBalancerServiceCreate(d *schema.ResourceData, meta interface{}) error {
	sess := meta.(*session.Session)

	// SoftLayer Local LBs consist of a multi-level hierarchy of types.
	// (virtualIpAddress -> []virtualServer -> []serviceGroup -> []service)

	// Using the service group ID provided in the config, find the IDs of the
	// respective virtualServer and virtualIpAddress
	sgID := d.Get("service_group_id").(int)
	serviceGroup, err := services.GetNetworkApplicationDeliveryControllerLoadBalancerServiceGroupService(sess).
		Id(sgID).
		Mask("id,routingMethodId,routingTypeId,virtualServer[id,allocation,port,virtualIpAddress[id]]").
		GetObject()

	if err != nil {
		return fmt.Errorf("Error retrieving load balancer service group from SoftLayer, %s", err)
	}

	// Store the IDs for later use
	vsID := *serviceGroup.VirtualServer.Id
	vipID := *serviceGroup.VirtualServer.VirtualIpAddress.Id

	// Convert the health check type name to an ID
	healthCheckTypeId, err := getHealthCheckTypeId(sess, d.Get("health_check_type").(string))
	if err != nil {
		return err
	}

	// The API only exposes edit capability at the root of the tree (virtualIpAddress),
	// so need to send the full structure from the root down to the node to be added or
	// modified
	vip := datatypes.Network_Application_Delivery_Controller_LoadBalancer_VirtualIpAddress{

		VirtualServers: []datatypes.Network_Application_Delivery_Controller_LoadBalancer_VirtualServer{{
			Id:         &vsID,
			Allocation: serviceGroup.VirtualServer.Allocation,
			Port:       serviceGroup.VirtualServer.Port,

			ServiceGroups: []datatypes.Network_Application_Delivery_Controller_LoadBalancer_Service_Group{{
				Id:              &sgID,
				RoutingMethodId: serviceGroup.RoutingMethodId,
				RoutingTypeId:   serviceGroup.RoutingTypeId,

				Services: []datatypes.Network_Application_Delivery_Controller_LoadBalancer_Service{{
					Enabled:     sl.Int(1),
					Port:        sl.Int(d.Get("port").(int)),
					IpAddressId: sl.Int(d.Get("ip_address_id").(int)),

					HealthChecks: []datatypes.Network_Application_Delivery_Controller_LoadBalancer_Health_Check{{
						HealthCheckTypeId: &healthCheckTypeId,
					}},

					GroupReferences: []datatypes.Network_Application_Delivery_Controller_LoadBalancer_Service_Group_CrossReference{{
						Weight: sl.Int(d.Get("weight").(int)),
					}},
				}},
			}},
		}},
	}

	log.Printf("[INFO] Creating load balancer service")

	success, err := services.GetNetworkApplicationDeliveryControllerLoadBalancerVirtualIpAddressService(sess).
		Id(vipID).
		EditObject(&vip)

	if err != nil {
		return fmt.Errorf("Error creating load balancer service: %s", err)
	}

	if !success {
		return fmt.Errorf("Error creating load balancer service")
	}

	// Retrieve the newly created object, to obtain its ID
	svcs, err := services.GetNetworkApplicationDeliveryControllerLoadBalancerServiceGroupService(sess).
		Id(sgID).
		Mask("mask[id,port,ipAddressId]").
		Filter(filter.New(
			filter.Path("port").Eq(d.Get("port")),
			filter.Path("ipAddressId").Eq(d.Get("ip_address_id"))).Build()).
		GetServices()

	if err != nil || len(svcs) == 0 {
		return fmt.Errorf("Error retrieving load balancer: %s", err)
	}

	d.SetId(strconv.Itoa(*svcs[0].Id))

	log.Printf("[INFO] Load Balancer Service ID: %s", d.Id())

	return resourceSoftLayerLocalLoadBalancerServiceRead(d, meta)
}

func resourceSoftLayerLocalLoadBalancerServiceUpdate(d *schema.ResourceData, meta interface{}) error {
	sess := meta.(*session.Session)

	// Using the ID stored in the config, find the IDs of the respective
	// serviceGroup, virtualServer and virtualIpAddress
	svcID, _ := strconv.Atoi(d.Id())
	svc, err := services.GetNetworkApplicationDeliveryControllerLoadBalancerServiceService(sess).
		Id(svcID).
		Mask("id,serviceGroup[id,routingTypeId,routingMethodId,virtualServer[id,,allocation,port,virtualIpAddress[id]]]").
		GetObject()

	if err != nil {
		return fmt.Errorf("Error retrieving load balancer service group from SoftLayer, %s", err)
	}

	// Store the IDs for later use
	sgID := *svc.ServiceGroup.Id
	vsID := *svc.ServiceGroup.VirtualServer.Id
	vipID := *svc.ServiceGroup.VirtualServer.VirtualIpAddress.Id

	// Convert the health check type name to an ID
	healthCheckTypeId, err := getHealthCheckTypeId(sess, d.Get("health_check_type").(string))
	if err != nil {
		return err
	}

	// The API only exposes edit capability at the root of the tree (virtualIpAddress),
	// so need to send the full structure from the root down to the node to be added or
	// modified
	vip := datatypes.Network_Application_Delivery_Controller_LoadBalancer_VirtualIpAddress{

		VirtualServers: []datatypes.Network_Application_Delivery_Controller_LoadBalancer_VirtualServer{{
			Id:         &vsID,
			Allocation: svc.ServiceGroup.VirtualServer.Allocation,
			Port:       svc.ServiceGroup.VirtualServer.Port,

			ServiceGroups: []datatypes.Network_Application_Delivery_Controller_LoadBalancer_Service_Group{{
				Id:              &sgID,
				RoutingMethodId: svc.ServiceGroup.RoutingMethodId,
				RoutingTypeId:   svc.ServiceGroup.RoutingTypeId,

				Services: []datatypes.Network_Application_Delivery_Controller_LoadBalancer_Service{{
					Id:          &svcID,
					Enabled:     sl.Int(1),
					Port:        sl.Int(d.Get("port").(int)),
					IpAddressId: sl.Int(d.Get("ip_address_id").(int)),

					HealthChecks: []datatypes.Network_Application_Delivery_Controller_LoadBalancer_Health_Check{{
						HealthCheckTypeId: &healthCheckTypeId,
					}},

					GroupReferences: []datatypes.Network_Application_Delivery_Controller_LoadBalancer_Service_Group_CrossReference{{
						Weight: sl.Int(d.Get("weight").(int)),
					}},
				}},
			}},
		}},
	}

	log.Printf("[INFO] Updating load balancer service")

	success, err := services.GetNetworkApplicationDeliveryControllerLoadBalancerVirtualIpAddressService(sess).
		Id(vipID).
		EditObject(&vip)

	if err != nil {
		return fmt.Errorf("Error updating load balancer service: %s", err)
	}

	if !success {
		return fmt.Errorf("Error updating load balancer service")
	}

	return resourceSoftLayerLocalLoadBalancerServiceRead(d, meta)
}

func resourceSoftLayerLocalLoadBalancerServiceRead(d *schema.ResourceData, meta interface{}) error {
	sess := meta.(*session.Session)

	svcID, _ := strconv.Atoi(d.Id())

	svc, err := services.GetNetworkApplicationDeliveryControllerLoadBalancerServiceService(sess).
		Id(svcID).
		Mask("ipAddressId,port,healthChecks[type[keyname]],groupReferences[weight]").
		GetObject()

	if err != nil {
		return fmt.Errorf("Error retrieving service: %s", err)
	}

	d.Set("ip_address_id", *svc.IpAddressId)
	d.Set("port", *svc.Port)
	d.Set("health_check_type", *svc.HealthChecks[0].Type.Keyname)
	d.Set("weight", *svc.GroupReferences[0].Weight)

	return nil
}

func resourceSoftLayerLocalLoadBalancerServiceDelete(d *schema.ResourceData, meta interface{}) error {
	sess := meta.(*session.Session)

	svcID, _ := strconv.Atoi(d.Id())
	success, err := services.GetNetworkApplicationDeliveryControllerLoadBalancerServiceService(sess).
		Id(svcID).
		DeleteObject()

	if err != nil {
		return fmt.Errorf("Error deleting service group: %s", err)
	}

	if !success {
		return fmt.Errorf("Error deleting service group")
	}

	return nil
}

func resourceSoftLayerLocalLoadBalancerServiceExists(d *schema.ResourceData, meta interface{}) (bool, error) {
	sess := meta.(*session.Session)

	svcID, _ := strconv.Atoi(d.Id())

	_, err := services.GetNetworkApplicationDeliveryControllerLoadBalancerServiceService(sess).
		Id(svcID).
		Mask("id").
		GetObject()

	if err != nil {
		return false, err
	}

	return true, nil
}

func getHealthCheckTypeId(sess *session.Session, healthCheckTypeName string) (int, error) {
	healthCheckTypes, err := services.GetNetworkApplicationDeliveryControllerLoadBalancerHealthCheckTypeService(sess).
		Mask("id").
		Filter(filter.Build(
			filter.Path("keyname").Eq(healthCheckTypeName))).
		Limit(1).
		GetAllObjects()

	if err != nil {
		return -1, err
	}

	if len(healthCheckTypes) < 1 {
		return -1, fmt.Errorf("Invalid health check type: %s", healthCheckTypeName)
	}

	return *healthCheckTypes[0].Id, nil
}
<|endoftext|>


<commit_before><commit_msg>Specify seq command can reverse complement (#307)<commit_after><|endoftext|>


<commit_before>package installation_test

import (
	"errors"

	. "github.com/cloudfoundry/bosh-init/installation"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	"code.google.com/p/gomock/gomock"
	"github.com/cloudfoundry/bosh-init/installation/blobextract/fakeblobextract"
	mock_install "github.com/cloudfoundry/bosh-init/installation/mocks"
	mock_registry "github.com/cloudfoundry/bosh-init/registry/mocks"

	biinstallmanifest "github.com/cloudfoundry/bosh-init/installation/manifest"
	bireljob "github.com/cloudfoundry/bosh-init/release/job"
	boshlog "github.com/cloudfoundry/bosh-utils/logger"
	biproperty "github.com/cloudfoundry/bosh-utils/property"

	fakebiui "github.com/cloudfoundry/bosh-init/ui/fakes"
)

var _ = Describe("Installer", func() {
	var mockCtrl *gomock.Controller

	BeforeEach(func() {
		mockCtrl = gomock.NewController(GinkgoT())
	})

	AfterEach(func() {
		mockCtrl.Finish()
	})

	var (
		installationManifest      biinstallmanifest.Manifest
		mockJobRenderer           *mock_install.MockJobRenderer
		mockJobResolver           *mock_install.MockJobResolver
		mockPackageCompiler       *mock_install.MockPackageCompiler
		fakeExtractor             *fakeblobextract.FakeExtractor
		mockRegistryServerManager *mock_registry.MockServerManager

		logger boshlog.Logger

		packagesPath string
		installer    Installer
		target       Target
		installedJob InstalledJob
	)

	BeforeEach(func() {
		logger = boshlog.NewWriterLogger(boshlog.LevelDebug, GinkgoWriter, GinkgoWriter)

		mockJobRenderer = mock_install.NewMockJobRenderer(mockCtrl)
		mockJobResolver = mock_install.NewMockJobResolver(mockCtrl)
		mockPackageCompiler = mock_install.NewMockPackageCompiler(mockCtrl)
		fakeExtractor = &fakeblobextract.FakeExtractor{}
		mockRegistryServerManager = mock_registry.NewMockServerManager(mockCtrl)

		packagesPath = "/path/to/installed/packages"
		target = NewTarget("fake-installation-path")
		installationManifest = biinstallmanifest.Manifest{
			Name:       "fake-installation-name",
			Properties: biproperty.Map{},
		}
		renderedCPIJob := NewRenderedJobRef("cpi", "fake-release-job-fingerprint", "fake-rendered-job-blobstore-id", "fake-rendered-job-blobstore-id")
		installedJob = NewInstalledJob(renderedCPIJob, "/extracted-release-path/cpi")
	})

	JustBeforeEach(func() {
		installer = NewInstaller(
			target,
			mockJobRenderer,
			mockJobResolver,
			mockPackageCompiler,
			packagesPath,
			fakeExtractor,
			mockRegistryServerManager,
			logger,
		)
	})

	Describe("Install", func() {
		var (
			fakeStage *fakebiui.FakeStage

			expectedResolveJobsFrom     *gomock.Call
			expectedPackageCompilerFrom *gomock.Call
			expectedRenderAndUploadFrom *gomock.Call
		)

		BeforeEach(func() {
			fakeStage = fakebiui.NewFakeStage()
		})

		JustBeforeEach(func() {
			ref := CompiledPackageRef{
				Name:        "fake-release-package-name",
				Version:     "fake-release-package-fingerprint",
				BlobstoreID: "fake-compiled-package-blobstore-id",
				SHA1:        "fake-compiled-package-blobstore-id",
			}
			compiledPackages := []CompiledPackageRef{ref}

			releaseJobs := []bireljob.Job{}
			renderedJobRefs := []RenderedJobRef{installedJob.RenderedJobRef}
			expectedResolveJobsFrom = mockJobResolver.EXPECT().From(installationManifest).Return(releaseJobs, nil).AnyTimes()
			expectedPackageCompilerFrom = mockPackageCompiler.EXPECT().For(releaseJobs, fakeStage).Return(compiledPackages, nil).AnyTimes()
			expectedRenderAndUploadFrom = mockJobRenderer.EXPECT().RenderAndUploadFrom(installationManifest, releaseJobs, fakeStage).Return(renderedJobRefs, nil).AnyTimes()
		})

		It("compiles and installs the jobs' packages", func() {
			_, err := installer.Install(installationManifest, fakeStage)
			Expect(err).NotTo(HaveOccurred())
		})

		It("installs the rendered jobs", func() {
			_, err := installer.Install(installationManifest, fakeStage)
			Expect(err).NotTo(HaveOccurred())
		})

		It("returns the installation", func() {
			installation, err := installer.Install(installationManifest, fakeStage)
			Expect(err).NotTo(HaveOccurred())
			Expect(installation.Target().JobsPath()).To(Equal(target.JobsPath()))
		})
	})

	Describe("Cleanup", func() {
		var installation Installation

		BeforeEach(func() {
			installation = NewInstallation(
				target,
				installedJob,
				installationManifest,
				mockRegistryServerManager,
			)
		})

		It("cleans up installed jobs", func() {
			err := installer.Cleanup(installation)
			Expect(err).ToNot(HaveOccurred())

			Expect(fakeExtractor.CleanupCallCount()).To(Equal(1))

			blobstoreID := fakeExtractor.CleanupArgsForCall(0)
			Expect(blobstoreID).To(Equal(installedJob.BlobstoreID))
		})

		It("returns errors when cleaning up installed jobs", func() {
			fakeExtractor.CleanupReturns(errors.New("nope"))

			err := installer.Cleanup(installation)
			Expect(err).To(HaveOccurred())
			Expect(err.Error()).To(ContainSubstring("nope"))
		})
	})
})
<commit_msg>Clean up of extracted temp blob files, part 2<commit_after>package installation_test

import (
	"errors"

	. "github.com/cloudfoundry/bosh-init/installation"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	"code.google.com/p/gomock/gomock"
	"github.com/cloudfoundry/bosh-init/installation/blobextract/fakeblobextract"
	mock_install "github.com/cloudfoundry/bosh-init/installation/mocks"
	mock_registry "github.com/cloudfoundry/bosh-init/registry/mocks"

	biinstallmanifest "github.com/cloudfoundry/bosh-init/installation/manifest"
	bireljob "github.com/cloudfoundry/bosh-init/release/job"
	boshlog "github.com/cloudfoundry/bosh-utils/logger"
	biproperty "github.com/cloudfoundry/bosh-utils/property"

	fakebiui "github.com/cloudfoundry/bosh-init/ui/fakes"
)

var _ = Describe("Installer", func() {
	var mockCtrl *gomock.Controller

	BeforeEach(func() {
		mockCtrl = gomock.NewController(GinkgoT())
	})

	AfterEach(func() {
		mockCtrl.Finish()
	})

	var (
		installationManifest      biinstallmanifest.Manifest
		mockJobRenderer           *mock_install.MockJobRenderer
		mockJobResolver           *mock_install.MockJobResolver
		mockPackageCompiler       *mock_install.MockPackageCompiler
		fakeExtractor             *fakeblobextract.FakeExtractor
		mockRegistryServerManager *mock_registry.MockServerManager

		logger boshlog.Logger

		packagesPath string
		installer    Installer
		target       Target
		installedJob InstalledJob
	)

	BeforeEach(func() {
		logger = boshlog.NewWriterLogger(boshlog.LevelDebug, GinkgoWriter, GinkgoWriter)

		mockJobRenderer = mock_install.NewMockJobRenderer(mockCtrl)
		mockJobResolver = mock_install.NewMockJobResolver(mockCtrl)
		mockPackageCompiler = mock_install.NewMockPackageCompiler(mockCtrl)
		fakeExtractor = &fakeblobextract.FakeExtractor{}
		mockRegistryServerManager = mock_registry.NewMockServerManager(mockCtrl)

		packagesPath = "/path/to/installed/packages"
		target = NewTarget("fake-installation-path")
		installationManifest = biinstallmanifest.Manifest{
			Name:       "fake-installation-name",
			Properties: biproperty.Map{},
		}
		renderedCPIJob := NewRenderedJobRef("cpi", "fake-release-job-fingerprint", "fake-rendered-job-blobstore-id", "fake-rendered-job-blobstore-id")
		installedJob = NewInstalledJob(renderedCPIJob, "/extracted-release-path/cpi")
	})

	JustBeforeEach(func() {
		installer = NewInstaller(
			target,
			mockJobRenderer,
			mockJobResolver,
			mockPackageCompiler,
			packagesPath,
			fakeExtractor,
			mockRegistryServerManager,
			logger,
		)
	})

	Describe("Install", func() {
		var (
			fakeStage *fakebiui.FakeStage

			expectedResolveJobsFrom     *gomock.Call
			expectedPackageCompilerFrom *gomock.Call
			expectedRenderAndUploadFrom *gomock.Call
		)

		BeforeEach(func() {
			fakeStage = fakebiui.NewFakeStage()
		})

		JustBeforeEach(func() {
			ref := CompiledPackageRef{
				Name:        "fake-release-package-name",
				Version:     "fake-release-package-fingerprint",
				BlobstoreID: "fake-compiled-package-blobstore-id",
				SHA1:        "fake-compiled-package-blobstore-id",
			}
			compiledPackages := []CompiledPackageRef{ref}

			releaseJobs := []bireljob.Job{}
			renderedJobRefs := []RenderedJobRef{installedJob.RenderedJobRef}
			expectedResolveJobsFrom = mockJobResolver.EXPECT().From(installationManifest).Return(releaseJobs, nil).AnyTimes()
			expectedPackageCompilerFrom = mockPackageCompiler.EXPECT().For(releaseJobs, fakeStage).Return(compiledPackages, nil).AnyTimes()
			expectedRenderAndUploadFrom = mockJobRenderer.EXPECT().RenderAndUploadFrom(installationManifest, releaseJobs, fakeStage).Return(renderedJobRefs, nil).AnyTimes()
		})

		It("compiles and installs the jobs' packages", func() {
			_, err := installer.Install(installationManifest, fakeStage)
			Expect(err).NotTo(HaveOccurred())
		})

		It("installs the rendered jobs", func() {
			_, err := installer.Install(installationManifest, fakeStage)
			Expect(err).NotTo(HaveOccurred())
		})

		It("returns the installation", func() {
			installation, err := installer.Install(installationManifest, fakeStage)
			Expect(err).NotTo(HaveOccurred())
			Expect(installation.Target().JobsPath()).To(Equal(target.JobsPath()))
		})
	})

	Describe("Cleanup", func() {
		var installation Installation

		BeforeEach(func() {
			installation = NewInstallation(
				target,
				installedJob,
				installationManifest,
				mockRegistryServerManager,
			)
		})

		It("cleans up installed jobs", func() {
			err := installer.Cleanup(installation)
			Expect(err).ToNot(HaveOccurred())

			Expect(fakeExtractor.CleanupCallCount()).To(Equal(1))

			blobstoreID, extractedBlobPath := fakeExtractor.CleanupArgsForCall(0)
			Expect(blobstoreID).To(Equal(installedJob.BlobstoreID))
			Expect(extractedBlobPath).To(Equal(installedJob.Path))
		})

		It("returns errors when cleaning up installed jobs", func() {
			fakeExtractor.CleanupReturns(errors.New("nope"))

			err := installer.Cleanup(installation)
			Expect(err).To(HaveOccurred())
			Expect(err.Error()).To(ContainSubstring("nope"))
		})
	})
})
<|endoftext|>


<commit_before>// +build integration

package integration

import (
	"bytes"
	"fmt"
	"os/exec"

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

var _ = Describe("completion", func() {
	var shellArg string
	var env []string
	var output string

	JustBeforeEach(func() {
		outbuf := bytes.Buffer{}

		args := []string{"completion"}
		if shellArg != "" {
			args = append(args, "--shell", shellArg)
		}
		fmt.Fprintf(GinkgoWriter, "Running %q %q\n", *kubecfgBin, args)
		cmd := exec.Command(*kubecfgBin, args...)
		cmd.Env = env
		cmd.Stdout = &outbuf
		cmd.Stderr = GinkgoWriter

		err := cmd.Run()
		Expect(err).NotTo(HaveOccurred())

		output = outbuf.String()
	})

	Context("With --shell=bash", func() {
		BeforeEach(func() {
			shellArg = "bash"
			env = []string{}
		})
		It("should produce bash completion", func() {
			Expect(output).To(MatchRegexp("complete .* kubecfg"))
		})
	})

	Context("With --shell=zsh", func() {
		BeforeEach(func() {
			shellArg = "zsh"
			env = []string{}
		})
		It("should produce zsh completion", func() {
			Expect(output).To(HavePrefix("#compdef kubecfg"))
		})
	})

	Context("With SHELL=/bin/bash4", func() {
		BeforeEach(func() {
			shellArg = ""
			env = append(env, "SHELL=/bin/bash4")
		})
		It("should produce bash completion", func() {
			Expect(output).To(MatchRegexp("complete .* kubecfg"))
		})
	})
})
<commit_msg>fix completion_test for zsh<commit_after>// +build integration

package integration

import (
	"bytes"
	"fmt"
	"os/exec"

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

var _ = Describe("completion", func() {
	var shellArg string
	var env []string
	var output string

	JustBeforeEach(func() {
		outbuf := bytes.Buffer{}

		args := []string{"completion"}
		if shellArg != "" {
			args = append(args, "--shell", shellArg)
		}
		fmt.Fprintf(GinkgoWriter, "Running %q %q\n", *kubecfgBin, args)
		cmd := exec.Command(*kubecfgBin, args...)
		cmd.Env = env
		cmd.Stdout = &outbuf
		cmd.Stderr = GinkgoWriter

		err := cmd.Run()
		Expect(err).NotTo(HaveOccurred())

		output = outbuf.String()
	})

	Context("With --shell=bash", func() {
		BeforeEach(func() {
			shellArg = "bash"
			env = []string{}
		})
		It("should produce bash completion", func() {
			Expect(output).To(MatchRegexp("complete .* kubecfg"))
		})
	})

	Context("With --shell=zsh", func() {
		BeforeEach(func() {
			shellArg = "zsh"
			env = []string{}
		})
		It("should produce zsh completion", func() {
			Expect(output).To(HavePrefix("#compdef _kubecfg kubecfg"))
		})
	})

	Context("With SHELL=/bin/bash4", func() {
		BeforeEach(func() {
			shellArg = ""
			env = append(env, "SHELL=/bin/bash4")
		})
		It("should produce bash completion", func() {
			Expect(output).To(MatchRegexp("complete .* kubecfg"))
		})
	})
})
<|endoftext|>


<commit_before>// Copyright © 2017 Circonus, Inc. <support@circonus.com>
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//

package server

import (
	"bytes"
	"context"
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/circonus-labs/circonus-agent/internal/config"
	"github.com/circonus-labs/circonus-agent/internal/plugins"
	"github.com/rs/zerolog"
	"github.com/spf13/viper"
)

func TestRouter(t *testing.T) {
	t.Log("Testing router")

	zerolog.SetGlobalLevel(zerolog.Disabled)

	{
		methods := []string{
			"CONNECT",
			"DELETE",
			"HEAD",
			"OPTIONS",
			"TRACE",
		}
		for _, method := range methods {
			t.Logf("Method not allowed (%s)", method)
			req := httptest.NewRequest(method, "/", nil)
			w := httptest.NewRecorder()

			s, _ := New(nil, nil)
			s.router(w, req)

			resp := w.Result()

			if resp.StatusCode != http.StatusMethodNotAllowed {
				t.Fatalf("expected %d, got %d", http.StatusMethodNotAllowed, resp.StatusCode)
			}
		}
	}

	{
		viper.Set(config.KeyPluginDir, "testdata/")
		p := plugins.New(context.Background())
		reqtests := []struct {
			method string
			path   string
		}{
			{"GET", "/invalid"},
			{"GET", "/run/invalid"},
			{"GET", "/inventory/invalid"},
			{"POST", "/invalid"},
			{"PUT", "/invalid"},
			{"PUT", "/write/"}, // /write/ must be followed by an id/name to use as "plugin namespace"
		}
		s, _ := New(p, nil)
		for _, reqtest := range reqtests {
			t.Logf("Invalid path (%s %s)", reqtest.method, reqtest.path)
			req := httptest.NewRequest(reqtest.method, reqtest.path, nil)
			w := httptest.NewRecorder()

			s.router(w, req)

			resp := w.Result()

			if resp.StatusCode != http.StatusNotFound {
				t.Fatalf("expected %d, got %d", http.StatusNotFound, resp.StatusCode)
			}
		}
	}

	{
		viper.Set(config.KeyStatsdDisabled, true)
		viper.Set(config.KeyPluginDir, "testdata/")
		p := plugins.New(context.Background())
		s, _ := New(p, nil)
		reqtests := []struct {
			method string
			path   string
			code   int
		}{
			{"GET", "/", http.StatusOK},
			{"GET", "/run", http.StatusOK},
			{"GET", "/run/", http.StatusOK},
			{"GET", "/inventory", http.StatusOK},
			{"GET", "/inventory/", http.StatusOK},
			{"GET", "/stats", http.StatusOK},
			{"GET", "/stats/", http.StatusOK},
			{"GET", "/prom", http.StatusNoContent},
			{"GET", "/prom/", http.StatusNoContent},
		}
		for _, reqtest := range reqtests {
			t.Logf("OK path (%s %s)", reqtest.method, reqtest.path)
			req := httptest.NewRequest(reqtest.method, reqtest.path, nil)
			w := httptest.NewRecorder()

			s.router(w, req)

			resp := w.Result()

			if resp.StatusCode != reqtest.code {
				t.Fatalf("expected %d, got %d", reqtest.code, resp.StatusCode)
			}
		}
	}

	t.Log("Invalid (PUT /write/foo) w/o data")
	{
		viper.Set(config.KeyStatsdDisabled, true)
		viper.Set(config.KeyPluginDir, "testdata/")
		p := plugins.New(context.Background())
		s, _ := New(p, nil)

		req := httptest.NewRequest("PUT", "/write/foo", nil)
		w := httptest.NewRecorder()

		s.router(w, req)

		resp := w.Result()

		if resp.StatusCode != http.StatusBadRequest {
			t.Fatalf("expected %d, got %d", http.StatusBadRequest, resp.StatusCode)
		}
	}

	t.Log("OK (PUT /write/foo) w/data")
	{

		s, _ := New(nil, nil)

		reqBody := bytes.NewReader([]byte(`{"test":{"_type":"i", "_value":1}}`))

		req := httptest.NewRequest("PUT", "/write/foo", reqBody)
		w := httptest.NewRecorder()

		s.router(w, req)

		resp := w.Result()

		if resp.StatusCode != http.StatusNoContent {
			t.Fatalf("expected %d, got %d", http.StatusNoContent, resp.StatusCode)
		}
	}
}
<commit_msg>cleanup<commit_after>// Copyright © 2017 Circonus, Inc. <support@circonus.com>
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//

package server

import (
	"bytes"
	"context"
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/circonus-labs/circonus-agent/internal/config"
	"github.com/circonus-labs/circonus-agent/internal/plugins"
	"github.com/rs/zerolog"
	"github.com/spf13/viper"
)

func TestRouter(t *testing.T) {
	t.Log("Testing router")
	viper.Reset()
	zerolog.SetGlobalLevel(zerolog.Disabled)

	t.Log("bad methods")
	{
		methods := []string{
			"CONNECT",
			"DELETE",
			"HEAD",
			"OPTIONS",
			"TRACE",
		}
		s, _ := New(nil, nil)
		for _, method := range methods {
			t.Logf("Method not allowed (%s)", method)
			req := httptest.NewRequest(method, "/", nil)
			w := httptest.NewRecorder()
			s.router(w, req)
			resp := w.Result()
			if resp.StatusCode != http.StatusMethodNotAllowed {
				t.Fatalf("expected %d, got %d", http.StatusMethodNotAllowed, resp.StatusCode)
			}
		}
		viper.Reset()
	}

	t.Log("invalid paths")
	{
		viper.Reset()
		viper.Set(config.KeyPluginDir, "testdata/")
		p := plugins.New(context.Background())
		reqtests := []struct {
			method string
			path   string
		}{
			{"GET", "/invalid"},
			{"GET", "/run/invalid"},
			{"GET", "/inventory/invalid"},
			{"POST", "/invalid"},
			{"PUT", "/invalid"},
			{"PUT", "/write/"}, // /write/ must be followed by an id/name to use as "plugin namespace"
		}
		s, _ := New(p, nil)
		for _, reqtest := range reqtests {
			t.Logf("Invalid path (%s %s)", reqtest.method, reqtest.path)
			req := httptest.NewRequest(reqtest.method, reqtest.path, nil)
			w := httptest.NewRecorder()
			s.router(w, req)
			resp := w.Result()
			if resp.StatusCode != http.StatusNotFound {
				t.Fatalf("expected %d, got %d", http.StatusNotFound, resp.StatusCode)
			}
		}
		viper.Reset()
	}

	t.Log("valid")
	{
		viper.Set(config.KeyStatsdDisabled, true)
		viper.Set(config.KeyPluginDir, "testdata/")
		p := plugins.New(context.Background())
		s, _ := New(p, nil)
		reqtests := []struct {
			method string
			path   string
			code   int
		}{
			{"GET", "/", http.StatusOK},
			{"GET", "/run", http.StatusOK},
			{"GET", "/run/", http.StatusOK},
			{"GET", "/inventory", http.StatusOK},
			{"GET", "/inventory/", http.StatusOK},
			{"GET", "/stats", http.StatusOK},
			{"GET", "/stats/", http.StatusOK},
			{"GET", "/prom", http.StatusNoContent},
			{"GET", "/prom/", http.StatusNoContent},
		}
		for _, reqtest := range reqtests {
			t.Logf("OK path (%s %s)", reqtest.method, reqtest.path)
			req := httptest.NewRequest(reqtest.method, reqtest.path, nil)
			w := httptest.NewRecorder()
			s.router(w, req)
			resp := w.Result()
			if resp.StatusCode != reqtest.code {
				t.Fatalf("expected %d, got %d", reqtest.code, resp.StatusCode)
			}
		}
		viper.Reset()
	}

	t.Log("invalid (PUT /write/foo) w/o data")
	{
		viper.Set(config.KeyStatsdDisabled, true)
		viper.Set(config.KeyPluginDir, "testdata/")
		p := plugins.New(context.Background())
		s, _ := New(p, nil)
		req := httptest.NewRequest("PUT", "/write/foo", nil)
		w := httptest.NewRecorder()
		s.router(w, req)
		resp := w.Result()
		if resp.StatusCode != http.StatusBadRequest {
			t.Fatalf("expected %d, got %d", http.StatusBadRequest, resp.StatusCode)
		}
		viper.Reset()
	}

	t.Log("OK (PUT /write/foo) w/data")
	{
		s, _ := New(nil, nil)
		reqBody := bytes.NewReader([]byte(`{"test":{"_type":"i", "_value":1}}`))
		req := httptest.NewRequest("PUT", "/write/foo", reqBody)
		w := httptest.NewRecorder()
		s.router(w, req)
		resp := w.Result()
		if resp.StatusCode != http.StatusNoContent {
			t.Fatalf("expected %d, got %d", http.StatusNoContent, resp.StatusCode)
		}
	}
}
<|endoftext|>


<commit_before>package tokenizer

import (
	"bytes"
	"regexp"
)

const byteLimit = 100000

func Tokenize(content []byte) []string {
	if len(content) > byteLimit {
		content = content[:byteLimit]
	}

	tokens := make([][]byte, 0, 50)
	for _, extract := range extractTokens {
		var extractedTokens [][]byte
		content, extractedTokens = extract(content)
		tokens = append(tokens, extractedTokens...)
	}

	return toString(tokens)
}

func toString(tokens [][]byte) []string {
	stokens := make([]string, 0, len(tokens))
	for _, token := range tokens {
		stokens = append(stokens, string(token))
	}

	return stokens
}

var (
	extractTokens = []func(content []byte) (replacedContent []byte, tokens [][]byte){
		// The order to must be this
		extractAndReplaceShebang,
		extractAndReplaceSGML,
		skipCommentsAndLiterals,
		extractAndReplacePunctuation,
		extractAndReplaceRegular,
		extractAndReplaceOperator,
		extractRemainders,
	}

	reLiteralStringQuotes = regexp.MustCompile(`(?sU)(".*"|'.*')`)
	reSingleLineComment   = regexp.MustCompile(`(?m)(//|--|#|%|")\s(.*$)`)
	reMultilineComment    = regexp.MustCompile(`(?sU)(/\*.*\*/|<!--.*-->|\{-.*-\}|\(\*.*\*\)|""".*"""|'''.*''')`)
	reLiteralNumber       = regexp.MustCompile(`(0x[0-9A-Fa-f]([0-9A-Fa-f]|\.)*|\d(\d|\.)*)([uU][lL]{0,2}|([eE][-+]\d*)?[fFlL]*)`)
	reShebang             = regexp.MustCompile(`(?m)^#!(?:/\w+)*/(?:(\w+)|\w+(?:\s*\w+=\w+\s*)*\s*(\w+))(?:\s*-\w+\s*)*$`)
	rePunctuation         = regexp.MustCompile(`;|\{|\}|\(|\)|\[|\]`)
	reSGML                = regexp.MustCompile(`(?sU)(<\/?[^\s<>=\d"']+)(?:\s.*\/?>|>)`)
	reSGMLComment         = regexp.MustCompile(`(?sU)(<!--.*-->)`)
	reSGMLAttributes      = regexp.MustCompile(`\s+(\w+=)|\s+([^\s>]+)`)
	reSGMLLoneAttribute   = regexp.MustCompile(`(\w+)`)
	reRegularToken        = regexp.MustCompile(`[\w\.@#\/\*]+`)
	reOperators           = regexp.MustCompile(`<<?|\+|\-|\*|\/|%|&&?|\|\|?`)

	regexToSkip = []*regexp.Regexp{
		// The order must be this
		reLiteralStringQuotes,
		reMultilineComment,
		reSingleLineComment,
		reLiteralNumber,
	}
)

func extractAndReplaceShebang(content []byte) ([]byte, [][]byte) {
	var shebangTokens [][]byte
	matches := reShebang.FindAllSubmatch(content, -1)
	if matches != nil {
		shebangTokens = make([][]byte, 0, 2)
		for _, match := range matches {
			shebangToken := getShebangToken(match)
			shebangTokens = append(shebangTokens, shebangToken)
		}

		reShebang.ReplaceAll(content, []byte(` `))
	}

	return content, shebangTokens
}

func getShebangToken(matchedShebang [][]byte) []byte {
	const prefix = `SHEBANG#!`
	var token []byte
	for i := 1; i < len(matchedShebang); i++ {
		if len(matchedShebang[i]) > 0 {
			token = matchedShebang[i]
			break
		}
	}

	tokenShebang := append([]byte(prefix), token...)
	return tokenShebang
}

func commonExtracAndReplace(content []byte, re *regexp.Regexp) ([]byte, [][]byte) {
	tokens := re.FindAll(content, -1)
	content = re.ReplaceAll(content, []byte(` `))
	return content, tokens
}

func extractAndReplacePunctuation(content []byte) ([]byte, [][]byte) {
	return commonExtracAndReplace(content, rePunctuation)
}

func extractAndReplaceRegular(content []byte) ([]byte, [][]byte) {
	return commonExtracAndReplace(content, reRegularToken)
}

func extractAndReplaceOperator(content []byte) ([]byte, [][]byte) {
	return commonExtracAndReplace(content, reOperators)
}

func extractAndReplaceSGML(content []byte) ([]byte, [][]byte) {
	var SGMLTokens [][]byte
	matches := reSGML.FindAllSubmatch(content, -1)
	if matches != nil {
		SGMLTokens = make([][]byte, 0, 2)
		for _, match := range matches {
			if reSGMLComment.Match(match[0]) {
				continue
			}

			token := append(match[1], '>')
			SGMLTokens = append(SGMLTokens, token)
			attributes := getSGMLAttributes(match[0])
			SGMLTokens = append(SGMLTokens, attributes...)
		}

		content = reSGML.ReplaceAll(content, []byte(` `))
	}

	return content, SGMLTokens
}

func getSGMLAttributes(SGMLTag []byte) [][]byte {
	var attributes [][]byte
	matches := reSGMLAttributes.FindAllSubmatch(SGMLTag, -1)
	if matches != nil {
		attributes = make([][]byte, 0, 5)
		for _, match := range matches {
			if len(match[1]) != 0 {
				attributes = append(attributes, match[1])
			}

			if len(match[2]) != 0 {
				loneAttributes := reSGMLLoneAttribute.FindAll(match[2], -1)
				attributes = append(attributes, loneAttributes...)
			}
		}
	}

	return attributes
}

func skipCommentsAndLiterals(content []byte) ([]byte, [][]byte) {
	for _, skip := range regexToSkip {
		content = skip.ReplaceAll(content, []byte(` `))
	}

	return content, nil
}

func extractRemainders(content []byte) ([]byte, [][]byte) {
	splitted := bytes.Fields(content)
	remainderTokens := make([][]byte, 0, len(splitted)*3)
	for _, remainder := range splitted {
		remainders := bytes.Split(remainder, nil)
		remainderTokens = append(remainderTokens, remainders...)
	}

	return content, remainderTokens
}
<commit_msg>Make tokenizer regexps work under rubex<commit_after>package tokenizer

import (
	"bytes"
	"regexp"
)

const byteLimit = 100000

func Tokenize(content []byte) []string {
	if len(content) > byteLimit {
		content = content[:byteLimit]
	}

	tokens := make([][]byte, 0, 50)
	for _, extract := range extractTokens {
		var extractedTokens [][]byte
		content, extractedTokens = extract(content)
		tokens = append(tokens, extractedTokens...)
	}

	return toString(tokens)
}

func toString(tokens [][]byte) []string {
	stokens := make([]string, 0, len(tokens))
	for _, token := range tokens {
		stokens = append(stokens, string(token))
	}

	return stokens
}

var (
	extractTokens = []func(content []byte) (replacedContent []byte, tokens [][]byte){
		// The order to must be this
		extractAndReplaceShebang,
		extractAndReplaceSGML,
		skipCommentsAndLiterals,
		extractAndReplacePunctuation,
		extractAndReplaceRegular,
		extractAndReplaceOperator,
		extractRemainders,
	}

	// Differences between golang regexp and onigumura:
	// 1. no (?s) in onigumura - makes dot match \n
	// 2. no (?U) in onigumura - ungreedy *
	// 3. (?m) implies dot matches \n in onigumura
	// 4. onigumura handles \w differently - impossible, but true
	//
	// Workarounds:
	// 1. (.|\n)
	// 2. replace * with *?
	// 3. replace . with [^\n]
	// 4. replace \w with [0-9A-Za-z_]
	//
	// Original golang regexps:
	//
	// reLiteralStringQuotes = regexp.MustCompile(`(?sU)(".*"|'.*')`)
	// reSingleLineComment   = regexp.MustCompile(`(?m)(//|--|#|%|")\s(.*$)`)
	// reMultilineComment    = regexp.MustCompile(`(?sU)(/\*.*\*/|<!--.*-->|\{-.*-\}|\(\*.*\*\)|""".*"""|'''.*''')`)
	// reLiteralNumber       = regexp.MustCompile(`(0x[0-9A-Fa-f]([0-9A-Fa-f]|\.)*|\d(\d|\.)*)([uU][lL]{0,2}|([eE][-+]\d*)?[fFlL]*)`)
	// reShebang             = regexp.MustCompile(`(?m)^#!(?:/\w+)*/(?:(\w+)|\w+(?:\s*\w+=\w+\s*)*\s*(\w+))(?:\s*-\w+\s*)*$`)
	// rePunctuation         = regexp.MustCompile(`;|\{|\}|\(|\)|\[|\]`)
	// reSGML                = regexp.MustCompile(`(?sU)(<\/?[^\s<>=\d"']+)(?:\s.*\/?>|>)`)
	// reSGMLComment         = regexp.MustCompile(`(?sU)(<!--.*-->)`)
	// reSGMLAttributes      = regexp.MustCompile(`\s+(\w+=)|\s+([^\s>]+)`)
	// reSGMLLoneAttribute   = regexp.MustCompile(`(\w+)`)
	// reRegularToken        = regexp.MustCompile(`[\w\.@#\/\*]+`)
	// reOperators           = regexp.MustCompile(`<<?|\+|\-|\*|\/|%|&&?|\|\|?`)
	//
	// These regexps were converted to work in the same way for both engines:
	//
	reLiteralStringQuotes = regexp.MustCompile(`("(.|\n)*?"|'(.|\n)*?')`)
	reSingleLineComment   = regexp.MustCompile(`(?m)(//|--|#|%|")\s([^\n]*$)`)
	reMultilineComment    = regexp.MustCompile(`(/\*(.|\n)*?\*/|<!--(.|\n)*?-->|\{-(.|\n)*?-\}|\(\*(.|\n)*?\*\)|"""(.|\n)*?"""|'''(.|\n)*?''')`)
	reLiteralNumber       = regexp.MustCompile(`(0x[0-9A-Fa-f]([0-9A-Fa-f]|\.)*|\d(\d|\.)*)([uU][lL]{0,2}|([eE][-+]\d*)?[fFlL]*)`)
	reShebang             = regexp.MustCompile(`(?m)^#!(?:/[0-9A-Za-z_]+)*/(?:([0-9A-Za-z_]+)|[0-9A-Za-z_]+(?:\s*[0-9A-Za-z_]+=[0-9A-Za-z_]+\s*)*\s*([0-9A-Za-z_]+))(?:\s*-[0-9A-Za-z_]+\s*)*$`)
	rePunctuation         = regexp.MustCompile(`;|\{|\}|\(|\)|\[|\]`)
	reSGML                = regexp.MustCompile(`(<\/?[^\s<>=\d"']+)(?:\s(.|\n)*?\/?>|>)`)
	reSGMLComment         = regexp.MustCompile(`(<!--(.|\n)*?-->)`)
	reSGMLAttributes      = regexp.MustCompile(`\s+([0-9A-Za-z_]+=)|\s+([^\s>]+)`)
	reSGMLLoneAttribute   = regexp.MustCompile(`([0-9A-Za-z_]+)`)
	reRegularToken        = regexp.MustCompile(`[0-9A-Za-z_\.@#\/\*]+`)
	reOperators           = regexp.MustCompile(`<<?|\+|\-|\*|\/|%|&&?|\|\|?`)

	regexToSkip = []*regexp.Regexp{
		// The order must be this
		reLiteralStringQuotes,
		reMultilineComment,
		reSingleLineComment,
		reLiteralNumber,
	}
)

func extractAndReplaceShebang(content []byte) ([]byte, [][]byte) {
	var shebangTokens [][]byte
	matches := reShebang.FindAllSubmatch(content, -1)
	if matches != nil {
		shebangTokens = make([][]byte, 0, 2)
		for _, match := range matches {
			shebangToken := getShebangToken(match)
			shebangTokens = append(shebangTokens, shebangToken)
		}

		reShebang.ReplaceAll(content, []byte(` `))
	}

	return content, shebangTokens
}

func getShebangToken(matchedShebang [][]byte) []byte {
	const prefix = `SHEBANG#!`
	var token []byte
	for i := 1; i < len(matchedShebang); i++ {
		if len(matchedShebang[i]) > 0 {
			token = matchedShebang[i]
			break
		}
	}

	tokenShebang := append([]byte(prefix), token...)
	return tokenShebang
}

func commonExtracAndReplace(content []byte, re *regexp.Regexp) ([]byte, [][]byte) {
	tokens := re.FindAll(content, -1)
	content = re.ReplaceAll(content, []byte(` `))
	return content, tokens
}

func extractAndReplacePunctuation(content []byte) ([]byte, [][]byte) {
	return commonExtracAndReplace(content, rePunctuation)
}

func extractAndReplaceRegular(content []byte) ([]byte, [][]byte) {
	return commonExtracAndReplace(content, reRegularToken)
}

func extractAndReplaceOperator(content []byte) ([]byte, [][]byte) {
	return commonExtracAndReplace(content, reOperators)
}

func extractAndReplaceSGML(content []byte) ([]byte, [][]byte) {
	var SGMLTokens [][]byte
	matches := reSGML.FindAllSubmatch(content, -1)
	if matches != nil {
		SGMLTokens = make([][]byte, 0, 2)
		for _, match := range matches {
			if reSGMLComment.Match(match[0]) {
				continue
			}

			token := append(match[1], '>')
			SGMLTokens = append(SGMLTokens, token)
			attributes := getSGMLAttributes(match[0])
			SGMLTokens = append(SGMLTokens, attributes...)
		}

		content = reSGML.ReplaceAll(content, []byte(` `))
	}

	return content, SGMLTokens
}

func getSGMLAttributes(SGMLTag []byte) [][]byte {
	var attributes [][]byte
	matches := reSGMLAttributes.FindAllSubmatch(SGMLTag, -1)
	if matches != nil {
		attributes = make([][]byte, 0, 5)
		for _, match := range matches {
			if len(match[1]) != 0 {
				attributes = append(attributes, match[1])
			}

			if len(match[2]) != 0 {
				loneAttributes := reSGMLLoneAttribute.FindAll(match[2], -1)
				attributes = append(attributes, loneAttributes...)
			}
		}
	}

	return attributes
}

func skipCommentsAndLiterals(content []byte) ([]byte, [][]byte) {
	for _, skip := range regexToSkip {
		content = skip.ReplaceAll(content, []byte(` `))
	}

	return content, nil
}

func extractRemainders(content []byte) ([]byte, [][]byte) {
	splitted := bytes.Fields(content)
	remainderTokens := make([][]byte, 0, len(splitted)*3)
	for _, remainder := range splitted {
		remainders := bytes.Split(remainder, nil)
		remainderTokens = append(remainderTokens, remainders...)
	}

	return content, remainderTokens
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"strconv"
	"time"
)

func responseBody(url string) ([]byte, error) {
	response, err := http.Get(url)
	if err != nil {
		return nil, err
	}
	defer response.Body.Close()
	contents, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}
	return contents, nil
}

func JenkinsJob(jenkins, jobName *string) (Job, error) {
	noJob := Job{}

	url := "http://" + *jenkins + "/job/" + *jobName + "/api/json?pretty=true"
	fmt.Printf("%s\n", url)
	contents, err := responseBody(url)
	if err != nil {
		return noJob, err
	}
	fmt.Printf("%s\n", string(contents))

	var data Job
	err = json.Unmarshal(contents, &data)
	if err != nil {
		return noJob, err
	}
	return data, nil
}

func JenkinsBuild(jenkins, jobName *string, buildNumber *int) (Build, error) {
	build := Build{}

	url := "http://" + *jenkins +
		"/job/" + *jobName + "/" +
		strconv.Itoa(*buildNumber) + "/api/json?pretty=true"

	fmt.Printf("%s\n", url)
	contents, err := responseBody(url)
	if err != nil {
		return build, err
	}
	fmt.Printf("%s\n", string(contents))

	err = json.Unmarshal(contents, &build)
	if err != nil {
		return build, err
	}
	return build, nil
}

type Job struct {
	Name            string `json:"name"`
	URL             string `json:"url"`
	Color           string `json:"color"`
	NextBuildNumber int    `json:"nextBuildNumber"`
	InQueue         bool   `json:"inQueue"`
}

type Build struct {
	Number            int    `json:"number"`
	Duration          int    `json:"duration"`
	EstimatedDuration int    `json:"estimatedDuration"`
	Timestamp         int    `json:"timestamp"`
	URL               string `json:"url"`
	Result            string `json:"result"`
	Building          bool   `json:"building"`
}

func main() {
	jenkins := flag.String("jenkins", "127.0.0.1:8080", "Jenkins hostname")
	jobName := flag.String("jobName", "test", "Jenkins job name")
	flag.Parse()

	job, err := JenkinsJob(jenkins, jobName)
	if err != nil {
		panic(err)
	}
	fmt.Printf("job.NextBuildNumber: %d\n", job.NextBuildNumber)
	buildNumber := job.NextBuildNumber

	url := "http://" + *jenkins + "/job/" + *jobName + "/build"
	_, err = http.Post(url, "", nil)
	if err != nil {
		panic(err)
	}
	fmt.Printf("%s\n", url)

	// InQueue
	for {
		time.Sleep(time.Second)
		job, err := JenkinsJob(jenkins, jobName)
		if err != nil {
			fmt.Printf("%s", err)
			os.Exit(1)
		}
		fmt.Println("Time:", time.Now())
		fmt.Println("Name:", job.Name)
		fmt.Println("URL:", job.URL)
		fmt.Println("Color:", job.Color)
		fmt.Println("InQueue:", job.InQueue)

		if !job.InQueue {
			break
		}
	}
	for {
		build, err := JenkinsBuild(jenkins, jobName, &buildNumber)
		if err != nil {
			fmt.Printf("%s", err)
			os.Exit(1)
		}
		fmt.Println("Number:", build.Number)
		fmt.Println("URL:", build.URL)
		fmt.Println("Building:", build.Building)
		fmt.Println("Timestamp:", build.Timestamp)
		fmt.Println("Duration:", build.Duration)
		fmt.Println("EstimatedDuration:", build.EstimatedDuration)
		fmt.Println("Result:", build.Result)
		if len(build.Result) > 0 {
			break
		}
	}
}
<commit_msg>sleep 1 second during Building polls<commit_after>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"strconv"
	"time"
)

func responseBody(url string) ([]byte, error) {
	response, err := http.Get(url)
	if err != nil {
		return nil, err
	}
	defer response.Body.Close()
	contents, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}
	return contents, nil
}

func JenkinsJob(jenkins, jobName *string) (Job, error) {
	url := "http://" + *jenkins + "/job/" + *jobName + "/api/json?pretty=true"
	fmt.Printf("%s\n", url)
	contents, err := responseBody(url)
	if err != nil {
		return Job{}, err
	}
	// fmt.Printf("%s\n", string(contents))

	var data Job
	err = json.Unmarshal(contents, &data)
	if err != nil {
		return Job{}, err
	}
	return data, nil
}

func JenkinsBuild(jenkins, jobName *string, buildNumber *int) (Build, error) {
	build := Build{}

	url := "http://" + *jenkins +
		"/job/" + *jobName + "/" +
		strconv.Itoa(*buildNumber) + "/api/json?pretty=true"

	fmt.Printf("%s\n", url)
	contents, err := responseBody(url)
	if err != nil {
		return build, err
	}
	// fmt.Printf("%s\n", string(contents))

	err = json.Unmarshal(contents, &build)
	if err != nil {
		return build, err
	}
	return build, nil
}

type Job struct {
	Name            string `json:"name"`
	URL             string `json:"url"`
	Color           string `json:"color"`
	NextBuildNumber int    `json:"nextBuildNumber"`
	InQueue         bool   `json:"inQueue"`
}

type Build struct {
	Number            int    `json:"number"`
	Duration          int    `json:"duration"`
	EstimatedDuration int    `json:"estimatedDuration"`
	Timestamp         int    `json:"timestamp"`
	URL               string `json:"url"`
	Result            string `json:"result"`
	Building          bool   `json:"building"`
}

func main() {
	jenkins := flag.String("jenkins", "127.0.0.1:8080", "Jenkins hostname")
	jobName := flag.String("jobName", "test", "Jenkins job name")
	flag.Parse()

	job, err := JenkinsJob(jenkins, jobName)
	if err != nil {
		panic(err)
	}
	fmt.Printf("job.NextBuildNumber: %d\n", job.NextBuildNumber)
	buildNumber := job.NextBuildNumber

	url := "http://" + *jenkins + "/job/" + *jobName + "/build"
	_, err = http.Post(url, "", nil)
	if err != nil {
		panic(err)
	}
	fmt.Printf("%s\n", url)

	// while InQueue
	for {
		time.Sleep(time.Second)
		job, err := JenkinsJob(jenkins, jobName)
		if err != nil {
			fmt.Printf("%s", err)
			os.Exit(1)
		}
		fmt.Println("Time:", time.Now())
		fmt.Println("Name:", job.Name)
		fmt.Println("InQueue:", job.InQueue)

		if !job.InQueue {
			break
		}
	}

	// while Building
	for {
		time.Sleep(time.Second)
		build, err := JenkinsBuild(jenkins, jobName, &buildNumber)
		if err != nil {
			fmt.Printf("%s", err)
			os.Exit(1)
		}
		fmt.Println("Time:", time.Now())
		fmt.Println("Number:", build.Number)
		fmt.Println("Building:", build.Building)
		fmt.Println("Timestamp:", build.Timestamp)
		fmt.Println("Duration:", build.Duration)
		fmt.Println("EstimatedDuration:", build.EstimatedDuration)
		fmt.Println("Result:", build.Result)
		if !build.Building {
			break
		}
	}

	build, err := JenkinsBuild(jenkins, jobName, &buildNumber)
	if err != nil {
		fmt.Printf("%s", err)
		os.Exit(1)
	}
	fmt.Println("Time:", time.Now())
	fmt.Println("Number:", build.Number)
	fmt.Println("Building:", build.Building)
	fmt.Println("Timestamp:", build.Timestamp)
	fmt.Println("Duration:", build.Duration)
	fmt.Println("EstimatedDuration:", build.EstimatedDuration)
	fmt.Println("Result:", build.Result)
}
<|endoftext|>


<commit_before>/*
    PulseHA - HA Cluster Daemon
    Copyright (C) 2017  Andrew Zak <andrew@pulseha.com>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published
    by the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package main

import (
	"reflect"
	"errors"
	"github.com/Syleron/PulseHA/src/utils"
	"github.com/coreos/go-log/log"
	"github.com/Syleron/PulseHA/proto"
	"sync"
)

/**
 * Memberlist struct type
 */
type Memberlist struct {
	Members []*Member
	sync.Mutex
}

/**
 * Member struct type
 */
type Member struct {
	hostname   string
	status proto.MemberStatus_Status
	Client
	sync.Mutex
}

/*
 Getters and setters for Member which allow us to make them go routine safe
 */

func (m *Member) getHostname()string {
	m.Lock()
	defer m.Unlock()
	return m.hostname
}
func (m *Member) setHostname(hostname string){
	m.Lock()
	defer m.Unlock()
	m.hostname = hostname
}

func (m *Member) getStatus()proto.MemberStatus_Status {
	m.Lock()
	defer m.Unlock()
	return m.status
}

func (m *Member) setStatus(status proto.MemberStatus_Status) {
	m.Lock()
	defer m.Unlock()
	m.status = status
}
func (m *Member) setClient(client Client) {
	m.Client = client
}
/**
 * Add a member to the client list
 */
func (m *Memberlist) MemberAdd(hostname string, client *Client) {
	m.Lock()
	defer m.Unlock()
	newMember := &Member{}

	newMember.setHostname(hostname)
	newMember.setStatus(proto.MemberStatus_UNAVAILABLE)
	newMember.setClient(*client)

	m.Members = append(m.Members, newMember)
}

/**
 * Remove a member from the client list by hostname
 */
func (m *Memberlist) MemberRemoveByName(hostname string) () {
	m.Lock()
	defer m.Unlock()
	for i, member := range m.Members {
		if member.getHostname() == hostname {
			m.Members = append(m.Members[:i], m.Members[i+1:]...)
		}
	}
}

/**
 * Return Member by hostname
 */
func (m *Memberlist) GetMemberByHostname(hostname string) (*Member) {
	m.Lock()
	defer m.Unlock()
	for _, member := range m.Members {
		if member.getHostname() == hostname {
			return member
		}
	}
	return nil
}

/**
 * Return true/false whether a member exists or not.
 */
func (m *Memberlist) MemberExists(hostname string) (bool) {
	m.Lock()
	defer m.Unlock()
	for _, member := range m.Members {
		if member.getHostname() == hostname {
			return true
		}
	}
	return false
}

/**
 * Attempt to broadcast a client function to other nodes (clients) within the memberlist
 */
func (m *Memberlist) Broadcast(funcName string, params ... interface{}) (interface{}, error) {
	m.Lock()
	defer m.Unlock()
	for _, member := range m.Members {
		funcList := member.GetFuncBroadcastList()
		f := reflect.ValueOf(funcList[funcName])
		if len(params) != f.Type().NumIn() {
			return nil, errors.New("the number of passed parameters do not match the function")
		}
		vals := make([]reflect.Value, len(params))
		for k, param := range params {
			vals[k] = reflect.ValueOf(param)
		}
		f.Call(vals)
	}
	return nil, nil
}

/**
 * check how many are in the cluster
 * if more than one, request who's active.
 * if no one responds assume active.
 * This should probably populate the memberlist
 */
func (m *Memberlist) Setup() {
	// todo work out hwo to handle mutex in here
	// Load members into our memberlist slice
	m.LoadMembers()
	// Check to see if we are in a cluster
	if clusterCheck() {
		// Are we the only member in the cluster?
		if clusterTotal() == 1 {
			// We are the only member in the cluster so
			// we are assume that we are now the active appliance.
			m.PromoteMember(utils.GetHostname())
		} else {
			// Contact a member in the list to see who is the "active" node.
			// Iterate through the memberlist until a response is receive.
			// If no response has been made then assume we should become the active appliance.
		}
	}
}

/**
	load the nodes in our config into our memberlist
 */
func (m *Memberlist) LoadMembers() {
	config := gconf.GetConfig()
	for key := range config.Nodes {
		log.Debug("Memberlist:LoadMembers() " + key + " added to memberlist")
		newClient := &Client{}
		m.MemberAdd(key, newClient)
	}
}

/**
	Attempt to connect to all nodes within the memberlist.
 */
func (m *Memberlist) MembersConnect() {
	m.Lock()
	defer m.Unlock()
	for _, member := range m.Members {
		// Make sure we are not connecting to ourself!
		if member.getHostname() != utils.GetHostname() {
			node, err := NodeGetByName(member.getHostname())
			if err != nil {
				log.Warning(member.getHostname() + " could not be found.")
			}
			err = member.Client.Connect(node.IP, node.Port, member.getHostname())
			if err != nil {
				continue
			}
			member.setStatus(proto.MemberStatus_PASSIVE)
		}
	}
}

/**
	Get status of a specific member by hostname
 */
func (m *Memberlist) MemberGetStatus(hostname string) (proto.MemberStatus_Status, error) {
	m.Lock()
	defer m.Unlock()
	for _, member := range m.Members {
		if member.getHostname() == hostname {
			return member.getStatus(), nil
		}
	}
	return proto.MemberStatus_UNAVAILABLE, errors.New("unable to find member with hostname " + hostname)
}

/**
	Promote a member within the memberlist to become the active
	node
 */
func (m *Memberlist) PromoteMember(hostname string)error {
	m.Lock()
	defer m.Unlock()
	// Inform everyone in the cluster that a specific node is now the new active
	// Demote if old active is no longer active. promote if the passive is the new active.

	// get host is it active?
	node := m.GetMemberByHostname(hostname)
	if node == nil {
		log.Errorf("Unknown hostname % give in call to promoteMember",hostname)
		return errors.New("Unknown hostname")
	}
	// if unavailable check it works or do nothing?

	// make current active node passive
	// make new node active
	// update all members

	return nil
}

/**
	Sync local config with each member in the cluster.
 */
func (m *Memberlist) SyncConfig() {
	//config := gconf.GetConfig()
}

<commit_msg>Resolving merge conflict<commit_after>/*
    PulseHA - HA Cluster Daemon
    Copyright (C) 2017  Andrew Zak <andrew@pulseha.com>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published
    by the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package main

import (
	"reflect"
	"errors"
	"github.com/Syleron/PulseHA/src/utils"
	"github.com/coreos/go-log/log"
	"github.com/Syleron/PulseHA/proto"
	"sync"
)

/**
 * Memberlist struct type
 */
type Memberlist struct {
	Members []*Member
	sync.Mutex
}

/**
 * Member struct type
 */
type Member struct {
	hostname   string
	status proto.MemberStatus_Status
	Client
	sync.Mutex
}

/*
 Getters and setters for Member which allow us to make them go routine safe
 */

func (m *Member) getHostname()string {
	m.Lock()
	defer m.Unlock()
	return m.hostname
}
func (m *Member) setHostname(hostname string){
	m.Lock()
	defer m.Unlock()
	m.hostname = hostname
}

func (m *Member) getStatus()proto.MemberStatus_Status {
	m.Lock()
	defer m.Unlock()
	return m.status
}

func (m *Member) setStatus(status proto.MemberStatus_Status) {
	m.Lock()
	defer m.Unlock()
	m.status = status
}
func (m *Member) setClient(client Client) {
	m.Client = client
}
/**
 * Add a member to the client list
 */
func (m *Memberlist) MemberAdd(hostname string, client *Client) {
	m.Lock()
	defer m.Unlock()
	newMember := &Member{}

	newMember.setHostname(hostname)
	newMember.setStatus(proto.MemberStatus_UNAVAILABLE)
	newMember.setClient(*client)

	m.Members = append(m.Members, newMember)
}

/**
 * Remove a member from the client list by hostname
 */
func (m *Memberlist) MemberRemoveByName(hostname string) () {
	m.Lock()
	defer m.Unlock()
	for i, member := range m.Members {
		if member.getHostname() == hostname {
			m.Members = append(m.Members[:i], m.Members[i+1:]...)
		}
	}
}

/**
 * Return Member by hostname
 */
func (m *Memberlist) GetMemberByHostname(hostname string) (*Member) {
	m.Lock()
	defer m.Unlock()
	for _, member := range m.Members {
		if member.getHostname() == hostname {
			return member
		}
	}
	return nil
}

/**
 * Return true/false whether a member exists or not.
 */
func (m *Memberlist) MemberExists(hostname string) (bool) {
	m.Lock()
	defer m.Unlock()
	for _, member := range m.Members {
		if member.getHostname() == hostname {
			return true
		}
	}
	return false
}

/**
 * Attempt to broadcast a client function to other nodes (clients) within the memberlist
 */
func (m *Memberlist) Broadcast(funcName string, params ... interface{}) (interface{}, error) {
	m.Lock()
	defer m.Unlock()
	for _, member := range m.Members {
		funcList := member.GetFuncBroadcastList()
		f := reflect.ValueOf(funcList[funcName])
		if len(params) != f.Type().NumIn() {
			return nil, errors.New("the number of passed parameters do not match the function")
		}
		vals := make([]reflect.Value, len(params))
		for k, param := range params {
			vals[k] = reflect.ValueOf(param)
		}
		f.Call(vals)
	}
	return nil, nil
}

/**
 * check how many are in the cluster
 * if more than one, request who's active.
 * if no one responds assume active.
 * This should probably populate the memberlist
 */
func (m *Memberlist) Setup() {
	// todo work out hwo to handle mutex in here
	// Load members into our memberlist slice
	m.LoadMembers()
	// Check to see if we are in a cluster
	if clusterCheck() {
		// Are we the only member in the cluster?
		if clusterTotal() == 1 {
			// We are the only member in the cluster so
			// we are assume that we are now the active appliance.
			m.PromoteMember(utils.GetHostname())
		} else {
			// Contact a member in the list to see who is the "active" node.
			// Iterate through the memberlist until a response is receive.
			// If no response has been made then assume we should become the active appliance.
		}
	}
}

/**
	load the nodes in our config into our memberlist
 */
func (m *Memberlist) LoadMembers() {
	config := gconf.GetConfig()
	for key := range config.Nodes {
		log.Debug("Memberlist:LoadMembers() " + key + " added to memberlist")
		newClient := &Client{}
		m.MemberAdd(key, newClient)
	}
}

/**
	Attempt to connect to all nodes within the memberlist.
 */
func (m *Memberlist) MembersConnect() {
	m.Lock()
	defer m.Unlock()
	for _, member := range m.Members {
		// Make sure we are not connecting to ourself!
		if member.getHostname() != utils.GetHostname() {
			node, err := NodeGetByName(member.getHostname())
			if err != nil {
				log.Warning(member.getHostname() + " could not be found.")
			}
			err = member.Client.Connect(node.IP, node.Port, member.getHostname())
			if err != nil {
				continue
			}
			member.setStatus(proto.MemberStatus_PASSIVE)
		}
	}
}

/**
	Get status of a specific member by hostname
 */
func (m *Memberlist) MemberGetStatus(hostname string) (proto.MemberStatus_Status, error) {
	m.Lock()
	defer m.Unlock()
	for _, member := range m.Members {
		if member.getHostname() == hostname {
			return member.getStatus(), nil
		}
	}
	return proto.MemberStatus_UNAVAILABLE, errors.New("unable to find member with hostname " + hostname)
}

/**
	Promote a member within the memberlist to become the active
	node
 */
func (m *Memberlist) PromoteMember(hostname string)error {
	m.Lock()
	defer m.Unlock()
	// Inform everyone in the cluster that a specific node is now the new active
	// Demote if old active is no longer active. promote if the passive is the new active.

	// get host is it active?
	node := m.GetMemberByHostname(hostname)
	if node == nil {
		log.Errorf("Unknown hostname % give in call to promoteMember",hostname)
		return errors.New("Unknown hostname")
	}
	// if unavailable check it works or do nothing?

	// make current active node passive
	// make new node active
	// update all members

	return nil
}

/**
	Sync local config with each member in the cluster.
 */
func (m *Memberlist) SyncConfig() {
	//config := gconf.GetConfig()
}

<|endoftext|>