<commit_before>package proxmox

// inspired by https://github.com/Telmate/vagrant-proxmox/blob/master/lib/vagrant-proxmox/proxmox/connection.rb

import (
	"crypto/tls"
	"errors"
	"fmt"
	"net/http"
	"regexp"
	"time"
)

const TaskTimeout = 60
const TaskStatusCheckInterval = 2

type Client struct {
	session *Session
}

// map[type:qemu node:proxmox1-xx id:qemu/132 diskread:5.57424738e+08 disk:0 netin:5.9297450593e+10 mem:3.3235968e+09 uptime:1.4567097e+07 vmid:132 template:0 maxcpu:2 netout:6.053310416e+09 maxdisk:3.4359738368e+10 maxmem:8.592031744e+09 diskwrite:1.49663619584e+12 status:running cpu:0.00386980694947209 name:appt-app1-dev.xxx.xx]
type VmRef struct {
	vmId   int
	node   string
	vmType string
}

func (vmr *VmRef) SetNode(node string) {
	vmr.node = node
	return
}

func (vmr *VmRef) SetVmType(vmType string) {
	vmr.vmType = vmType
	return
}

func (vmr *VmRef) VmId() int {
	return vmr.vmId
}

func NewVmRef(vmId int) (vmr *VmRef) {
	vmr = &VmRef{vmId: vmId, node: "", vmType: ""}
	return
}

func NewClient(apiUrl string, hclient *http.Client, tls *tls.Config) (client *Client, err error) {
	var sess *Session
	sess, err = NewSession(apiUrl, hclient, tls)
	if err == nil {
		client = &Client{session: sess}
	}
	return client, err
}

func (c *Client) Login(username string, password string) (err error) {
	return c.session.Login(username, password)
}

func (c *Client) GetNodeList() (list map[string]interface{}, err error) {
	_, err = c.session.GetJSON("/nodes", nil, nil, &list)
	return
}

func (c *Client) GetVmList() (list map[string]interface{}, err error) {
	_, err = c.session.GetJSON("/cluster/resources?type=vm", nil, nil, &list)
	return
}

func (c *Client) CheckVmRef(vmr *VmRef) (err error) {
	if vmr.node == "" || vmr.vmType == "" {
		_, err = c.GetVmInfo(vmr)
	}
	return
}

func (c *Client) GetVmInfo(vmr *VmRef) (vmInfo map[string]interface{}, err error) {
	resp, err := c.GetVmList()
	vms := resp["data"].([]interface{})
	for vmii := range vms {
		vm := vms[vmii].(map[string]interface{})
		if int(vm["vmid"].(float64)) == vmr.vmId {
			vmInfo = vm
			vmr.node = vmInfo["node"].(string)
			vmr.vmType = vmInfo["type"].(string)
			return
		}
	}
	return nil, errors.New("Vm INFO not found")
}

func (c *Client) GetVmRefByName(vmName string) (vmr *VmRef, err error) {
	resp, err := c.GetVmList()
	vms := resp["data"].([]interface{})
	for vmii := range vms {
		vm := vms[vmii].(map[string]interface{})
		if vm["name"].(string) == vmName {
			vmr = NewVmRef(int(vm["vmid"].(float64)))
			vmr.node = vm["node"].(string)
			vmr.vmType = vm["type"].(string)
			return
		}
	}
	return nil, errors.New("Vm INFO not found")
}

func (c *Client) GetVmState(vmr *VmRef) (vmState map[string]interface{}, err error) {
	err = c.CheckVmRef(vmr)
	if err != nil {
		return nil, err
	}
	var data map[string]interface{}
	url := fmt.Sprintf("/nodes/%s/%s/%d/status/current", vmr.node, vmr.vmType, vmr.vmId)
	_, err = c.session.GetJSON(url, nil, nil, &data)
	if err != nil {
		return nil, err
	}
	vmState = data["data"].(map[string]interface{})
	return
}

func (c *Client) GetVmConfig(vmr *VmRef) (vmConfig map[string]interface{}, err error) {
	err = c.CheckVmRef(vmr)
	if err != nil {
		return nil, err
	}
	var data map[string]interface{}
	url := fmt.Sprintf("/nodes/%s/%s/%d/config", vmr.node, vmr.vmType, vmr.vmId)
	_, err = c.session.GetJSON(url, nil, nil, &data)
	if err != nil {
		return nil, err
	}
	vmConfig = data["data"].(map[string]interface{})
	return
}

func (c *Client) MonitorCmd(vmr *VmRef, command string) (monitorRes map[string]interface{}, err error) {
	err = c.CheckVmRef(vmr)
	if err != nil {
		return nil, err
	}
	reqbody := ParamsToBody(map[string]string{"command": command})
	url := fmt.Sprintf("/nodes/%s/%s/%d/monitor", vmr.node, vmr.vmType, vmr.vmId)
	resp, err := c.session.Post(url, nil, nil, &reqbody)
	monitorRes = ResponseJSON(resp)
	return
}

func (c *Client) WaitForCompletion(taskResponse map[string]interface{}) (waitExitStatus string, err error) {
	waited := 1
	taskUpid := taskResponse["data"].(string)
	for waited < TaskTimeout {
		exitStatus, statErr := c.GetTaskExitstatus(taskUpid)
		if statErr != nil {
			return "", statErr
		}
		if exitStatus != nil {
			waitExitStatus = exitStatus.(string)
			return
		}
		time.Sleep(TaskStatusCheckInterval * time.Second)
		waited = waited + TaskStatusCheckInterval
	}
	return "", errors.New("Wait timeout for:" + taskUpid)
}

var rxTaskNode = regexp.MustCompile("UPID:(.*?):")

func (c *Client) GetTaskExitstatus(taskUpid string) (exitStatus interface{}, err error) {
	node := rxTaskNode.FindStringSubmatch(taskUpid)[1]
	url := fmt.Sprintf("/nodes/%s/tasks/%s/status", node, taskUpid)
	var data map[string]interface{}
	_, err = c.session.GetJSON(url, nil, nil, &data)
	if err == nil {
		exitStatus = data["data"].(map[string]interface{})["exitstatus"]
	}
	return
}

func (c *Client) StatusChangeVm(vmr *VmRef, setStatus string) (exitStatus string, err error) {
	err = c.CheckVmRef(vmr)
	if err != nil {
		return "", err
	}
	url := fmt.Sprintf("/nodes/%s/%s/%d/status/%s", vmr.node, vmr.vmType, vmr.vmId, setStatus)
	var taskResponse map[string]interface{}
	_, err = c.session.PostJSON(url, nil, nil, nil, &taskResponse)
	exitStatus, err = c.WaitForCompletion(taskResponse)
	return
}

func (c *Client) StartVm(vmr *VmRef) (exitStatus string, err error) {
	return c.StatusChangeVm(vmr, "start")
}

func (c *Client) StopVm(vmr *VmRef) (exitStatus string, err error) {
	return c.StatusChangeVm(vmr, "stop")
}

func (c *Client) ShutdownVm(vmr *VmRef) (exitStatus string, err error) {
	return c.StatusChangeVm(vmr, "shutdown")
}

func (c *Client) DeleteVm(vmr *VmRef) (exitStatus string, err error) {
	err = c.CheckVmRef(vmr)
	if err != nil {
		return "", err
	}
	url := fmt.Sprintf("/nodes/%s/%s/%d", vmr.node, vmr.vmType, vmr.vmId)
	var taskResponse map[string]interface{}
	_, err = c.session.RequestJSON("DELETE", url, nil, nil, nil, &taskResponse)
	exitStatus, err = c.WaitForCompletion(taskResponse)
	return
}

func (c *Client) CreateQemuVm(node string, vmParams map[string]string) (exitStatus string, err error) {
	reqbody := ParamsToBody(vmParams)
	url := fmt.Sprintf("/nodes/%s/qemu", node)
	resp, err := c.session.Post(url, nil, nil, &reqbody)
	if err == nil {
		taskResponse := ResponseJSON(resp)
		exitStatus, err = c.WaitForCompletion(taskResponse)
	}
	return
}

func (c *Client) CloneQemuVm(vmr *VmRef, vmParams map[string]string) (exitStatus string, err error) {
	reqbody := ParamsToBody(vmParams)
	url := fmt.Sprintf("/nodes/%s/qemu/%d/clone", vmr.node, vmr.vmId)
	resp, err := c.session.Post(url, nil, nil, &reqbody)
	if err == nil {
		taskResponse := ResponseJSON(resp)
		exitStatus, err = c.WaitForCompletion(taskResponse)
	}
	return
}

func (c *Client) SetVmConfig(vmr *VmRef, vmParams map[string]string) (exitStatus string, err error) {
	reqbody := ParamsToBody(vmParams)
	url := fmt.Sprintf("/nodes/%s/%s/%d/config", vmr.node, vmr.vmType, vmr.vmId)
	resp, err := c.session.Post(url, nil, nil, &reqbody)
	if err == nil {
		taskResponse := ResponseJSON(resp)
		exitStatus, err = c.WaitForCompletion(taskResponse)
	}
	return
}

func (c *Client) ResizeQemuDisk(vmr *VmRef, disk string, moreSizeGB int) (exitStatus string, err error) {
	// PUT
	//disk:virtio0
	//size:+2G
	if disk == "" {
		disk = "virtio0"
	}
	size := fmt.Sprintf("+%dG", moreSizeGB)
	reqbody := ParamsToBody(map[string]string{"disk": disk, "size": size})
	url := fmt.Sprintf("/nodes/%s/%s/%d/resize", vmr.node, vmr.vmType, vmr.vmId)
	resp, err := c.session.Put(url, nil, nil, &reqbody)
	if err == nil {
		taskResponse := ResponseJSON(resp)
		exitStatus, err = c.WaitForCompletion(taskResponse)
	}
	return
}
<commit_msg>support reading the node too<commit_after>package proxmox

// inspired by https://github.com/Telmate/vagrant-proxmox/blob/master/lib/vagrant-proxmox/proxmox/connection.rb

import (
	"crypto/tls"
	"errors"
	"fmt"
	"net/http"
	"regexp"
	"time"
)

const TaskTimeout = 60
const TaskStatusCheckInterval = 2

type Client struct {
	session *Session
}

// map[type:qemu node:proxmox1-xx id:qemu/132 diskread:5.57424738e+08 disk:0 netin:5.9297450593e+10 mem:3.3235968e+09 uptime:1.4567097e+07 vmid:132 template:0 maxcpu:2 netout:6.053310416e+09 maxdisk:3.4359738368e+10 maxmem:8.592031744e+09 diskwrite:1.49663619584e+12 status:running cpu:0.00386980694947209 name:appt-app1-dev.xxx.xx]
type VmRef struct {
	vmId   int
	node   string
	vmType string
}

func (vmr *VmRef) SetNode(node string) {
	vmr.node = node
	return
}

func (vmr *VmRef) SetVmType(vmType string) {
	vmr.vmType = vmType
	return
}

func (vmr *VmRef) VmId() int {
	return vmr.vmId
}

func (vmr *VmRef) Node() string {
	return vmr.node
}

func NewVmRef(vmId int) (vmr *VmRef) {
	vmr = &VmRef{vmId: vmId, node: "", vmType: ""}
	return
}

func NewClient(apiUrl string, hclient *http.Client, tls *tls.Config) (client *Client, err error) {
	var sess *Session
	sess, err = NewSession(apiUrl, hclient, tls)
	if err == nil {
		client = &Client{session: sess}
	}
	return client, err
}

func (c *Client) Login(username string, password string) (err error) {
	return c.session.Login(username, password)
}

func (c *Client) GetNodeList() (list map[string]interface{}, err error) {
	_, err = c.session.GetJSON("/nodes", nil, nil, &list)
	return
}

func (c *Client) GetVmList() (list map[string]interface{}, err error) {
	_, err = c.session.GetJSON("/cluster/resources?type=vm", nil, nil, &list)
	return
}

func (c *Client) CheckVmRef(vmr *VmRef) (err error) {
	if vmr.node == "" || vmr.vmType == "" {
		_, err = c.GetVmInfo(vmr)
	}
	return
}

func (c *Client) GetVmInfo(vmr *VmRef) (vmInfo map[string]interface{}, err error) {
	resp, err := c.GetVmList()
	vms := resp["data"].([]interface{})
	for vmii := range vms {
		vm := vms[vmii].(map[string]interface{})
		if int(vm["vmid"].(float64)) == vmr.vmId {
			vmInfo = vm
			vmr.node = vmInfo["node"].(string)
			vmr.vmType = vmInfo["type"].(string)
			return
		}
	}
	return nil, errors.New("Vm INFO not found")
}

func (c *Client) GetVmRefByName(vmName string) (vmr *VmRef, err error) {
	resp, err := c.GetVmList()
	vms := resp["data"].([]interface{})
	for vmii := range vms {
		vm := vms[vmii].(map[string]interface{})
		if vm["name"].(string) == vmName {
			vmr = NewVmRef(int(vm["vmid"].(float64)))
			vmr.node = vm["node"].(string)
			vmr.vmType = vm["type"].(string)
			return
		}
	}
	return nil, errors.New("Vm INFO not found")
}

func (c *Client) GetVmState(vmr *VmRef) (vmState map[string]interface{}, err error) {
	err = c.CheckVmRef(vmr)
	if err != nil {
		return nil, err
	}
	var data map[string]interface{}
	url := fmt.Sprintf("/nodes/%s/%s/%d/status/current", vmr.node, vmr.vmType, vmr.vmId)
	_, err = c.session.GetJSON(url, nil, nil, &data)
	if err != nil {
		return nil, err
	}
	vmState = data["data"].(map[string]interface{})
	return
}

func (c *Client) GetVmConfig(vmr *VmRef) (vmConfig map[string]interface{}, err error) {
	err = c.CheckVmRef(vmr)
	if err != nil {
		return nil, err
	}
	var data map[string]interface{}
	url := fmt.Sprintf("/nodes/%s/%s/%d/config", vmr.node, vmr.vmType, vmr.vmId)
	_, err = c.session.GetJSON(url, nil, nil, &data)
	if err != nil {
		return nil, err
	}
	vmConfig = data["data"].(map[string]interface{})
	return
}

func (c *Client) MonitorCmd(vmr *VmRef, command string) (monitorRes map[string]interface{}, err error) {
	err = c.CheckVmRef(vmr)
	if err != nil {
		return nil, err
	}
	reqbody := ParamsToBody(map[string]string{"command": command})
	url := fmt.Sprintf("/nodes/%s/%s/%d/monitor", vmr.node, vmr.vmType, vmr.vmId)
	resp, err := c.session.Post(url, nil, nil, &reqbody)
	monitorRes = ResponseJSON(resp)
	return
}

func (c *Client) WaitForCompletion(taskResponse map[string]interface{}) (waitExitStatus string, err error) {
	waited := 1
	taskUpid := taskResponse["data"].(string)
	for waited < TaskTimeout {
		exitStatus, statErr := c.GetTaskExitstatus(taskUpid)
		if statErr != nil {
			return "", statErr
		}
		if exitStatus != nil {
			waitExitStatus = exitStatus.(string)
			return
		}
		time.Sleep(TaskStatusCheckInterval * time.Second)
		waited = waited + TaskStatusCheckInterval
	}
	return "", errors.New("Wait timeout for:" + taskUpid)
}

var rxTaskNode = regexp.MustCompile("UPID:(.*?):")

func (c *Client) GetTaskExitstatus(taskUpid string) (exitStatus interface{}, err error) {
	node := rxTaskNode.FindStringSubmatch(taskUpid)[1]
	url := fmt.Sprintf("/nodes/%s/tasks/%s/status", node, taskUpid)
	var data map[string]interface{}
	_, err = c.session.GetJSON(url, nil, nil, &data)
	if err == nil {
		exitStatus = data["data"].(map[string]interface{})["exitstatus"]
	}
	return
}

func (c *Client) StatusChangeVm(vmr *VmRef, setStatus string) (exitStatus string, err error) {
	err = c.CheckVmRef(vmr)
	if err != nil {
		return "", err
	}
	url := fmt.Sprintf("/nodes/%s/%s/%d/status/%s", vmr.node, vmr.vmType, vmr.vmId, setStatus)
	var taskResponse map[string]interface{}
	_, err = c.session.PostJSON(url, nil, nil, nil, &taskResponse)
	exitStatus, err = c.WaitForCompletion(taskResponse)
	return
}

func (c *Client) StartVm(vmr *VmRef) (exitStatus string, err error) {
	return c.StatusChangeVm(vmr, "start")
}

func (c *Client) StopVm(vmr *VmRef) (exitStatus string, err error) {
	return c.StatusChangeVm(vmr, "stop")
}

func (c *Client) ShutdownVm(vmr *VmRef) (exitStatus string, err error) {
	return c.StatusChangeVm(vmr, "shutdown")
}

func (c *Client) DeleteVm(vmr *VmRef) (exitStatus string, err error) {
	err = c.CheckVmRef(vmr)
	if err != nil {
		return "", err
	}
	url := fmt.Sprintf("/nodes/%s/%s/%d", vmr.node, vmr.vmType, vmr.vmId)
	var taskResponse map[string]interface{}
	_, err = c.session.RequestJSON("DELETE", url, nil, nil, nil, &taskResponse)
	exitStatus, err = c.WaitForCompletion(taskResponse)
	return
}

func (c *Client) CreateQemuVm(node string, vmParams map[string]string) (exitStatus string, err error) {
	reqbody := ParamsToBody(vmParams)
	url := fmt.Sprintf("/nodes/%s/qemu", node)
	resp, err := c.session.Post(url, nil, nil, &reqbody)
	if err == nil {
		taskResponse := ResponseJSON(resp)
		exitStatus, err = c.WaitForCompletion(taskResponse)
	}
	return
}

func (c *Client) CloneQemuVm(vmr *VmRef, vmParams map[string]string) (exitStatus string, err error) {
	reqbody := ParamsToBody(vmParams)
	url := fmt.Sprintf("/nodes/%s/qemu/%d/clone", vmr.node, vmr.vmId)
	resp, err := c.session.Post(url, nil, nil, &reqbody)
	if err == nil {
		taskResponse := ResponseJSON(resp)
		exitStatus, err = c.WaitForCompletion(taskResponse)
	}
	return
}

func (c *Client) SetVmConfig(vmr *VmRef, vmParams map[string]string) (exitStatus string, err error) {
	reqbody := ParamsToBody(vmParams)
	url := fmt.Sprintf("/nodes/%s/%s/%d/config", vmr.node, vmr.vmType, vmr.vmId)
	resp, err := c.session.Post(url, nil, nil, &reqbody)
	if err == nil {
		taskResponse := ResponseJSON(resp)
		exitStatus, err = c.WaitForCompletion(taskResponse)
	}
	return
}

func (c *Client) ResizeQemuDisk(vmr *VmRef, disk string, moreSizeGB int) (exitStatus string, err error) {
	// PUT
	//disk:virtio0
	//size:+2G
	if disk == "" {
		disk = "virtio0"
	}
	size := fmt.Sprintf("+%dG", moreSizeGB)
	reqbody := ParamsToBody(map[string]string{"disk": disk, "size": size})
	url := fmt.Sprintf("/nodes/%s/%s/%d/resize", vmr.node, vmr.vmType, vmr.vmId)
	resp, err := c.session.Put(url, nil, nil, &reqbody)
	if err == nil {
		taskResponse := ResponseJSON(resp)
		exitStatus, err = c.WaitForCompletion(taskResponse)
	}
	return
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"math"
	"time"

	"github.com/ChristopherRabotin/smd"
	"github.com/gonum/floats"
	"github.com/gonum/matrix/mat64"
)

const (
	r2d = 180 / math.Pi
	d2r = 1 / r2d
)

var (
	minRadius = 300 + smd.Earth.Radius // km
	launch    = time.Date(1989, 10, 8, 0, 0, 0, 0, time.UTC)
	vga1      = time.Date(1990, 2, 10, 0, 0, 0, 0, time.UTC)
	ega1      = time.Date(1990, 12, 10, 0, 0, 0, 0, time.UTC)
	ega2      = time.Date(1992, 12, 9, 12, 0, 0, 0, time.UTC)
	joi       = time.Date(1996, 3, 21, 12, 0, 0, 0, time.UTC)
)

func main() {
	resonance := ega2.Sub(ega1).Hours() / (365.242189 * 24)
	fmt.Printf("%s\t~%f orbits\n", ega2.Sub(ega1), resonance)

	fmt.Println("==== Launch -> VGA ====")
	// hwQ 1
	earthAtLaunch := smd.Earth.HelioOrbit(launch)
	eLaunchR := mat64.NewVector(3, earthAtLaunch.R())
	venusAtVGA := smd.Venus.HelioOrbit(vga1)
	vga1R := mat64.NewVector(3, venusAtVGA.R())
	_, VfVGA, _, _ := smd.Lambert(eLaunchR, vga1R, vga1.Sub(launch), smd.TTypeAuto, smd.Sun)
	vfloatsVGA := []float64{VfVGA.At(0, 0), VfVGA.At(1, 0), VfVGA.At(2, 0)}
	scOrbitAtVGAIn := smd.NewOrbitFromRV(venusAtVGA.R(), vfloatsVGA, smd.Sun)
	scOrbitAtVGAIn.ToXCentric(smd.Venus, vga1)

	fmt.Println("==== VGA -> EGA1 ====")
	earthAtEGA1 := smd.Earth.HelioOrbit(ega1)
	ega1R := mat64.NewVector(3, earthAtEGA1.R())
	ViVGA, VfGA1, _, _ := smd.Lambert(vga1R, ega1R, ega1.Sub(vga1), smd.TTypeAuto, smd.Sun)
	scOrbitAtVGAOut := smd.NewOrbitFromRV(venusAtVGA.R(), []float64{ViVGA.At(0, 0), ViVGA.At(1, 0), ViVGA.At(2, 0)}, smd.Sun)
	scOrbitAtVGAOut.ToXCentric(smd.Venus, vga1)
	// Okay, we have all the info for Venus, let's compute stuff.
	_, rPVenus, bTVenus, bRVenus, _, _ := smd.GAFromVinf(scOrbitAtVGAIn.V(), scOrbitAtVGAOut.V(), smd.Venus)
	fmt.Printf("==== VENUS INFO ====\nrP=%f km\tBt=%f km\tBr=%f\nVin=%f\tVout=%f\nDelta=%f\n\n", rPVenus, bTVenus, bRVenus, scOrbitAtVGAIn.VNorm(), scOrbitAtVGAOut.VNorm(), scOrbitAtVGAOut.VNorm()-scOrbitAtVGAIn.VNorm())

	scOrbitAtEGA1 := smd.NewOrbitFromRV(earthAtEGA1.R(), []float64{VfGA1.At(0, 0), VfGA1.At(1, 0), VfGA1.At(2, 0)}, smd.Sun)
	scOrbitAtEGA1.ToXCentric(smd.Earth, ega1)
	vInfInGA1 := scOrbitAtEGA1.V()
	vInfOutGA1Norm := scOrbitAtEGA1.VNorm() // Called OutGA1 because we suppose there was no maneuver during the flyby

	fmt.Println("==== EGA2 -> JOI ====")
	// hwQ 2
	earthAtEGA2 := smd.Earth.HelioOrbit(ega2)
	jupiterAtJOI := smd.Jupiter.HelioOrbit(joi)
	ega2R := mat64.NewVector(3, earthAtEGA2.R())
	joiR := mat64.NewVector(3, jupiterAtJOI.R())
	ViGA2, VfJOI, _, _ := smd.Lambert(ega2R, joiR, joi.Sub(ega2), smd.TTypeAuto, smd.Sun)
	scOrbitAtEGA2 := smd.NewOrbitFromRV(earthAtEGA2.R(), []float64{ViGA2.At(0, 0), ViGA2.At(1, 0), ViGA2.At(2, 0)}, smd.Sun)
	// Let's propagate this spacecraft until JOI time.
	smd.NewPreciseMission(smd.NewEmptySC("galileo", 0), scOrbitAtEGA2, ega2, joi, smd.Cartesian, smd.Perturbations{}, time.Hour, smd.ExportConfig{}).Propagate()
	// Check how big the difference is between the Lambert expected value and the true value.
	vJOIExp := mat64.NewVector(3, []float64{VfJOI.At(0, 0), VfJOI.At(1, 0), VfJOI.At(2, 0)})
	vJOIGot := mat64.NewVector(3, scOrbitAtEGA2.V())
	vJOIGot.SubVec(vJOIGot, vJOIExp)
	// Must print information now because Vector is updated with the slice.
	fmt.Printf("\nDelta V @ JOI\n%+v\n", mat64.Formatted(vJOIGot))
	// Convert to Jupiter centric orbit
	scOrbitAtEGA2.ToXCentric(smd.Jupiter, joi)
	jupiterAtJOIR := jupiterAtJOI.R()
	jupiterAtJOIR[0] = scOrbitAtEGA2.VNorm()
	scOrbitAtJOI := smd.NewOrbitFromRV(jupiterAtJOIR, scOrbitAtEGA2.V(), smd.Sun)
	scOrbitAtJOI.ToXCentric(smd.Jupiter, joi)
	Φfpa := math.Atan2(scOrbitAtJOI.SinΦfpa(), scOrbitAtJOI.CosΦfpa())
	ψJupiter := smd.GATurnAngle(scOrbitAtEGA2.VNorm(), 4*smd.Jupiter.Radius, smd.Jupiter)
	fmt.Printf("==== JUPITER INFO ====\nWARNING: Probably incorrect\nOrbit %s\nPeriod: %s (~%f days)\tEnergy: %f\tΦfpa=%f\napo=%f km\tperi=%f km\nV=%f km\tψ=%f deg\n\n", scOrbitAtJOI, scOrbitAtJOI.Period(), scOrbitAtJOI.Period().Hours()/24, scOrbitAtJOI.Energyξ(), Φfpa*r2d, scOrbitAtJOI.Apoapsis(), scOrbitAtJOI.Periapsis(), scOrbitAtJOI.VNorm(), ψJupiter*r2d)
	// Set the radius of periapsis at Jupiter to be 4*R_j (similar to that of the mission).

	fmt.Println("==== Earth resonnance ====")
	aResonance := math.Pow(smd.Sun.GM()*math.Pow(resonance*earthAtEGA1.Period().Seconds()/(2*math.Pi), 2), 1/3.)
	VScSunNorm := math.Sqrt(smd.Sun.GM() * ((2 / earthAtEGA1.RNorm()) - 1/aResonance))
	// Compute angle theta for EGA1
	theta := math.Acos((math.Pow(VScSunNorm, 2) - math.Pow(vInfOutGA1Norm, 2) - math.Pow(earthAtEGA1.VNorm(), 2)) / (-2 * vInfOutGA1Norm * earthAtEGA1.VNorm()))
	fmt.Printf("theta = %f\n", theta*r2d)
	// Compute the VNC2ECI DCMs for EGA1 and EGA2.
	V := unit(earthAtEGA1.V())
	N := unit(earthAtEGA1.H())
	C := cross(V, N)
	dcmVal := make([]float64, 9)
	for i := 0; i < 3; i++ {
		dcmVal[i] = V[i]
		dcmVal[i+3] = N[i]
		dcmVal[i+6] = C[i]
	}
	DCM := mat64.NewDense(3, 3, dcmVal)

	ψ := 165.924 * d2r // My choice of Phi for the resonance.
	// Reset scOrbitAtEGA2 because we used that for the propagation.
	scOrbitAtEGA2 = smd.NewOrbitFromRV(earthAtEGA2.R(), []float64{ViGA2.At(0, 0), ViGA2.At(1, 0), ViGA2.At(2, 0)}, smd.Sun)
	scOrbitAtEGA2.ToXCentric(smd.Earth, ega2)

	sψ, cψ := math.Sincos(ψ)
	vInfOutGA1VNC := []float64{vInfOutGA1Norm * math.Cos(math.Pi-theta), vInfOutGA1Norm * math.Sin(math.Pi-theta) * cψ, -vInfOutGA1Norm * math.Sin(math.Pi-theta) * sψ}
	vInfOutGA1 := MxV33(DCM, vInfOutGA1VNC)
	_, rPEGA1, bTEGA1, bREGA1, _, _ := smd.GAFromVinf(vInfInGA1, vInfOutGA1, smd.Earth)
	fmt.Printf("==== EGA1 INFO ====\nrP=%f km\tBt=%f km\tBr=%f\nVin=%f\tVout=%f\nDelta=%f\n\n", rPEGA1, bTEGA1, bREGA1, norm(vInfInGA1), norm(vInfOutGA1), norm(vInfOutGA1)-norm(vInfInGA1))

	vInfInGA2 := make([]float64, 3)
	for i := 0; i < 3; i++ {
		vInfInGA2[i] = vInfOutGA1[i] + scOrbitAtEGA1.V()[i] - scOrbitAtEGA2.V()[i]
	}
	_, rPEGA2, bTEGA2, bREGA2, _, _ := smd.GAFromVinf(vInfOutGA1, vInfInGA2, smd.Earth)
	fmt.Printf("==== EGA2 INFO ====\nrP=%f km\tBt=%f km\tBr=%f\nVin=%f\tVout=%f\nDelta=%f\n\n", rPEGA2, bTEGA2, bREGA2, norm(vInfOutGA1), norm(vInfInGA2), norm(vInfInGA2)-norm(vInfOutGA1))

}

// Unshamefully copied from smd/math.go
func cross(a, b []float64) []float64 {
	return []float64{a[1]*b[2] - a[2]*b[1],
		a[2]*b[0] - a[0]*b[2],
		a[0]*b[1] - a[1]*b[0]} // Cross product R x V.
}

// norm returns the norm of a given vector which is supposed to be 3x1.
func norm(v []float64) float64 {
	return math.Sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2])
}

// unit returns the unit vector of a given vector.
func unit(a []float64) (b []float64) {
	n := norm(a)
	if floats.EqualWithinAbs(n, 0, 1e-12) {
		return []float64{0, 0, 0}
	}
	b = make([]float64, len(a))
	for i, val := range a {
		b[i] = val / n
	}
	return
}

// MxV33 multiplies a matrix with a vector. Note that there is no dimension check!
func MxV33(m *mat64.Dense, v []float64) (o []float64) {
	vVec := mat64.NewVector(len(v), v)
	var rVec mat64.Vector
	rVec.MulVec(m, vVec)
	return []float64{rVec.At(0, 0), rVec.At(1, 0), rVec.At(2, 0)}
}
<commit_msg>Ha! I was in the wrong center<commit_after>package main

import (
	"fmt"
	"math"
	"time"

	"github.com/ChristopherRabotin/smd"
	"github.com/gonum/floats"
	"github.com/gonum/matrix/mat64"
)

const (
	r2d = 180 / math.Pi
	d2r = 1 / r2d
)

var (
	minRadius = 300 + smd.Earth.Radius // km
	launch    = time.Date(1989, 10, 8, 0, 0, 0, 0, time.UTC)
	vga1      = time.Date(1990, 2, 10, 0, 0, 0, 0, time.UTC)
	ega1      = time.Date(1990, 12, 10, 0, 0, 0, 0, time.UTC)
	ega2      = time.Date(1992, 12, 9, 12, 0, 0, 0, time.UTC)
	joi       = time.Date(1996, 3, 21, 12, 0, 0, 0, time.UTC)
)

func main() {
	resonance := ega2.Sub(ega1).Hours() / (365.242189 * 24)
	fmt.Printf("%s\t~%f orbits\n", ega2.Sub(ega1), resonance)

	fmt.Println("==== Launch -> VGA ====")
	// hwQ 1
	earthAtLaunch := smd.Earth.HelioOrbit(launch)
	eLaunchR := mat64.NewVector(3, earthAtLaunch.R())
	venusAtVGA := smd.Venus.HelioOrbit(vga1)
	vga1R := mat64.NewVector(3, venusAtVGA.R())
	_, VfVGA, _, _ := smd.Lambert(eLaunchR, vga1R, vga1.Sub(launch), smd.TTypeAuto, smd.Sun)
	vfloatsVGA := []float64{VfVGA.At(0, 0), VfVGA.At(1, 0), VfVGA.At(2, 0)}
	scOrbitAtVGAIn := smd.NewOrbitFromRV(venusAtVGA.R(), vfloatsVGA, smd.Sun)
	scOrbitAtVGAIn.ToXCentric(smd.Venus, vga1)

	fmt.Println("==== VGA -> EGA1 ====")
	earthAtEGA1 := smd.Earth.HelioOrbit(ega1)
	ega1R := mat64.NewVector(3, earthAtEGA1.R())
	ViVGA, VfGA1, _, _ := smd.Lambert(vga1R, ega1R, ega1.Sub(vga1), smd.TTypeAuto, smd.Sun)
	scOrbitAtVGAOut := smd.NewOrbitFromRV(venusAtVGA.R(), []float64{ViVGA.At(0, 0), ViVGA.At(1, 0), ViVGA.At(2, 0)}, smd.Sun)
	scOrbitAtVGAOut.ToXCentric(smd.Venus, vga1)
	// Okay, we have all the info for Venus, let's compute stuff.
	_, rPVenus, bTVenus, bRVenus, _, _ := smd.GAFromVinf(scOrbitAtVGAIn.V(), scOrbitAtVGAOut.V(), smd.Venus)
	fmt.Printf("==== VENUS INFO ====\nrP=%f km\tBt=%f km\tBr=%f\nVin=%f\tVout=%f\nDelta=%f\n\n", rPVenus, bTVenus, bRVenus, scOrbitAtVGAIn.VNorm(), scOrbitAtVGAOut.VNorm(), scOrbitAtVGAOut.VNorm()-scOrbitAtVGAIn.VNorm())

	scOrbitAtEGA1 := smd.NewOrbitFromRV(earthAtEGA1.R(), []float64{VfGA1.At(0, 0), VfGA1.At(1, 0), VfGA1.At(2, 0)}, smd.Sun)
	scOrbitAtEGA1.ToXCentric(smd.Earth, ega1)
	vInfInGA1 := scOrbitAtEGA1.V()
	vInfOutGA1Norm := scOrbitAtEGA1.VNorm() // Called OutGA1 because we suppose there was no maneuver during the flyby

	fmt.Println("==== EGA2 -> JOI ====")
	// hwQ 2
	earthAtEGA2 := smd.Earth.HelioOrbit(ega2)
	jupiterAtJOI := smd.Jupiter.HelioOrbit(joi)
	ega2R := mat64.NewVector(3, earthAtEGA2.R())
	joiR := mat64.NewVector(3, jupiterAtJOI.R())
	ViGA2, VfJOI, _, _ := smd.Lambert(ega2R, joiR, joi.Sub(ega2), smd.TTypeAuto, smd.Sun)
	scOrbitAtEGA2 := smd.NewOrbitFromRV(earthAtEGA2.R(), []float64{ViGA2.At(0, 0), ViGA2.At(1, 0), ViGA2.At(2, 0)}, smd.Sun)
	// Let's propagate this spacecraft until JOI time.
	smd.NewPreciseMission(smd.NewEmptySC("galileo", 0), scOrbitAtEGA2, ega2, joi, smd.Cartesian, smd.Perturbations{}, time.Hour, smd.ExportConfig{}).Propagate()
	// Check how big the difference is between the Lambert expected value and the true value.
	vJOIExp := mat64.NewVector(3, []float64{VfJOI.At(0, 0), VfJOI.At(1, 0), VfJOI.At(2, 0)})
	vJOIGot := mat64.NewVector(3, scOrbitAtEGA2.V())
	vJOIGot.SubVec(vJOIGot, vJOIExp)
	// Must print information now because Vector is updated with the slice.
	fmt.Printf("\nDelta V @ JOI\n%+v\n", mat64.Formatted(vJOIGot))
	// Convert to Jupiter centric orbit
	scOrbitAtEGA2.ToXCentric(smd.Jupiter, joi)
	jupiterAtJOIR := []float64{0, 0, 4 * smd.Jupiter.Radius}
	scOrbitAtJOI := smd.NewOrbitFromRV(jupiterAtJOIR, scOrbitAtEGA2.V(), smd.Jupiter)
	Φfpa := math.Atan2(scOrbitAtJOI.SinΦfpa(), scOrbitAtJOI.CosΦfpa())
	ψJupiter := smd.GATurnAngle(scOrbitAtEGA2.VNorm(), 4*smd.Jupiter.Radius, smd.Jupiter)
	fmt.Printf("==== JUPITER INFO ====\nOrbit %s\nPeriod: %s (~%f days)\tEnergy: %f\tΦfpa=%f\napo=%f km\tperi=%f km\nV=%f km\tψ=%f deg\n\n", scOrbitAtJOI, scOrbitAtJOI.Period(), scOrbitAtJOI.Period().Hours()/24, scOrbitAtJOI.Energyξ(), Φfpa*r2d, scOrbitAtJOI.Apoapsis(), scOrbitAtJOI.Periapsis(), scOrbitAtJOI.VNorm(), ψJupiter*r2d)
	// Set the radius of periapsis at Jupiter to be 4*R_j (similar to that of the mission).

	fmt.Println("==== Earth resonnance ====")
	aResonance := math.Pow(smd.Sun.GM()*math.Pow(resonance*earthAtEGA1.Period().Seconds()/(2*math.Pi), 2), 1/3.)
	VScSunNorm := math.Sqrt(smd.Sun.GM() * ((2 / earthAtEGA1.RNorm()) - 1/aResonance))
	// Compute angle theta for EGA1
	theta := math.Acos((math.Pow(VScSunNorm, 2) - math.Pow(vInfOutGA1Norm, 2) - math.Pow(earthAtEGA1.VNorm(), 2)) / (-2 * vInfOutGA1Norm * earthAtEGA1.VNorm()))
	fmt.Printf("theta = %f\n", theta*r2d)
	// Compute the VNC2ECI DCMs for EGA1 and EGA2.
	V := unit(earthAtEGA1.V())
	N := unit(earthAtEGA1.H())
	C := cross(V, N)
	dcmVal := make([]float64, 9)
	for i := 0; i < 3; i++ {
		dcmVal[i] = V[i]
		dcmVal[i+3] = N[i]
		dcmVal[i+6] = C[i]
	}
	DCM := mat64.NewDense(3, 3, dcmVal)

	ψ := 165.924 * d2r // My choice of Phi for the resonance.
	// Reset scOrbitAtEGA2 because we used that for the propagation.
	scOrbitAtEGA2 = smd.NewOrbitFromRV(earthAtEGA2.R(), []float64{ViGA2.At(0, 0), ViGA2.At(1, 0), ViGA2.At(2, 0)}, smd.Sun)
	scOrbitAtEGA2.ToXCentric(smd.Earth, ega2)

	sψ, cψ := math.Sincos(ψ)
	vInfOutGA1VNC := []float64{vInfOutGA1Norm * math.Cos(math.Pi-theta), vInfOutGA1Norm * math.Sin(math.Pi-theta) * cψ, -vInfOutGA1Norm * math.Sin(math.Pi-theta) * sψ}
	vInfOutGA1 := MxV33(DCM, vInfOutGA1VNC)
	_, rPEGA1, bTEGA1, bREGA1, _, _ := smd.GAFromVinf(vInfInGA1, vInfOutGA1, smd.Earth)
	fmt.Printf("==== EGA1 INFO ====\nrP=%f km\tBt=%f km\tBr=%f\nVin=%f\tVout=%f\nDelta=%f\n\n", rPEGA1, bTEGA1, bREGA1, norm(vInfInGA1), norm(vInfOutGA1), norm(vInfOutGA1)-norm(vInfInGA1))

	vInfInGA2 := make([]float64, 3)
	for i := 0; i < 3; i++ {
		vInfInGA2[i] = vInfOutGA1[i] + scOrbitAtEGA1.V()[i] - scOrbitAtEGA2.V()[i]
	}
	_, rPEGA2, bTEGA2, bREGA2, _, _ := smd.GAFromVinf(vInfOutGA1, vInfInGA2, smd.Earth)
	fmt.Printf("==== EGA2 INFO ====\nrP=%f km\tBt=%f km\tBr=%f\nVin=%f\tVout=%f\nDelta=%f\n\n", rPEGA2, bTEGA2, bREGA2, norm(vInfOutGA1), norm(vInfInGA2), norm(vInfInGA2)-norm(vInfOutGA1))

}

// Unshamefully copied from smd/math.go
func cross(a, b []float64) []float64 {
	return []float64{a[1]*b[2] - a[2]*b[1],
		a[2]*b[0] - a[0]*b[2],
		a[0]*b[1] - a[1]*b[0]} // Cross product R x V.
}

// norm returns the norm of a given vector which is supposed to be 3x1.
func norm(v []float64) float64 {
	return math.Sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2])
}

// unit returns the unit vector of a given vector.
func unit(a []float64) (b []float64) {
	n := norm(a)
	if floats.EqualWithinAbs(n, 0, 1e-12) {
		return []float64{0, 0, 0}
	}
	b = make([]float64, len(a))
	for i, val := range a {
		b[i] = val / n
	}
	return
}

// MxV33 multiplies a matrix with a vector. Note that there is no dimension check!
func MxV33(m *mat64.Dense, v []float64) (o []float64) {
	vVec := mat64.NewVector(len(v), v)
	var rVec mat64.Vector
	rVec.MulVec(m, vVec)
	return []float64{rVec.At(0, 0), rVec.At(1, 0), rVec.At(2, 0)}
}
<|endoftext|>


<commit_before>package client_fakes

import (
	"bytes"
	"errors"
	"fmt"
	"os"
	"path/filepath"

	services "github.com/maximilien/softlayer-go/services"
	softlayer "github.com/maximilien/softlayer-go/softlayer"
)

const (
	SOFTLAYER_API_URL  = "api.softlayer.com/rest/v3"
	TEMPLATE_ROOT_PATH = "templates"
)

type FakeSoftLayerClient struct {
	Username string
	ApiKey   string

	TemplatePath string

	SoftLayerServices map[string]softlayer.Service

	DoRawHttpRequestResponseCount int

	DoRawHttpRequestResponse       []byte
	DoRawHttpRequestResponses      [][]byte
	DoRawHttpRequestResponsesIndex int
	DoRawHttpRequestError          error
	DoRawHttpRequestPath           string
	DoRawHttpRequestRequestType    string

	GenerateRequestBodyBuffer *bytes.Buffer
	GenerateRequestBodyError  error

	HasErrorsError, CheckForHttpResponseError error
}

func NewFakeSoftLayerClient(username, apiKey string) *FakeSoftLayerClient {
	pwd, _ := os.Getwd()
	fslc := &FakeSoftLayerClient{
		Username: username,
		ApiKey:   apiKey,

		TemplatePath: filepath.Join(pwd, TEMPLATE_ROOT_PATH),

		SoftLayerServices: map[string]softlayer.Service{},

		DoRawHttpRequestResponseCount: 0,

		DoRawHttpRequestResponse:       nil,
		DoRawHttpRequestResponses:      [][]byte{},
		DoRawHttpRequestResponsesIndex: 0,
		DoRawHttpRequestError:          nil,
		DoRawHttpRequestPath:           "",
		DoRawHttpRequestRequestType:    "",

		GenerateRequestBodyBuffer: new(bytes.Buffer),
		GenerateRequestBodyError:  nil,

		HasErrorsError:            nil,
		CheckForHttpResponseError: nil,
	}

	fslc.initSoftLayerServices()

	return fslc
}

//softlayer.Client interface methods

func (fslc *FakeSoftLayerClient) GetService(serviceName string) (softlayer.Service, error) {
	slService, ok := fslc.SoftLayerServices[serviceName]
	if !ok {
		return nil, errors.New(fmt.Sprintf("softlayer-go does not support service '%s'", serviceName))
	}

	return slService, nil
}

func (fslc *FakeSoftLayerClient) GetSoftLayer_Account_Service() (softlayer.SoftLayer_Account_Service, error) {
	slService, err := fslc.GetService("SoftLayer_Account")
	if err != nil {
		return nil, err
	}

	return slService.(softlayer.SoftLayer_Account_Service), nil
}

func (fslc *FakeSoftLayerClient) GetSoftLayer_Virtual_Guest_Service() (softlayer.SoftLayer_Virtual_Guest_Service, error) {
	slService, err := fslc.GetService("SoftLayer_Virtual_Guest")
	if err != nil {
		return nil, err
	}

	return slService.(softlayer.SoftLayer_Virtual_Guest_Service), nil
}

func (fslc *FakeSoftLayerClient) GetSoftLayer_Dns_Domain_Service() (softlayer.SoftLayer_Dns_Domain_Service, error) {
	slService, err := fslc.GetService("SoftLayer_Dns_Domain")
	if err != nil {
		return nil, err
	}

	return slService.(softlayer.SoftLayer_Dns_Domain_Service), nil
}

func (fslc *FakeSoftLayerClient) GetSoftLayer_Virtual_Disk_Image_Service() (softlayer.SoftLayer_Virtual_Disk_Image_Service, error) {
	slService, err := fslc.GetService("SoftLayer_Virtual_Disk_Image")
	if err != nil {
		return nil, err
	}

	return slService.(softlayer.SoftLayer_Virtual_Disk_Image_Service), nil
}

func (fslc *FakeSoftLayerClient) GetSoftLayer_Security_Ssh_Key_Service() (softlayer.SoftLayer_Security_Ssh_Key_Service, error) {
	slService, err := fslc.GetService("SoftLayer_Security_Ssh_Key")
	if err != nil {
		return nil, err
	}

	return slService.(softlayer.SoftLayer_Security_Ssh_Key_Service), nil
}

func (fslc *FakeSoftLayerClient) GetSoftLayer_Network_Storage_Service() (softlayer.SoftLayer_Network_Storage_Service, error) {
	slService, err := fslc.GetService("SoftLayer_Network_Storage")
	if err != nil {
		return nil, err
	}

	return slService.(softlayer.SoftLayer_Network_Storage_Service), nil
}

func (fslc *FakeSoftLayerClient) GetSoftLayer_Network_Storage_Allowed_Host_Service() (softlayer.SoftLayer_Network_Storage_Allowed_Host_Service, error) {
	slService, err := fslc.GetService("SoftLayer_Network_Storage_Allowed_Host")
	if err != nil {
		return nil, err
	}

	return slService.(softlayer.SoftLayer_Network_Storage_Allowed_Host_Service), nil
}

func (fslc *FakeSoftLayerClient) GetSoftLayer_Product_Order_Service() (softlayer.SoftLayer_Product_Order_Service, error) {
	slService, err := fslc.GetService("SoftLayer_Product_Order")
	if err != nil {
		return nil, err
	}

	return slService.(softlayer.SoftLayer_Product_Order_Service), nil
}

func (fslc *FakeSoftLayerClient) GetSoftLayer_Product_Package_Service() (softlayer.SoftLayer_Product_Package_Service, error) {
	slService, err := fslc.GetService("SoftLayer_Product_Package")
	if err != nil {
		return nil, err
	}

	return slService.(softlayer.SoftLayer_Product_Package_Service), nil
}

func (fslc *FakeSoftLayerClient) GetSoftLayer_Billing_Item_Cancellation_Request_Service() (softlayer.SoftLayer_Billing_Item_Cancellation_Request_Service, error) {
	slService, err := fslc.GetService("SoftLayer_Billing_Item_Cancellation_Request")
	if err != nil {
		return nil, err
	}

	return slService.(softlayer.SoftLayer_Billing_Item_Cancellation_Request_Service), nil
}

func (fslc *FakeSoftLayerClient) GetSoftLayer_Virtual_Guest_Block_Device_Template_Group_Service() (softlayer.SoftLayer_Virtual_Guest_Block_Device_Template_Group_Service, error) {
	slService, err := fslc.GetService("SoftLayer_Virtual_Guest_Block_Device_Template_Group")
	if err != nil {
		return nil, err
	}

	return slService.(softlayer.SoftLayer_Virtual_Guest_Block_Device_Template_Group_Service), nil
}

func (fslc *FakeSoftLayerClient) GetSoftLayer_Hardware_Service() (softlayer.SoftLayer_Hardware_Service, error) {
	slService, err := fslc.GetService("SoftLayer_Hardware")
	if err != nil {
		return nil, err
	}

	return slService.(softlayer.SoftLayer_Hardware_Service), nil
}

func (fslc *FakeSoftLayerClient) GetSoftLayer_Dns_Domain_Resource_Record_Service() (softlayer.SoftLayer_Dns_Domain_Resource_Record_Service, error) {
	slService, err := fslc.GetService("SoftLayer_Dns_Domain_ResourceRecord")
	if err != nil {
		return nil, err
	}

	return slService.(softlayer.SoftLayer_Dns_Domain_Resource_Record_Service), nil
}

//Public methods
func (fslc *FakeSoftLayerClient) DoRawHttpRequestWithObjectMask(path string, masks []string, requestType string, requestBody *bytes.Buffer) ([]byte, error) {
	fslc.DoRawHttpRequestPath = path
	fslc.DoRawHttpRequestRequestType = requestType

	fslc.DoRawHttpRequestResponseCount += 1

	if fslc.DoRawHttpRequestError != nil {
		return []byte{}, fslc.DoRawHttpRequestError
	}

	if fslc.DoRawHttpRequestResponse != nil {
		return fslc.DoRawHttpRequestResponse, fslc.DoRawHttpRequestError
	} else {
		fslc.DoRawHttpRequestResponsesIndex = fslc.DoRawHttpRequestResponsesIndex + 1
		return fslc.DoRawHttpRequestResponses[fslc.DoRawHttpRequestResponsesIndex-1], fslc.DoRawHttpRequestError
	}
}

func (fslc *FakeSoftLayerClient) DoRawHttpRequestWithObjectFilter(path string, filters string, requestType string, requestBody *bytes.Buffer) ([]byte, error) {
	fslc.DoRawHttpRequestPath = path
	fslc.DoRawHttpRequestRequestType = requestType

	fslc.DoRawHttpRequestResponseCount += 1

	if fslc.DoRawHttpRequestError != nil {
		return []byte{}, fslc.DoRawHttpRequestError
	}

	if fslc.DoRawHttpRequestResponse != nil {
		return fslc.DoRawHttpRequestResponse, fslc.DoRawHttpRequestError
	} else {
		fslc.DoRawHttpRequestResponsesIndex = fslc.DoRawHttpRequestResponsesIndex + 1
		return fslc.DoRawHttpRequestResponses[fslc.DoRawHttpRequestResponsesIndex-1], fslc.DoRawHttpRequestError
	}
}

func (fslc *FakeSoftLayerClient) DoRawHttpRequestWithObjectFilterAndObjectMask(path string, masks []string, filters string, requestType string, requestBody *bytes.Buffer) ([]byte, error) {
	fslc.DoRawHttpRequestPath = path
	fslc.DoRawHttpRequestRequestType = requestType

	fslc.DoRawHttpRequestResponseCount += 1

	if fslc.DoRawHttpRequestError != nil {
		return []byte{}, fslc.DoRawHttpRequestError
	}

	if fslc.DoRawHttpRequestResponse != nil {
		return fslc.DoRawHttpRequestResponse, fslc.DoRawHttpRequestError
	} else {
		fslc.DoRawHttpRequestResponsesIndex = fslc.DoRawHttpRequestResponsesIndex + 1
		return fslc.DoRawHttpRequestResponses[fslc.DoRawHttpRequestResponsesIndex-1], fslc.DoRawHttpRequestError
	}
}

func (fslc *FakeSoftLayerClient) DoRawHttpRequest(path string, requestType string, requestBody *bytes.Buffer) ([]byte, error) {
	fslc.DoRawHttpRequestPath = path
	fslc.DoRawHttpRequestRequestType = requestType

	fslc.DoRawHttpRequestResponseCount += 1

	if fslc.DoRawHttpRequestError != nil {
		return []byte{}, fslc.DoRawHttpRequestError
	}

	if fslc.DoRawHttpRequestResponse != nil {
		return fslc.DoRawHttpRequestResponse, fslc.DoRawHttpRequestError
	} else {
		fslc.DoRawHttpRequestResponsesIndex = fslc.DoRawHttpRequestResponsesIndex + 1
		return fslc.DoRawHttpRequestResponses[fslc.DoRawHttpRequestResponsesIndex-1], fslc.DoRawHttpRequestError
	}
}

func (fslc *FakeSoftLayerClient) GenerateRequestBody(templateData interface{}) (*bytes.Buffer, error) {
	return fslc.GenerateRequestBodyBuffer, fslc.GenerateRequestBodyError
}

func (fslc *FakeSoftLayerClient) HasErrors(body map[string]interface{}) error {
	return fslc.HasErrorsError
}

func (fslc *FakeSoftLayerClient) CheckForHttpResponseErrors(data []byte) error {
	return fslc.CheckForHttpResponseError
}

//Private methods

func (fslc *FakeSoftLayerClient) initSoftLayerServices() {
	fslc.SoftLayerServices["SoftLayer_Account"] = services.NewSoftLayer_Account_Service(fslc)
	fslc.SoftLayerServices["SoftLayer_Virtual_Guest"] = services.NewSoftLayer_Virtual_Guest_Service(fslc)
	fslc.SoftLayerServices["SoftLayer_Virtual_Disk_Image"] = services.NewSoftLayer_Virtual_Disk_Image_Service(fslc)
	fslc.SoftLayerServices["SoftLayer_Security_Ssh_Key"] = services.NewSoftLayer_Security_Ssh_Key_Service(fslc)
	fslc.SoftLayerServices["SoftLayer_Network_Storage"] = services.NewSoftLayer_Network_Storage_Service(fslc)
	fslc.SoftLayerServices["SoftLayer_Network_Storage_Allowed_Host"] = services.NewSoftLayer_Network_Storage_Allowed_Host_Service(fslc)
	fslc.SoftLayerServices["SoftLayer_Product_Order"] = services.NewSoftLayer_Product_Order_Service(fslc)
	fslc.SoftLayerServices["SoftLayer_Product_Package"] = services.NewSoftLayer_Product_Package_Service(fslc)
	fslc.SoftLayerServices["SoftLayer_Billing_Item_Cancellation_Request"] = services.NewSoftLayer_Billing_Item_Cancellation_Request_Service(fslc)
	fslc.SoftLayerServices["SoftLayer_Virtual_Guest_Block_Device_Template_Group"] = services.NewSoftLayer_Virtual_Guest_Block_Device_Template_Group_Service(fslc)
	fslc.SoftLayerServices["SoftLayer_Hardware"] = services.NewSoftLayer_Hardware_Service(fslc)
	fslc.SoftLayerServices["SoftLayer_Dns_Domain"] = services.NewSoftLayer_Dns_Domain_Service(fslc)
	fslc.SoftLayerServices["SoftLayer_Dns_Domain_ResourceRecord"] = services.NewSoftLayer_Dns_Domain_Resource_Record_Service(fslc)
}
<commit_msg>#4 Reverting additional checks in fake client<commit_after>package client_fakes

import (
	"bytes"
	"errors"
	"fmt"
	"os"
	"path/filepath"

	services "github.com/maximilien/softlayer-go/services"
	softlayer "github.com/maximilien/softlayer-go/softlayer"
)

const (
	SOFTLAYER_API_URL  = "api.softlayer.com/rest/v3"
	TEMPLATE_ROOT_PATH = "templates"
)

type FakeSoftLayerClient struct {
	Username string
	ApiKey   string

	TemplatePath string

	SoftLayerServices map[string]softlayer.Service

	DoRawHttpRequestResponseCount int

	DoRawHttpRequestResponse       []byte
	DoRawHttpRequestResponses      [][]byte
	DoRawHttpRequestResponsesIndex int
	DoRawHttpRequestError          error
	DoRawHttpRequestPath           string
	DoRawHttpRequestRequestType    string

	GenerateRequestBodyBuffer *bytes.Buffer
	GenerateRequestBodyError  error

	HasErrorsError, CheckForHttpResponseError error
}

func NewFakeSoftLayerClient(username, apiKey string) *FakeSoftLayerClient {
	pwd, _ := os.Getwd()
	fslc := &FakeSoftLayerClient{
		Username: username,
		ApiKey:   apiKey,

		TemplatePath: filepath.Join(pwd, TEMPLATE_ROOT_PATH),

		SoftLayerServices: map[string]softlayer.Service{},

		DoRawHttpRequestResponseCount: 0,

		DoRawHttpRequestResponse:       nil,
		DoRawHttpRequestResponses:      [][]byte{},
		DoRawHttpRequestResponsesIndex: 0,
		DoRawHttpRequestError:          nil,
		DoRawHttpRequestPath:           "",
		DoRawHttpRequestRequestType:    "",

		GenerateRequestBodyBuffer: new(bytes.Buffer),
		GenerateRequestBodyError:  nil,

		HasErrorsError:            nil,
		CheckForHttpResponseError: nil,
	}

	fslc.initSoftLayerServices()

	return fslc
}

//softlayer.Client interface methods

func (fslc *FakeSoftLayerClient) GetService(serviceName string) (softlayer.Service, error) {
	slService, ok := fslc.SoftLayerServices[serviceName]
	if !ok {
		return nil, errors.New(fmt.Sprintf("softlayer-go does not support service '%s'", serviceName))
	}

	return slService, nil
}

func (fslc *FakeSoftLayerClient) GetSoftLayer_Account_Service() (softlayer.SoftLayer_Account_Service, error) {
	slService, err := fslc.GetService("SoftLayer_Account")
	if err != nil {
		return nil, err
	}

	return slService.(softlayer.SoftLayer_Account_Service), nil
}

func (fslc *FakeSoftLayerClient) GetSoftLayer_Virtual_Guest_Service() (softlayer.SoftLayer_Virtual_Guest_Service, error) {
	slService, err := fslc.GetService("SoftLayer_Virtual_Guest")
	if err != nil {
		return nil, err
	}

	return slService.(softlayer.SoftLayer_Virtual_Guest_Service), nil
}

func (fslc *FakeSoftLayerClient) GetSoftLayer_Dns_Domain_Service() (softlayer.SoftLayer_Dns_Domain_Service, error) {
	slService, err := fslc.GetService("SoftLayer_Dns_Domain")
	if err != nil {
		return nil, err
	}

	return slService.(softlayer.SoftLayer_Dns_Domain_Service), nil
}

func (fslc *FakeSoftLayerClient) GetSoftLayer_Virtual_Disk_Image_Service() (softlayer.SoftLayer_Virtual_Disk_Image_Service, error) {
	slService, err := fslc.GetService("SoftLayer_Virtual_Disk_Image")
	if err != nil {
		return nil, err
	}

	return slService.(softlayer.SoftLayer_Virtual_Disk_Image_Service), nil
}

func (fslc *FakeSoftLayerClient) GetSoftLayer_Security_Ssh_Key_Service() (softlayer.SoftLayer_Security_Ssh_Key_Service, error) {
	slService, err := fslc.GetService("SoftLayer_Security_Ssh_Key")
	if err != nil {
		return nil, err
	}

	return slService.(softlayer.SoftLayer_Security_Ssh_Key_Service), nil
}

func (fslc *FakeSoftLayerClient) GetSoftLayer_Network_Storage_Service() (softlayer.SoftLayer_Network_Storage_Service, error) {
	slService, err := fslc.GetService("SoftLayer_Network_Storage")
	if err != nil {
		return nil, err
	}

	return slService.(softlayer.SoftLayer_Network_Storage_Service), nil
}

func (fslc *FakeSoftLayerClient) GetSoftLayer_Network_Storage_Allowed_Host_Service() (softlayer.SoftLayer_Network_Storage_Allowed_Host_Service, error) {
	slService, err := fslc.GetService("SoftLayer_Network_Storage_Allowed_Host")
	if err != nil {
		return nil, err
	}

	return slService.(softlayer.SoftLayer_Network_Storage_Allowed_Host_Service), nil
}

func (fslc *FakeSoftLayerClient) GetSoftLayer_Product_Order_Service() (softlayer.SoftLayer_Product_Order_Service, error) {
	slService, err := fslc.GetService("SoftLayer_Product_Order")
	if err != nil {
		return nil, err
	}

	return slService.(softlayer.SoftLayer_Product_Order_Service), nil
}

func (fslc *FakeSoftLayerClient) GetSoftLayer_Product_Package_Service() (softlayer.SoftLayer_Product_Package_Service, error) {
	slService, err := fslc.GetService("SoftLayer_Product_Package")
	if err != nil {
		return nil, err
	}

	return slService.(softlayer.SoftLayer_Product_Package_Service), nil
}

func (fslc *FakeSoftLayerClient) GetSoftLayer_Billing_Item_Cancellation_Request_Service() (softlayer.SoftLayer_Billing_Item_Cancellation_Request_Service, error) {
	slService, err := fslc.GetService("SoftLayer_Billing_Item_Cancellation_Request")
	if err != nil {
		return nil, err
	}

	return slService.(softlayer.SoftLayer_Billing_Item_Cancellation_Request_Service), nil
}

func (fslc *FakeSoftLayerClient) GetSoftLayer_Virtual_Guest_Block_Device_Template_Group_Service() (softlayer.SoftLayer_Virtual_Guest_Block_Device_Template_Group_Service, error) {
	slService, err := fslc.GetService("SoftLayer_Virtual_Guest_Block_Device_Template_Group")
	if err != nil {
		return nil, err
	}

	return slService.(softlayer.SoftLayer_Virtual_Guest_Block_Device_Template_Group_Service), nil
}

func (fslc *FakeSoftLayerClient) GetSoftLayer_Hardware_Service() (softlayer.SoftLayer_Hardware_Service, error) {
	slService, err := fslc.GetService("SoftLayer_Hardware")
	if err != nil {
		return nil, err
	}

	return slService.(softlayer.SoftLayer_Hardware_Service), nil
}

func (fslc *FakeSoftLayerClient) GetSoftLayer_Dns_Domain_Resource_Record_Service() (softlayer.SoftLayer_Dns_Domain_Resource_Record_Service, error) {
	slService, err := fslc.GetService("SoftLayer_Dns_Domain_ResourceRecord")
	if err != nil {
		return nil, err
	}

	return slService.(softlayer.SoftLayer_Dns_Domain_Resource_Record_Service), nil
}

//Public methods
func (fslc *FakeSoftLayerClient) DoRawHttpRequestWithObjectMask(path string, masks []string, requestType string, requestBody *bytes.Buffer) ([]byte, error) {
	fslc.DoRawHttpRequestPath = path
	fslc.DoRawHttpRequestRequestType = requestType

	fslc.DoRawHttpRequestResponseCount += 1

	if fslc.DoRawHttpRequestError != nil {
		return []byte{}, fslc.DoRawHttpRequestError
	}

	if fslc.DoRawHttpRequestResponse != nil && len(fslc.DoRawHttpRequestResponses) == 0 {
		return fslc.DoRawHttpRequestResponse, fslc.DoRawHttpRequestError
	} else {
		fslc.DoRawHttpRequestResponsesIndex = fslc.DoRawHttpRequestResponsesIndex + 1
		return fslc.DoRawHttpRequestResponses[fslc.DoRawHttpRequestResponsesIndex-1], fslc.DoRawHttpRequestError
	}
}

func (fslc *FakeSoftLayerClient) DoRawHttpRequestWithObjectFilter(path string, filters string, requestType string, requestBody *bytes.Buffer) ([]byte, error) {
	fslc.DoRawHttpRequestPath = path
	fslc.DoRawHttpRequestRequestType = requestType

	fslc.DoRawHttpRequestResponseCount += 1

	if fslc.DoRawHttpRequestError != nil {
		return []byte{}, fslc.DoRawHttpRequestError
	}

	if fslc.DoRawHttpRequestResponse != nil && len(fslc.DoRawHttpRequestResponses) == 0 {
		return fslc.DoRawHttpRequestResponse, fslc.DoRawHttpRequestError
	} else {
		fslc.DoRawHttpRequestResponsesIndex = fslc.DoRawHttpRequestResponsesIndex + 1
		return fslc.DoRawHttpRequestResponses[fslc.DoRawHttpRequestResponsesIndex-1], fslc.DoRawHttpRequestError
	}
}

func (fslc *FakeSoftLayerClient) DoRawHttpRequestWithObjectFilterAndObjectMask(path string, masks []string, filters string, requestType string, requestBody *bytes.Buffer) ([]byte, error) {
	fslc.DoRawHttpRequestPath = path
	fslc.DoRawHttpRequestRequestType = requestType

	fslc.DoRawHttpRequestResponseCount += 1

	if fslc.DoRawHttpRequestError != nil {
		return []byte{}, fslc.DoRawHttpRequestError
	}

	if fslc.DoRawHttpRequestResponse != nil && len(fslc.DoRawHttpRequestResponses) == 0 {
		return fslc.DoRawHttpRequestResponse, fslc.DoRawHttpRequestError
	} else {
		fslc.DoRawHttpRequestResponsesIndex = fslc.DoRawHttpRequestResponsesIndex + 1
		return fslc.DoRawHttpRequestResponses[fslc.DoRawHttpRequestResponsesIndex-1], fslc.DoRawHttpRequestError
	}
}

func (fslc *FakeSoftLayerClient) DoRawHttpRequest(path string, requestType string, requestBody *bytes.Buffer) ([]byte, error) {
	fslc.DoRawHttpRequestPath = path
	fslc.DoRawHttpRequestRequestType = requestType

	fslc.DoRawHttpRequestResponseCount += 1

	if fslc.DoRawHttpRequestError != nil {
		return []byte{}, fslc.DoRawHttpRequestError
	}

	if fslc.DoRawHttpRequestResponse != nil && len(fslc.DoRawHttpRequestResponses) == 0 {
		return fslc.DoRawHttpRequestResponse, fslc.DoRawHttpRequestError
	} else {
		fslc.DoRawHttpRequestResponsesIndex = fslc.DoRawHttpRequestResponsesIndex + 1
		return fslc.DoRawHttpRequestResponses[fslc.DoRawHttpRequestResponsesIndex-1], fslc.DoRawHttpRequestError
	}
}

func (fslc *FakeSoftLayerClient) GenerateRequestBody(templateData interface{}) (*bytes.Buffer, error) {
	return fslc.GenerateRequestBodyBuffer, fslc.GenerateRequestBodyError
}

func (fslc *FakeSoftLayerClient) HasErrors(body map[string]interface{}) error {
	return fslc.HasErrorsError
}

func (fslc *FakeSoftLayerClient) CheckForHttpResponseErrors(data []byte) error {
	return fslc.CheckForHttpResponseError
}

//Private methods

func (fslc *FakeSoftLayerClient) initSoftLayerServices() {
	fslc.SoftLayerServices["SoftLayer_Account"] = services.NewSoftLayer_Account_Service(fslc)
	fslc.SoftLayerServices["SoftLayer_Virtual_Guest"] = services.NewSoftLayer_Virtual_Guest_Service(fslc)
	fslc.SoftLayerServices["SoftLayer_Virtual_Disk_Image"] = services.NewSoftLayer_Virtual_Disk_Image_Service(fslc)
	fslc.SoftLayerServices["SoftLayer_Security_Ssh_Key"] = services.NewSoftLayer_Security_Ssh_Key_Service(fslc)
	fslc.SoftLayerServices["SoftLayer_Network_Storage"] = services.NewSoftLayer_Network_Storage_Service(fslc)
	fslc.SoftLayerServices["SoftLayer_Network_Storage_Allowed_Host"] = services.NewSoftLayer_Network_Storage_Allowed_Host_Service(fslc)
	fslc.SoftLayerServices["SoftLayer_Product_Order"] = services.NewSoftLayer_Product_Order_Service(fslc)
	fslc.SoftLayerServices["SoftLayer_Product_Package"] = services.NewSoftLayer_Product_Package_Service(fslc)
	fslc.SoftLayerServices["SoftLayer_Billing_Item_Cancellation_Request"] = services.NewSoftLayer_Billing_Item_Cancellation_Request_Service(fslc)
	fslc.SoftLayerServices["SoftLayer_Virtual_Guest_Block_Device_Template_Group"] = services.NewSoftLayer_Virtual_Guest_Block_Device_Template_Group_Service(fslc)
	fslc.SoftLayerServices["SoftLayer_Hardware"] = services.NewSoftLayer_Hardware_Service(fslc)
	fslc.SoftLayerServices["SoftLayer_Dns_Domain"] = services.NewSoftLayer_Dns_Domain_Service(fslc)
	fslc.SoftLayerServices["SoftLayer_Dns_Domain_ResourceRecord"] = services.NewSoftLayer_Dns_Domain_Resource_Record_Service(fslc)
}
<|endoftext|>


<commit_before>package scalyr

import (
	"bytes"
	"encoding/json"
	"net/http"
	"strconv"
	"time"
)

var _config Config
var _scalyrEventsWrapper scalyrEventsWrapper
var _scalyrEvents []scalyrEvent

type Application interface {
	Event(sev Severity, attributes interface{})
}

type app struct {
	config Config
}

//
// event should accept Severity ( 0 - 6 ??, 3 being info:  and a message :  and 1 or more additional attributes)
// The "sev" (severity) field should range from 0 to 6, and identifies the importance of this event, using the
//  classic scale "finest, finer, fine, info, warning, error, fatal". This field is optional (defaults to 3 / info).
//
func (app *app) Event(sev Severity, attributes interface{}) {

	se := &scalyrEvent{
		TS:    strconv.FormatInt(time.Now().UnixNano(), 10),
		Type:  0,
		Sev:   int(sev),
		Attrs: attributes,
	}

	if _scalyrEvents == nil {

		_scalyrEvents = make([]scalyrEvent, 1)
		_scalyrEvents[0] = *se

	} else {
		_scalyrEvents = append(_scalyrEvents, *se)
	}

}

//
// returns a new config struct configured with values...
//
func NewApplication(config Config) Application {

	_config = config

	a := &app{}

	initialize()

	start()

	return a
}

func initialize() {
	si := &scalyrSessionInfo{
		ServerType: "server type here TODO replace this...",
		ServerId:   _APPLICATION_HOSTNAME,
	}

	_scalyrEventsWrapper = scalyrEventsWrapper{
		Token:       _config.ScalyrEventWriteKey,
		Session:     _APPLICATION_PROCESS_ID,
		SessionInfo: *si,
		Events:      nil,
	}

	Print("Events wrapper created: ", _scalyrEventsWrapper)
}

func start() {

	go func() {
		for range ticker.C {
			flush()
		}
	}()

}

func flush() {
	Print("Flushing events NOW. ", nil)

	_scalyrEventsWrapper.Events = _scalyrEvents

	json, _ := json.Marshal(_scalyrEventsWrapper)

	Print("Events being sent to Scalyr: ", string(json))
	//fmt.Println(string(json))

	url := _SCALYR_ADDEVENTS_ENDPOINT

	req, err := http.NewRequest("POST", url, bytes.NewBuffer(json))
	req.Header.Set("Content-Type", "application/json")

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		//panic(err)
		Print("ERROR trying to POST to Scalyr API:", err)
	}
	defer resp.Body.Close()

	Print("Status that came back from Scalyr: ", resp.Status)

	//fmt.Println("response Status:", resp.Status)
	//fmt.Println("response Headers:", resp.Header)
	//body, _ := ioutil.ReadAll(resp.Body)
	//fmt.Println("response Body:", string(body))
}
<commit_msg>first iteration on implementing mutex<commit_after>package scalyr

import (
	"bytes"
	"encoding/json"
	"net/http"
	"strconv"
	"sync"
	"time"
)

var _config Config
var _scalyrEventsWrapper scalyrEventsWrapper
var _scalyrEvents []scalyrEvent
var mutex = &sync.Mutex{}

type Application interface {
	Event(sev Severity, attributes interface{})
}

type app struct {
	config Config
}

//
// event should accept Severity ( 0 - 6 ??, 3 being info:  and a message :  and 1 or more additional attributes)
// The "sev" (severity) field should range from 0 to 6, and identifies the importance of this event, using the
//  classic scale "finest, finer, fine, info, warning, error, fatal". This field is optional (defaults to 3 / info).
//
func (app *app) Event(sev Severity, attributes interface{}) {

	se := &scalyrEvent{
		TS:    strconv.FormatInt(time.Now().UnixNano(), 10),
		Type:  0,
		Sev:   int(sev),
		Attrs: attributes,
	}

	if _scalyrEvents == nil {

		_scalyrEvents = make([]scalyrEvent, 1)
		_scalyrEvents[0] = *se

	} else {
		_scalyrEvents = append(_scalyrEvents, *se)
	}

}

//
// returns a new config struct configured with values...
//
func NewApplication(config Config) Application {

	_config = config

	a := &app{}

	initialize()

	start()

	return a
}

func initialize() {
	si := &scalyrSessionInfo{
		ServerType: "server type here TODO replace this...",
		ServerId:   _APPLICATION_HOSTNAME,
	}

	_scalyrEventsWrapper = scalyrEventsWrapper{
		Token:       _config.ScalyrEventWriteKey,
		Session:     _APPLICATION_PROCESS_ID,
		SessionInfo: *si,
		Events:      nil,
	}

	Print("Events wrapper created: ", _scalyrEventsWrapper)
}

func start() {

	go func() {
		for range ticker.C {
			go flush()
		}
	}()

}

func flush() {
	Print("Flushing events NOW. ", nil)

	mutex.Lock()

	_scalyrEventsWrapper.Events = _scalyrEvents

	json, _ := json.Marshal(_scalyrEventsWrapper)

	Print("Events being sent to Scalyr: ", string(json))
	//fmt.Println(string(json))

	url := _SCALYR_ADDEVENTS_ENDPOINT

	req, err := http.NewRequest("POST", url, bytes.NewBuffer(json))
	req.Header.Set("Content-Type", "application/json")

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		//panic(err)
		Print("ERROR trying to POST to Scalyr API:", err)
	} else {

		//
		// TODO check for 200, raise err if it is not good...
		//
		_scalyrEvents = _scalyrEvents[:0]
		mutex.Unlock()
	}
	defer resp.Body.Close()

	Print("Status that came back from Scalyr: ", resp.Status)

	//fmt.Println("response Status:", resp.Status)
	//fmt.Println("response Headers:", resp.Header)
	//body, _ := ioutil.ReadAll(resp.Body)
	//fmt.Println("response Body:", string(body))
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/amlun/linda/linda"
	"github.com/amlun/linda/modules/server"
)

func main() {
	var config = linda.Config{
		BrokerURL: "redis://10.60.81.83:6379",
		SaverURL:  "cassandra://cassandra:cassandra@10.60.81.83:9042/linda",
	}
	l := linda.NewLinda(&config)
	server.Start(l)
}
<commit_msg>delete server<commit_after><|endoftext|>


<commit_before>// Package appsettings provides simple key/value store functionality
package appsettings

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"strconv"
)

type DataTree map[string]string

type dataStruct struct {
	Tree map[string]DataTree
}

type AppSettings struct {
	filename string
	data     dataStruct
}

func NewAppSettings(dbFilename string) (*AppSettings, error) {
	var data dataStruct
	if _, err := os.Stat(dbFilename); os.IsNotExist(err) {
		data = dataStruct{
			Tree: make(map[string]DataTree),
		}

		d1, _ := json.Marshal(data)
		err := ioutil.WriteFile(dbFilename, d1, 0644)
		if err != nil {
			return nil, err
		}
	} else {
		d1, err := ioutil.ReadFile(dbFilename)
		if err != nil {
			return nil, err
		}
		json.Unmarshal(d1, &data)

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

	return &AppSettings{filename: dbFilename, data: data}, nil
}

func (a *DataTree) GetString(key string) (string, error) {
	y := *a
	if _, ok := y[key]; !ok {
		return "", fmt.Errorf("undefined key %s", key)
	}

	return y[key], nil
}

func (a *DataTree) SetString(key string, val string) {
	y := *a
	y[key] = val
}

func (a *DataTree) GetInt(key string) (int, error) {
	str, err := a.GetString(key)
	if err != nil {
		return 0, err
	}

	i, err := strconv.Atoi(str)
	if err != nil {
		return 0, err
	}
	return i, nil
}

func (a *DataTree) SetInt(key string, val int) {
	y := *a
	y[key] = strconv.Itoa(val)
}

func (a *DataTree) GetInt64(key string) (int64, error) {
	str, err := a.GetString(key)
	if err != nil {
		return 0, err
	}

	i, err := strconv.ParseInt(str, 10, 64)
	if err != nil {
		return 0, err
	}
	return i, nil
}

func (a *DataTree) SetInt64(key string, val int64) {
	y := *a
	y[key] = strconv.FormatInt(val, 10)
}

func (a *DataTree) Delete(key string) {
	delete(*a, key)
}

func (a *AppSettings) GetTree(key string) DataTree {
	if _, ok := a.data.Tree[key]; !ok {
		a.data.Tree[key] = make(DataTree)
	}

	return a.data.Tree[key]
}

func (a *AppSettings) Persist() error {
	d1, _ := json.Marshal(a.data)
	err := ioutil.WriteFile(a.filename, d1, 0644)
	if err != nil {
		return err
	}

	return nil
}
<commit_msg>Makes persistence thread safe.<commit_after>// Package appsettings provides simple key/value store functionality
package appsettings

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"strconv"
	"sync"
)

type DataTree map[string]string

type dataStruct struct {
	Tree map[string]DataTree
}

type AppSettings struct {
	filename string
	data     dataStruct

	sync.Mutex
}

func NewAppSettings(dbFilename string) (*AppSettings, error) {
	var data dataStruct
	if _, err := os.Stat(dbFilename); os.IsNotExist(err) {
		data = dataStruct{
			Tree: make(map[string]DataTree),
		}

		d1, _ := json.Marshal(data)
		err := ioutil.WriteFile(dbFilename, d1, 0644)
		if err != nil {
			return nil, err
		}
	} else {
		d1, err := ioutil.ReadFile(dbFilename)
		if err != nil {
			return nil, err
		}

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

	return &AppSettings{filename: dbFilename, data: data}, nil
}

func (a *DataTree) GetString(key string) (string, error) {
	y := *a
	if _, ok := y[key]; !ok {
		return "", fmt.Errorf("undefined key %s", key)
	}

	return y[key], nil
}

func (a *DataTree) SetString(key string, val string) {
	y := *a
	y[key] = val
}

func (a *DataTree) GetInt(key string) (int, error) {
	str, err := a.GetString(key)
	if err != nil {
		return 0, err
	}

	i, err := strconv.Atoi(str)
	if err != nil {
		return 0, err
	}
	return i, nil
}

func (a *DataTree) SetInt(key string, val int) {
	y := *a
	y[key] = strconv.Itoa(val)
}

func (a *DataTree) GetInt64(key string) (int64, error) {
	str, err := a.GetString(key)
	if err != nil {
		return 0, err
	}

	i, err := strconv.ParseInt(str, 10, 64)
	if err != nil {
		return 0, err
	}
	return i, nil
}

func (a *DataTree) SetInt64(key string, val int64) {
	y := *a
	y[key] = strconv.FormatInt(val, 10)
}

func (a *DataTree) Delete(key string) {
	delete(*a, key)
}

func (a *AppSettings) GetTree(key string) DataTree {
	a.Lock()
	defer a.Unlock()

	if _, ok := a.data.Tree[key]; !ok {
		a.data.Tree[key] = make(DataTree)
	}

	return a.data.Tree[key]
}

// Persist causes the current state of the app settings to be persisted.
func (a *AppSettings) Persist() error {
	a.Lock()
	defer a.Unlock()

	d1, _ := json.Marshal(a.data)
	err := ioutil.WriteFile(a.filename, d1, 0644)
	if err != nil {
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>package main
// Print the MX records of a domain
// (c) Miek Gieben - 2011
import (
	"dns"
	"fmt"
	"os"
)

func main() {
	if len(os.Args) != 2 {
		fmt.Printf("%s DOMAIN\n", os.Args[0])
		os.Exit(1)
	}

	// Error checking
	config, _ := dns.ClientConfigFromFile("/etc/resolv.conf")
	c := dns.NewClient()

	m := new(dns.Msg)
	m.SetQuestion(os.Args[1], dns.TypeMX)
	m.MsgHdr.RecursionDesired = true

	// Simple sync query, nothing fancy
        r, err := c.Exchange(m, config.Servers[0] + ":" + config.Port)
	if err != nil {
		fmt.Printf("%s\n", err.Error())
		os.Exit(1)
	}

	if r.Rcode != dns.RcodeSuccess {
		fmt.Printf(" *** invalid answer name %s after MX query for %s\n", os.Args[1], os.Args[1])
		os.Exit(1)
	}
	// Stuff must be in the answer section
	for _, a := range r.Answer {
		fmt.Printf("%v\n", a)
	}
}
<commit_msg>Make it fqdn<commit_after>package main
// Print the MX records of a domain
// (c) Miek Gieben - 2011
import (
	"dns"
	"fmt"
	"os"
)

func main() {
	if len(os.Args) != 2 {
		fmt.Printf("%s DOMAIN\n", os.Args[0])
		os.Exit(1)
	}

	// Error checking
	config, _ := dns.ClientConfigFromFile("/etc/resolv.conf")
	c := dns.NewClient()

	m := new(dns.Msg)
	m.SetQuestion(dns.Fqdn(os.Args[1]), dns.TypeMX)
	m.MsgHdr.RecursionDesired = true

	// Simple sync query, nothing fancy
        r, err := c.Exchange(m, config.Servers[0] + ":" + config.Port)
	if err != nil {
		fmt.Printf("%s\n", err.Error())
		os.Exit(1)
	}

	if r.Rcode != dns.RcodeSuccess {
		fmt.Printf(" *** invalid answer name %s after MX query for %s\n", os.Args[1], os.Args[1])
		os.Exit(1)
	}
	// Stuff must be in the answer section
	for _, a := range r.Answer {
		fmt.Printf("%v\n", a)
	}
}
<|endoftext|>


<commit_before>package main
// Print the MX records of a domain
// (c) Miek Gieben - 2011
import (
	"dns"
	"fmt"
	"os"
)

func main() {
	if len(os.Args) != 2 {
		fmt.Printf("%s DOMAIN\n", os.Args[0])
		os.Exit(1)
	}

	// Error checking
	config, _ := dns.ClientConfigFromFile("/etc/resolv.conf")
	c := dns.NewClient()

	m := new(dns.Msg)
	m.SetQuestion(dns.Fqdn(os.Args[1]), dns.TypeMX)
	m.MsgHdr.RecursionDesired = true

	// Simple sync query, nothing fancy
        r, err := c.Exchange(m, config.Servers[0] + ":" + config.Port)
	if err != nil {
		fmt.Printf("%s\n", err.Error())
		os.Exit(1)
	}
	if r.Rcode != dns.RcodeSuccess {
		fmt.Printf(" *** invalid answer name %s after MX query for %s\n", os.Args[1], os.Args[1])
		os.Exit(1)
	}
	// Stuff must be in the answer section
	for _, a := range r.Answer {
		fmt.Printf("%v\n", a)
	}
        println(r.String())
        buf, _ := r.Pack()
        r1 := new(dns.Msg)
        ok := r1.Unpack(buf)
        if ok {
                fmt.Printf("%s", r1.String())
        } else {
                fmt.Printf("%s", r1.String())
                fmt.Printf("Failed to unpack compressed msg")
        }
}
<commit_msg>Cleanup mx.go<commit_after>package main
// Print the MX records of a domain
// (c) Miek Gieben - 2011
import (
	"dns"
	"fmt"
	"os"
)

func main() {
	if len(os.Args) != 2 {
		fmt.Printf("%s DOMAIN\n", os.Args[0])
		os.Exit(1)
	}

	// Error checking
	config, _ := dns.ClientConfigFromFile("/etc/resolv.conf")
	c := dns.NewClient()

	m := new(dns.Msg)
	m.SetQuestion(dns.Fqdn(os.Args[1]), dns.TypeMX)
	m.MsgHdr.RecursionDesired = true

	// Simple sync query, nothing fancy
        r, err := c.Exchange(m, config.Servers[0] + ":" + config.Port)
	if err != nil {
		fmt.Printf("%s\n", err.Error())
		os.Exit(1)
	}
	if r.Rcode != dns.RcodeSuccess {
		fmt.Printf(" *** invalid answer name %s after MX query for %s\n", os.Args[1], os.Args[1])
		os.Exit(1)
	}
	// Stuff must be in the answer section
	for _, a := range r.Answer {
		fmt.Printf("%v\n", a)
	}
}
<|endoftext|>


<commit_before>// Copyright 2015 CoreOS, Inc.
//
// 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 docker2aci implements a simple library for converting docker images to
// App Container Images (ACIs).
package docker2aci

import (
	"archive/tar"
	"compress/gzip"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"

	"github.com/appc/docker2aci/lib/backend/file"
	"github.com/appc/docker2aci/lib/backend/repository"
	"github.com/appc/docker2aci/lib/common"
	"github.com/appc/docker2aci/lib/types"
	"github.com/appc/docker2aci/lib/util"
	"github.com/appc/docker2aci/tarball"
	"github.com/appc/spec/pkg/acirenderer"
	"github.com/appc/spec/schema"
	appctypes "github.com/appc/spec/schema/types"
)

type Docker2ACIBackend interface {
	GetImageInfo(dockerUrl string) ([]string, *types.ParsedDockerURL, error)
	BuildACI(layerID string, dockerURL *types.ParsedDockerURL, outputDir string, tmpBaseDir string, curPWl []string, compress bool) (string, *schema.ImageManifest, error)
}

// Convert generates ACI images from docker registry URLs.
// It takes as input a dockerURL of the form:
//
// 	{docker registry URL}/{image name}:{tag}
//
// It then gets all the layers of the requested image and converts each of
// them to ACI.
// If the squash flag is true, it squashes all the layers in one file and
// places this file in outputDir; if it is false, it places every layer in its
// own ACI in outputDir.
// It will use the temporary directory specified by tmpDir, or the default
// temporary directory if tmpDir is "".
// username and password can be passed if the image needs authentication.
// It returns the list of generated ACI paths.
func Convert(dockerURL string, squash bool, outputDir string, tmpDir string, username string, password string) ([]string, error) {
	repositoryBackend := repository.NewRepositoryBackend(username, password)
	return convertReal(repositoryBackend, dockerURL, squash, outputDir, tmpDir)
}

// ConvertFile generates ACI images from a file generated with "docker save".
// If there are several images/tags in the file, a particular image can be
// chosen with the syntax:
//
//	{docker registry URL}/{image name}:{tag}
//
// It takes as input the docker-generated file
//
// If the squash flag is true, it squashes all the layers in one file and
// places this file in outputDir; if it is false, it places every layer in its
// own ACI in outputDir.
// It will use the temporary directory specified by tmpDir, or the default
// temporary directory if tmpDir is "".
// It returns the list of generated ACI paths.
func ConvertFile(dockerURL string, filePath string, squash bool, outputDir string, tmpDir string) ([]string, error) {
	f, err := os.Open(filePath)
	if err != nil {
		return nil, fmt.Errorf("error opening file: %v", err)
	}
	defer f.Close()

	fileBackend := file.NewFileBackend(f)
	return convertReal(fileBackend, dockerURL, squash, outputDir, tmpDir)
}

// GetIndexName returns the docker index server from a docker URL.
func GetIndexName(dockerURL string) string {
	index, _ := common.SplitReposName(dockerURL)
	return index
}

// GetDockercfgAuth reads a ~/.dockercfg file and returns the username and password
// of the given docker index server.
func GetDockercfgAuth(indexServer string) (string, string, error) {
	return common.GetAuthInfo(indexServer)
}

func convertReal(backend Docker2ACIBackend, dockerURL string, squash bool, outputDir string, tmpDir string) ([]string, error) {
	util.Debug("Getting image info...")
	ancestry, parsedDockerURL, err := backend.GetImageInfo(dockerURL)
	if err != nil {
		return nil, err
	}

	layersOutputDir := outputDir
	if squash {
		layersOutputDir, err = ioutil.TempDir(tmpDir, "docker2aci-")
		if err != nil {
			return nil, fmt.Errorf("error creating dir: %v", err)
		}
		defer os.RemoveAll(layersOutputDir)
	}

	conversionStore := NewConversionStore()

	var images acirenderer.Images
	var aciLayerPaths []string
	var curPwl []string
	for i := len(ancestry) - 1; i >= 0; i-- {
		layerID := ancestry[i]

		// only compress individual layers if we're not squashing
		aciPath, manifest, err := backend.BuildACI(layerID, parsedDockerURL, layersOutputDir, tmpDir, curPwl, !squash)
		if err != nil {
			return nil, fmt.Errorf("error building layer: %v", err)
		}

		key, err := conversionStore.WriteACI(aciPath)
		if err != nil {
			return nil, fmt.Errorf("error inserting in the conversion store: %v", err)
		}

		images = append(images, acirenderer.Image{Im: manifest, Key: key, Level: uint16(i)})
		aciLayerPaths = append(aciLayerPaths, aciPath)
		curPwl = manifest.PathWhitelist
	}

	// acirenderer expects images in order from upper to base layer
	images = util.ReverseImages(images)
	if squash {
		squashedImagePath, err := SquashLayers(images, conversionStore, *parsedDockerURL, outputDir)
		if err != nil {
			return nil, fmt.Errorf("error squashing image: %v", err)
		}
		aciLayerPaths = []string{squashedImagePath}
	}

	return aciLayerPaths, nil
}

// SquashLayers receives a list of ACI layer file names ordered from base image
// to application image and squashes them into one ACI
func SquashLayers(images []acirenderer.Image, aciRegistry acirenderer.ACIRegistry, parsedDockerURL types.ParsedDockerURL, outputDir string) (path string, err error) {
	util.Debug("Squashing layers...")
	util.Debug("Rendering ACI...")
	renderedACI, err := acirenderer.GetRenderedACIFromList(images, aciRegistry)
	if err != nil {
		return "", fmt.Errorf("error rendering squashed image: %v", err)
	}
	manifests, err := getManifests(renderedACI, aciRegistry)
	if err != nil {
		return "", fmt.Errorf("error getting manifests: %v", err)
	}

	squashedFilename := getSquashedFilename(parsedDockerURL)
	squashedImagePath := filepath.Join(outputDir, squashedFilename)

	squashedTempFile, err := ioutil.TempFile(outputDir, "docker2aci-squashedFile-")
	if err != nil {
		return "", err
	}
	defer func() {
		if err == nil {
			err = squashedTempFile.Close()
		} else {
			// remove temp file on error
			// we ignore its error to not mask the real error
			os.Remove(squashedTempFile.Name())
		}
	}()

	util.Debug("Writing squashed ACI...")
	if err := writeSquashedImage(squashedTempFile, renderedACI, aciRegistry, manifests); err != nil {
		return "", fmt.Errorf("error writing squashed image: %v", err)
	}

	util.Debug("Validating squashed ACI...")
	if err := common.ValidateACI(squashedTempFile.Name()); err != nil {
		return "", fmt.Errorf("error validating image: %v", err)
	}

	if err := os.Rename(squashedTempFile.Name(), squashedImagePath); err != nil {
		return "", err
	}

	util.Debug("ACI squashed!")
	return squashedImagePath, nil
}

func getSquashedFilename(parsedDockerURL types.ParsedDockerURL) string {
	squashedFilename := strings.Replace(parsedDockerURL.ImageName, "/", "-", -1)
	if parsedDockerURL.Tag != "" {
		squashedFilename += "-" + parsedDockerURL.Tag
	}
	squashedFilename += ".aci"

	return squashedFilename
}

func getManifests(renderedACI acirenderer.RenderedACI, aciRegistry acirenderer.ACIRegistry) ([]schema.ImageManifest, error) {
	var manifests []schema.ImageManifest

	for _, aci := range renderedACI {
		im, err := aciRegistry.GetImageManifest(aci.Key)
		if err != nil {
			return nil, err
		}
		manifests = append(manifests, *im)
	}

	return manifests, nil
}

func writeSquashedImage(outputFile *os.File, renderedACI acirenderer.RenderedACI, aciProvider acirenderer.ACIProvider, manifests []schema.ImageManifest) error {
	gw := gzip.NewWriter(outputFile)
	defer gw.Close()
	outputWriter := tar.NewWriter(gw)
	defer outputWriter.Close()

	for _, aciFile := range renderedACI {
		rs, err := aciProvider.ReadStream(aciFile.Key)
		if err != nil {
			return err
		}
		defer rs.Close()

		squashWalker := func(t *tarball.TarFile) error {
			cleanName := filepath.Clean(t.Name())

			if _, ok := aciFile.FileMap[cleanName]; ok {
				// we generate and add the squashed manifest later
				if cleanName == "manifest" {
					return nil
				}
				if err := outputWriter.WriteHeader(t.Header); err != nil {
					return fmt.Errorf("error writing header: %v", err)
				}
				if _, err := io.Copy(outputWriter, t.TarStream); err != nil {
					return fmt.Errorf("error copying file into the tar out: %v", err)
				}
			}
			return nil
		}

		tr := tar.NewReader(rs)
		if err := tarball.Walk(*tr, squashWalker); err != nil {
			return err
		}
	}

	if err := common.WriteRootfsDir(outputWriter); err != nil {
		return err
	}

	finalManifest := mergeManifests(manifests)

	if err := common.WriteManifest(outputWriter, finalManifest); err != nil {
		return err
	}

	return nil
}

func mergeManifests(manifests []schema.ImageManifest) schema.ImageManifest {
	// FIXME(iaguis) we take app layer's manifest as the final manifest for now
	manifest := manifests[0]

	manifest.Dependencies = nil

	layerIndex := -1
	for i, l := range manifest.Labels {
		if l.Name.String() == "layer" {
			layerIndex = i
		}
	}

	if layerIndex != -1 {
		manifest.Labels = append(manifest.Labels[:layerIndex], manifest.Labels[layerIndex+1:]...)
	}

	nameWithoutLayerID := appctypes.MustACIdentifier(stripLayerID(manifest.Name.String()))

	manifest.Name = *nameWithoutLayerID

	// once the image is squashed, we don't need a pathWhitelist
	manifest.PathWhitelist = nil

	return manifest
}

// striplayerID strips the layer ID from an app name:
//
// myregistry.com/organization/app-name-85738f8f9a7f1b04b5329c590ebcb9e425925c6d0984089c43a022de4f19c281
// myregistry.com/organization/app-name
func stripLayerID(layerName string) string {
	n := strings.LastIndex(layerName, "-")
	return layerName[:n]
}
<commit_msg>lib: fix multiple rootfs entries<commit_after>// Copyright 2015 CoreOS, Inc.
//
// 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 docker2aci implements a simple library for converting docker images to
// App Container Images (ACIs).
package docker2aci

import (
	"archive/tar"
	"compress/gzip"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"

	"github.com/appc/docker2aci/lib/backend/file"
	"github.com/appc/docker2aci/lib/backend/repository"
	"github.com/appc/docker2aci/lib/common"
	"github.com/appc/docker2aci/lib/types"
	"github.com/appc/docker2aci/lib/util"
	"github.com/appc/docker2aci/tarball"
	"github.com/appc/spec/pkg/acirenderer"
	"github.com/appc/spec/schema"
	appctypes "github.com/appc/spec/schema/types"
)

type Docker2ACIBackend interface {
	GetImageInfo(dockerUrl string) ([]string, *types.ParsedDockerURL, error)
	BuildACI(layerID string, dockerURL *types.ParsedDockerURL, outputDir string, tmpBaseDir string, curPWl []string, compress bool) (string, *schema.ImageManifest, error)
}

// Convert generates ACI images from docker registry URLs.
// It takes as input a dockerURL of the form:
//
// 	{docker registry URL}/{image name}:{tag}
//
// It then gets all the layers of the requested image and converts each of
// them to ACI.
// If the squash flag is true, it squashes all the layers in one file and
// places this file in outputDir; if it is false, it places every layer in its
// own ACI in outputDir.
// It will use the temporary directory specified by tmpDir, or the default
// temporary directory if tmpDir is "".
// username and password can be passed if the image needs authentication.
// It returns the list of generated ACI paths.
func Convert(dockerURL string, squash bool, outputDir string, tmpDir string, username string, password string) ([]string, error) {
	repositoryBackend := repository.NewRepositoryBackend(username, password)
	return convertReal(repositoryBackend, dockerURL, squash, outputDir, tmpDir)
}

// ConvertFile generates ACI images from a file generated with "docker save".
// If there are several images/tags in the file, a particular image can be
// chosen with the syntax:
//
//	{docker registry URL}/{image name}:{tag}
//
// It takes as input the docker-generated file
//
// If the squash flag is true, it squashes all the layers in one file and
// places this file in outputDir; if it is false, it places every layer in its
// own ACI in outputDir.
// It will use the temporary directory specified by tmpDir, or the default
// temporary directory if tmpDir is "".
// It returns the list of generated ACI paths.
func ConvertFile(dockerURL string, filePath string, squash bool, outputDir string, tmpDir string) ([]string, error) {
	f, err := os.Open(filePath)
	if err != nil {
		return nil, fmt.Errorf("error opening file: %v", err)
	}
	defer f.Close()

	fileBackend := file.NewFileBackend(f)
	return convertReal(fileBackend, dockerURL, squash, outputDir, tmpDir)
}

// GetIndexName returns the docker index server from a docker URL.
func GetIndexName(dockerURL string) string {
	index, _ := common.SplitReposName(dockerURL)
	return index
}

// GetDockercfgAuth reads a ~/.dockercfg file and returns the username and password
// of the given docker index server.
func GetDockercfgAuth(indexServer string) (string, string, error) {
	return common.GetAuthInfo(indexServer)
}

func convertReal(backend Docker2ACIBackend, dockerURL string, squash bool, outputDir string, tmpDir string) ([]string, error) {
	util.Debug("Getting image info...")
	ancestry, parsedDockerURL, err := backend.GetImageInfo(dockerURL)
	if err != nil {
		return nil, err
	}

	layersOutputDir := outputDir
	if squash {
		layersOutputDir, err = ioutil.TempDir(tmpDir, "docker2aci-")
		if err != nil {
			return nil, fmt.Errorf("error creating dir: %v", err)
		}
		defer os.RemoveAll(layersOutputDir)
	}

	conversionStore := NewConversionStore()

	var images acirenderer.Images
	var aciLayerPaths []string
	var curPwl []string
	for i := len(ancestry) - 1; i >= 0; i-- {
		layerID := ancestry[i]

		// only compress individual layers if we're not squashing
		aciPath, manifest, err := backend.BuildACI(layerID, parsedDockerURL, layersOutputDir, tmpDir, curPwl, !squash)
		if err != nil {
			return nil, fmt.Errorf("error building layer: %v", err)
		}

		key, err := conversionStore.WriteACI(aciPath)
		if err != nil {
			return nil, fmt.Errorf("error inserting in the conversion store: %v", err)
		}

		images = append(images, acirenderer.Image{Im: manifest, Key: key, Level: uint16(i)})
		aciLayerPaths = append(aciLayerPaths, aciPath)
		curPwl = manifest.PathWhitelist
	}

	// acirenderer expects images in order from upper to base layer
	images = util.ReverseImages(images)
	if squash {
		squashedImagePath, err := SquashLayers(images, conversionStore, *parsedDockerURL, outputDir)
		if err != nil {
			return nil, fmt.Errorf("error squashing image: %v", err)
		}
		aciLayerPaths = []string{squashedImagePath}
	}

	return aciLayerPaths, nil
}

// SquashLayers receives a list of ACI layer file names ordered from base image
// to application image and squashes them into one ACI
func SquashLayers(images []acirenderer.Image, aciRegistry acirenderer.ACIRegistry, parsedDockerURL types.ParsedDockerURL, outputDir string) (path string, err error) {
	util.Debug("Squashing layers...")
	util.Debug("Rendering ACI...")
	renderedACI, err := acirenderer.GetRenderedACIFromList(images, aciRegistry)
	if err != nil {
		return "", fmt.Errorf("error rendering squashed image: %v", err)
	}
	manifests, err := getManifests(renderedACI, aciRegistry)
	if err != nil {
		return "", fmt.Errorf("error getting manifests: %v", err)
	}

	squashedFilename := getSquashedFilename(parsedDockerURL)
	squashedImagePath := filepath.Join(outputDir, squashedFilename)

	squashedTempFile, err := ioutil.TempFile(outputDir, "docker2aci-squashedFile-")
	if err != nil {
		return "", err
	}
	defer func() {
		if err == nil {
			err = squashedTempFile.Close()
		} else {
			// remove temp file on error
			// we ignore its error to not mask the real error
			os.Remove(squashedTempFile.Name())
		}
	}()

	util.Debug("Writing squashed ACI...")
	if err := writeSquashedImage(squashedTempFile, renderedACI, aciRegistry, manifests); err != nil {
		return "", fmt.Errorf("error writing squashed image: %v", err)
	}

	util.Debug("Validating squashed ACI...")
	if err := common.ValidateACI(squashedTempFile.Name()); err != nil {
		return "", fmt.Errorf("error validating image: %v", err)
	}

	if err := os.Rename(squashedTempFile.Name(), squashedImagePath); err != nil {
		return "", err
	}

	util.Debug("ACI squashed!")
	return squashedImagePath, nil
}

func getSquashedFilename(parsedDockerURL types.ParsedDockerURL) string {
	squashedFilename := strings.Replace(parsedDockerURL.ImageName, "/", "-", -1)
	if parsedDockerURL.Tag != "" {
		squashedFilename += "-" + parsedDockerURL.Tag
	}
	squashedFilename += ".aci"

	return squashedFilename
}

func getManifests(renderedACI acirenderer.RenderedACI, aciRegistry acirenderer.ACIRegistry) ([]schema.ImageManifest, error) {
	var manifests []schema.ImageManifest

	for _, aci := range renderedACI {
		im, err := aciRegistry.GetImageManifest(aci.Key)
		if err != nil {
			return nil, err
		}
		manifests = append(manifests, *im)
	}

	return manifests, nil
}

func writeSquashedImage(outputFile *os.File, renderedACI acirenderer.RenderedACI, aciProvider acirenderer.ACIProvider, manifests []schema.ImageManifest) error {
	gw := gzip.NewWriter(outputFile)
	defer gw.Close()
	outputWriter := tar.NewWriter(gw)
	defer outputWriter.Close()

	for _, aciFile := range renderedACI {
		rs, err := aciProvider.ReadStream(aciFile.Key)
		if err != nil {
			return err
		}
		defer rs.Close()

		squashWalker := func(t *tarball.TarFile) error {
			cleanName := filepath.Clean(t.Name())

			if _, ok := aciFile.FileMap[cleanName]; ok {
				// we generate and add rootfs and the squashed manifest later
				if cleanName == "manifest" || cleanName == "rootfs" {
					return nil
				}
				if err := outputWriter.WriteHeader(t.Header); err != nil {
					return fmt.Errorf("error writing header: %v", err)
				}
				if _, err := io.Copy(outputWriter, t.TarStream); err != nil {
					return fmt.Errorf("error copying file into the tar out: %v", err)
				}
			}
			return nil
		}

		tr := tar.NewReader(rs)
		if err := tarball.Walk(*tr, squashWalker); err != nil {
			return err
		}
	}

	if err := common.WriteRootfsDir(outputWriter); err != nil {
		return err
	}

	finalManifest := mergeManifests(manifests)

	if err := common.WriteManifest(outputWriter, finalManifest); err != nil {
		return err
	}

	return nil
}

func mergeManifests(manifests []schema.ImageManifest) schema.ImageManifest {
	// FIXME(iaguis) we take app layer's manifest as the final manifest for now
	manifest := manifests[0]

	manifest.Dependencies = nil

	layerIndex := -1
	for i, l := range manifest.Labels {
		if l.Name.String() == "layer" {
			layerIndex = i
		}
	}

	if layerIndex != -1 {
		manifest.Labels = append(manifest.Labels[:layerIndex], manifest.Labels[layerIndex+1:]...)
	}

	nameWithoutLayerID := appctypes.MustACIdentifier(stripLayerID(manifest.Name.String()))

	manifest.Name = *nameWithoutLayerID

	// once the image is squashed, we don't need a pathWhitelist
	manifest.PathWhitelist = nil

	return manifest
}

// striplayerID strips the layer ID from an app name:
//
// myregistry.com/organization/app-name-85738f8f9a7f1b04b5329c590ebcb9e425925c6d0984089c43a022de4f19c281
// myregistry.com/organization/app-name
func stripLayerID(layerName string) string {
	n := strings.LastIndex(layerName, "-")
	return layerName[:n]
}
<|endoftext|>


<commit_before>package gopenid

import (
	"crypto/hmac"
	"crypto/sha1"
	"crypto/sha256"
	"errors"
	"fmt"
	"github.com/nu7hatch/gouuid"
	"hash"
	"io"
	"strings"
	"time"
)

const (
	ASSOCIATION_LIFETIME = 60 * 60 * 24 * 1
)

var (
	ErrGeneratingAssociationFailed = errors.New("generating association failed")
	ErrAssociationNotFound         = errors.New("association not found")
	ErrUnknownSessionType          = errors.New("unknown session type")
	ErrUnknownAssocType            = errors.New("unknown association type")

	ASSOC_HMAC_SHA1 = AssocType{
		name:       "HMAC-SHA1",
		hashFunc:   sha1.New,
		secretSize: sha1.Size,
	}
	ASSOC_HMAC_SHA256 = AssocType{
		name:       "HMAC-SHA256",
		hashFunc:   sha256.New,
		secretSize: sha256.Size,
	}

	SESSION_DH_SHA1 = SessionType{
		name: "DH-SHA1",
		assocTypes: []AssocType{
			ASSOC_HMAC_SHA1,
		},
	}
	SESSION_DH_SHA256 = SessionType{
		name: "DH-SHA256",
		assocTypes: []AssocType{
			ASSOC_HMAC_SHA256,
		},
	}
	SESSION_NO_ENCRYPTION = SessionType{
		name: "no-encryption",
		assocTypes: []AssocType{
			ASSOC_HMAC_SHA1,
			ASSOC_HMAC_SHA256,
		},
	}

	SESSION_DEFAULT = SESSION_DH_SHA256
	ASSOC_DEFAULT   = ASSOC_HMAC_SHA256
)

type AssocType struct {
	name       string
	hashFunc   func() hash.Hash
	secretSize int
}

func (t *AssocType) Name() string {
	return t.name
}

func (t *AssocType) GetSecretSize() int {
	return t.secretSize
}

func GetAssocTypeByName(name string) (assocType AssocType, err error) {
	switch name {
	case "HMAC-SHA1":
		assocType = ASSOC_HMAC_SHA1
	case "HMAC-SHA256":
		assocType = ASSOC_HMAC_SHA256
	default:
		err = ErrUnknownAssocType
	}

	return
}

type SessionType struct {
	name       string
	assocTypes []AssocType
}

func (t *SessionType) Name() string {
	return t.name
}

func GetSessionTypeByName(name string) (sessionType SessionType, err error) {
	switch name {
	case "no-encryption":
		sessionType = SESSION_NO_ENCRYPTION
	case "DH-SHA1":
		sessionType = SESSION_DH_SHA1
	case "DH-SHA256":
		sessionType = SESSION_DH_SHA256
	default:
		err = ErrUnknownSessionType
	}

	return
}

type Association struct {
	assocType   AssocType
	handle      string
	secret      []byte
	expires     int64
	isStateless bool
}

func NewAssociation(assocType AssocType, handle string, secret []byte, expires int64, isStateless bool) *Association {
	if expires < 1 {
		expires = time.Now().Unix() + ASSOCIATION_LIFETIME
	}

	return &Association{
		assocType:   assocType,
		handle:      handle,
		secret:      secret,
		expires:     expires,
		isStateless: isStateless,
	}
}

func CreateAssociation(random io.Reader, assocType AssocType, expires int64, isStateless bool) (assoc *Association, err error) {
	handle, err := uuid.NewV4()
	if err != nil {
		err = ErrGeneratingAssociationFailed
		return
	}

	secret := make([]byte, assocType.GetSecretSize())
	_, err = io.ReadFull(random, secret)
	if err != nil {
		err = ErrGeneratingAssociationFailed
		return
	}

	assoc = NewAssociation(assocType, handle.String(), secret, expires, isStateless)
	return
}

func (assoc *Association) GetAssocType() AssocType {
	return assoc.assocType
}

func (assoc *Association) GetHandle() string {
	return assoc.handle
}

func (assoc *Association) GetSecret() []byte {
	return assoc.secret
}

func (assoc *Association) GetExpires() int64 {
	return assoc.expires
}

func (assoc *Association) IsValid() bool {
	return time.Now().Before(time.Unix(assoc.GetExpires(), 0))
}

func (assoc *Association) IsStateless() bool {
	return assoc.isStateless
}

func (assoc *Association) Sign(msg Message, signed []string) (err error) {
	order := make([]string, len(signed))
	for i, key := range signed {
		order[i] = fmt.Sprintf("openid.%s", key)
	}

	mac := hmac.New(assoc.assocType.hashFunc, assoc.secret)
	kv, err := msg.ToKeyValue(order)
	if err != nil {
		return
	}
	mac.Write(kv)
	sig, err := EncodeBase64(mac.Sum(nil))
	if err != nil {
		return
	}

	msg.AddArg(
		NewMessageKey(msg.GetOpenIDNamespace(), "signed"),
		MessageValue(strings.Join(signed, ",")),
	)
	msg.AddArg(
		NewMessageKey(msg.GetOpenIDNamespace(), "sig"),
		MessageValue(sig),
	)

	return
}
<commit_msg>add AssocType#Hash<commit_after>package gopenid

import (
	"crypto/hmac"
	"crypto/sha1"
	"crypto/sha256"
	"errors"
	"fmt"
	"github.com/nu7hatch/gouuid"
	"hash"
	"io"
	"strings"
	"time"
)

const (
	ASSOCIATION_LIFETIME = 60 * 60 * 24 * 1
)

var (
	ErrGeneratingAssociationFailed = errors.New("generating association failed")
	ErrAssociationNotFound         = errors.New("association not found")
	ErrUnknownSessionType          = errors.New("unknown session type")
	ErrUnknownAssocType            = errors.New("unknown association type")

	ASSOC_HMAC_SHA1 = AssocType{
		name:       "HMAC-SHA1",
		hashFunc:   sha1.New,
		secretSize: sha1.Size,
	}
	ASSOC_HMAC_SHA256 = AssocType{
		name:       "HMAC-SHA256",
		hashFunc:   sha256.New,
		secretSize: sha256.Size,
	}

	SESSION_DH_SHA1 = SessionType{
		name: "DH-SHA1",
		assocTypes: []AssocType{
			ASSOC_HMAC_SHA1,
		},
	}
	SESSION_DH_SHA256 = SessionType{
		name: "DH-SHA256",
		assocTypes: []AssocType{
			ASSOC_HMAC_SHA256,
		},
	}
	SESSION_NO_ENCRYPTION = SessionType{
		name: "no-encryption",
		assocTypes: []AssocType{
			ASSOC_HMAC_SHA1,
			ASSOC_HMAC_SHA256,
		},
	}

	SESSION_DEFAULT = SESSION_DH_SHA256
	ASSOC_DEFAULT   = ASSOC_HMAC_SHA256
)

type AssocType struct {
	name       string
	hashFunc   func() hash.Hash
	secretSize int
}

func (t *AssocType) Name() string {
	return t.name
}

func (t *AssocType) Hash() hash.Hash {
	return t.hashFunc()
}

func (t *AssocType) GetSecretSize() int {
	return t.secretSize
}

func GetAssocTypeByName(name string) (assocType AssocType, err error) {
	switch name {
	case "HMAC-SHA1":
		assocType = ASSOC_HMAC_SHA1
	case "HMAC-SHA256":
		assocType = ASSOC_HMAC_SHA256
	default:
		err = ErrUnknownAssocType
	}

	return
}

type SessionType struct {
	name       string
	assocTypes []AssocType
}

func (t *SessionType) Name() string {
	return t.name
}

func GetSessionTypeByName(name string) (sessionType SessionType, err error) {
	switch name {
	case "no-encryption":
		sessionType = SESSION_NO_ENCRYPTION
	case "DH-SHA1":
		sessionType = SESSION_DH_SHA1
	case "DH-SHA256":
		sessionType = SESSION_DH_SHA256
	default:
		err = ErrUnknownSessionType
	}

	return
}

type Association struct {
	assocType   AssocType
	handle      string
	secret      []byte
	expires     int64
	isStateless bool
}

func NewAssociation(assocType AssocType, handle string, secret []byte, expires int64, isStateless bool) *Association {
	if expires < 1 {
		expires = time.Now().Unix() + ASSOCIATION_LIFETIME
	}

	return &Association{
		assocType:   assocType,
		handle:      handle,
		secret:      secret,
		expires:     expires,
		isStateless: isStateless,
	}
}

func CreateAssociation(random io.Reader, assocType AssocType, expires int64, isStateless bool) (assoc *Association, err error) {
	handle, err := uuid.NewV4()
	if err != nil {
		err = ErrGeneratingAssociationFailed
		return
	}

	secret := make([]byte, assocType.GetSecretSize())
	_, err = io.ReadFull(random, secret)
	if err != nil {
		err = ErrGeneratingAssociationFailed
		return
	}

	assoc = NewAssociation(assocType, handle.String(), secret, expires, isStateless)
	return
}

func (assoc *Association) GetAssocType() AssocType {
	return assoc.assocType
}

func (assoc *Association) GetHandle() string {
	return assoc.handle
}

func (assoc *Association) GetSecret() []byte {
	return assoc.secret
}

func (assoc *Association) GetExpires() int64 {
	return assoc.expires
}

func (assoc *Association) IsValid() bool {
	return time.Now().Before(time.Unix(assoc.GetExpires(), 0))
}

func (assoc *Association) IsStateless() bool {
	return assoc.isStateless
}

func (assoc *Association) Sign(msg Message, signed []string) (err error) {
	order := make([]string, len(signed))
	for i, key := range signed {
		order[i] = fmt.Sprintf("openid.%s", key)
	}

	mac := hmac.New(assoc.assocType.hashFunc, assoc.secret)
	kv, err := msg.ToKeyValue(order)
	if err != nil {
		return
	}
	mac.Write(kv)
	sig, err := EncodeBase64(mac.Sum(nil))
	if err != nil {
		return
	}

	msg.AddArg(
		NewMessageKey(msg.GetOpenIDNamespace(), "signed"),
		MessageValue(strings.Join(signed, ",")),
	)
	msg.AddArg(
		NewMessageKey(msg.GetOpenIDNamespace(), "sig"),
		MessageValue(sig),
	)

	return
}
<|endoftext|>