diff --git a/.travis.yml b/.travis.yml index 05a9b80..b6f6044 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: go -go: 1.4.2 +go: 1.5.3 install: - export PATH=$PATH:$HOME/gopath/bin diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json deleted file mode 100644 index 96e05c8..0000000 --- a/Godeps/Godeps.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "ImportPath": "github.com/cloudfoundry-community/gogobosh", - "GoVersion": "go1.4", - "Deps": [ - { - "ImportPath": "github.com/onsi/ginkgo", - "Comment": "v1.1.0-29-g18c73cf", - "Rev": "18c73cfeca1095f984c036a04c42ac0b08048685" - }, - { - "ImportPath": "github.com/onsi/gomega", - "Comment": "v1.0-23-g2cd6d99", - "Rev": "2cd6d99ccf3ac7ae8398d8296429161bf7061ae2" - } - ] -} diff --git a/Godeps/Readme b/Godeps/Readme deleted file mode 100644 index 4cdaa53..0000000 --- a/Godeps/Readme +++ /dev/null @@ -1,5 +0,0 @@ -This directory tree is generated automatically by godep. - -Please do not edit. - -See https://github.com/tools/godep for more information. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..b03f378 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License + +Copyright (c) 2016 Dr Nic, Long Nguyen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/TODO b/TODO new file mode 100644 index 0000000..b9d1311 --- /dev/null +++ b/TODO @@ -0,0 +1 @@ +UAA Support \ No newline at end of file diff --git a/api.go b/api.go new file mode 100644 index 0000000..aee6f23 --- /dev/null +++ b/api.go @@ -0,0 +1,253 @@ +package gogobosh + +import ( + "bytes" + "encoding/json" + "io/ioutil" + "log" + "strconv" + "strings" + "time" +) + +// GetStemcells from given BOSH +func (c *Client) GetStemcells() (stemcells []Stemcell, err error) { + r := c.NewRequest("GET", "/stemcells") + resp, err := c.DoRequest(r) + + if err != nil { + log.Printf("Error requesting stemcells %v", err) + return + } + resBody, err := ioutil.ReadAll(resp.Body) + if err != nil { + log.Printf("Error reading stemcells request %v", resBody) + return + } + err = json.Unmarshal(resBody, &stemcells) + if err != nil { + log.Printf("Error unmarshaling stemcells %v", err) + return + } + return +} + +// GetReleases from given BOSH +func (c *Client) GetReleases() (releases []Release, err error) { + r := c.NewRequest("GET", "/releases") + resp, err := c.DoRequest(r) + + if err != nil { + log.Printf("Error requesting releases %v", err) + return + } + resBody, err := ioutil.ReadAll(resp.Body) + if err != nil { + log.Printf("Error reading releases request %v", resBody) + return + } + err = json.Unmarshal(resBody, &releases) + if err != nil { + log.Printf("Error unmarshaling releases %v", err) + return + } + return +} + +// GetDeployments from given BOSH +func (c *Client) GetDeployments() (deployments []Deployment, err error) { + r := c.NewRequest("GET", "/deployments") + resp, err := c.DoRequest(r) + + if err != nil { + log.Printf("Error requesting deployments %v", err) + return + } + resBody, err := ioutil.ReadAll(resp.Body) + if err != nil { + log.Printf("Error reading deployments request %v", resBody) + return + } + err = json.Unmarshal(resBody, &deployments) + if err != nil { + log.Printf("Error unmarshaling deployments %v", err) + return + } + return +} + +// GetDeployment from given BOSH +func (c *Client) GetDeployment(name string) (manifest Manifest, err error) { + r := c.NewRequest("GET", "/deployments/"+name) + resp, err := c.DoRequest(r) + + if err != nil { + log.Printf("Error requesting deployment manifest %v", err) + return + } + resBody, err := ioutil.ReadAll(resp.Body) + if err != nil { + log.Printf("Error reading deployment manifest request %v", resBody) + return + } + err = json.Unmarshal(resBody, &manifest) + if err != nil { + log.Printf("Error unmarshaling deployment manifest %v", err) + return + } + return +} + +// DeleteDeployment from given BOSH +func (c *Client) DeleteDeployment(name string) (task Task, err error) { + r := c.NewRequest("DELETE", "/deployments/"+name+"?force=true") + resp, err := c.DoRequest(r) + + if err != nil { + log.Printf("Error requesting deleting deployment %v", err) + return + } + resBody, err := ioutil.ReadAll(resp.Body) + if err != nil { + log.Printf("Error reading deleting deployment request %v", resBody) + return + } + err = json.Unmarshal(resBody, &task) + if err != nil { + log.Printf("Error unmarshaling tasks %v", err) + return + } + return +} + +// CreateDeployment from given BOSH +func (c *Client) CreateDeployment(manifest string) (task Task, err error) { + r := c.NewRequest("POST", "/deployments") + buffer := bytes.NewBufferString(manifest) + r.body = buffer + r.header["Content-Type"] = "text/yaml" + + resp, err := c.DoRequest(r) + if err != nil { + log.Printf("Error requesting create deployment %v", err) + return + } + resBody, err := ioutil.ReadAll(resp.Body) + if err != nil { + log.Printf("Error reading task request %v", resBody) + return + } + err = json.Unmarshal(resBody, &task) + if err != nil { + log.Printf("Error unmarshaling task %v", err) + return + } + return +} + +// GetDeploymentVMs from given BOSH +func (c *Client) GetDeploymentVMs(name string) (vms []VM, err error) { + var task Task + r := c.NewRequest("GET", "/deployments/"+name+"/vms?format=full") + resp, err := c.DoRequest(r) + if err != nil { + log.Printf("Error requesting deployment vms %v", err) + return + } + + resBody, err := ioutil.ReadAll(resp.Body) + if err != nil { + log.Printf("Error reading deployment vms request %v", resBody) + return + } + err = json.Unmarshal(resBody, &task) + if err != nil { + log.Printf("Error unmarshaling tasks %v", err) + return + } + for { + taskStatus, err := c.GetTask(task.ID) + if err != nil { + log.Printf("Error getting task %v", err) + } + if taskStatus.State == "done" { + break + } + time.Sleep(1 * time.Second) + } + output := c.GetTaskResult(task.ID) + for _, value := range output { + if len(value) > 0 { + var vm VM + err = json.Unmarshal([]byte(value), &vm) + if err != nil { + log.Printf("Error unmarshaling vms %v %v", value, err) + return + } + vms = append(vms, vm) + } + } + return +} + +// GetTasks from given BOSH +func (c *Client) GetTasks() (tasks []Task, err error) { + r := c.NewRequest("GET", "/tasks") + resp, err := c.DoRequest(r) + + if err != nil { + log.Printf("Error requesting tasks %v", err) + return + } + resBody, err := ioutil.ReadAll(resp.Body) + if err != nil { + log.Printf("Error reading tasks request %v", resBody) + return + } + err = json.Unmarshal(resBody, &tasks) + if err != nil { + log.Printf("Error unmarshaling tasks %v", err) + return + } + return +} + +// GetTask from given BOSH +func (c *Client) GetTask(id int) (task Task, err error) { + stringID := strconv.Itoa(id) + r := c.NewRequest("GET", "/tasks/"+stringID) + resp, err := c.DoRequest(r) + + if err != nil { + log.Printf("Error requesting task %v", err) + return + } + resBody, err := ioutil.ReadAll(resp.Body) + if err != nil { + log.Printf("Error reading task request %v", resBody) + return + } + err = json.Unmarshal(resBody, &task) + if err != nil { + log.Printf("Error unmarshaling task %v", err) + return + } + return +} + +// GetTaskResult from given BOSH +func (c *Client) GetTaskResult(id int) (output []string) { + stringID := strconv.Itoa(id) + r := c.NewRequest("GET", "/tasks/"+stringID+"/output?type=result") + resp, err := c.DoRequest(r) + + if err != nil { + log.Printf("Error requesting task %v", err) + } + resBody, err := ioutil.ReadAll(resp.Body) + if err != nil { + log.Printf("Error reading task request %v", resBody) + } + output = strings.Split(string(resBody), "\n") + return +} diff --git a/api/director_deployments.go b/api/director_deployments.go deleted file mode 100644 index 8e2708c..0000000 --- a/api/director_deployments.go +++ /dev/null @@ -1,122 +0,0 @@ -package api - -import ( - "fmt" - "net/url" - "time" - - "launchpad.net/goyaml" - - "github.com/cloudfoundry-community/gogobosh/models" - "github.com/cloudfoundry-community/gogobosh/net" -) - -// GetDeployments returns a list of deployments, and the releases/stemcells being used -func (repo BoshDirectorRepository) GetDeployments() (deployments models.Deployments, apiResponse net.ApiResponse) { - response := []deploymentResponse{} - - path := "/deployments" - apiResponse = repo.gateway.GetResource(repo.config.TargetURL+path, repo.config.Username, repo.config.Password, &response) - if apiResponse.IsNotSuccessful() { - return - } - - list := []*models.Deployment{} - for _, resource := range response { - list = append(list, resource.ToModel()) - } - deployments = models.Deployments(list) - - return -} - -// GetDeploymentManifest returns a deployment manifest -func (repo BoshDirectorRepository) GetDeploymentManifest(deploymentName string) (manifest *models.DeploymentManifest, apiResponse net.ApiResponse) { - deploymentManifestResponse := deploymentManifestResponse{} - - path := fmt.Sprintf("/deployments/%s", deploymentName) - apiResponse = repo.gateway.GetResource(repo.config.TargetURL+path, repo.config.Username, repo.config.Password, &deploymentManifestResponse) - if apiResponse.IsNotSuccessful() { - return - } - - return deploymentManifestResponse.ToModel(), apiResponse -} - -// DeleteDeployment asks the director to delete a deployment -func (repo BoshDirectorRepository) DeleteDeployment(deploymentName string) (apiResponse net.ApiResponse) { - path := fmt.Sprintf("/deployments/%s?force=true", deploymentName) - apiResponse = repo.gateway.DeleteResource(repo.config.TargetURL+path, repo.config.Username, repo.config.Password) - if apiResponse.IsNotSuccessful() { - return - } - if !apiResponse.IsRedirection() { - return - } - - var taskStatus models.TaskStatus - taskURL, err := url.Parse(apiResponse.RedirectLocation) - if err != nil { - return - } - - apiResponse = repo.gateway.GetResource(repo.config.TargetURL+taskURL.Path, repo.config.Username, repo.config.Password, &taskStatus) - if apiResponse.IsNotSuccessful() { - return - } - - /* Progression should be: queued, progressing, done */ - /* TODO task might fail; end states: done, error, cancelled */ - for taskStatus.State != "done" { - time.Sleep(1) - taskStatus, apiResponse = repo.GetTaskStatus(taskStatus.ID) - if apiResponse.IsNotSuccessful() { - return - } - } - - return -} - -type deploymentResponse struct { - Name string `json:"name"` - Releases []nameVersion `json:"releases"` - Stemcells []nameVersion `json:"stemcells"` -} - -type deploymentManifestResponse struct { - RawManifest string `json:"manifest"` -} - -type nameVersion struct { - Name string `json:"name"` - Version string `json:"version"` -} - -func (resource deploymentResponse) ToModel() (deployment *models.Deployment) { - deployment = &models.Deployment{} - deployment.Name = resource.Name - for _, releaseResponse := range resource.Releases { - release := models.NameVersion{} - release.Name = releaseResponse.Name - release.Version = releaseResponse.Version - - deployment.Releases = append(deployment.Releases, release) - } - - for _, stemcellResponse := range resource.Stemcells { - stemcell := models.NameVersion{} - stemcell.Name = stemcellResponse.Name - stemcell.Version = stemcellResponse.Version - - deployment.Stemcells = append(deployment.Stemcells, stemcell) - } - return -} - -// ToModel converts a GetDeploymentManifest API response into models.DeploymentManifest -func (resource deploymentManifestResponse) ToModel() (manifest *models.DeploymentManifest) { - manifest = &models.DeploymentManifest{} - goyaml.Unmarshal([]byte(resource.RawManifest), manifest) - return -} diff --git a/api/director_deployments_test.go b/api/director_deployments_test.go deleted file mode 100644 index 169fd6d..0000000 --- a/api/director_deployments_test.go +++ /dev/null @@ -1,119 +0,0 @@ -package api_test - -import ( - "fmt" - "net/http" - - "github.com/cloudfoundry-community/gogobosh/testhelpers" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -var _ = Describe("Deployments", func() { - It("GetDeployments() - list of deployments", func() { - request := testhelpers.NewDirectorTestRequest(testhelpers.TestRequest{ - Method: "GET", - Path: "/deployments", - Response: testhelpers.TestResponse{ - Status: http.StatusOK, - Body: `[ - { - "name": "cf-warden", - "releases": [ - { - "name": "cf", - "version": "153" - } - ], - "stemcells": [ - { - "name": "bosh-stemcell", - "version": "993" - } - ] - } - ]`}}) - ts, handler, repo := createDirectorRepo(request) - defer ts.Close() - - deployments, apiResponse := repo.GetDeployments() - - deployment := deployments[0] - Expect(deployment.Name).To(Equal("cf-warden")) - - deploymentRelease := deployment.Releases[0] - Expect(deploymentRelease.Name).To(Equal("cf")) - Expect(deploymentRelease.Version).To(Equal("153")) - - deploymentStemcell := deployment.Stemcells[0] - Expect(deploymentStemcell.Name).To(Equal("bosh-stemcell")) - Expect(deploymentStemcell.Version).To(Equal("993")) - - Expect(apiResponse.IsSuccessful()).To(Equal(true)) - Expect(handler.AllRequestsCalled()).To(Equal(true)) - }) - - It("GetDeployment(name) - get deployment, including manifest", func() { - request := testhelpers.NewDirectorTestRequest(testhelpers.TestRequest{ - Method: "GET", - Path: "/deployments/cf-warden", - Response: testhelpers.TestResponse{ - Status: http.StatusOK, - Body: `{ - "manifest": "name: cf-warden" - }`, - }}) - ts, handler, repo := createDirectorRepo(request) - defer ts.Close() - - manifest, apiResponse := repo.GetDeploymentManifest("cf-warden") - Expect(apiResponse.IsSuccessful()).To(Equal(true)) - Expect(handler.AllRequestsCalled()).To(Equal(true)) - - Expect(manifest.Name).To(Equal("cf-warden")) - }) - - It("DeleteDeployment(name) forcefully", func() { - request := testhelpers.NewDirectorTestRequest(testhelpers.TestRequest{ - Method: "DELETE", - Path: "/deployments/cf-warden?force=true", - Response: testhelpers.TestResponse{ - Status: http.StatusFound, - Header: http.Header{ - "Location": {"https://some.host/tasks/20"}, - }, - }}) - ts, handler, repo := createDirectorRepo( - request, - taskTestRequest(20, "queued"), - taskTestRequest(20, "processing"), - taskTestRequest(20, "done"), - ) - defer ts.Close() - - apiResponse := repo.DeleteDeployment("cf-warden") - - Expect(apiResponse.IsSuccessful()).To(Equal(true)) - Expect(handler.AllRequestsCalled()).To(Equal(true)) - }) -}) - -// Shared helper for asserting that a /tasks/ID is requested and returns a models.TaskStatus response -func taskTestRequest(taskID int, state string) testhelpers.TestRequest { - baseJSON := `{ - "id": %d, - "state": "%s", - "description": "some task", - "timestamp": 1390174354, - "result": null, - "user": "admin" - }` - return testhelpers.NewDirectorTestRequest(testhelpers.TestRequest{ - Method: "GET", - Path: fmt.Sprintf("/tasks/%d", taskID), - Response: testhelpers.TestResponse{ - Status: http.StatusOK, - Body: fmt.Sprintf(baseJSON, taskID, state), - }, - }) -} diff --git a/api/director_fetch_vms_state.go b/api/director_fetch_vms_state.go deleted file mode 100644 index cf44480..0000000 --- a/api/director_fetch_vms_state.go +++ /dev/null @@ -1,122 +0,0 @@ -package api - -import ( - "encoding/json" - "fmt" - "strings" - "time" - - "github.com/cloudfoundry-community/gogobosh/models" - "github.com/cloudfoundry-community/gogobosh/net" -) - -func (repo BoshDirectorRepository) FetchVMsStatus(deploymentName string) (vmsStatuses []models.VMStatus, apiResponse net.ApiResponse) { - var taskStatus models.TaskStatus - - /* - * Two API calls - * 1. GET /deployments/%s/vms?format=full and be redirected to a /tasks/123 - * 2. Streaming GET on /tasks/123/output?type=result - each line is a models.VMStatus - */ - path := fmt.Sprintf("/deployments/%s/vms?format=full", deploymentName) - apiResponse = repo.gateway.GetResource(repo.config.TargetURL+path, repo.config.Username, repo.config.Password, &taskStatus) - if apiResponse.IsNotSuccessful() { - return - } - - /* Progression should be: queued, progressing, done */ - /* TODO task might fail; end states: done, error, cancelled */ - for taskStatus.State != "done" { - time.Sleep(1) - taskStatus, apiResponse = repo.GetTaskStatus(taskStatus.ID) - if apiResponse.IsNotSuccessful() { - return - } - } - - path = fmt.Sprintf("/tasks/%d/output?type=result", taskStatus.ID) - request, apiResponse := repo.gateway.NewRequest("GET", repo.config.TargetURL+path, repo.config.Username, repo.config.Password, nil) - if apiResponse.IsNotSuccessful() { - return - } - - bytes, _, apiResponse := repo.gateway.PerformRequestForResponseBytes(request) - if apiResponse.IsNotSuccessful() { - return - } - - if apiResponse.StatusCode > 203 { - return - } - - for _, vmStatusItem := range strings.Split(string(bytes), "\n") { - resource := vmStatusResponse{} - err := json.Unmarshal([]byte(vmStatusItem), &resource) - if err == nil { - vmsStatuses = append(vmsStatuses, resource.ToModel()) - } - } - - return -} - -type vmStatusResponse struct { - JobName string `json:"job_name"` - Index int `json:"index"` - JobState string `json:"job_state"` - VMCid string `json:"vm_cid"` - AgentID string `json:"agent_id"` - IPs []string `json:"ips"` - DNSs []string `json:"dns"` - ResourcePool string `json:"resource_pool"` - ResurrectionPaused bool `json:"resurrection_paused"` - Vitals vitalsResponse `json:"vitals"` -} - -type vitalsResponse struct { - Load []string `json:"load"` - CPU cpuResponse `json:"cpu"` - Memory percentKbResponse `json:"mem"` - Swap percentKbResponse `json:"swap"` - Disk diskResponse `json:"disk"` -} - -type cpuResponse struct { - User float64 `json:"user,string"` - System float64 `json:"sys,string"` - Wait float64 `json:"wait,string"` -} - -type diskResponse struct { - Persistent percentKbResponse `json:"persistent"` -} - -type percentKbResponse struct { - Percent float64 `json:"percent,string"` - Kb int `json:"kb,string"` -} - -func (resource vmStatusResponse) ToModel() (status models.VMStatus) { - status = models.VMStatus{} - status.JobName = resource.JobName - status.Index = resource.Index - status.JobState = resource.JobState - status.VMCid = resource.VMCid - status.AgentID = resource.AgentID - status.ResourcePool = resource.ResourcePool - status.ResurrectionPaused = resource.ResurrectionPaused - - status.IPs = resource.IPs - status.DNSs = resource.DNSs - - status.CPUUser = resource.Vitals.CPU.User - status.CPUSys = resource.Vitals.CPU.System - status.CPUWait = resource.Vitals.CPU.Wait - status.MemoryPercent = resource.Vitals.Memory.Percent - status.MemoryKb = resource.Vitals.Memory.Kb - status.SwapPercent = resource.Vitals.Swap.Percent - status.SwapKb = resource.Vitals.Swap.Kb - status.DiskPersistentPercent = resource.Vitals.Disk.Persistent.Percent - - return -} diff --git a/api/director_fetch_vms_state_test.go b/api/director_fetch_vms_state_test.go deleted file mode 100644 index e15a4af..0000000 --- a/api/director_fetch_vms_state_test.go +++ /dev/null @@ -1,60 +0,0 @@ -package api_test - -import ( - "github.com/cloudfoundry-community/gogobosh/testhelpers" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - "net/http" -) - -var _ = Describe("parse full vms task output", func() { - It("GET /deployments/cf-warden/vms?format=full to return Director{}", func() { - vmsRequest := testhelpers.NewDirectorTestRequest(testhelpers.TestRequest{ - Method: "GET", - Path: "/deployments/cf-warden/vms?format=full", - Response: testhelpers.TestResponse{ - Status: http.StatusFound, - Header: http.Header{ - "Location": {"https://some.host/tasks/12"}, - }, - }, - }) - taskOutputRequest := testhelpers.NewDirectorTestRequest(testhelpers.TestRequest{ - Method: "GET", - Path: "/tasks/12/output?type=result", - Response: testhelpers.TestResponse{ - Status: http.StatusOK, - Body: `{"vm_cid":"vm-a1a3d634-367d-4b75-940c-ef7742a970d9","ips":["10.244.1.14"],"dns":[],"agent_id":"c0da6161-e66f-4910-a0eb-dc6fc19b4b25","job_name":"hm9000_z1","index":0,"job_state":"running","resource_pool":"medium_z1","vitals":{"load":["0.11","0.21","0.18"],"cpu":{"user":"1.5","sys":"2.8","wait":"0.1"},"mem":{"percent":"46.8","kb":"2864212"},"swap":{"percent":"0.0","kb":"0"},"disk":{"system":{"percent":null},"persistent":{"percent":"1"}}},"resurrection_paused":false} - {"vm_cid":"vm-affdbbdb-b91e-4838-b068-f1a057242169","ips":["10.244.0.38"],"dns":[],"agent_id":"bec309f8-0e2d-4843-9db3-a419adab4d38","job_name":"etcd_leader_z1","index":0,"job_state":"running","resource_pool":"medium_z1","vitals":{"load":["0.13","0.22","0.18"],"cpu":{"user":"0.4","sys":"2.0","wait":"0.1"},"mem":{"percent":"46.8","kb":"2863012"},"swap":{"percent":"0.0","kb":"0"},"disk":{"system":{"percent":null},"persistent":{"percent":"1"}}},"resurrection_paused":false} - `}}) - - ts, handler, repo := createDirectorRepo( - vmsRequest, - taskTestRequest(12, "queued"), - taskTestRequest(12, "processing"), - taskTestRequest(12, "done"), - taskOutputRequest) - defer ts.Close() - - vmStatuses, apiResponse := repo.FetchVMsStatus("cf-warden") - - /* TODO convert vmStatuses to a chan and pluck first item from chan */ - Expect(len(vmStatuses)).To(Equal(2)) - vmStatus := vmStatuses[0] - Expect(vmStatus.JobName).To(Equal("hm9000_z1")) - Expect(vmStatus.Index).To(Equal(0)) - Expect(vmStatus.JobState).To(Equal("running")) - Expect(vmStatus.VMCid).To(Equal("vm-a1a3d634-367d-4b75-940c-ef7742a970d9")) - Expect(vmStatus.AgentID).To(Equal("c0da6161-e66f-4910-a0eb-dc6fc19b4b25")) - Expect(vmStatus.ResourcePool).To(Equal("medium_z1")) - Expect(vmStatus.ResurrectionPaused).To(Equal(false)) - - Expect(len(vmStatus.IPs)).To(Equal(1)) - Expect(vmStatus.IPs[0]).To(Equal("10.244.1.14")) - - Expect(len(vmStatus.DNSs)).To(Equal(0)) - - Expect(apiResponse.IsSuccessful()).To(Equal(true)) - Expect(handler.AllRequestsCalled()).To(Equal(true)) - }) -}) diff --git a/api/director_info.go b/api/director_info.go deleted file mode 100644 index 8acb5a2..0000000 --- a/api/director_info.go +++ /dev/null @@ -1,74 +0,0 @@ -package api - -import ( - "github.com/cloudfoundry-community/gogobosh/models" - "github.com/cloudfoundry-community/gogobosh/net" -) - -func (repo BoshDirectorRepository) GetInfo() (directorInfo models.DirectorInfo, apiResponse net.ApiResponse) { - infoResource := directorInfoResponse{} - - path := "/info" - apiResponse = repo.gateway.GetResource(repo.config.TargetURL+path, repo.config.Username, repo.config.Password, &infoResource) - if apiResponse.IsNotSuccessful() { - return - } - - directorInfo = infoResource.ToModel() - - return -} - -type directorInfoResponse struct { - Name string `json:"name"` - UUID string `json:"uuid"` - Version string `json:"version"` - User string `json:"user"` - CPI string `json:"cpi"` - Features directorInfoFeaturesResponse `json:"features"` -} - -type directorInfoFeaturesResponse struct { - DNS directorInfoFeaturesDNS `json:"dns"` - CompiledPackageCache directorInfoFeaturesCompiledPackageCache `json:"compiled_package_cache"` - Snapshots directorInfoFeaturesSnapshots `json:"snapshots"` -} - -type directorInfoFeaturesDNS struct { - Status bool `json:"status"` - Extras directorInfoFeaturesDNSExtras `json:"extras"` -} - -type directorInfoFeaturesDNSExtras struct { - DomainName string `json:"domain_name"` -} - -type directorInfoFeaturesCompiledPackageCache struct { - Status bool `json:"status"` - Extras directorInfoFeaturesCompiledPackageCacheExtras `json:"extras"` -} - -type directorInfoFeaturesCompiledPackageCacheExtras struct { - Provider string `json:"provider"` -} - -type directorInfoFeaturesSnapshots struct { - Status bool `json:"status"` -} - -func (resource directorInfoResponse) ToModel() (director models.DirectorInfo) { - director = models.DirectorInfo{} - director.Name = resource.Name - director.Version = resource.Version - director.User = resource.User - director.UUID = resource.UUID - director.CPI = resource.CPI - - director.DNSEnabled = resource.Features.DNS.Status - director.DNSDomainName = resource.Features.DNS.Extras.DomainName - director.CompiledPackageCacheEnabled = resource.Features.CompiledPackageCache.Status - director.CompiledPackageCacheProvider = resource.Features.CompiledPackageCache.Extras.Provider - director.SnapshotsEnabled = resource.Features.Snapshots.Status - - return -} diff --git a/api/director_info_test.go b/api/director_info_test.go deleted file mode 100644 index 0e96663..0000000 --- a/api/director_info_test.go +++ /dev/null @@ -1,77 +0,0 @@ -package api_test - -import ( - "net/http" - "net/http/httptest" - - "github.com/cloudfoundry-community/gogobosh/api" - "github.com/cloudfoundry-community/gogobosh/models" - "github.com/cloudfoundry-community/gogobosh/net" - "github.com/cloudfoundry-community/gogobosh/testhelpers" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -var _ = Describe("get director info", func() { - It("GET /info to return Director{}", func() { - request := testhelpers.NewDirectorTestRequest(testhelpers.TestRequest{ - Method: "GET", - Path: "/info", - Response: testhelpers.TestResponse{ - Status: http.StatusOK, - Body: `{ - "name": "Bosh Lite Director", - "uuid": "bd462a15-213d-448c-aa5b-66624dad3f0e", - "version": "1.5.0.pre.1657 (14bc162c)", - "user": "admin", - "cpi": "warden", - "features": { - "dns": { - "status": false, - "extras": { - "domain_name": "bosh" - } - }, - "compiled_package_cache": { - "status": true, - "extras": { - "provider": "local" - } - }, - "snapshots": { - "status": false - } - } - }`}}) - ts, handler, repo := createDirectorRepo(request) - defer ts.Close() - - info, apiResponse := repo.GetInfo() - - Expect(info.Name).To(Equal("Bosh Lite Director")) - Expect(info.UUID).To(Equal("bd462a15-213d-448c-aa5b-66624dad3f0e")) - Expect(info.Version).To(Equal("1.5.0.pre.1657 (14bc162c)")) - Expect(info.User).To(Equal("admin")) - Expect(info.CPI).To(Equal("warden")) - Expect(info.DNSEnabled).To(Equal(false)) - Expect(info.DNSDomainName).To(Equal("bosh")) - Expect(info.CompiledPackageCacheEnabled).To(Equal(true)) - Expect(info.CompiledPackageCacheProvider).To(Equal("local")) - Expect(info.SnapshotsEnabled).To(Equal(false)) - - Expect(apiResponse.IsSuccessful()).To(Equal(true)) - Expect(handler.AllRequestsCalled()).To(Equal(true)) - }) -}) - -func createDirectorRepo(reqs ...testhelpers.TestRequest) (ts *httptest.Server, handler *testhelpers.TestHandler, repo api.DirectorRepository) { - ts, handler = testhelpers.NewTLSServer(reqs) - config := &models.Director{ - TargetURL: ts.URL, - Username: "admin", - Password: "admin", - } - gateway := net.NewDirectorGateway() - repo = api.NewBoshDirectorRepository(config, gateway) - return -} diff --git a/api/director_list_deployment_vms.go b/api/director_list_deployment_vms.go deleted file mode 100644 index c427666..0000000 --- a/api/director_list_deployment_vms.go +++ /dev/null @@ -1,41 +0,0 @@ -package api - -import ( - "fmt" - - "github.com/cloudfoundry-community/gogobosh/models" - "github.com/cloudfoundry-community/gogobosh/net" -) - -func (repo BoshDirectorRepository) ListDeploymentVMs(deploymentName string) (deploymentVMs []models.DeploymentVM, apiResponse net.ApiResponse) { - resources := []deploymentVMResponse{} - - path := fmt.Sprintf("/deployments/%s/vms", deploymentName) - apiResponse = repo.gateway.GetResource(repo.config.TargetURL+path, repo.config.Username, repo.config.Password, &resources) - if apiResponse.IsNotSuccessful() { - return - } - - for _, resource := range resources { - deploymentVMs = append(deploymentVMs, resource.ToModel()) - } - - return -} - -type deploymentVMResponse struct { - JobName string `json:"job"` - Index int `json:"index"` - VMCid string `json:"cid"` - AgentID string `json:"agent_id"` -} - -func (resource deploymentVMResponse) ToModel() (vm models.DeploymentVM) { - vm = models.DeploymentVM{} - vm.JobName = resource.JobName - vm.Index = resource.Index - vm.VMCid = resource.VMCid - vm.AgentID = resource.AgentID - - return -} diff --git a/api/director_list_deployment_vms_test.go b/api/director_list_deployment_vms_test.go deleted file mode 100644 index 51306d7..0000000 --- a/api/director_list_deployment_vms_test.go +++ /dev/null @@ -1,47 +0,0 @@ -package api_test - -import ( - "github.com/cloudfoundry-community/gogobosh/testhelpers" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - "net/http" -) - -var _ = Describe("simple list of vms", func() { - It("GET /deployments/$name/vms to return []models.DeploymentVM{}", func() { - request := testhelpers.NewDirectorTestRequest(testhelpers.TestRequest{ - Method: "GET", - Path: "/deployments/cf-warden/vms", - Response: testhelpers.TestResponse{ - Status: http.StatusOK, - Body: `[ - { - "agent_id": "b11f259c-79dd-4d6d-8aa5-5969d569a2a6", - "cid": "vm-8a03a314-6f16-45f6-a377-1a36e763ee45", - "job": "ha_proxy_z1", - "index": 0 - }, - { - "agent_id": "5c7708c9-1631-48b3-9833-6b7d0f6c6cd4", - "cid": "vm-37926289-487d-4ee9-b556-9684350d1d14", - "job": "login_z1", - "index": 0 - } - ]`}}) - ts, handler, repo := createDirectorRepo(request) - defer ts.Close() - - deploymentVMs, apiResponse := repo.ListDeploymentVMs("cf-warden") - - Expect(len(deploymentVMs)).To(Equal(2)) - - vm := deploymentVMs[0] - Expect(vm.JobName).To(Equal("ha_proxy_z1")) - Expect(vm.Index).To(Equal(0)) - Expect(vm.AgentID).To(Equal("b11f259c-79dd-4d6d-8aa5-5969d569a2a6")) - Expect(vm.VMCid).To(Equal("vm-8a03a314-6f16-45f6-a377-1a36e763ee45")) - - Expect(apiResponse.IsSuccessful()).To(Equal(true)) - Expect(handler.AllRequestsCalled()).To(Equal(true)) - }) -}) diff --git a/api/director_releases.go b/api/director_releases.go deleted file mode 100644 index 6cb438b..0000000 --- a/api/director_releases.go +++ /dev/null @@ -1,126 +0,0 @@ -package api - -import ( - "fmt" - "net/url" - "time" - - "github.com/cloudfoundry-community/gogobosh/models" - "github.com/cloudfoundry-community/gogobosh/net" -) - -// GetReleases returns the list of releases, and versions available -func (repo BoshDirectorRepository) GetReleases() (releases models.Releases, apiResponse net.ApiResponse) { - response := []releaseResponse{} - - path := "/releases" - apiResponse = repo.gateway.GetResource(repo.config.TargetURL+path, repo.config.Username, repo.config.Password, &response) - if apiResponse.IsNotSuccessful() { - return - } - - list := []*models.Release{} - for _, resource := range response { - list = append(list, resource.ToModel()) - } - releases = models.Releases(list) - - return -} - -// DeleteReleases deletes all versions of a release from the BOSH director -func (repo BoshDirectorRepository) DeleteReleases(name string) (apiResponse net.ApiResponse) { - path := fmt.Sprintf("/releases/%s?force=true", name) - apiResponse = repo.gateway.DeleteResource(repo.config.TargetURL+path, repo.config.Username, repo.config.Password) - if apiResponse.IsNotSuccessful() { - return - } - if !apiResponse.IsRedirection() { - return - } - - var taskStatus models.TaskStatus - taskURL, err := url.Parse(apiResponse.RedirectLocation) - if err != nil { - return - } - - apiResponse = repo.gateway.GetResource(repo.config.TargetURL+taskURL.Path, repo.config.Username, repo.config.Password, &taskStatus) - if apiResponse.IsNotSuccessful() { - return - } - - /* Progression should be: queued, progressing, done */ - /* TODO task might fail; end states: done, error, cancelled */ - for taskStatus.State != "done" { - time.Sleep(1) - taskStatus, apiResponse = repo.GetTaskStatus(taskStatus.ID) - if apiResponse.IsNotSuccessful() { - return - } - } - - return -} - -// DeleteRelease deletes a specific version of a release from the BOSH director -func (repo BoshDirectorRepository) DeleteRelease(name string, version string) (apiResponse net.ApiResponse) { - path := fmt.Sprintf("/releases/%s?force=true&version=%s", name, version) - apiResponse = repo.gateway.DeleteResource(repo.config.TargetURL+path, repo.config.Username, repo.config.Password) - if apiResponse.IsNotSuccessful() { - return - } - if !apiResponse.IsRedirection() { - return - } - - var taskStatus models.TaskStatus - taskURL, err := url.Parse(apiResponse.RedirectLocation) - if err != nil { - return - } - - apiResponse = repo.gateway.GetResource(repo.config.TargetURL+taskURL.Path, repo.config.Username, repo.config.Password, &taskStatus) - if apiResponse.IsNotSuccessful() { - return - } - - /* Progression should be: queued, progressing, done */ - /* TODO task might fail; end states: done, error, cancelled */ - for taskStatus.State != "done" { - time.Sleep(1) - taskStatus, apiResponse = repo.GetTaskStatus(taskStatus.ID) - if apiResponse.IsNotSuccessful() { - return - } - } - - return -} - -type releaseResponse struct { - Name string `json:"name"` - Versions []releaseVersionResponse `json:"release_versions"` -} - -type releaseVersionResponse struct { - Version string `json:"version"` - CommitHash string `json:"commit_hash"` - UncommittedChanges bool `json:"uncommitted_changes"` - CurrentlyDeployed bool `json:"currently_deployed"` -} - -func (resource releaseResponse) ToModel() (release *models.Release) { - release = &models.Release{} - release.Name = resource.Name - for _, versionResponse := range resource.Versions { - version := models.ReleaseVersion{} - version.Version = versionResponse.Version - version.CommitHash = versionResponse.CommitHash - version.UncommittedChanges = versionResponse.UncommittedChanges - version.CurrentlyDeployed = versionResponse.CurrentlyDeployed - - release.Versions = append(release.Versions, version) - } - return -} diff --git a/api/director_releases_test.go b/api/director_releases_test.go deleted file mode 100644 index e786d27..0000000 --- a/api/director_releases_test.go +++ /dev/null @@ -1,118 +0,0 @@ -package api_test - -import ( - "github.com/cloudfoundry-community/gogobosh/testhelpers" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - "net/http" -) - -var _ = Describe("get list of releases", func() { - It("GET /releases to return []DirectorRelease{}", func() { - request := testhelpers.NewDirectorTestRequest(testhelpers.TestRequest{ - Method: "GET", - Path: "/releases", - Response: testhelpers.TestResponse{ - Status: http.StatusOK, - Body: `[ - { - "name": "cf", - "release_versions": [ - { - "version": "153", - "commit_hash": "009fdd9a", - "uncommitted_changes": true, - "currently_deployed": true, - "job_names": [ - "cloud_controller_ng", - "nats", - "dea_next", - "login", - "health_manager_next", - "uaa", - "debian_nfs_server", - "loggregator", - "postgres", - "dea_logging_agent", - "syslog_aggregator", - "narc", - "haproxy", - "hm9000", - "saml_login", - "nats_stream_forwarder", - "collector", - "pivotal_login", - "loggregator_trafficcontroller", - "etcd", - "gorouter" - ] - } - ] - } - ]`}}) - ts, handler, repo := createDirectorRepo(request) - defer ts.Close() - - releases, apiResponse := repo.GetReleases() - - release := releases[0] - Expect(release.Name).To(Equal("cf")) - - releaseVersion := release.Versions[0] - Expect(releaseVersion.Version).To(Equal("153")) - Expect(releaseVersion.CommitHash).To(Equal("009fdd9a")) - Expect(releaseVersion.UncommittedChanges).To(Equal(true)) - Expect(releaseVersion.CurrentlyDeployed).To(Equal(true)) - - Expect(apiResponse.IsSuccessful()).To(Equal(true)) - Expect(handler.AllRequestsCalled()).To(Equal(true)) - }) - - It("DeleteReleases(name)", func() { - request := testhelpers.NewDirectorTestRequest(testhelpers.TestRequest{ - Method: "DELETE", - Path: "/releases/cf?force=true", - Response: testhelpers.TestResponse{ - Status: http.StatusFound, - Header: http.Header{ - "Location": {"https://some.host/tasks/25"}, - }, - }}) - ts, handler, repo := createDirectorRepo( - request, - taskTestRequest(25, "queued"), - taskTestRequest(25, "processing"), - taskTestRequest(25, "done"), - ) - defer ts.Close() - - apiResponse := repo.DeleteReleases("cf") - - Expect(apiResponse.IsSuccessful()).To(Equal(true)) - Expect(handler.AllRequestsCalled()).To(Equal(true)) - }) - - It("DeleteRelease(name, version)", func() { - request := testhelpers.NewDirectorTestRequest(testhelpers.TestRequest{ - Method: "DELETE", - Path: "/releases/cf?force=true&version=144", - Response: testhelpers.TestResponse{ - Status: http.StatusFound, - Header: http.Header{ - "Location": {"https://some.host/tasks/26"}, - }, - }}) - ts, handler, repo := createDirectorRepo( - request, - taskTestRequest(26, "queued"), - taskTestRequest(26, "processing"), - taskTestRequest(26, "done"), - ) - defer ts.Close() - - apiResponse := repo.DeleteRelease("cf", "144") - - Expect(apiResponse.IsSuccessful()).To(Equal(true)) - Expect(handler.AllRequestsCalled()).To(Equal(true)) - }) -}) diff --git a/api/director_repository.go b/api/director_repository.go deleted file mode 100644 index dcf4435..0000000 --- a/api/director_repository.go +++ /dev/null @@ -1,40 +0,0 @@ -package api - -import ( - "github.com/cloudfoundry-community/gogobosh/models" - "github.com/cloudfoundry-community/gogobosh/net" -) - -// DirectorRepository is the interface for accessing a BOSH director -type DirectorRepository interface { - GetInfo() (directorInfo models.DirectorInfo, apiResponse net.ApiResponse) - - GetStemcells() (stemcells models.Stemcells, apiResponse net.ApiResponse) - DeleteStemcell(name string, version string) (apiResponse net.ApiResponse) - - GetReleases() (releases models.Releases, apiResponse net.ApiResponse) - DeleteReleases(name string) (apiResponse net.ApiResponse) - DeleteRelease(name string, version string) (apiResponse net.ApiResponse) - - GetDeployments() (deployments models.Deployments, apiResponse net.ApiResponse) - GetDeploymentManifest(deploymentName string) (manifest *models.DeploymentManifest, apiResponse net.ApiResponse) - DeleteDeployment(deploymentName string) (apiResponse net.ApiResponse) - ListDeploymentVMs(deploymentName string) (deploymentVMs []models.DeploymentVM, apiResponse net.ApiResponse) - FetchVMsStatus(deploymentName string) (vmsStatus []models.VMStatus, apiResponse net.ApiResponse) - - GetTaskStatuses() (task []models.TaskStatus, apiResponse net.ApiResponse) - GetTaskStatus(taskID int) (task models.TaskStatus, apiResponse net.ApiResponse) -} - -// BoshDirectorRepository represents a Director -type BoshDirectorRepository struct { - config *models.Director - gateway net.Gateway -} - -// NewBoshDirectorRepository is a constructor for a BoshDirectorRepository -func NewBoshDirectorRepository(config *models.Director, gateway net.Gateway) (repo BoshDirectorRepository) { - repo.config = config - repo.gateway = gateway - return -} diff --git a/api/director_stemcells.go b/api/director_stemcells.go deleted file mode 100644 index 56cb5ab..0000000 --- a/api/director_stemcells.go +++ /dev/null @@ -1,79 +0,0 @@ -package api - -import ( - "fmt" - "net/url" - "time" - - "github.com/cloudfoundry-community/gogobosh/models" - "github.com/cloudfoundry-community/gogobosh/net" -) - -// GetStemcells returns the list of stemcells & versions available -func (repo BoshDirectorRepository) GetStemcells() (stemcells models.Stemcells, apiResponse net.ApiResponse) { - response := []stemcellResponse{} - - path := "/stemcells" - apiResponse = repo.gateway.GetResource(repo.config.TargetURL+path, repo.config.Username, repo.config.Password, &response) - if apiResponse.IsNotSuccessful() { - return - } - - list := []*models.Stemcell{} - for _, resource := range response { - list = append(list, resource.ToModel()) - } - stemcells = models.Stemcells(list) - - return -} - -// DeleteStemcell deletes a specific stemcell version -func (repo BoshDirectorRepository) DeleteStemcell(name string, version string) (apiResponse net.ApiResponse) { - path := fmt.Sprintf("/stemcells/%s/%s?force=true", name, version) - apiResponse = repo.gateway.DeleteResource(repo.config.TargetURL+path, repo.config.Username, repo.config.Password) - if apiResponse.IsNotSuccessful() { - return - } - if !apiResponse.IsRedirection() { - return - } - - var taskStatus models.TaskStatus - taskURL, err := url.Parse(apiResponse.RedirectLocation) - if err != nil { - return - } - - apiResponse = repo.gateway.GetResource(repo.config.TargetURL+taskURL.Path, repo.config.Username, repo.config.Password, &taskStatus) - if apiResponse.IsNotSuccessful() { - return - } - - /* Progression should be: queued, progressing, done */ - /* TODO task might fail; end states: done, error, cancelled */ - for taskStatus.State != "done" { - time.Sleep(1) - taskStatus, apiResponse = repo.GetTaskStatus(taskStatus.ID) - if apiResponse.IsNotSuccessful() { - return - } - } - - return -} - -type stemcellResponse struct { - Name string `json:"name"` - Version string `json:"version"` - Cid string `json:"cid"` -} - -func (resource stemcellResponse) ToModel() (stemcell *models.Stemcell) { - stemcell = &models.Stemcell{} - stemcell.Name = resource.Name - stemcell.Version = resource.Version - stemcell.Cid = resource.Cid - - return -} diff --git a/api/director_stemcells_test.go b/api/director_stemcells_test.go deleted file mode 100644 index bc039c2..0000000 --- a/api/director_stemcells_test.go +++ /dev/null @@ -1,72 +0,0 @@ -package api_test - -import ( - "github.com/cloudfoundry-community/gogobosh/testhelpers" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - "net/http" -) - -var _ = Describe("get list of stemcells", func() { - It("GET /stemcells to return []DirectorStemcell{}", func() { - request := testhelpers.NewDirectorTestRequest(testhelpers.TestRequest{ - Method: "GET", - Path: "/stemcells", - Response: testhelpers.TestResponse{ - Status: http.StatusOK, - Body: `[ - { - "name": "bosh-stemcell", - "version": "993", - "cid": "stemcell-6e6b9689-8b03-42cd-a6de-7784e3c421ec", - "deployments": [ - "#" - ] - }, - { - "name": "bosh-warden-boshlite-ubuntu", - "version": "24", - "cid": "stemcell-6936d497-b8cd-4e12-af0a-5f2151834a1a", - "deployments": [ - - ] - } - ]`}}) - ts, handler, repo := createDirectorRepo(request) - defer ts.Close() - - stemcells, apiResponse := repo.GetStemcells() - stemcell := stemcells[0] - - Expect(stemcell.Name).To(Equal("bosh-stemcell")) - Expect(stemcell.Version).To(Equal("993")) - Expect(stemcell.Cid).To(Equal("stemcell-6e6b9689-8b03-42cd-a6de-7784e3c421ec")) - - Expect(apiResponse.IsSuccessful()).To(Equal(true)) - Expect(handler.AllRequestsCalled()).To(Equal(true)) - }) - - It("DeleteStemcell(name, version)", func() { - request := testhelpers.NewDirectorTestRequest(testhelpers.TestRequest{ - Method: "DELETE", - Path: "/stemcells/bosh-stemcell/993?force=true", - Response: testhelpers.TestResponse{ - Status: http.StatusFound, - Header: http.Header{ - "Location": {"https://some.host/tasks/24"}, - }, - }}) - ts, handler, repo := createDirectorRepo( - request, - taskTestRequest(24, "queued"), - taskTestRequest(24, "processing"), - taskTestRequest(24, "done"), - ) - defer ts.Close() - - apiResponse := repo.DeleteStemcell("bosh-stemcell", "993") - - Expect(apiResponse.IsSuccessful()).To(Equal(true)) - Expect(handler.AllRequestsCalled()).To(Equal(true)) - }) -}) diff --git a/api/director_task_status.go b/api/director_task_status.go deleted file mode 100644 index 8ce43b1..0000000 --- a/api/director_task_status.go +++ /dev/null @@ -1,79 +0,0 @@ -package api - -import ( - "fmt" - - "github.com/cloudfoundry-community/gogobosh/models" - "github.com/cloudfoundry-community/gogobosh/net" -) - -// GetTaskStatuses returns a list of most recent task statuses -func (repo BoshDirectorRepository) GetTaskStatuses() (tasks []models.TaskStatus, apiResponse net.ApiResponse) { - taskResponses := []taskStatusResponse{} - - path := fmt.Sprintf("/tasks") - apiResponse = repo.gateway.GetResource(repo.config.TargetURL+path, repo.config.Username, repo.config.Password, &taskResponses) - if apiResponse.IsNotSuccessful() { - return - } - - for _, resource := range taskResponses { - tasks = append(tasks, resource.ToModel()) - } - - return -} - -// GetTaskStatusesWithLimit returns a max of 'limit' task statuses -func (repo BoshDirectorRepository) GetTaskStatusesWithLimit(limit int) (tasks []models.TaskStatus, apiResponse net.ApiResponse) { - taskResponses := []taskStatusResponse{} - - path := fmt.Sprintf("/tasks?limit=%d", limit) - apiResponse = repo.gateway.GetResource(repo.config.TargetURL+path, repo.config.Username, repo.config.Password, &taskResponses) - if apiResponse.IsNotSuccessful() { - return - } - - for _, resource := range taskResponses { - tasks = append(tasks, resource.ToModel()) - } - - return -} - -// GetTaskStatus returns details of a specific task to allow polling for state change -func (repo BoshDirectorRepository) GetTaskStatus(taskID int) (task models.TaskStatus, apiResponse net.ApiResponse) { - taskResponse := taskStatusResponse{} - - path := fmt.Sprintf("/tasks/%d", taskID) - apiResponse = repo.gateway.GetResource(repo.config.TargetURL+path, repo.config.Username, repo.config.Password, &taskResponse) - if apiResponse.IsNotSuccessful() { - return - } - - task = taskResponse.ToModel() - - return -} - -type taskStatusResponse struct { - ID int `json:"id"` - State string `json:"state"` - Description string `json:"description"` - TimeStamp int `json:"timestamp"` - Result string `json:"result"` - User string `json:"user"` -} - -func (resource taskStatusResponse) ToModel() (task models.TaskStatus) { - task = models.TaskStatus{} - - task.ID = resource.ID - task.State = resource.State - task.Description = resource.Description - task.TimeStamp = resource.TimeStamp - task.Result = resource.Result - task.User = resource.User - - return -} diff --git a/api/director_task_status_test.go b/api/director_task_status_test.go deleted file mode 100644 index f56642c..0000000 --- a/api/director_task_status_test.go +++ /dev/null @@ -1,92 +0,0 @@ -package api_test - -import ( - "github.com/cloudfoundry-community/gogobosh/testhelpers" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - "net/http" -) - -var _ = Describe("models.TaskStatus", func() { - It("GetTaskStatus returns models.TaskStatus{}", func() { - request := testhelpers.NewDirectorTestRequest(testhelpers.TestRequest{ - Method: "GET", - Path: "/tasks/1", - Response: testhelpers.TestResponse{ - Status: http.StatusOK, - Body: `{ - "id": 1, - "state": "done", - "description": "create release", - "timestamp": 1390068518, - "result": "Created release cf/153", - "user": "admin" - }`}}) - ts, handler, repo := createDirectorRepo(request) - defer ts.Close() - - task, apiResponse := repo.GetTaskStatus(1) - - Expect(task.ID).To(Equal(1)) - Expect(task.State).To(Equal("done")) - Expect(task.Description).To(Equal("create release")) - Expect(task.TimeStamp).To(Equal(1390068518)) - Expect(task.Result).To(Equal("Created release cf/153")) - Expect(task.User).To(Equal("admin")) - - Expect(apiResponse.IsSuccessful()).To(Equal(true)) - Expect(handler.AllRequestsCalled()).To(Equal(true)) - }) - - It("() returns []models.TaskStatus{}", func() { - request := testhelpers.NewDirectorTestRequest(testhelpers.TestRequest{ - Method: "GET", - Path: "/tasks", - Response: testhelpers.TestResponse{ - Status: http.StatusOK, - Body: `[{ - "id": 2, - "state": "done", - "description": "create release", - "timestamp": 1390068525, - "result": "Created release 'etcd/3'", - "user": "admin" - }, - { - "id": 1, - "state": "done", - "description": "create release", - "timestamp": 1390068518, - "result": "Created release 'cf/153'", - "user": "admin" - } - ]`}}) - ts, handler, repo := createDirectorRepo(request) - defer ts.Close() - - tasks, apiResponse := repo.GetTaskStatuses() - - Expect(len(tasks)).To(Equal(2)) - - task := tasks[1] - Expect(task.ID).To(Equal(1)) - Expect(task.State).To(Equal("done")) - Expect(task.Description).To(Equal("create release")) - Expect(task.TimeStamp).To(Equal(1390068518)) - Expect(task.Result).To(Equal("Created release 'cf/153'")) - Expect(task.User).To(Equal("admin")) - - Expect(apiResponse.IsSuccessful()).To(Equal(true)) - Expect(handler.AllRequestsCalled()).To(Equal(true)) - }) - - // verbose: true/false - show internal tasks - - // limit: nil or integer limit - - // states: all, processing,cancelling,queued ("running"), or specific list - XIt("GetRunningTaskStatuses", func() { - // states: processing,cancelling,queued - }) - -}) diff --git a/api/doc.go b/api/doc.go deleted file mode 100644 index 2af47eb..0000000 --- a/api/doc.go +++ /dev/null @@ -1,2 +0,0 @@ -// Package api implements the BOSH API client functions -package api diff --git a/api/suite_test.go b/api/suite_test.go deleted file mode 100644 index c9142d3..0000000 --- a/api/suite_test.go +++ /dev/null @@ -1,12 +0,0 @@ -package api_test - -import ( - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - "testing" -) - -func TestApi(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "GoGoBOSH API suite") -} diff --git a/api_test.go b/api_test.go new file mode 100644 index 0000000..a4d4ec0 --- /dev/null +++ b/api_test.go @@ -0,0 +1,256 @@ +package gogobosh_test + +import ( + "net/http" + + . "github.com/cloudfoundry-community/boshclient" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "github.com/onsi/gomega/ghttp" +) + +var _ = Describe("Api", func() { + Describe("Test API", func() { + var server *ghttp.Server + var client *Client + + BeforeEach(func() { + server = ghttp.NewServer() + config := &Config{ + BOSHAddress: server.URL(), + Username: "admin", + Password: "admin", + } + client = NewClient(config) + }) + + AfterEach(func() { + //shut down the server between tests + server.Close() + }) + + Describe("Test get stemcells", func() { + BeforeEach(func() { + stemcells := []Stemcell{ + Stemcell{ + Name: "bosh-warden-boshlite-ubuntu-trusty-go_agent", + OperatingSystem: "ubuntu-trusty", + Version: "3126", + CID: "c3705a0d-0dd3-4b67-52b5-50533a432244", + }, + } + server.AppendHandlers( + ghttp.CombineHandlers( + ghttp.VerifyBasicAuth("admin", "admin"), + ghttp.VerifyRequest("GET", "/stemcells"), + ghttp.RespondWithJSONEncoded(http.StatusOK, stemcells), + ), + ) + }) + + It("can get stemcells", func() { + stemcells, err := client.GetStemcells() + Expect(err).Should(BeNil()) + Expect(stemcells[0].Name).Should(Equal("bosh-warden-boshlite-ubuntu-trusty-go_agent")) + Expect(stemcells[0].OperatingSystem).Should(Equal("ubuntu-trusty")) + Expect(stemcells[0].Version).Should(Equal("3126")) + Expect(stemcells[0].CID).Should(Equal("c3705a0d-0dd3-4b67-52b5-50533a432244")) + }) + }) + + Describe("Test get releases", func() { + BeforeEach(func() { + releases := []Release{ + Release{ + Name: "bosh-warden-cpi", + ReleaseVersions: []ReleaseVersion{ + ReleaseVersion{ + Version: "28", + CommitHash: "4c36884a", + UncommittedChanges: false, + CurrentlyDeployed: true, + }, + }, + }, + } + server.AppendHandlers( + ghttp.CombineHandlers( + ghttp.VerifyBasicAuth("admin", "admin"), + ghttp.VerifyRequest("GET", "/releases"), + ghttp.RespondWithJSONEncoded(http.StatusOK, releases), + ), + ) + }) + + It("can get releases", func() { + releases, err := client.GetReleases() + Expect(err).Should(BeNil()) + Expect(releases[0].Name).Should(Equal("bosh-warden-cpi")) + Expect(releases[0].ReleaseVersions[0].Version).Should(Equal("28")) + Expect(releases[0].ReleaseVersions[0].CommitHash).Should(Equal("4c36884a")) + Expect(releases[0].ReleaseVersions[0].UncommittedChanges).Should(Equal(false)) + Expect(releases[0].ReleaseVersions[0].CurrentlyDeployed).Should(Equal(true)) + + }) + }) + + Describe("Test deployments", func() { + Describe("get deployments", func() { + BeforeEach(func() { + deployments := []Deployment{ + Deployment{ + Name: "cf-warden", + CloudConfig: "none", + Releases: []Resource{ + Resource{ + Name: "cf", + Version: "223", + }, + }, + Stemcells: []Resource{ + Resource{ + Name: "bosh-warden-boshlite-ubuntu-trusty-go_agent", + Version: "3126", + }, + }, + }, + } + server.AppendHandlers( + ghttp.CombineHandlers( + ghttp.VerifyBasicAuth("admin", "admin"), + ghttp.VerifyRequest("GET", "/deployments"), + ghttp.RespondWithJSONEncoded(http.StatusOK, deployments), + ), + ) + }) + + It("can get deployments", func() { + deployments, err := client.GetDeployments() + Expect(err).Should(BeNil()) + Expect(deployments[0].Name).Should(Equal("cf-warden")) + Expect(deployments[0].CloudConfig).Should(Equal("none")) + Expect(deployments[0].Releases[0].Name).Should(Equal("cf")) + Expect(deployments[0].Releases[0].Version).Should(Equal("223")) + Expect(deployments[0].Stemcells[0].Name).Should(Equal("bosh-warden-boshlite-ubuntu-trusty-go_agent")) + Expect(deployments[0].Stemcells[0].Version).Should(Equal("3126")) + }) + }) + Describe("create deployments", func() { + BeforeEach(func() { + task := Task{ + ID: 2, + State: "processing", + Description: "run errand acceptance_tests from deployment cf-warden", + } + server.AppendHandlers( + ghttp.CombineHandlers( + ghttp.VerifyBasicAuth("admin", "admin"), + ghttp.VerifyContentType("text/yaml"), + ghttp.VerifyRequest("POST", "/deployments"), + ghttp.RespondWithJSONEncoded(http.StatusOK, task), + ), + ) + }) + It("can create deployments", func() { + task, err := client.CreateDeployment("---\nname: foo") + Expect(err).Should(BeNil()) + Expect(task.ID).Should(Equal(2)) + }) + }) + }) + + Describe("Test tasks", func() { + BeforeEach(func() { + tasks := []Task{ + Task{ + ID: 1180, + State: "processing", + Description: "run errand acceptance_tests from deployment cf-warden", + }, + } + server.AppendHandlers( + ghttp.CombineHandlers( + ghttp.VerifyBasicAuth("admin", "admin"), + ghttp.VerifyRequest("GET", "/tasks"), + ghttp.RespondWithJSONEncoded(http.StatusOK, tasks), + ), + ) + }) + + It("can get tasks", func() { + tasks, err := client.GetTasks() + Expect(err).Should(BeNil()) + Expect(tasks[0].ID).Should(Equal(1180)) + Expect(tasks[0].State).Should(Equal("processing")) + Expect(tasks[0].Description).Should(Equal("run errand acceptance_tests from deployment cf-warden")) + }) + }) + + Describe("Test get deployment manifest", func() { + BeforeEach(func() { + manifest := Manifest{ + Manifest: "---\nfoo: bar\n", + } + server.AppendHandlers( + ghttp.CombineHandlers( + ghttp.VerifyBasicAuth("admin", "admin"), + ghttp.VerifyRequest("GET", "/deployments/foo"), + ghttp.RespondWithJSONEncoded(http.StatusOK, manifest), + ), + ) + }) + + It("can get deployments manifest", func() { + manifest, err := client.GetDeployment("foo") + Expect(err).Should(BeNil()) + Expect(manifest.Manifest).Should(Equal("---\nfoo: bar\n")) + }) + }) + + Describe("Test get deployment vms", func() { + BeforeEach(func() { + task := Task{ + ID: 2, + State: "done", + Description: "run errand acceptance_tests from deployment cf-warden", + } + vms := `{"vm_cid":"ec974048-3352-4ba4-669d-beab87b16bcb","disk_cid":null,"ips":["10.244.0.142"],"dns":[],"agent_id":"c5e7c705-459e-41c0-b640-db32d8dc6e71","job_name":"doppler_z1","index":0,"job_state":"running","resource_pool":"medium_z1","vitals":{"cpu":{"sys":"9.1","user":"2.1","wait":"1.7"},"disk":{"ephemeral":{"inode_percent":"11","percent":"36"},"system":{"inode_percent":"11","percent":"36"}},"load":["0.61","0.74","1.10"],"mem":{"kb":"2520960","percent":"41"},"swap":{"kb":"102200","percent":"10"}},"processes":[{"name":"doppler","state":"running"},{"name":"syslog_drain_binder","state":"running"},{"name":"metron_agent","state":"running"}],"resurrection_paused":false}` + redirect := http.Header{} + redirect.Add("Location", server.URL()+"/tasks/2") + server.AppendHandlers( + ghttp.CombineHandlers( + ghttp.VerifyBasicAuth("admin", "admin"), + ghttp.VerifyRequest("GET", "/deployments/foo/vms"), + ghttp.RespondWith(http.StatusMovedPermanently, nil, redirect), + ), + ghttp.CombineHandlers( + ghttp.VerifyBasicAuth("admin", "admin"), + ghttp.VerifyRequest("GET", "/tasks/2"), + ghttp.RespondWithJSONEncoded(http.StatusOK, task), + ), + ghttp.CombineHandlers( + ghttp.VerifyBasicAuth("admin", "admin"), + ghttp.VerifyRequest("GET", "/tasks/2"), + ghttp.RespondWithJSONEncoded(http.StatusOK, task), + ), + ghttp.CombineHandlers( + ghttp.VerifyBasicAuth("admin", "admin"), + ghttp.VerifyRequest("GET", "/tasks/2/output", "type=result"), + ghttp.RespondWith(http.StatusOK, vms, nil), + ), + ) + }) + + It("can get deployments manifest", func() { + vms, err := client.GetDeploymentVMs("foo") + Expect(err).Should(BeNil()) + Expect(vms[0].VMCID).Should(Equal("ec974048-3352-4ba4-669d-beab87b16bcb")) + Expect(vms[0].IPs[0]).Should(Equal("10.244.0.142")) + Expect(vms[0].AgentID).Should(Equal("c5e7c705-459e-41c0-b640-db32d8dc6e71")) + Expect(vms[0].JobName).Should(Equal("doppler_z1")) + }) + }) + + }) +}) diff --git a/client.go b/client.go new file mode 100644 index 0000000..b0cc148 --- /dev/null +++ b/client.go @@ -0,0 +1,168 @@ +package gogobosh + +import ( + "bytes" + "crypto/tls" + "encoding/json" + "fmt" + "io" + "io/ioutil" + "log" + "net/http" + "net/url" + "strings" +) + +//Client used to communicate with BOSH +type Client struct { + config Config +} + +//Config is used to configure the creation of a client +type Config struct { + BOSHAddress string + Port string + Username string + Password string + HttpClient *http.Client + SkipSslValidation bool +} + +// request is used to help build up a request +type request struct { + method string + url string + header map[string]string + params url.Values + body io.Reader + obj interface{} +} + +//DefaultConfig configuration for client +func DefaultConfig() *Config { + return &Config{ + BOSHAddress: "https://192.168.50.4:25555", + Username: "admin", + Password: "admin", + HttpClient: http.DefaultClient, + SkipSslValidation: false, + } +} + +// NewClient returns a new client +func NewClient(config *Config) *Client { + // bootstrap the config + defConfig := DefaultConfig() + + if len(config.BOSHAddress) == 0 { + config.BOSHAddress = defConfig.BOSHAddress + } + + if len(config.Username) == 0 { + config.Username = defConfig.Username + } + + if len(config.Password) == 0 { + config.Password = defConfig.Password + } + + config.HttpClient = &http.Client{ + Transport: &http.Transport{ + TLSClientConfig: &tls.Config{ + InsecureSkipVerify: config.SkipSslValidation, + }, + }, + CheckRedirect: func(req *http.Request, via []*http.Request) error { + if len(via) > 10 { + return fmt.Errorf("stopped after 10 redirects") + } + req.URL.Host = strings.TrimPrefix(config.BOSHAddress, req.URL.Scheme+"://") + req.SetBasicAuth(config.Username, config.Password) + return nil + }} + client := &Client{ + config: *config, + } + return client +} + +// NewRequest is used to create a new request +func (c *Client) NewRequest(method, path string) *request { + r := &request{ + method: method, + url: c.config.BOSHAddress + path, + params: make(map[string][]string), + header: make(map[string]string), + } + return r +} + +// DoRequest runs a request with our client +func (c *Client) DoRequest(r *request) (*http.Response, error) { + req, err := r.toHTTP() + if err != nil { + return nil, err + } + for key, value := range r.header { + req.Header.Add(key, value) + } + req.SetBasicAuth(c.config.Username, c.config.Password) + req.Header.Add("User-Agent", "gogo-bosh") + resp, err := c.config.HttpClient.Do(req) + return resp, err +} + +// GetInfo returns BOSH Info +func (c *Client) GetInfo() (info Info, err error) { + r := c.NewRequest("GET", "/info") + resp, err := c.DoRequest(r) + + if err != nil { + log.Printf("Error requesting info %v", err) + return info, err + } + resBody, err := ioutil.ReadAll(resp.Body) + if err != nil { + log.Printf("Error reading info request %v", resBody) + return info, err + } + err = json.Unmarshal(resBody, &info) + if err != nil { + log.Printf("Error unmarshaling info %v", err) + return info, err + } + return info, nil +} + +// toHTTP converts the request to an HTTP request +func (r *request) toHTTP() (*http.Request, error) { + + // Check if we should encode the body + if r.body == nil && r.obj != nil { + if b, err := encodeBody(r.obj); err != nil { + return nil, err + } else { + r.body = b + } + } + + // Create the HTTP request + return http.NewRequest(r.method, r.url, r.body) +} + +// decodeBody is used to JSON decode a body +func decodeBody(resp *http.Response, out interface{}) error { + defer resp.Body.Close() + dec := json.NewDecoder(resp.Body) + return dec.Decode(out) +} + +// encodeBody is used to encode a request body +func encodeBody(obj interface{}) (io.Reader, error) { + buf := bytes.NewBuffer(nil) + enc := json.NewEncoder(buf) + if err := enc.Encode(obj); err != nil { + return nil, err + } + return buf, nil +} diff --git a/client_test.go b/client_test.go new file mode 100644 index 0000000..b81cca4 --- /dev/null +++ b/client_test.go @@ -0,0 +1,64 @@ +package gogobosh_test + +import ( + "net/http" + + . "github.com/cloudfoundry-community/boshclient" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "github.com/onsi/gomega/ghttp" +) + +var _ = Describe("Client", func() { + Describe("Test Default Config", func() { + config := DefaultConfig() + + It("returns default config", func() { + Expect(config.BOSHAddress).Should(Equal("https://192.168.50.4:25555")) + Expect(config.Username).Should(Equal("admin")) + Expect(config.Password).Should(Equal("admin")) + }) + }) + + Describe("Test Creating client", func() { + var server *ghttp.Server + var client *Client + + BeforeEach(func() { + server = ghttp.NewServer() + config := &Config{ + BOSHAddress: server.URL(), + Username: "admin", + Password: "admin", + } + info := &Info{ + Name: "bosh-lite", + UUID: "2daf673a-9755-4b4f-aa6d-3632fbed8012", + Version: "1.3126.0 (00000000)", + User: "admin", + CPI: "warden_cpi", + } + client = NewClient(config) + + server.AppendHandlers( + ghttp.CombineHandlers( + ghttp.VerifyBasicAuth("admin", "admin"), + ghttp.VerifyRequest("GET", "/info"), + ghttp.RespondWithJSONEncoded(http.StatusOK, info), + ), + ) + }) + + It("can get bosh info", func() { + info, err := client.GetInfo() + Expect(info.Name).Should(Equal("bosh-lite")) + Expect(info.UUID).Should(Equal("2daf673a-9755-4b4f-aa6d-3632fbed8012")) + Expect(info.Version).Should(Equal("1.3126.0 (00000000)")) + Expect(info.User).Should(Equal("admin")) + Expect(info.CPI).Should(Equal("warden_cpi")) + + Expect(err).Should(BeNil()) + }) + }) +}) diff --git a/constants/version.go b/constants/version.go deleted file mode 100644 index b1a895b..0000000 --- a/constants/version.go +++ /dev/null @@ -1,5 +0,0 @@ -package constants - -const ( - Version = "0.1.0" -) diff --git a/doc.go b/doc.go deleted file mode 100644 index b9dd8f8..0000000 --- a/doc.go +++ /dev/null @@ -1,2 +0,0 @@ -// Package gogobosh is a client library for applications wanting to talk to a Cloud Foundry BOSH/MicroBOSH or bosh-lite. -package gogobosh diff --git a/example/bosh-lite-example.go b/example/bosh-lite-example.go deleted file mode 100644 index de058cd..0000000 --- a/example/bosh-lite-example.go +++ /dev/null @@ -1,124 +0,0 @@ -package main - -import ( - "flag" - "fmt" - - "github.com/cloudfoundry-community/gogobosh" - "github.com/cloudfoundry-community/gogobosh/api" - "github.com/cloudfoundry-community/gogobosh/net" - "github.com/cloudfoundry-community/gogobosh/utils" -) - -func main() { - utils.Logger = utils.NewLogger() - - target := flag.String("target", "https://192.168.50.4:25555", "BOSH director host") - username := flag.String("username", "admin", "Login with username") - password := flag.String("password", "admin", "Login with password") - flag.Parse() - - director := gogobosh.NewDirector(*target, *username, *password) - repo := api.NewBoshDirectorRepository(&director, net.NewDirectorGateway()) - - info, apiResponse := repo.GetInfo() - if apiResponse.IsNotSuccessful() { - fmt.Println("Could not fetch BOSH info") - return - } - - fmt.Println("Director") - fmt.Printf(" Name %s\n", info.Name) - fmt.Printf(" URL %s\n", info.URL) - fmt.Printf(" Version %s\n", info.Version) - fmt.Printf(" User %s\n", info.User) - fmt.Printf(" UUID %s\n", info.UUID) - fmt.Printf(" CPI %s\n", info.CPI) - if info.DNSEnabled { - fmt.Printf(" dns %#v (%s)\n", info.DNSEnabled, info.DNSDomainName) - } else { - fmt.Printf(" dns %#v\n", info.DNSEnabled) - } - if info.CompiledPackageCacheEnabled { - fmt.Printf(" compiled_package_cache %#v (provider: %s)\n", info.CompiledPackageCacheEnabled, info.CompiledPackageCacheProvider) - } else { - fmt.Printf(" compiled_package_cache %#v\n", info.CompiledPackageCacheEnabled) - } - fmt.Printf(" snapshots %#v\n", info.SnapshotsEnabled) - fmt.Println("") - fmt.Printf("%#v\n", info) - fmt.Println("") - - stemcells, apiResponse := repo.GetStemcells() - if apiResponse.IsNotSuccessful() { - fmt.Println("Could not fetch BOSH stemcells") - return - } else { - for _, stemcell := range stemcells { - fmt.Printf("%#v\n", stemcell) - } - fmt.Println("") - } - - releases, apiResponse := repo.GetReleases() - if apiResponse.IsNotSuccessful() { - fmt.Println("Could not fetch BOSH releases") - return - } else { - for _, release := range releases { - fmt.Printf("%#v\n", release) - } - fmt.Println("") - } - - deployments, apiResponse := repo.GetDeployments() - if apiResponse.IsNotSuccessful() { - fmt.Println("Could not fetch BOSH deployments") - return - } else { - for _, deployment := range deployments { - fmt.Printf("%#v\n", deployment) - } - fmt.Println("") - } - - tasks, apiResponse := repo.GetTaskStatusesWithLimit(3) - if apiResponse.IsNotSuccessful() { - fmt.Println("Could not fetch tasks") - return - } else { - fmt.Printf("%#v\n", tasks) - } - - task, apiResponse := repo.GetTaskStatus(tasks[0].ID) - if apiResponse.IsNotSuccessful() { - fmt.Println("Could not fetch BOSH task 1") - return - } else { - fmt.Printf("%#v\n", task) - } - - fmt.Println("") - fmt.Println("VMs in cf-warden deployment:") - vms, apiResponse := repo.ListDeploymentVMs("cf-warden") - if apiResponse.IsNotSuccessful() { - fmt.Println("Could not get list of VM for cf-warden") - return - } else { - for _, vm := range vms { - fmt.Printf("%#v\n", vm) - } - } - - fmt.Println("") - fmt.Println("VMs status in cf-warden deployment:") - vmsStatuses, apiResponse := repo.FetchVMsStatus("cf-warden") - if apiResponse.IsNotSuccessful() { - fmt.Println("Could not fetch VMs status for cf-warden") - return - } else { - for _, vmStatus := range vmsStatuses { - fmt.Printf("%s/%d is %s, IPs %#v\n", vmStatus.JobName, vmStatus.Index, vmStatus.JobState, vmStatus.IPs) - } - } -} diff --git a/gogobosh.go b/gogobosh.go deleted file mode 100644 index 708b284..0000000 --- a/gogobosh.go +++ /dev/null @@ -1,12 +0,0 @@ -package gogobosh - -import "github.com/cloudfoundry-community/gogobosh/models" - -// NewDirector constructs a Director -func NewDirector(targetURL string, username string, password string) (director models.Director) { - director = models.Director{} - director.TargetURL = targetURL - director.Username = username - director.Password = password - return -} diff --git a/gogobosh_suite_test.go b/gogobosh_suite_test.go index d420724..c45d802 100644 --- a/gogobosh_suite_test.go +++ b/gogobosh_suite_test.go @@ -3,10 +3,11 @@ package gogobosh_test import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + "testing" ) -func TestGoGoBosh(t *testing.T) { +func TestBoshclient(t *testing.T) { RegisterFailHandler(Fail) - RunSpecs(t, "GoGoBOSH suite") + RunSpecs(t, "Boshclient Suite") } diff --git a/gogobosh_test.go b/gogobosh_test.go deleted file mode 100644 index 4b477c4..0000000 --- a/gogobosh_test.go +++ /dev/null @@ -1,10 +0,0 @@ -package gogobosh_test - -import ( - . "github.com/onsi/ginkgo" -) - -var _ = Describe("GoGoBOSH", func() { - It("parse response", func() { - }) -}) diff --git a/local/director.go b/local/director.go deleted file mode 100644 index 056a42d..0000000 --- a/local/director.go +++ /dev/null @@ -1,65 +0,0 @@ -package local - -import ( - "errors" - "io/ioutil" - "os/user" - "path/filepath" - - "launchpad.net/goyaml" -) - -// BoshConfig describes a local ~/.bosh_config file -// See testhelpers/fixtures/bosh_config.yml -type BoshConfig struct { - Target string - Name string `yaml:"target_name"` - Version string `yaml:"target_version"` - UUID string `yaml:"target_uuid"` - Aliases map[string]map[string]string - Authentication map[string]*authentication `yaml:"auth"` - Deployments map[string]string `yaml:"deployment"` -} - -type authentication struct { - Username string - Password string -} - -// LoadBoshConfig loads and unmarshals ~/.bosh_config -func LoadBoshConfig(configPath string) (config *BoshConfig, err error) { - config = &BoshConfig{} - - contents, err := ioutil.ReadFile(configPath) - if err != nil { - return config, err - } - goyaml.Unmarshal(contents, config) - return -} - -// DefaultBoshConfigPath returns the path to ~/.bosh_config -func DefaultBoshConfigPath() (configPath string, err error) { - usr, err := user.Current() - if err != nil { - return "", err - } - return filepath.Abs(usr.HomeDir + "/.bosh_config") -} - -// CurrentBoshTarget returns the connection information for local user's current target BOSH -func (config *BoshConfig) CurrentBoshTarget() (target, username, password string, err error) { - if config.Target == "" { - return "", "", "", errors.New("Please target a BOSH first. Run 'bosh target DIRECTOR_IP'.") - } - auth := config.Authentication[config.Target] - if auth == nil { - return "", "", "", errors.New("Current target has not been authenticated yet. Run 'bosh login'.") - } - return config.Target, auth.Username, auth.Password, nil -} - -// CurrentDeploymentManifest returns the path to the deployment manifest for the currently target BOSH -func (config *BoshConfig) CurrentDeploymentManifest() (manifestPath string) { - return config.Deployments[config.Target] -} diff --git a/local/director_test.go b/local/director_test.go deleted file mode 100644 index dee293f..0000000 --- a/local/director_test.go +++ /dev/null @@ -1,47 +0,0 @@ -package local_test - -import ( - "path/filepath" - - "github.com/cloudfoundry-community/gogobosh/local" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -var _ = Describe("Local config", func() { - It("Loads BOSH config", func() { - configPath, err := filepath.Abs("../testhelpers/fixtures/bosh_config.yml") - Expect(err).ShouldNot(HaveOccurred()) - - config, err := local.LoadBoshConfig(configPath) - Expect(err).ShouldNot(HaveOccurred()) - Expect(config).ToNot(BeNil()) - Expect(config.Name).To(Equal("Bosh Lite Director")) - Expect(config.Authentication["https://192.168.50.4:25555"].Username).To(Equal("admin")) - }) - - It("CurrentBoshTarget", func() { - configPath, err := filepath.Abs("../testhelpers/fixtures/bosh_config.yml") - Expect(err).ShouldNot(HaveOccurred()) - config, err := local.LoadBoshConfig(configPath) - Expect(err).ShouldNot(HaveOccurred()) - Expect(config).ToNot(BeNil()) - - target, username, password, err := config.CurrentBoshTarget() - Expect(err).ShouldNot(HaveOccurred()) - Expect(target).To(Equal("https://192.168.50.4:25555")) - Expect(username).To(Equal("admin")) - Expect(password).To(Equal("password")) - }) - - It("CurrentBoshDeployment", func() { - configPath, err := filepath.Abs("../testhelpers/fixtures/bosh_config.yml") - Expect(err).ShouldNot(HaveOccurred()) - config, err := local.LoadBoshConfig(configPath) - Expect(err).ShouldNot(HaveOccurred()) - Expect(config).ToNot(BeNil()) - - manifestPath := config.CurrentDeploymentManifest() - Expect(manifestPath).To(Equal("path/to/manifest.yml")) - }) -}) diff --git a/local/suite_test.go b/local/suite_test.go deleted file mode 100644 index ec9b048..0000000 --- a/local/suite_test.go +++ /dev/null @@ -1,13 +0,0 @@ -package local_test - -import ( - "testing" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -func TestApi(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "GoGoBOSH Local suite") -} diff --git a/models.go b/models.go new file mode 100644 index 0000000..2d0e995 --- /dev/null +++ b/models.go @@ -0,0 +1,84 @@ +package gogobosh + +// Info struct +type Info struct { + Name string `json:"name"` + UUID string `json:"uuid"` + Version string `json:"version"` + User string `json:"user"` + CPI string `json:"cpi"` + UserAuthenication UserAuthenication `json:"user_authenication"` +} + +// UserAuthenication struct +type UserAuthenication struct { + Type string `json:"type"` + Options interface{} `json:"options"` +} + +// Stemcell struct +type Stemcell struct { + Name string `json:"name"` + OperatingSystem string `json:"operating_system"` + Version string `json:"version"` + CID string `json:"cid"` + Deployments []struct { + Name string `json:"name"` + } `json:"deployments"` +} + +// Release struct +type Release struct { + Name string `json:"name"` + ReleaseVersions []ReleaseVersion `json:"release_versions"` +} + +//ReleaseVersion struct +type ReleaseVersion struct { + Version string `json:"version"` + CommitHash string `json:"commit_hash"` + UncommittedChanges bool `json:"uncommitted_changes"` + CurrentlyDeployed bool `json:"currently_deployed"` + JobNames []string `json:"job_names"` +} + +// Deployment struct +type Deployment struct { + Name string `json:"name"` + CloudConfig string `json:"cloud_config"` + Releases []Resource `json:"releases"` + Stemcells []Resource `json:"stemcells"` +} + +// Resource struct +type Resource struct { + Name string `json:"name"` + Version string `json:"version"` +} + +// Manifest struct +type Manifest struct { + Manifest string `json:"manifest"` +} + +// VM struct +type VM struct { + AgentID string `json:"agent_id"` + VMCID string `json:"vm_cid"` + CID string `json:"cid"` + JobName string `json:"job_name"` + Index int `json:"index"` + IPs []string `json:"ips"` + DNS []string `json:"dns"` + ResurectionPaused bool `json:"resurrection_paused"` +} + +// Task struct +type Task struct { + ID int `json:"id"` + State string `json:"state"` + Description string `json:"description"` + Timestamp int `json:"timestamp"` + Result string `json:"result"` + User string `json:"user"` +} diff --git a/models/deployment.go b/models/deployment.go deleted file mode 100644 index d9d5f26..0000000 --- a/models/deployment.go +++ /dev/null @@ -1,34 +0,0 @@ -package models - -// Deployments is a collection of deployments in the Director -type Deployments []*Deployment - -// Deployment describes a running BOSH deployment and the -// Releases and Stemcells it is using. -type Deployment struct { - Name string - Releases []NameVersion - Stemcells []NameVersion -} - -// DeploymentVM describes the association of a running server -// within a Deployment -type DeploymentVM struct { - JobName string - Index int - VMCid string - AgentID string -} - -// FindByRelease returns a list of deployments that use a release -func (deployments Deployments) FindByRelease(releaseName string) Deployments { - subset := []*Deployment{} - for _, deployment := range deployments { - for _, release := range deployment.Releases { - if release.Name == releaseName { - subset = append(subset, deployment) - } - } - } - return Deployments(subset) -} diff --git a/models/deployment_manifest.go b/models/deployment_manifest.go deleted file mode 100644 index 2ab422f..0000000 --- a/models/deployment_manifest.go +++ /dev/null @@ -1,87 +0,0 @@ -package models - -// DeploymentManifest describes all the configuration for any BOSH deployment -type DeploymentManifest struct { - Meta map[string]interface{} `yaml:"meta,omitempty"` - Name string - DirectorUUID string `yaml:"director_uuid"` - Releases []*NameVersion - Compilation *manifestCompilation - Update *manifestUpdate - Networks []*manifestNetwork - ResourcePools []*manifestResourcePool `yaml:"resource_pools"` - Jobs []*ManifestJob - Properties *map[string]interface{} `yaml:"properties,omitempty"` -} - -type manifestCompilation struct { - Workers int `yaml:"workers"` - NetworkName string `yaml:"network"` - ReuseCompilationVMs bool `yaml:"reuse_compilation_vms"` - CloudProperties *map[string]interface{} `yaml:"cloud_properties"` -} - -type manifestUpdate struct { - Canaries int - MaxInFlight int `yaml:"max_in_flight"` - CanaryWatchTime string `yaml:"canary_watch_time"` - UpdateWatchTime string `yaml:"update_watch_time"` - Serial bool -} - -type manifestNetwork struct { - Name string - Type string - CloudProperties *map[string]interface{} `yaml:"cloud_properties"` - Subnets interface{} -} - -type manifestResourcePool struct { - Name string - NetworkName string `yaml:"network"` - Stemcell *manifestStemcell - CloudProperties *map[string]interface{} `yaml:"cloud_properties"` -} - -// ManifestJob describes a cluster of VMs each running the same set of job templates -type ManifestJob struct { - Name string - JobTemplates []*ManifestJobTemplate `yaml:"templates"` - Instances int `yaml:"instances"` - ResourcePoolName string `yaml:"resource_pool"` - PersistentDisk int `yaml:"persistent_disk,omitempty"` - Lifecycle string `yaml:"lifecycle,omitempty"` - Update *manifestUpdate `yaml:"update,omitempty"` - Networks []*manifestJobNetwork - Properties *map[string]interface{} `yaml:"properties,omitempty"` -} - -// ManifestJobTemplate describes a job template included in a ManifestJob -type ManifestJobTemplate struct { - Name string - Release string -} - -type manifestJobNetwork struct { - Name string - Default *[]string `yaml:"default,omitempty"` - StaticIPs *[]string `yaml:"static_ips,omitempty"` -} - -type manifestStemcell struct { - Name string - Version string -} - -// FindByJobTemplates returns the subnet of ManifestJobs that include a specific job template -func (manifest *DeploymentManifest) FindByJobTemplates(jobTemplateName string) (jobs []*ManifestJob) { - jobs = []*ManifestJob{} - for _, job := range manifest.Jobs { - for _, jobTemplate := range job.JobTemplates { - if jobTemplate.Name == jobTemplateName { - jobs = append(jobs, job) - } - } - } - return -} diff --git a/models/deployment_manifest_test.go b/models/deployment_manifest_test.go deleted file mode 100644 index 557d2e3..0000000 --- a/models/deployment_manifest_test.go +++ /dev/null @@ -1,22 +0,0 @@ -package models_test - -import ( - "github.com/cloudfoundry-community/gogobosh/models" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -var _ = Describe("DeploymentManifest", func() { - It("FindByJobTemplates", func() { - manifest := &models.DeploymentManifest{ - Jobs: []*models.ManifestJob{ - {Name: "job1", JobTemplates: []*models.ManifestJobTemplate{{Name: "common"}}}, - {Name: "job2", JobTemplates: []*models.ManifestJobTemplate{{Name: "common"}}}, - {Name: "other", JobTemplates: []*models.ManifestJobTemplate{{Name: "other"}}}, - }, - } - jobs := manifest.FindByJobTemplates("common") - Expect(len(jobs)).To(Equal(2)) - }) -}) diff --git a/models/deployment_test.go b/models/deployment_test.go deleted file mode 100644 index deb1e42..0000000 --- a/models/deployment_test.go +++ /dev/null @@ -1,31 +0,0 @@ -package models_test - -import ( - "github.com/cloudfoundry-community/gogobosh/models" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -var _ = Describe("Deployments", func() { - It("FindByRelease", func() { - manifest := &models.Deployments{ - { - Name: "cf-warden", - Releases: []models.NameVersion{ - {Name: "nagios"}, - {Name: "cf"}, - }, - }, - { - Name: "other", - Releases: []models.NameVersion{ - {Name: "nagios"}, - {Name: "other"}, - }, - }, - } - deployments := manifest.FindByRelease("cf") - Expect(len(deployments)).To(Equal(1)) - }) -}) diff --git a/models/doc.go b/models/doc.go deleted file mode 100644 index a2d99a1..0000000 --- a/models/doc.go +++ /dev/null @@ -1,2 +0,0 @@ -// Package models contains the public repsentations of BOSH resources -package models diff --git a/models/models.go b/models/models.go deleted file mode 100644 index 7752518..0000000 --- a/models/models.go +++ /dev/null @@ -1,88 +0,0 @@ -package models - -// Director is a targeted BOSH director and login credentials -type Director struct { - TargetURL string - Username string - Password string -} - -// DirectorInfo contains the status of a target Director -type DirectorInfo struct { - Name string - URL string - Version string - User string - UUID string - CPI string - DNSEnabled bool - DNSDomainName string - CompiledPackageCacheEnabled bool - CompiledPackageCacheProvider string - SnapshotsEnabled bool -} - -// Stemcells is a collection of stemcell in the Director -type Stemcells []*Stemcell - -// Stemcell describes an available versioned stemcell -type Stemcell struct { - Name string - Version string - Cid string -} - -// Releases is a collection of releases in the Director -type Releases []*Release - -// Release describes a release and all available versions -type Release struct { - Name string - Versions []ReleaseVersion -} - -// ReleaseVersion describes an available versioned release -type ReleaseVersion struct { - Version string - CommitHash string - UncommittedChanges bool - CurrentlyDeployed bool -} - -// NameVersion is a reusable structure for Name/Version information -type NameVersion struct { - Name string - Version string -} - -// TaskStatus summarizes the current status of a Task -type TaskStatus struct { - ID int - State string - Description string - TimeStamp int - Result string - User string -} - -// VMStatus summarizes the current status of a VM/server -// within a running deployment -type VMStatus struct { - JobName string - Index int - JobState string - VMCid string - AgentID string - ResourcePool string - ResurrectionPaused bool - IPs []string - DNSs []string - CPUUser float64 - CPUSys float64 - CPUWait float64 - MemoryPercent float64 - MemoryKb int - SwapPercent float64 - SwapKb int - DiskPersistentPercent float64 -} diff --git a/models/suite_test.go b/models/suite_test.go deleted file mode 100644 index 5761252..0000000 --- a/models/suite_test.go +++ /dev/null @@ -1,13 +0,0 @@ -package models_test - -import ( - "testing" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -func TestApi(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "GoGoBOSH Models suite") -} diff --git a/net/api_response.go b/net/api_response.go deleted file mode 100644 index c995782..0000000 --- a/net/api_response.go +++ /dev/null @@ -1,85 +0,0 @@ -package net - -import ( - "fmt" - "net/http" -) - -type ApiResponse struct { - Message string - ErrorCode string - StatusCode int - RedirectLocation string - - isError bool - isNotFound bool - isRedirection bool -} - -func NewApiResponse(message string, errorCode string, statusCode int) (apiResponse ApiResponse) { - return ApiResponse{ - Message: message, - ErrorCode: errorCode, - StatusCode: statusCode, - isError: true, - } -} - -func NewApiResponseWithRedirect(location string) (apiResponse ApiResponse) { - return ApiResponse{ - StatusCode: http.StatusFound, - RedirectLocation: location, - isRedirection: true, - } -} - -func NewApiResponseWithStatusCode(statusCode int) (apiResponse ApiResponse) { - return ApiResponse{ - StatusCode: statusCode, - } -} - -func NewApiResponseWithMessage(message string, a ...interface{}) (apiResponse ApiResponse) { - return ApiResponse{ - Message: fmt.Sprintf(message, a...), - isError: true, - } -} - -func NewApiResponseWithError(message string, err error) (apiResponse ApiResponse) { - return ApiResponse{ - Message: fmt.Sprintf("%s: %s", message, err.Error()), - isError: true, - } -} - -func NewNotFoundApiResponse(message string, a ...interface{}) (apiResponse ApiResponse) { - return ApiResponse{ - Message: fmt.Sprintf(message, a...), - isNotFound: true, - } -} - -func NewSuccessfulApiResponse() (apiResponse ApiResponse) { - return ApiResponse{} -} - -func (apiResponse ApiResponse) IsError() bool { - return apiResponse.isError -} - -func (apiResponse ApiResponse) IsNotFound() bool { - return apiResponse.isNotFound -} - -func (apiResponse ApiResponse) IsRedirection() bool { - return apiResponse.isRedirection -} - -func (apiResponse ApiResponse) IsSuccessful() bool { - return !apiResponse.IsNotSuccessful() -} - -func (apiResponse ApiResponse) IsNotSuccessful() bool { - return apiResponse.IsError() || apiResponse.IsNotFound() -} diff --git a/net/director_gateway.go b/net/director_gateway.go deleted file mode 100644 index 8584b8e..0000000 --- a/net/director_gateway.go +++ /dev/null @@ -1,35 +0,0 @@ -package net - -import ( - "encoding/json" - "io/ioutil" - "net/http" - "strconv" -) - -func NewDirectorGateway() Gateway { - invalidTokenCode := "1000" - - type ccErrorResponse struct { - Code int - Description string - } - - errorHandler := func(response *http.Response) errorResponse { - jsonBytes, _ := ioutil.ReadAll(response.Body) - response.Body.Close() - - ccResp := ccErrorResponse{} - json.Unmarshal(jsonBytes, &ccResp) - - code := strconv.Itoa(ccResp.Code) - if code == invalidTokenCode { - code = INVALID_TOKEN_CODE - } - - return errorResponse{Code: code, Description: ccResp.Description} - } - - gateway := newGateway(errorHandler) - return gateway -} diff --git a/net/doc.go b/net/doc.go deleted file mode 100644 index 51017b4..0000000 --- a/net/doc.go +++ /dev/null @@ -1,4 +0,0 @@ -/* -Package net includes helper libraries for performing HTTP requests & processing the responses -*/ -package net diff --git a/net/gateway.go b/net/gateway.go deleted file mode 100644 index 27ec555..0000000 --- a/net/gateway.go +++ /dev/null @@ -1,207 +0,0 @@ -package net - -import ( - "encoding/base64" - "encoding/json" - "fmt" - "github.com/cloudfoundry-community/gogobosh/constants" - "io" - "io/ioutil" - "net/http" - "os" - "runtime" - "strings" - "time" -) - -const ( - INVALID_TOKEN_CODE = "GATEWAY INVALID TOKEN CODE" - JOB_FINISHED = "finished" - JOB_FAILED = "failed" - DEFAULT_POLLING_THROTTLE = 5 * time.Second -) - -type JobEntity struct { - Status string -} - -type JobResponse struct { - Entity JobEntity -} - -type AsyncMetadata struct { - Url string -} - -type AsyncResponse struct { - Metadata AsyncMetadata -} - -type errorResponse struct { - Code string - Description string -} - -type errorHandler func(*http.Response) errorResponse - -type Request struct { - HttpReq *http.Request - SeekableBody io.ReadSeeker -} - -type Gateway struct { - errHandler errorHandler -} - -func newGateway(errHandler errorHandler) (gateway Gateway) { - gateway.errHandler = errHandler - return -} - -func (gateway Gateway) GetResource(url, username string, password string, resource interface{}) (apiResponse ApiResponse) { - request, apiResponse := gateway.NewRequest("GET", url, username, password, nil) - if apiResponse.IsNotSuccessful() { - return - } - - _, apiResponse = gateway.PerformRequestForJSONResponse(request, resource) - return -} - -func (gateway Gateway) CreateResource(url, username string, password string, body io.ReadSeeker) (apiResponse ApiResponse) { - return gateway.createUpdateOrDeleteResource("POST", url, username, password, body, nil) -} - -func (gateway Gateway) CreateResourceForResponse(url, username string, password string, body io.ReadSeeker, resource interface{}) (apiResponse ApiResponse) { - return gateway.createUpdateOrDeleteResource("POST", url, username, password, body, resource) -} - -func (gateway Gateway) UpdateResource(url, username string, password string, body io.ReadSeeker) (apiResponse ApiResponse) { - return gateway.createUpdateOrDeleteResource("PUT", url, username, password, body, nil) -} - -func (gateway Gateway) UpdateResourceForResponse(url, username string, password string, body io.ReadSeeker, resource interface{}) (apiResponse ApiResponse) { - return gateway.createUpdateOrDeleteResource("PUT", url, username, password, body, resource) -} - -func (gateway Gateway) DeleteResource(url, username string, password string) (apiResponse ApiResponse) { - return gateway.createUpdateOrDeleteResource("DELETE", url, username, password, nil, &AsyncResponse{}) -} - -func (gateway Gateway) createUpdateOrDeleteResource(verb, url, username string, password string, body io.ReadSeeker, resource interface{}) (apiResponse ApiResponse) { - request, apiResponse := gateway.NewRequest(verb, url, username, password, body) - if apiResponse.IsNotSuccessful() { - return - } - - if resource == nil { - return gateway.PerformRequest(request) - } - - _, apiResponse = gateway.PerformRequestForJSONResponse(request, resource) - return -} - -func (gateway Gateway) NewRequest(method, path, username string, password string, body io.ReadSeeker) (req *Request, apiResponse ApiResponse) { - if body != nil { - body.Seek(0, 0) - } - - request, err := http.NewRequest(method, path, body) - if err != nil { - apiResponse = NewApiResponseWithError("Error building request", err) - return - } - - if password != "" { - data := []byte(username + ":" + password) - auth := base64.StdEncoding.EncodeToString(data) - request.Header.Set("Authorization", "Basic "+auth) - } - - request.Header.Set("accept", "application/json") - request.Header.Set("content-type", "application/json") - request.Header.Set("User-Agent", "gogobosh "+constants.Version+" / "+runtime.GOOS) - - if body != nil { - switch v := body.(type) { - case *os.File: - fileStats, err := v.Stat() - if err != nil { - break - } - request.ContentLength = fileStats.Size() - } - } - - req = &Request{HttpReq: request, SeekableBody: body} - return -} - -func (gateway Gateway) PerformRequest(request *Request) (apiResponse ApiResponse) { - _, apiResponse = gateway.doRequestAndHandlerError(request) - return -} - -func (gateway Gateway) PerformRequestForResponseBytes(request *Request) (bytes []byte, headers http.Header, apiResponse ApiResponse) { - rawResponse, apiResponse := gateway.doRequestAndHandlerError(request) - if apiResponse.IsNotSuccessful() { - return - } - - bytes, err := ioutil.ReadAll(rawResponse.Body) - if err != nil { - apiResponse = NewApiResponseWithError("Error reading response", err) - } - - headers = rawResponse.Header - return -} - -func (gateway Gateway) PerformRequestForTextResponse(request *Request) (response string, headers http.Header, apiResponse ApiResponse) { - bytes, headers, apiResponse := gateway.PerformRequestForResponseBytes(request) - response = string(bytes) - return -} - -func (gateway Gateway) PerformRequestForJSONResponse(request *Request, response interface{}) (headers http.Header, apiResponse ApiResponse) { - bytes, headers, apiResponse := gateway.PerformRequestForResponseBytes(request) - if apiResponse.IsNotSuccessful() { - return - } - - if apiResponse.StatusCode > 203 || strings.TrimSpace(string(bytes)) == "" { - return - } - - err := json.Unmarshal(bytes, &response) - if err != nil { - apiResponse = NewApiResponseWithError("Invalid JSON response from server", err) - } - return -} - -func (gateway Gateway) doRequestAndHandlerError(request *Request) (rawResponse *http.Response, apiResponse ApiResponse) { - rawResponse, err := doRequest(request.HttpReq) - if err != nil { - apiResponse = NewApiResponseWithError("Error performing request", err) - return - } - - if rawResponse.StatusCode == 302 { - /* DELETE requests do not automatically redirect; all others should not return 302 */ - apiResponse = NewApiResponseWithRedirect(rawResponse.Header.Get("location")) - } else if rawResponse.StatusCode > 299 { - errorResponse := gateway.errHandler(rawResponse) - message := fmt.Sprintf( - "Server error, status code: %d, error code: %s, message: %s", - rawResponse.StatusCode, - errorResponse.Code, - errorResponse.Description, - ) - apiResponse = NewApiResponse(message, errorResponse.Code, rawResponse.StatusCode) - } else { - apiResponse = NewApiResponseWithStatusCode(rawResponse.StatusCode) - } - return -} diff --git a/net/gateway_test.go b/net/gateway_test.go deleted file mode 100644 index ccd174f..0000000 --- a/net/gateway_test.go +++ /dev/null @@ -1,21 +0,0 @@ -package net - -import ( - "github.com/cloudfoundry-community/gogobosh/constants" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - "runtime" -) - -var _ = Describe("Gateway", func() { - It("NewRequest successfully", func() { - gateway := NewDirectorGateway() - - request, apiResponse := gateway.NewRequest("GET", "https://example.com/v2/apps", "admin", "admin", nil) - - Expect(apiResponse.IsSuccessful()).To(Equal(true)) - Expect(request.HttpReq.Header.Get("Authorization")).To(Equal("Basic YWRtaW46YWRtaW4=")) - Expect(request.HttpReq.Header.Get("accept")).To(Equal("application/json")) - Expect(request.HttpReq.Header.Get("User-Agent")).To(Equal("gogobosh " + constants.Version + " / " + runtime.GOOS)) - }) -}) diff --git a/net/http_client.go b/net/http_client.go deleted file mode 100644 index 2b7f12e..0000000 --- a/net/http_client.go +++ /dev/null @@ -1,101 +0,0 @@ -package net - -import ( - "crypto/tls" - "errors" - "fmt" - "github.com/cloudfoundry-community/gogobosh/utils" - "net/http" - "net/http/httputil" - "regexp" - "strings" -) - -const ( - PRIVATE_DATA_PLACEHOLDER = "[PRIVATE DATA HIDDEN]" -) - -func newHttpClient() *http.Client { - tr := &http.Transport{ - TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, - Proxy: http.ProxyFromEnvironment, - } - return &http.Client{ - Transport: tr, - CheckRedirect: PrepareRedirect, - } -} - -func PrepareRedirect(req *http.Request, via []*http.Request) error { - if len(via) > 1 { - return errors.New("stopped after 1 redirect") - } - - prevReq := via[len(via)-1] - - /* Ensure redirect includes original IP:PORT & Authorization */ - req.URL.Host = prevReq.URL.Host - req.Host = prevReq.Host - req.Header.Set("Authorization", prevReq.Header.Get("Authorization")) - req.Header.Set("Accept", prevReq.Header.Get("Accept")) - req.Header.Set("Content-Type", prevReq.Header.Get("Content-Type")) - req.Header.Set("User-Agent", prevReq.Header.Get("User-Agent")) - - dumpRequest(req) - - return nil -} - -func Sanitize(input string) (sanitized string) { - var sanitizeJson = func(propertyName string, json string) string { - re := regexp.MustCompile(fmt.Sprintf(`"%s":"[^"]*"`, propertyName)) - return re.ReplaceAllString(json, fmt.Sprintf(`"%s":"`+PRIVATE_DATA_PLACEHOLDER+`"`, propertyName)) - } - - re := regexp.MustCompile(`(?m)^Authorization: .*`) - sanitized = re.ReplaceAllString(input, "Authorization: "+PRIVATE_DATA_PLACEHOLDER) - re = regexp.MustCompile(`password=[^&]*&`) - sanitized = re.ReplaceAllString(sanitized, "password="+PRIVATE_DATA_PLACEHOLDER+"&") - - sanitized = sanitizeJson("access_token", sanitized) - sanitized = sanitizeJson("refresh_token", sanitized) - sanitized = sanitizeJson("token", sanitized) - - return -} - -func doRequest(request *http.Request) (response *http.Response, err error) { - httpClient := newHttpClient() - - dumpRequest(request) - - response, err = httpClient.Do(request) - if err != nil { - return - } - - dumpResponse(response) - return -} - -func dumpRequest(req *http.Request) { - shouldDisplayBody := !strings.Contains(req.Header.Get("Content-Type"), "multipart/form-data") - dumpedRequest, err := httputil.DumpRequest(req, shouldDisplayBody) - if err != nil { - utils.Logger.Printf("Error dumping request\n%s\n", err) - } else { - utils.Logger.Printf("\n%s\n%s\n", "REQUEST:", Sanitize(string(dumpedRequest))) - if !shouldDisplayBody { - utils.Logger.Println("[MULTIPART/FORM-DATA CONTENT HIDDEN]") - } - } -} - -func dumpResponse(res *http.Response) { - dumpedResponse, err := httputil.DumpResponse(res, true) - if err != nil { - utils.Logger.Printf("Error dumping response\n%s\n", err) - } else { - utils.Logger.Printf("\n%s\n%s\n", "RESPONSE:", Sanitize(string(dumpedResponse))) - } -} diff --git a/net/suite_test.go b/net/suite_test.go deleted file mode 100644 index 19a70e2..0000000 --- a/net/suite_test.go +++ /dev/null @@ -1,12 +0,0 @@ -package net_test - -import ( - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - "testing" -) - -func TestNet(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "GoGoBOSH Net suite") -} diff --git a/testhelpers/fixtures/bosh_config.yml b/testhelpers/fixtures/bosh_config.yml deleted file mode 100644 index a79f07a..0000000 --- a/testhelpers/fixtures/bosh_config.yml +++ /dev/null @@ -1,15 +0,0 @@ ---- -target: https://192.168.50.4:25555 -target_name: Bosh Lite Director -target_version: 1.2732.0 (00000000) -target_uuid: 4e46066f-e59b-493e-b775-accc1a7bc6e2 -aliases: - target: - lite: https://192.168.50.4:25555 - 4e46066f-e59b-493e-b775-accc1a7bc6e2: https://192.168.50.4:25555 -auth: - https://192.168.50.4:25555: - username: admin - password: password -deployment: - https://192.168.50.4:25555: "path/to/manifest.yml" diff --git a/testhelpers/fixtures/manifests/bosh-lite-cf.yml b/testhelpers/fixtures/manifests/bosh-lite-cf.yml deleted file mode 100644 index 478f52f..0000000 --- a/testhelpers/fixtures/manifests/bosh-lite-cf.yml +++ /dev/null @@ -1,2775 +0,0 @@ -compilation: - cloud_properties: - name: random - network: cf1 - reuse_compilation_vms: true - workers: 6 -director_uuid: UUID -jobs: -- default_networks: - - name: cf1 - static_ips: null - instances: 1 - name: ha_proxy_z1 - networks: - - name: cf1 - static_ips: - - 10.244.0.34 - properties: - ha_proxy: - ssl_pem: '-----BEGIN CERTIFICATE----- - - MIICLzCCAZgCCQCSoIG3LoeSMTANBgkqhkiG9w0BAQUFADBcMQswCQYDVQQGEwJV - - UzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xEDAOBgNVBAoT - - B1Bpdm90YWwxFjAUBgNVBAsTDUNsb3VkIEZvdW5kcnkwHhcNMTMxMDE3MjMxNzM5 - - WhcNMTQxMDE3MjMxNzM5WjBcMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExFjAU - - BgNVBAcTDVNhbiBGcmFuY2lzY28xEDAOBgNVBAoTB1Bpdm90YWwxFjAUBgNVBAsT - - DUNsb3VkIEZvdW5kcnkwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANqyjJMH - - FDbJ4XM2vLRxz6i82Gd2Y2dnAKYgu67FgheHGQJSv38lvn8JrAOBXu2QJgP8sJa+ - - XqUWUTMo9BWvhvedQLojtcpLdULc0FhlIXn8bThGlTQyrSg9QJobhQZGziFVrdQM - - UZy4X+s6A2Szb9iOg3TYibnnfnuvdZli83eRAgMBAAEwDQYJKoZIhvcNAQEFBQAD - - gYEAbFu65WT+czpiJqHhNz5AnGYA8kieVlV7KhcljLtsU4Sxut5Vq9uXFBE09KCg - - YkyZ9KfzXArTeRCfcbm5xq12I+1nf6q0QjT1y3P6ztax0rpyb0i+4GWvA+ruMhfx - - n4QM1MkiJVYBGKkXFZDd1zsdR3pY4vm1uiMY75IvJQfgb08= - - -----END CERTIFICATE----- - - -----BEGIN RSA PRIVATE KEY----- - - MIICXQIBAAKBgQDasoyTBxQ2yeFzNry0cc+ovNhndmNnZwCmILuuxYIXhxkCUr9/ - - Jb5/CawDgV7tkCYD/LCWvl6lFlEzKPQVr4b3nUC6I7XKS3VC3NBYZSF5/G04RpU0 - - Mq0oPUCaG4UGRs4hVa3UDFGcuF/rOgNks2/YjoN02Im55357r3WZYvN3kQIDAQAB - - AoGAa88G81fTBCtDA1vhbIaKWuE1QNOgrxGcxUhvnPlqZxTHJFkMY66EmPV4oYW9 - - +RhNVTvVBYq092boAnNW1/Xebvrk1SnBDkrLntnGPmExkatOkPTFFlNXfePu6qOJ - - ULwYg8rKRwpvLoQXxbzMDXApPBifBNWGHVneGuHLpwPEQgECQQD0IJOecEyorrCR - - 6+wmJBS/IwqQO0Ooj7kZEg65MHi9exVe+XFvP0lW2NAUsDuBLz79hjslSqIJjRG8 - - c6q36oqhAkEA5VVeEip+T4DV12I5A5maGexVMeC92K7EGU/H8YhltxVZ/RtNngdT - - 3r19WeDbDF7R5CJy2f7AYullk3S6fkk28QJBALdEiW1k4rezRMyW7tYHOifvN2vl - - gbpWAt/GRZVSxSGB+B4vZq/cM8NlynftgQ5PGJucnGQ3bgN7irgNoTimc2ECQFMX - - QBMy5DroAhKcmu2r/IKB90gwFnjosVI+bsIbWkcgbE9hUhj8rK2aWE11Q8hSnpea - - x6QmQgxUZiIr+9n/qvECQQDiDIeSmo2mRYsaqr4CQ3Ak+EDjsm9XTpXHuqm+xgFO - - iDIeQCWd3/twqdDTR7FaDE7Q0i559u7A1yLumUn8caLF - - -----END RSA PRIVATE KEY----- - -' - networks: - apps: cf1 - router: - servers: - z1: - - 10.244.0.22 - z2: [] - resource_pool: router_z1 - templates: - - name: haproxy - release: cf -- instances: 1 - name: nats_z1 - networks: - - name: cf1 - static_ips: - - 10.244.0.6 - properties: - networks: - apps: cf1 - resource_pool: medium_z1 - templates: - - name: nats - release: cf - - name: nats_stream_forwarder - release: cf -- instances: 0 - name: nats_z2 - networks: - - name: cf2 - static_ips: [] - properties: - networks: - apps: cf2 - resource_pool: medium_z2 - templates: - - name: nats - release: cf - - name: nats_stream_forwarder - release: cf -- instances: 1 - name: etcd_z1 - networks: - - name: cf1 - static_ips: - - 10.244.0.42 - persistent_disk: 10024 - properties: - networks: - apps: cf1 - resource_pool: medium_z1 - templates: - - name: etcd - release: cf - - name: etcd_metrics_server - release: cf -- instances: 0 - name: etcd_z2 - networks: - - name: cf2 - static_ips: [] - persistent_disk: 10024 - properties: - networks: - apps: cf2 - resource_pool: medium_z2 - templates: - - name: etcd - release: cf - - name: etcd_metrics_server - release: cf -- instances: 0 - name: logs_z1 - networks: - - name: cf1 - static_ips: [] - persistent_disk: 4096 - properties: - networks: - apps: cf1 - resource_pool: medium_z1 - templates: - - name: syslog_aggregator - release: cf -- instances: 0 - name: logs_z2 - networks: - - name: cf2 - static_ips: [] - persistent_disk: 4096 - properties: - networks: - apps: cf2 - resource_pool: medium_z2 - templates: - - name: syslog_aggregator - release: cf -- instances: 0 - name: stats_z1 - networks: - - name: cf1 - properties: - networks: - apps: cf1 - resource_pool: small_z1 - templates: - - name: collector - release: cf -- instances: 0 - name: nfs_z1 - networks: - - name: cf1 - static_ips: null - persistent_disk: 102400 - resource_pool: medium_z1 - templates: - - name: debian_nfs_server - release: cf -- instances: 1 - name: postgres_z1 - networks: - - name: cf1 - static_ips: - - 10.244.0.30 - persistent_disk: 4096 - resource_pool: medium_z1 - templates: - - name: postgres - release: cf -- instances: 1 - name: uaa_z1 - networks: - - name: cf1 - properties: - networks: - apps: cf1 - resource_pool: medium_z1 - templates: - - name: uaa - release: cf -- instances: 0 - name: uaa_z2 - networks: - - name: cf2 - properties: - networks: - apps: cf2 - resource_pool: medium_z2 - templates: - - name: uaa - release: cf -- instances: 1 - name: login_z1 - networks: - - name: cf1 - properties: - networks: - apps: cf1 - resource_pool: medium_z1 - templates: - - name: login - release: cf -- instances: 0 - name: login_z2 - networks: - - name: cf2 - properties: - networks: - apps: cf2 - resource_pool: medium_z2 - templates: - - name: login - release: cf -- instances: 1 - name: api_z1 - networks: - - name: cf1 - persistent_disk: 4096 - properties: - metron_agent: - zone: z1 - networks: - apps: cf1 - nfs_server: - address: null - allow_from_entries: - - 10.244.0.0/30 - - 10.244.2.0/30 - share: null - resource_pool: large_z1 - templates: - - name: cloud_controller_ng - - name: cloud_controller_clock - - name: cloud_controller_worker - - name: metron_agent -- instances: 0 - name: api_z2 - networks: - - name: cf2 - persistent_disk: 4096 - properties: - metron_agent: - zone: z2 - networks: - apps: cf2 - nfs_server: - address: null - allow_from_entries: - - 10.244.0.0/30 - - 10.244.2.0/30 - share: null - resource_pool: large_z2 - templates: - - name: cloud_controller_ng - release: cf - - name: metron_agent - release: cf -- instances: 0 - name: clock_global - networks: - - name: cf1 - persistent_disk: 4096 - properties: - metron_agent: - zone: z1 - networks: - apps: cf1 - resource_pool: medium_z1 - templates: - - name: cloud_controller_clock - release: cf - - name: metron_agent - release: cf -- instances: 0 - name: api_worker_z1 - networks: - - name: cf1 - persistent_disk: 0 - properties: - metron_agent: - zone: z1 - networks: - apps: cf1 - nfs_server: - address: null - allow_from_entries: - - 10.244.0.0/30 - - 10.244.2.0/30 - share: null - resource_pool: small_z1 - templates: - - name: cloud_controller_worker - release: cf - - name: metron_agent - release: cf -- instances: 0 - name: api_worker_z2 - networks: - - name: cf2 - persistent_disk: 0 - properties: - metron_agent: - zone: z2 - networks: - apps: cf2 - nfs_server: - address: null - allow_from_entries: - - 10.244.0.0/30 - - 10.244.2.0/30 - share: null - resource_pool: small_z2 - templates: - - name: cloud_controller_worker - release: cf - - name: metron_agent - release: cf -- instances: 1 - name: hm9000_z1 - networks: - - name: cf1 - properties: - networks: - apps: cf1 - resource_pool: medium_z1 - templates: - - name: hm9000 - release: cf -- instances: 0 - name: hm9000_z2 - networks: - - name: cf2 - properties: - networks: - apps: cf2 - resource_pool: medium_z2 - templates: - - name: hm9000 - release: cf -- instances: 1 - name: runner_z1 - networks: - - name: cf1 - static_ips: - - 10.244.0.26 - properties: - dea_next: - zone: z1 - metron_agent: - zone: z1 - networks: - apps: cf1 - resource_pool: runner_z1 - templates: - - name: dea_next - release: cf - - name: dea_logging_agent - release: cf - - name: metron_agent - release: cf - update: - max_in_flight: 1 -- instances: 0 - name: runner_z2 - networks: - - name: cf2 - static_ips: null - properties: - dea_next: - zone: z2 - metron_agent: - zone: z2 - networks: - apps: cf2 - resource_pool: runner_z2 - templates: - - name: dea_next - release: cf - - name: dea_logging_agent - release: cf - - name: metron_agent - release: cf - update: - max_in_flight: 1 -- instances: 1 - name: loggregator_z1 - networks: - - name: cf1 - static_ips: - - 10.244.0.14 - properties: - doppler: - zone: z1 - networks: - apps: cf1 - resource_pool: medium_z1 - templates: - - name: doppler - release: cf -- instances: 0 - name: loggregator_z2 - networks: - - name: cf2 - static_ips: [] - properties: - doppler: - zone: z2 - networks: - apps: cf2 - resource_pool: medium_z2 - templates: - - name: doppler - release: cf -- instances: 1 - name: loggregator_trafficcontroller_z1 - networks: - - name: cf1 - static_ips: - - 10.244.0.10 - properties: - metron_agent: - zone: z1 - networks: - apps: cf1 - traffic_controller: - zone: z1 - resource_pool: small_z1 - templates: - - name: loggregator_trafficcontroller - release: cf - - name: metron_agent - release: cf -- instances: 0 - name: loggregator_trafficcontroller_z2 - networks: - - name: cf2 - static_ips: [] - properties: - metron_agent: - zone: z2 - networks: - apps: cf2 - traffic_controller: - zone: z2 - resource_pool: small_z2 - templates: - - name: loggregator_trafficcontroller - release: cf - - name: metron_agent - release: cf -- instances: 1 - name: router_z1 - networks: - - name: cf1 - static_ips: - - 10.244.0.22 - properties: - metron_agent: - zone: z1 - networks: - apps: cf1 - resource_pool: router_z1 - templates: - - name: gorouter - release: cf - - name: metron_agent - release: cf -- instances: 0 - name: router_z2 - networks: - - name: cf2 - static_ips: [] - properties: - metron_agent: - zone: z2 - networks: - apps: cf2 - resource_pool: router_z2 - templates: - - name: gorouter - release: cf - - name: metron_agent - release: cf -- instances: 1 - lifecycle: errand - name: acceptance_tests - networks: - - name: cf1 - resource_pool: small_errand - templates: - - name: acceptance-tests - release: cf -- instances: 1 - lifecycle: errand - name: smoke_tests - networks: - - name: cf1 - resource_pool: small_errand - templates: - - name: smoke-tests - release: cf -meta: - environment: cf-warden - releases: - - name: cf - version: latest - stemcell: - name: bosh-warden-boshlite-ubuntu-trusty-go_agent - version: latest -name: cf-warden -networks: -- name: cf1 - subnets: - - cloud_properties: - name: random - range: 10.244.0.0/30 - reserved: - - 10.244.0.1 - static: - - 10.244.0.2 - - cloud_properties: - name: random - range: 10.244.0.4/30 - reserved: - - 10.244.0.5 - static: - - 10.244.0.6 - - cloud_properties: - name: random - range: 10.244.0.8/30 - reserved: - - 10.244.0.9 - static: - - 10.244.0.10 - - cloud_properties: - name: random - range: 10.244.0.12/30 - reserved: - - 10.244.0.13 - static: - - 10.244.0.14 - - cloud_properties: - name: random - range: 10.244.0.16/30 - reserved: - - 10.244.0.17 - static: - - 10.244.0.18 - - cloud_properties: - name: random - range: 10.244.0.20/30 - reserved: - - 10.244.0.21 - static: - - 10.244.0.22 - - cloud_properties: - name: random - range: 10.244.0.24/30 - reserved: - - 10.244.0.25 - static: - - 10.244.0.26 - - cloud_properties: - name: random - range: 10.244.0.28/30 - reserved: - - 10.244.0.29 - static: - - 10.244.0.30 - - cloud_properties: - name: random - range: 10.244.0.32/30 - reserved: - - 10.244.0.33 - static: - - 10.244.0.34 - - cloud_properties: - name: random - range: 10.244.0.36/30 - reserved: - - 10.244.0.37 - static: - - 10.244.0.38 - - cloud_properties: - name: random - range: 10.244.0.40/30 - reserved: - - 10.244.0.41 - static: - - 10.244.0.42 - - cloud_properties: - name: random - range: 10.244.0.44/30 - reserved: - - 10.244.0.45 - static: - - 10.244.0.46 - - cloud_properties: - name: random - range: 10.244.0.48/30 - reserved: - - 10.244.0.49 - static: - - 10.244.0.50 - - cloud_properties: - name: random - range: 10.244.0.52/30 - reserved: - - 10.244.0.53 - static: - - 10.244.0.54 - - cloud_properties: - name: random - range: 10.244.0.56/30 - reserved: - - 10.244.0.57 - static: - - 10.244.0.58 - - cloud_properties: - name: random - range: 10.244.0.60/30 - reserved: - - 10.244.0.61 - static: - - 10.244.0.62 - - cloud_properties: - name: random - range: 10.244.0.64/30 - reserved: - - 10.244.0.65 - static: - - 10.244.0.66 - - cloud_properties: - name: random - range: 10.244.0.68/30 - reserved: - - 10.244.0.69 - static: - - 10.244.0.70 - - cloud_properties: - name: random - range: 10.244.0.72/30 - reserved: - - 10.244.0.73 - static: - - 10.244.0.74 - - cloud_properties: - name: random - range: 10.244.0.76/30 - reserved: - - 10.244.0.77 - static: - - 10.244.0.78 - - cloud_properties: - name: random - range: 10.244.0.80/30 - reserved: - - 10.244.0.81 - static: - - 10.244.0.82 - - cloud_properties: - name: random - range: 10.244.0.84/30 - reserved: - - 10.244.0.85 - static: - - 10.244.0.86 - - cloud_properties: - name: random - range: 10.244.0.88/30 - reserved: - - 10.244.0.89 - static: - - 10.244.0.90 - - cloud_properties: - name: random - range: 10.244.0.92/30 - reserved: - - 10.244.0.93 - static: - - 10.244.0.94 - - cloud_properties: - name: random - range: 10.244.0.96/30 - reserved: - - 10.244.0.97 - static: - - 10.244.0.98 - - cloud_properties: - name: random - range: 10.244.0.100/30 - reserved: - - 10.244.0.101 - static: - - 10.244.0.102 - - cloud_properties: - name: random - range: 10.244.0.104/30 - reserved: - - 10.244.0.105 - static: - - 10.244.0.106 - - cloud_properties: - name: random - range: 10.244.0.108/30 - reserved: - - 10.244.0.109 - static: - - 10.244.0.110 - - cloud_properties: - name: random - range: 10.244.0.112/30 - reserved: - - 10.244.0.113 - static: - - 10.244.0.114 - - cloud_properties: - name: random - range: 10.244.0.116/30 - reserved: - - 10.244.0.117 - static: - - 10.244.0.118 - - cloud_properties: - name: random - range: 10.244.0.120/30 - reserved: - - 10.244.0.121 - static: - - 10.244.0.122 - - cloud_properties: - name: random - range: 10.244.0.124/30 - reserved: - - 10.244.0.125 - static: - - 10.244.0.126 - - cloud_properties: - name: random - range: 10.244.0.128/30 - reserved: - - 10.244.0.129 - static: [] - - cloud_properties: - name: random - range: 10.244.0.132/30 - reserved: - - 10.244.0.133 - static: [] - - cloud_properties: - name: random - range: 10.244.0.136/30 - reserved: - - 10.244.0.137 - static: [] - - cloud_properties: - name: random - range: 10.244.0.140/30 - reserved: - - 10.244.0.141 - static: [] - - cloud_properties: - name: random - range: 10.244.0.144/30 - reserved: - - 10.244.0.145 - static: [] - - cloud_properties: - name: random - range: 10.244.0.148/30 - reserved: - - 10.244.0.149 - static: [] - - cloud_properties: - name: random - range: 10.244.0.152/30 - reserved: - - 10.244.0.153 - static: [] - - cloud_properties: - name: random - range: 10.244.0.156/30 - reserved: - - 10.244.0.157 - static: [] - - cloud_properties: - name: random - range: 10.244.0.160/30 - reserved: - - 10.244.0.161 - static: [] - - cloud_properties: - name: random - range: 10.244.0.164/30 - reserved: - - 10.244.0.165 - static: [] - - cloud_properties: - name: random - range: 10.244.0.168/30 - reserved: - - 10.244.0.169 - static: [] - - cloud_properties: - name: random - range: 10.244.0.172/30 - reserved: - - 10.244.0.173 - static: [] - - cloud_properties: - name: random - range: 10.244.0.176/30 - reserved: - - 10.244.0.177 - static: [] - - cloud_properties: - name: random - range: 10.244.0.180/30 - reserved: - - 10.244.0.181 - static: [] - - cloud_properties: - name: random - range: 10.244.0.184/30 - reserved: - - 10.244.0.185 - static: [] - - cloud_properties: - name: random - range: 10.244.0.188/30 - reserved: - - 10.244.0.189 - static: [] - - cloud_properties: - name: random - range: 10.244.0.192/30 - reserved: - - 10.244.0.193 - static: [] - - cloud_properties: - name: random - range: 10.244.0.196/30 - reserved: - - 10.244.0.197 - static: [] - - cloud_properties: - name: random - range: 10.244.0.200/30 - reserved: - - 10.244.0.201 - static: [] - - cloud_properties: - name: random - range: 10.244.0.204/30 - reserved: - - 10.244.0.205 - static: [] - - cloud_properties: - name: random - range: 10.244.0.208/30 - reserved: - - 10.244.0.209 - static: [] - - cloud_properties: - name: random - range: 10.244.0.212/30 - reserved: - - 10.244.0.213 - static: [] - - cloud_properties: - name: random - range: 10.244.0.216/30 - reserved: - - 10.244.0.217 - static: [] - - cloud_properties: - name: random - range: 10.244.0.220/30 - reserved: - - 10.244.0.221 - static: [] - - cloud_properties: - name: random - range: 10.244.0.224/30 - reserved: - - 10.244.0.225 - static: [] - - cloud_properties: - name: random - range: 10.244.0.228/30 - reserved: - - 10.244.0.229 - static: [] - - cloud_properties: - name: random - range: 10.244.0.232/30 - reserved: - - 10.244.0.233 - static: [] - - cloud_properties: - name: random - range: 10.244.0.236/30 - reserved: - - 10.244.0.237 - static: [] - - cloud_properties: - name: random - range: 10.244.0.240/30 - reserved: - - 10.244.0.241 - static: [] - - cloud_properties: - name: random - range: 10.244.0.244/30 - reserved: - - 10.244.0.245 - static: [] - - cloud_properties: - name: random - range: 10.244.0.248/30 - reserved: - - 10.244.0.249 - static: [] - - cloud_properties: - name: random - range: 10.244.0.252/30 - reserved: - - 10.244.0.253 - static: [] -- name: cf2 - subnets: - - cloud_properties: - name: random - range: 10.244.2.0/30 - reserved: - - 10.244.2.1 - static: - - 10.244.2.2 - - cloud_properties: - name: random - range: 10.244.2.4/30 - reserved: - - 10.244.2.5 - static: - - 10.244.2.6 - - cloud_properties: - name: random - range: 10.244.2.8/30 - reserved: - - 10.244.2.9 - static: - - 10.244.2.10 - - cloud_properties: - name: random - range: 10.244.2.12/30 - reserved: - - 10.244.2.13 - static: - - 10.244.2.14 - - cloud_properties: - name: random - range: 10.244.2.16/30 - reserved: - - 10.244.2.17 - static: - - 10.244.2.18 - - cloud_properties: - name: random - range: 10.244.2.20/30 - reserved: - - 10.244.2.21 - static: - - 10.244.2.22 - - cloud_properties: - name: random - range: 10.244.2.24/30 - reserved: - - 10.244.2.25 - static: - - 10.244.2.26 - - cloud_properties: - name: random - range: 10.244.2.28/30 - reserved: - - 10.244.2.29 - static: - - 10.244.2.30 - - cloud_properties: - name: random - range: 10.244.2.32/30 - reserved: - - 10.244.2.33 - static: - - 10.244.2.34 - - cloud_properties: - name: random - range: 10.244.2.36/30 - reserved: - - 10.244.2.37 - static: - - 10.244.2.38 - - cloud_properties: - name: random - range: 10.244.2.40/30 - reserved: - - 10.244.2.41 - static: - - 10.244.2.42 - - cloud_properties: - name: random - range: 10.244.2.44/30 - reserved: - - 10.244.2.45 - static: - - 10.244.2.46 - - cloud_properties: - name: random - range: 10.244.2.48/30 - reserved: - - 10.244.2.49 - static: - - 10.244.2.50 - - cloud_properties: - name: random - range: 10.244.2.52/30 - reserved: - - 10.244.2.53 - static: - - 10.244.2.54 - - cloud_properties: - name: random - range: 10.244.2.56/30 - reserved: - - 10.244.2.57 - static: - - 10.244.2.58 - - cloud_properties: - name: random - range: 10.244.2.60/30 - reserved: - - 10.244.2.61 - static: - - 10.244.2.62 - - cloud_properties: - name: random - range: 10.244.2.64/30 - reserved: - - 10.244.2.65 - static: - - 10.244.2.66 - - cloud_properties: - name: random - range: 10.244.2.68/30 - reserved: - - 10.244.2.69 - static: - - 10.244.2.70 - - cloud_properties: - name: random - range: 10.244.2.72/30 - reserved: - - 10.244.2.73 - static: - - 10.244.2.74 - - cloud_properties: - name: random - range: 10.244.2.76/30 - reserved: - - 10.244.2.77 - static: - - 10.244.2.78 - - cloud_properties: - name: random - range: 10.244.2.80/30 - reserved: - - 10.244.2.81 - static: - - 10.244.2.82 - - cloud_properties: - name: random - range: 10.244.2.84/30 - reserved: - - 10.244.2.85 - static: - - 10.244.2.86 - - cloud_properties: - name: random - range: 10.244.2.88/30 - reserved: - - 10.244.2.89 - static: - - 10.244.2.90 - - cloud_properties: - name: random - range: 10.244.2.92/30 - reserved: - - 10.244.2.93 - static: - - 10.244.2.94 - - cloud_properties: - name: random - range: 10.244.2.96/30 - reserved: - - 10.244.2.97 - static: - - 10.244.2.98 - - cloud_properties: - name: random - range: 10.244.2.100/30 - reserved: - - 10.244.2.101 - static: - - 10.244.2.102 - - cloud_properties: - name: random - range: 10.244.2.104/30 - reserved: - - 10.244.2.105 - static: - - 10.244.2.106 - - cloud_properties: - name: random - range: 10.244.2.108/30 - reserved: - - 10.244.2.109 - static: - - 10.244.2.110 - - cloud_properties: - name: random - range: 10.244.2.112/30 - reserved: - - 10.244.2.113 - static: - - 10.244.2.114 - - cloud_properties: - name: random - range: 10.244.2.116/30 - reserved: - - 10.244.2.117 - static: - - 10.244.2.118 - - cloud_properties: - name: random - range: 10.244.2.120/30 - reserved: - - 10.244.2.121 - static: - - 10.244.2.122 - - cloud_properties: - name: random - range: 10.244.2.124/30 - reserved: - - 10.244.2.125 - static: - - 10.244.2.126 - - cloud_properties: - name: random - range: 10.244.2.128/30 - reserved: - - 10.244.2.129 - static: [] - - cloud_properties: - name: random - range: 10.244.2.132/30 - reserved: - - 10.244.2.133 - static: [] - - cloud_properties: - name: random - range: 10.244.2.136/30 - reserved: - - 10.244.2.137 - static: [] - - cloud_properties: - name: random - range: 10.244.2.140/30 - reserved: - - 10.244.2.141 - static: [] - - cloud_properties: - name: random - range: 10.244.2.144/30 - reserved: - - 10.244.2.145 - static: [] - - cloud_properties: - name: random - range: 10.244.2.148/30 - reserved: - - 10.244.2.149 - static: [] - - cloud_properties: - name: random - range: 10.244.2.152/30 - reserved: - - 10.244.2.153 - static: [] - - cloud_properties: - name: random - range: 10.244.2.156/30 - reserved: - - 10.244.2.157 - static: [] - - cloud_properties: - name: random - range: 10.244.2.160/30 - reserved: - - 10.244.2.161 - static: [] - - cloud_properties: - name: random - range: 10.244.2.164/30 - reserved: - - 10.244.2.165 - static: [] - - cloud_properties: - name: random - range: 10.244.2.168/30 - reserved: - - 10.244.2.169 - static: [] - - cloud_properties: - name: random - range: 10.244.2.172/30 - reserved: - - 10.244.2.173 - static: [] - - cloud_properties: - name: random - range: 10.244.2.176/30 - reserved: - - 10.244.2.177 - static: [] - - cloud_properties: - name: random - range: 10.244.2.180/30 - reserved: - - 10.244.2.181 - static: [] - - cloud_properties: - name: random - range: 10.244.2.184/30 - reserved: - - 10.244.2.185 - static: [] - - cloud_properties: - name: random - range: 10.244.2.188/30 - reserved: - - 10.244.2.189 - static: [] - - cloud_properties: - name: random - range: 10.244.2.192/30 - reserved: - - 10.244.2.193 - static: [] - - cloud_properties: - name: random - range: 10.244.2.196/30 - reserved: - - 10.244.2.197 - static: [] - - cloud_properties: - name: random - range: 10.244.2.200/30 - reserved: - - 10.244.2.201 - static: [] - - cloud_properties: - name: random - range: 10.244.2.204/30 - reserved: - - 10.244.2.205 - static: [] - - cloud_properties: - name: random - range: 10.244.2.208/30 - reserved: - - 10.244.2.209 - static: [] - - cloud_properties: - name: random - range: 10.244.2.212/30 - reserved: - - 10.244.2.213 - static: [] - - cloud_properties: - name: random - range: 10.244.2.216/30 - reserved: - - 10.244.2.217 - static: [] - - cloud_properties: - name: random - range: 10.244.2.220/30 - reserved: - - 10.244.2.221 - static: [] - - cloud_properties: - name: random - range: 10.244.2.224/30 - reserved: - - 10.244.2.225 - static: [] - - cloud_properties: - name: random - range: 10.244.2.228/30 - reserved: - - 10.244.2.229 - static: [] - - cloud_properties: - name: random - range: 10.244.2.232/30 - reserved: - - 10.244.2.233 - static: [] - - cloud_properties: - name: random - range: 10.244.2.236/30 - reserved: - - 10.244.2.237 - static: [] - - cloud_properties: - name: random - range: 10.244.2.240/30 - reserved: - - 10.244.2.241 - static: [] - - cloud_properties: - name: random - range: 10.244.2.244/30 - reserved: - - 10.244.2.245 - static: [] - - cloud_properties: - name: random - range: 10.244.2.248/30 - reserved: - - 10.244.2.249 - static: [] - - cloud_properties: - name: random - range: 10.244.2.252/30 - reserved: - - 10.244.2.253 - static: [] -- name: services1 - subnets: - - cloud_properties: - name: random - range: 10.244.1.0/30 - reserved: - - 10.244.1.1 - static: - - 10.244.1.2 - - cloud_properties: - name: random - range: 10.244.1.4/30 - reserved: - - 10.244.1.5 - static: - - 10.244.1.6 - - cloud_properties: - name: random - range: 10.244.1.8/30 - reserved: - - 10.244.1.9 - static: - - 10.244.1.10 - - cloud_properties: - name: random - range: 10.244.1.12/30 - reserved: - - 10.244.1.13 - static: - - 10.244.1.14 - - cloud_properties: - name: random - range: 10.244.1.16/30 - reserved: - - 10.244.1.17 - static: - - 10.244.1.18 - - cloud_properties: - name: random - range: 10.244.1.20/30 - reserved: - - 10.244.1.21 - static: - - 10.244.1.22 - - cloud_properties: - name: random - range: 10.244.1.24/30 - reserved: - - 10.244.1.25 - static: - - 10.244.1.26 - - cloud_properties: - name: random - range: 10.244.1.28/30 - reserved: - - 10.244.1.29 - static: - - 10.244.1.30 - - cloud_properties: - name: random - range: 10.244.1.32/30 - reserved: - - 10.244.1.33 - static: - - 10.244.1.34 - - cloud_properties: - name: random - range: 10.244.1.36/30 - reserved: - - 10.244.1.37 - static: - - 10.244.1.38 - - cloud_properties: - name: random - range: 10.244.1.40/30 - reserved: - - 10.244.1.41 - static: - - 10.244.1.42 - - cloud_properties: - name: random - range: 10.244.1.44/30 - reserved: - - 10.244.1.45 - static: - - 10.244.1.46 - - cloud_properties: - name: random - range: 10.244.1.48/30 - reserved: - - 10.244.1.49 - static: - - 10.244.1.50 - - cloud_properties: - name: random - range: 10.244.1.52/30 - reserved: - - 10.244.1.53 - static: - - 10.244.1.54 - - cloud_properties: - name: random - range: 10.244.1.56/30 - reserved: - - 10.244.1.57 - static: - - 10.244.1.58 - - cloud_properties: - name: random - range: 10.244.1.60/30 - reserved: - - 10.244.1.61 - static: - - 10.244.1.62 - - cloud_properties: - name: random - range: 10.244.1.64/30 - reserved: - - 10.244.1.65 - static: - - 10.244.1.66 - - cloud_properties: - name: random - range: 10.244.1.68/30 - reserved: - - 10.244.1.69 - static: - - 10.244.1.70 - - cloud_properties: - name: random - range: 10.244.1.72/30 - reserved: - - 10.244.1.73 - static: - - 10.244.1.74 - - cloud_properties: - name: random - range: 10.244.1.76/30 - reserved: - - 10.244.1.77 - static: - - 10.244.1.78 - - cloud_properties: - name: random - range: 10.244.1.80/30 - reserved: - - 10.244.1.81 - static: - - 10.244.1.82 - - cloud_properties: - name: random - range: 10.244.1.84/30 - reserved: - - 10.244.1.85 - static: - - 10.244.1.86 - - cloud_properties: - name: random - range: 10.244.1.88/30 - reserved: - - 10.244.1.89 - static: - - 10.244.1.90 - - cloud_properties: - name: random - range: 10.244.1.92/30 - reserved: - - 10.244.1.93 - static: - - 10.244.1.94 - - cloud_properties: - name: random - range: 10.244.1.96/30 - reserved: - - 10.244.1.97 - static: - - 10.244.1.98 - - cloud_properties: - name: random - range: 10.244.1.100/30 - reserved: - - 10.244.1.101 - static: - - 10.244.1.102 - - cloud_properties: - name: random - range: 10.244.1.104/30 - reserved: - - 10.244.1.105 - static: - - 10.244.1.106 - - cloud_properties: - name: random - range: 10.244.1.108/30 - reserved: - - 10.244.1.109 - static: - - 10.244.1.110 - - cloud_properties: - name: random - range: 10.244.1.112/30 - reserved: - - 10.244.1.113 - static: - - 10.244.1.114 - - cloud_properties: - name: random - range: 10.244.1.116/30 - reserved: - - 10.244.1.117 - static: - - 10.244.1.118 - - cloud_properties: - name: random - range: 10.244.1.120/30 - reserved: - - 10.244.1.121 - static: - - 10.244.1.122 - - cloud_properties: - name: random - range: 10.244.1.124/30 - reserved: - - 10.244.1.125 - static: - - 10.244.1.126 - - cloud_properties: - name: random - range: 10.244.1.128/30 - reserved: - - 10.244.1.129 - static: [] - - cloud_properties: - name: random - range: 10.244.1.132/30 - reserved: - - 10.244.1.133 - static: [] - - cloud_properties: - name: random - range: 10.244.1.136/30 - reserved: - - 10.244.1.137 - static: [] - - cloud_properties: - name: random - range: 10.244.1.140/30 - reserved: - - 10.244.1.141 - static: [] - - cloud_properties: - name: random - range: 10.244.1.144/30 - reserved: - - 10.244.1.145 - static: [] - - cloud_properties: - name: random - range: 10.244.1.148/30 - reserved: - - 10.244.1.149 - static: [] - - cloud_properties: - name: random - range: 10.244.1.152/30 - reserved: - - 10.244.1.153 - static: [] - - cloud_properties: - name: random - range: 10.244.1.156/30 - reserved: - - 10.244.1.157 - static: [] - - cloud_properties: - name: random - range: 10.244.1.160/30 - reserved: - - 10.244.1.161 - static: [] - - cloud_properties: - name: random - range: 10.244.1.164/30 - reserved: - - 10.244.1.165 - static: [] - - cloud_properties: - name: random - range: 10.244.1.168/30 - reserved: - - 10.244.1.169 - static: [] - - cloud_properties: - name: random - range: 10.244.1.172/30 - reserved: - - 10.244.1.173 - static: [] - - cloud_properties: - name: random - range: 10.244.1.176/30 - reserved: - - 10.244.1.177 - static: [] - - cloud_properties: - name: random - range: 10.244.1.180/30 - reserved: - - 10.244.1.181 - static: [] - - cloud_properties: - name: random - range: 10.244.1.184/30 - reserved: - - 10.244.1.185 - static: [] - - cloud_properties: - name: random - range: 10.244.1.188/30 - reserved: - - 10.244.1.189 - static: [] - - cloud_properties: - name: random - range: 10.244.1.192/30 - reserved: - - 10.244.1.193 - static: [] - - cloud_properties: - name: random - range: 10.244.1.196/30 - reserved: - - 10.244.1.197 - static: [] - - cloud_properties: - name: random - range: 10.244.1.200/30 - reserved: - - 10.244.1.201 - static: [] - - cloud_properties: - name: random - range: 10.244.1.204/30 - reserved: - - 10.244.1.205 - static: [] - - cloud_properties: - name: random - range: 10.244.1.208/30 - reserved: - - 10.244.1.209 - static: [] - - cloud_properties: - name: random - range: 10.244.1.212/30 - reserved: - - 10.244.1.213 - static: [] - - cloud_properties: - name: random - range: 10.244.1.216/30 - reserved: - - 10.244.1.217 - static: [] - - cloud_properties: - name: random - range: 10.244.1.220/30 - reserved: - - 10.244.1.221 - static: [] - - cloud_properties: - name: random - range: 10.244.1.224/30 - reserved: - - 10.244.1.225 - static: [] - - cloud_properties: - name: random - range: 10.244.1.228/30 - reserved: - - 10.244.1.229 - static: [] - - cloud_properties: - name: random - range: 10.244.1.232/30 - reserved: - - 10.244.1.233 - static: [] - - cloud_properties: - name: random - range: 10.244.1.236/30 - reserved: - - 10.244.1.237 - static: [] - - cloud_properties: - name: random - range: 10.244.1.240/30 - reserved: - - 10.244.1.241 - static: [] - - cloud_properties: - name: random - range: 10.244.1.244/30 - reserved: - - 10.244.1.245 - static: [] - - cloud_properties: - name: random - range: 10.244.1.248/30 - reserved: - - 10.244.1.249 - static: [] - - cloud_properties: - name: random - range: 10.244.1.252/30 - reserved: - - 10.244.1.253 - static: [] -- name: services2 - subnets: - - cloud_properties: - name: random - range: 10.244.3.0/30 - reserved: - - 10.244.3.1 - static: - - 10.244.3.2 - - cloud_properties: - name: random - range: 10.244.3.4/30 - reserved: - - 10.244.3.5 - static: - - 10.244.3.6 - - cloud_properties: - name: random - range: 10.244.3.8/30 - reserved: - - 10.244.3.9 - static: - - 10.244.3.10 - - cloud_properties: - name: random - range: 10.244.3.12/30 - reserved: - - 10.244.3.13 - static: - - 10.244.3.14 - - cloud_properties: - name: random - range: 10.244.3.16/30 - reserved: - - 10.244.3.17 - static: - - 10.244.3.18 - - cloud_properties: - name: random - range: 10.244.3.20/30 - reserved: - - 10.244.3.21 - static: - - 10.244.3.22 - - cloud_properties: - name: random - range: 10.244.3.24/30 - reserved: - - 10.244.3.25 - static: - - 10.244.3.26 - - cloud_properties: - name: random - range: 10.244.3.28/30 - reserved: - - 10.244.3.29 - static: - - 10.244.3.30 - - cloud_properties: - name: random - range: 10.244.3.32/30 - reserved: - - 10.244.3.33 - static: - - 10.244.3.34 - - cloud_properties: - name: random - range: 10.244.3.36/30 - reserved: - - 10.244.3.37 - static: - - 10.244.3.38 - - cloud_properties: - name: random - range: 10.244.3.40/30 - reserved: - - 10.244.3.41 - static: - - 10.244.3.42 - - cloud_properties: - name: random - range: 10.244.3.44/30 - reserved: - - 10.244.3.45 - static: - - 10.244.3.46 - - cloud_properties: - name: random - range: 10.244.3.48/30 - reserved: - - 10.244.3.49 - static: - - 10.244.3.50 - - cloud_properties: - name: random - range: 10.244.3.52/30 - reserved: - - 10.244.3.53 - static: - - 10.244.3.54 - - cloud_properties: - name: random - range: 10.244.3.56/30 - reserved: - - 10.244.3.57 - static: - - 10.244.3.58 - - cloud_properties: - name: random - range: 10.244.3.60/30 - reserved: - - 10.244.3.61 - static: - - 10.244.3.62 - - cloud_properties: - name: random - range: 10.244.3.64/30 - reserved: - - 10.244.3.65 - static: - - 10.244.3.66 - - cloud_properties: - name: random - range: 10.244.3.68/30 - reserved: - - 10.244.3.69 - static: - - 10.244.3.70 - - cloud_properties: - name: random - range: 10.244.3.72/30 - reserved: - - 10.244.3.73 - static: - - 10.244.3.74 - - cloud_properties: - name: random - range: 10.244.3.76/30 - reserved: - - 10.244.3.77 - static: - - 10.244.3.78 - - cloud_properties: - name: random - range: 10.244.3.80/30 - reserved: - - 10.244.3.81 - static: - - 10.244.3.82 - - cloud_properties: - name: random - range: 10.244.3.84/30 - reserved: - - 10.244.3.85 - static: - - 10.244.3.86 - - cloud_properties: - name: random - range: 10.244.3.88/30 - reserved: - - 10.244.3.89 - static: - - 10.244.3.90 - - cloud_properties: - name: random - range: 10.244.3.92/30 - reserved: - - 10.244.3.93 - static: - - 10.244.3.94 - - cloud_properties: - name: random - range: 10.244.3.96/30 - reserved: - - 10.244.3.97 - static: - - 10.244.3.98 - - cloud_properties: - name: random - range: 10.244.3.100/30 - reserved: - - 10.244.3.101 - static: - - 10.244.3.102 - - cloud_properties: - name: random - range: 10.244.3.104/30 - reserved: - - 10.244.3.105 - static: - - 10.244.3.106 - - cloud_properties: - name: random - range: 10.244.3.108/30 - reserved: - - 10.244.3.109 - static: - - 10.244.3.110 - - cloud_properties: - name: random - range: 10.244.3.112/30 - reserved: - - 10.244.3.113 - static: - - 10.244.3.114 - - cloud_properties: - name: random - range: 10.244.3.116/30 - reserved: - - 10.244.3.117 - static: - - 10.244.3.118 - - cloud_properties: - name: random - range: 10.244.3.120/30 - reserved: - - 10.244.3.121 - static: - - 10.244.3.122 - - cloud_properties: - name: random - range: 10.244.3.124/30 - reserved: - - 10.244.3.125 - static: - - 10.244.3.126 - - cloud_properties: - name: random - range: 10.244.3.128/30 - reserved: - - 10.244.3.129 - static: [] - - cloud_properties: - name: random - range: 10.244.3.132/30 - reserved: - - 10.244.3.133 - static: [] - - cloud_properties: - name: random - range: 10.244.3.136/30 - reserved: - - 10.244.3.137 - static: [] - - cloud_properties: - name: random - range: 10.244.3.140/30 - reserved: - - 10.244.3.141 - static: [] - - cloud_properties: - name: random - range: 10.244.3.144/30 - reserved: - - 10.244.3.145 - static: [] - - cloud_properties: - name: random - range: 10.244.3.148/30 - reserved: - - 10.244.3.149 - static: [] - - cloud_properties: - name: random - range: 10.244.3.152/30 - reserved: - - 10.244.3.153 - static: [] - - cloud_properties: - name: random - range: 10.244.3.156/30 - reserved: - - 10.244.3.157 - static: [] - - cloud_properties: - name: random - range: 10.244.3.160/30 - reserved: - - 10.244.3.161 - static: [] - - cloud_properties: - name: random - range: 10.244.3.164/30 - reserved: - - 10.244.3.165 - static: [] - - cloud_properties: - name: random - range: 10.244.3.168/30 - reserved: - - 10.244.3.169 - static: [] - - cloud_properties: - name: random - range: 10.244.3.172/30 - reserved: - - 10.244.3.173 - static: [] - - cloud_properties: - name: random - range: 10.244.3.176/30 - reserved: - - 10.244.3.177 - static: [] - - cloud_properties: - name: random - range: 10.244.3.180/30 - reserved: - - 10.244.3.181 - static: [] - - cloud_properties: - name: random - range: 10.244.3.184/30 - reserved: - - 10.244.3.185 - static: [] - - cloud_properties: - name: random - range: 10.244.3.188/30 - reserved: - - 10.244.3.189 - static: [] - - cloud_properties: - name: random - range: 10.244.3.192/30 - reserved: - - 10.244.3.193 - static: [] - - cloud_properties: - name: random - range: 10.244.3.196/30 - reserved: - - 10.244.3.197 - static: [] - - cloud_properties: - name: random - range: 10.244.3.200/30 - reserved: - - 10.244.3.201 - static: [] - - cloud_properties: - name: random - range: 10.244.3.204/30 - reserved: - - 10.244.3.205 - static: [] - - cloud_properties: - name: random - range: 10.244.3.208/30 - reserved: - - 10.244.3.209 - static: [] - - cloud_properties: - name: random - range: 10.244.3.212/30 - reserved: - - 10.244.3.213 - static: [] - - cloud_properties: - name: random - range: 10.244.3.216/30 - reserved: - - 10.244.3.217 - static: [] - - cloud_properties: - name: random - range: 10.244.3.220/30 - reserved: - - 10.244.3.221 - static: [] - - cloud_properties: - name: random - range: 10.244.3.224/30 - reserved: - - 10.244.3.225 - static: [] - - cloud_properties: - name: random - range: 10.244.3.228/30 - reserved: - - 10.244.3.229 - static: [] - - cloud_properties: - name: random - range: 10.244.3.232/30 - reserved: - - 10.244.3.233 - static: [] - - cloud_properties: - name: random - range: 10.244.3.236/30 - reserved: - - 10.244.3.237 - static: [] - - cloud_properties: - name: random - range: 10.244.3.240/30 - reserved: - - 10.244.3.241 - static: [] - - cloud_properties: - name: random - range: 10.244.3.244/30 - reserved: - - 10.244.3.245 - static: [] - - cloud_properties: - name: random - range: 10.244.3.248/30 - reserved: - - 10.244.3.249 - static: [] - - cloud_properties: - name: random - range: 10.244.3.252/30 - reserved: - - 10.244.3.253 - static: [] -properties: - acceptance_tests: - admin_password: admin - admin_user: admin - api: api.10.244.0.34.xip.io - apps_domain: 10.244.0.34.xip.io - nodes: 1 - skip_ssl_validation: true - app_domains: - - 10.244.0.34.xip.io - cc: - allowed_cors_domains: [] - app_events: - cutoff_age_in_days: 31 - app_usage_events: - cutoff_age_in_days: 31 - audit_events: - cutoff_age_in_days: 31 - billing_event_writing_enabled: true - broker_client_timeout_seconds: 70 - buildpacks: - buildpack_directory_key: 10.244.0.34.xip.io-cc-buildpacks - cdn: null - fog_connection: - local_root: /var/vcap/store - provider: Local - bulk_api_password: bulk-password - client_max_body_size: 1536M - db_encryption_key: db-encryption-key - default_app_disk_in_mb: 1024 - default_app_memory: 256 - default_buildpacks: - - name: java_buildpack - package: buildpack_java - - name: ruby_buildpack - package: buildpack_ruby - - name: nodejs_buildpack - package: buildpack_nodejs - - name: go_buildpack - package: buildpack_go - - name: python_buildpack - package: buildpack_python - - name: php_buildpack - package: buildpack_php - default_quota_definition: default - default_running_security_groups: - - public_networks - - dns - default_staging_security_groups: - - public_networks - - dns - development_mode: false - diego: - running: disabled - staging: disabled - diego_docker: false - directories: null - disable_custom_buildpacks: false - droplets: - cdn: null - droplet_directory_key: 10.244.0.34.xip.io-cc-droplets - fog_connection: - local_root: /var/vcap/store - provider: Local - external_host: api - install_buildpacks: - - name: java_buildpack - package: buildpack_java - - name: ruby_buildpack - package: buildpack_ruby - - name: nodejs_buildpack - package: buildpack_nodejs - - name: go_buildpack - package: buildpack_go - - name: python_buildpack - package: buildpack_python - - name: php_buildpack - package: buildpack_php - jobs: - app_bits_packer: - timeout_in_seconds: null - app_events_cleanup: - timeout_in_seconds: null - app_usage_events_cleanup: - timeout_in_seconds: null - blobstore_delete: - timeout_in_seconds: null - blobstore_upload: - timeout_in_seconds: null - droplet_deletion: - timeout_in_seconds: null - droplet_upload: - timeout_in_seconds: null - generic: - number_of_workers: null - global: - timeout_in_seconds: 14400 - model_deletion: - timeout_in_seconds: null - maximum_app_disk_in_mb: 2048 - newrelic: - capture_params: false - developer_mode: false - environment_name: cf-warden - license_key: null - monitor_mode: false - transaction_tracer: - enabled: true - record_sql: obfuscated - packages: - app_package_directory_key: 10.244.0.34.xip.io-cc-packages - cdn: null - fog_connection: - local_root: /var/vcap/store - provider: Local - max_package_size: 1073741824 - quota_definitions: - default: - memory_limit: 10240 - non_basic_services_allowed: true - total_routes: 1000 - total_services: 100 - resource_pool: - cdn: null - fog_connection: - local_root: /var/vcap/store - provider: Local - resource_directory_key: 10.244.0.34.xip.io-cc-resources - security_group_definitions: - - name: public_networks - rules: - - destination: 0.0.0.0-9.255.255.255 - protocol: all - - destination: 11.0.0.0-169.253.255.255 - protocol: all - - destination: 169.255.0.0-172.15.255.255 - protocol: all - - destination: 172.32.0.0-192.167.255.255 - protocol: all - - destination: 192.169.0.0-255.255.255.255 - protocol: all - - name: dns - rules: - - destination: 0.0.0.0/0 - ports: "53" - protocol: tcp - - destination: 0.0.0.0/0 - ports: "53" - protocol: udp - srv_api_uri: https://api.10.244.0.34.xip.io - stacks: null - staging_upload_password: upload-password - staging_upload_user: upload-user - system_buildpacks: - - name: java_buildpack - package: buildpack_java - - name: ruby_buildpack - package: buildpack_ruby - - name: nodejs_buildpack - package: buildpack_nodejs - - name: go_buildpack - package: buildpack_go - - name: python_buildpack - package: buildpack_python - - name: php_buildpack - package: buildpack_php - thresholds: - api: - alert_if_above_mb: null - restart_if_above_mb: null - restart_if_consistently_above_mb: null - worker: - alert_if_above_mb: null - restart_if_above_mb: null - restart_if_consistently_above_mb: null - user_buildpacks: [] - ccdb: - address: 10.244.0.30 - databases: - - citext: true - name: ccdb - tag: cc - db_scheme: postgres - port: 5524 - roles: - - name: ccadmin - password: admin - tag: admin - collector: null - databases: - address: 10.244.0.30 - databases: - - citext: true - name: ccdb - tag: cc - - citext: true - name: uaadb - tag: uaa - db_scheme: postgres - port: 5524 - roles: - - name: ccadmin - password: admin - tag: admin - - name: uaaadmin - password: admin - tag: admin - dea_next: - advertise_interval_in_seconds: 5 - allow_networks: [] - default_health_check_timeout: 60 - deny_networks: [] - directory_server_protocol: https - disk_mb: 16384 - disk_overcommit_factor: 2 - evacuation_bail_out_time_in_seconds: 0 - heartbeat_interval_in_seconds: 10 - instance_disk_inode_limit: 200000 - kernel_network_tuning_enabled: false - logging_level: debug - memory_mb: 8192 - memory_overcommit_factor: 3 - staging_disk_inode_limit: 200000 - staging_disk_limit_mb: 4096 - staging_memory_limit_mb: 1024 - description: Cloud Foundry sponsored by Pivotal - disk_quota_enabled: false - domain: 10.244.0.34.xip.io - doppler: - blacklisted_syslog_ranges: null - debug: false - maxRetainedLogMessages: 100 - doppler_endpoint: - shared_secret: loggregator-secret - dropsonde: - enabled: true - etcd: - machines: - - 10.244.0.42 - etcd_metrics_server: - nats: - machines: - - 10.244.0.6 - password: nats - username: nats - logger_endpoint: null - loggregator: - blacklisted_syslog_ranges: null - debug: false - maxRetainedLogMessages: 100 - loggregator_endpoint: - shared_secret: loggregator-secret - login: - analytics: - code: null - domain: null - asset_base_url: null - brand: oss - catalina_opts: -Xmx96m -XX:MaxPermSize=64m - links: - home: https://console.10.244.0.34.xip.io - network: null - passwd: https://console.10.244.0.34.xip.io/password_resets/new - signup: https://console.10.244.0.34.xip.io/register - signup-network: null - protocol: http - saml: null - signups_enabled: null - smtp: - host: null - password: null - port: null - user: null - spring_profiles: null - tiles: null - uaa_base: null - uaa_certificate: null - url: null - metron_endpoint: - shared_secret: loggregator-secret - nats: - address: 10.244.0.6 - debug: false - machines: - - 10.244.0.6 - monitor_port: 0 - password: nats - port: 4222 - prof_port: 0 - trace: false - user: nats - nfs_server: - address: null - allow_from_entries: - - 10.244.0.0/30 - - 10.244.2.0/30 - share: null - request_timeout_in_seconds: 300 - router: - requested_route_registration_interval_in_seconds: 20 - status: - password: router - user: router - smoke_tests: - api: api.10.244.0.34.xip.io - apps_domain: 10.244.0.34.xip.io - org: SMOKE_TEST_ORG - password: admin - skip_ssl_validation: true - space: SMOKE_TEST_SPACE - user: admin - ssl: - skip_cert_verify: true - support_address: http://support.cloudfoundry.com - syslog_aggregator: null - system_domain: 10.244.0.34.xip.io - system_domain_organization: null - uaa: - admin: - client_secret: admin-secret - authentication: - policy: - countFailuresWithinSeconds: null - lockoutAfterFailures: null - lockoutPeriodSeconds: null - batch: - password: batch-password - username: batch-username - catalina_opts: -Xmx192m -XX:MaxPermSize=128m - cc: - client_secret: cc-secret - clients: - app-direct: - access-token-validity: 1209600 - authorities: app_direct_invoice.write - authorized-grant-types: authorization_code,client_credentials,password,refresh_token,implicit - override: true - redirect-uri: https://console.10.244.0.34.xip.io - refresh-token-validity: 1209600 - secret: app-direct-secret - cc-service-dashboards: - authorities: clients.read,clients.write,clients.admin - authorized-grant-types: client_credentials - scope: openid,cloud_controller_service_permissions.read - secret: cc-broker-secret - developer_console: - access-token-validity: 1209600 - authorities: scim.write,scim.read,cloud_controller.read,cloud_controller.write,password.write,uaa.admin,uaa.resource,cloud_controller.admin,billing.admin - authorized-grant-types: authorization_code,client_credentials - override: true - redirect-uri: https://console.10.244.0.34.xip.io/oauth/callback - refresh-token-validity: 1209600 - scope: openid,cloud_controller.read,cloud_controller.write,password.write,console.admin,console.support - secret: console-secret - login: - authorities: oauth.login - authorized-grant-types: authorization_code,client_credentials,refresh_token - override: true - redirect-uri: http://login.10.244.0.34.xip.io - scope: openid,oauth.approvals - secret: login-secret - notifications: - authorities: cloud_controller.admin,scim.read - authorized-grant-types: client_credentials - secret: notification-secret - servicesmgmt: - authorities: uaa.resource,oauth.service,clients.read,clients.write,clients.secret - authorized-grant-types: authorization_code,client_credentials,password,implicit - autoapprove: true - override: true - redirect-uri: http://servicesmgmt.10.244.0.34.xip.io/auth/cloudfoundry/callback - scope: openid,cloud_controller.read,cloud_controller.write - secret: servicesmgmt-secret - space-mail: - access-token-validity: 1209600 - authorities: scim.read,scim.write,cloud_controller.admin - authorized-grant-types: client_credentials - override: true - refresh-token-validity: 1209600 - secret: space-mail-secret - support-services: - access-token-validity: 1209600 - authorities: portal.users.read - authorized-grant-types: authorization_code,client_credentials - redirect-uri: http://support-signon.10.244.0.34.xip.io - refresh-token-validity: 1209600 - scope: scim.write,scim.read,openid,cloud_controller.read,cloud_controller.write - secret: support-services-secret - jwt: - signing_key: '-----BEGIN RSA PRIVATE KEY----- - - MIICXAIBAAKBgQDHFr+KICms+tuT1OXJwhCUmR2dKVy7psa8xzElSyzqx7oJyfJ1 - - JZyOzToj9T5SfTIq396agbHJWVfYphNahvZ/7uMXqHxf+ZH9BL1gk9Y6kCnbM5R6 - - 0gfwjyW1/dQPjOzn9N394zd2FJoFHwdq9Qs0wBugspULZVNRxq7veq/fzwIDAQAB - - AoGBAJ8dRTQFhIllbHx4GLbpTQsWXJ6w4hZvskJKCLM/o8R4n+0W45pQ1xEiYKdA - - Z/DRcnjltylRImBD8XuLL8iYOQSZXNMb1h3g5/UGbUXLmCgQLOUUlnYt34QOQm+0 - - KvUqfMSFBbKMsYBAoQmNdTHBaz3dZa8ON9hh/f5TT8u0OWNRAkEA5opzsIXv+52J - - duc1VGyX3SwlxiE2dStW8wZqGiuLH142n6MKnkLU4ctNLiclw6BZePXFZYIK+AkE - - xQ+k16je5QJBAN0TIKMPWIbbHVr5rkdUqOyezlFFWYOwnMmw/BKa1d3zp54VP/P8 - - +5aQ2d4sMoKEOfdWH7UqMe3FszfYFvSu5KMCQFMYeFaaEEP7Jn8rGzfQ5HQd44ek - - lQJqmq6CE2BXbY/i34FuvPcKU70HEEygY6Y9d8J3o6zQ0K9SYNu+pcXt4lkCQA3h - - jJQQe5uEGJTExqed7jllQ0khFJzLMx0K6tj0NeeIzAaGCQz13oo2sCdeGRHO4aDh - - HH6Qlq/6UOV5wP8+GAcCQFgRCcB+hrje8hfEEefHcFpyKH+5g1Eu1k0mLrxK2zd+ - - 4SlotYRHgPCEubokb2S1zfZDWIXW3HmggnGgM949TlY= - - -----END RSA PRIVATE KEY----- - -' - verification_key: '-----BEGIN PUBLIC KEY----- - - MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDHFr+KICms+tuT1OXJwhCUmR2d - - KVy7psa8xzElSyzqx7oJyfJ1JZyOzToj9T5SfTIq396agbHJWVfYphNahvZ/7uMX - - qHxf+ZH9BL1gk9Y6kCnbM5R60gfwjyW1/dQPjOzn9N394zd2FJoFHwdq9Qs0wBug - - spULZVNRxq7veq/fzwIDAQAB - - -----END PUBLIC KEY----- - -' - ldap: null - login: null - no_ssl: true - scim: - external_groups: null - userids_enabled: false - users: - - admin|admin|scim.write,scim.read,openid,cloud_controller.admin,clients.read,clients.write - spring_profiles: null - url: https://uaa.10.244.0.34.xip.io - user: null - uaadb: - address: 10.244.0.30 - databases: - - citext: true - name: uaadb - tag: uaa - db_scheme: postgresql - port: 5524 - roles: - - name: uaaadmin - password: admin - tag: admin -releases: -- name: cf - version: latest -resource_pools: -- cloud_properties: - name: random - name: small_z1 - network: cf1 - size: 1 - stemcell: - name: bosh-warden-boshlite-ubuntu-trusty-go_agent - version: latest -- cloud_properties: - name: random - name: small_z2 - network: cf2 - size: 0 - stemcell: - name: bosh-warden-boshlite-ubuntu-trusty-go_agent - version: latest -- cloud_properties: - name: random - name: medium_z1 - network: cf1 - size: 7 - stemcell: - name: bosh-warden-boshlite-ubuntu-trusty-go_agent - version: latest -- cloud_properties: - name: random - name: medium_z2 - network: cf2 - size: 0 - stemcell: - name: bosh-warden-boshlite-ubuntu-trusty-go_agent - version: latest -- cloud_properties: - name: random - name: large_z1 - network: cf1 - size: 1 - stemcell: - name: bosh-warden-boshlite-ubuntu-trusty-go_agent - version: latest -- cloud_properties: - name: random - name: large_z2 - network: cf2 - size: 0 - stemcell: - name: bosh-warden-boshlite-ubuntu-trusty-go_agent - version: latest -- cloud_properties: - name: random - name: runner_z1 - network: cf1 - size: 1 - stemcell: - name: bosh-warden-boshlite-ubuntu-trusty-go_agent - version: latest -- cloud_properties: - name: random - name: runner_z2 - network: cf2 - size: 0 - stemcell: - name: bosh-warden-boshlite-ubuntu-trusty-go_agent - version: latest -- cloud_properties: - name: random - name: router_z1 - network: cf1 - size: 2 - stemcell: - name: bosh-warden-boshlite-ubuntu-trusty-go_agent - version: latest -- cloud_properties: - name: random - name: router_z2 - network: cf2 - size: 0 - stemcell: - name: bosh-warden-boshlite-ubuntu-trusty-go_agent - version: latest -- cloud_properties: - name: random - name: small_errand - network: cf1 - size: 2 - stemcell: - name: bosh-warden-boshlite-ubuntu-trusty-go_agent - version: latest -update: - canaries: 1 - canary_watch_time: 1000-180000 - max_in_flight: 50 - serial: true - update_watch_time: 1000-180000 diff --git a/testhelpers/testapi.go b/testhelpers/testapi.go deleted file mode 100644 index 2dd6be1..0000000 --- a/testhelpers/testapi.go +++ /dev/null @@ -1,122 +0,0 @@ -package testhelpers - -import ( - "fmt" - . "github.com/onsi/ginkgo" - "net/http" - "net/http/httptest" - "strings" -) - -func NewDirectorTestRequest(request TestRequest) TestRequest { - request.Header = http.Header{ - "accept": {"application/json"}, - "authorization": {"Basic YWRtaW46YWRtaW4="}, - } - - return request -} - -type TestRequest struct { - Method string - Path string - Header http.Header - Matcher RequestMatcher - Response TestResponse -} - -type RequestMatcher func(*http.Request) - -type TestResponse struct { - Body string - Status int - Header http.Header -} - -type TestHandler struct { - Requests []TestRequest - CallCount int -} - -func (h *TestHandler) AllRequestsCalled() bool { - if h.CallCount == len(h.Requests) { - return true - } - fmt.Print("Failed to call requests:\n") - for i := h.CallCount; i < len(h.Requests); i++ { - fmt.Printf("%#v\n", h.Requests[i]) - } - fmt.Print("\n\n") - return false -} - -func (h *TestHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { - if len(h.Requests) <= h.CallCount { - h.logError("Index out of range! Test server called too many times. Final Request:", r.Method, r.RequestURI) - return - } - - tester := h.Requests[h.CallCount] - h.CallCount++ - - // match method - if tester.Method != r.Method { - h.logError("Method does not match.\nExpected: %s\nActual: %s", tester.Method, r.Method) - } - - // match path - paths := strings.Split(tester.Path, "?") - if paths[0] != r.URL.Path { - h.logError("Path does not match.\nExpected: %s\nActual: %s", paths[0], r.URL.Path) - } - // match query string - if len(paths) > 1 { - if !strings.Contains(r.URL.RawQuery, paths[1]) { - h.logError("Query string does not match.\nExpected: %s\nActual: %s", paths[1], r.URL.RawQuery) - } - } - - for key, values := range tester.Header { - key = http.CanonicalHeaderKey(key) - actualValues := strings.Join(r.Header[key], ";") - expectedValues := strings.Join(values, ";") - - if key == "Authorization" && !strings.Contains(actualValues, expectedValues) { - h.logError("%s header is not contained in actual value.\nExpected: %s\nActual: %s", key, expectedValues, actualValues) - } - if key != "Authorization" && actualValues != expectedValues { - h.logError("%s header did not match.\nExpected: %s\nActual: %s", key, expectedValues, actualValues) - } - } - - // match custom request matcher - if tester.Matcher != nil { - tester.Matcher(r) - } - - // set response headers - header := w.Header() - for name, values := range tester.Response.Header { - if len(values) < 1 { - continue - } - header.Set(name, values[0]) - } - - // write response - w.WriteHeader(tester.Response.Status) - fmt.Fprintln(w, tester.Response.Body) -} - -func NewTLSServer(requests []TestRequest) (s *httptest.Server, h *TestHandler) { - h = &TestHandler{ - Requests: requests, - } - s = httptest.NewTLSServer(h) - return -} - -func (h *TestHandler) logError(msg string, args ...interface{}) { - completeMsg := fmt.Sprintf(msg, args...) - Fail(completeMsg) -} diff --git a/utils/doc.go b/utils/doc.go deleted file mode 100644 index cccc026..0000000 --- a/utils/doc.go +++ /dev/null @@ -1,4 +0,0 @@ -/* -Package utils is a collection of utilities used within gogobosh -*/ -package utils diff --git a/utils/file_utils.go b/utils/file_utils.go deleted file mode 100644 index 84256b9..0000000 --- a/utils/file_utils.go +++ /dev/null @@ -1,107 +0,0 @@ -package utils - -import ( - "bytes" - "io" - "os" - "path/filepath" -) - -func OpenFile(path string) (file *os.File, err error) { - err = os.MkdirAll(filepath.Dir(path), os.ModeDir|os.ModeTemporary|os.ModePerm) - if err != nil { - return - } - - return os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) -} - -func CreateFile(path string) (file *os.File, err error) { - err = os.MkdirAll(filepath.Dir(path), os.ModeDir|os.ModeTemporary|os.ModePerm) - if err != nil { - return - } - - return os.Create(path) -} - -func ReadFile(file *os.File) string { - buf := &bytes.Buffer{} - _, err := io.Copy(buf, file) - - if err != nil { - return "" - } - - return string(buf.Bytes()) -} - -func CopyFilePaths(fromPath, toPath string) (err error) { - dst, err := CreateFile(toPath) - if err != nil { - return - } - defer dst.Close() - - return CopyPathToWriter(fromPath, dst) -} - -func IsDirEmpty(dir string) (isEmpty bool, err error) { - dirFile, err := os.Open(dir) - if err != nil { - return - } - - _, readErr := dirFile.Readdirnames(1) - if readErr != nil { - isEmpty = true - } else { - isEmpty = false - } - return -} - -func CopyPathToWriter(originalFilePath string, targetWriter io.Writer) (err error) { - originalFile, err := os.Open(originalFilePath) - if err != nil { - return - } - defer originalFile.Close() - - _, err = io.Copy(targetWriter, originalFile) - if err != nil { - return - } - - return -} - -func CopyReaderToPath(src io.Reader, targetPath string) (err error) { - destFile, err := CreateFile(targetPath) - if err != nil { - return - } - defer destFile.Close() - - _, err = io.Copy(destFile, src) - return -} - -func SetExecutableBits(dest string, fileInfoToCopy os.FileInfo) (err error) { - destFileInfo, err := os.Stat(dest) - if err != nil { - return - } - - err = os.Chmod(dest, destFileInfo.Mode()|(fileInfoToCopy.Mode()&0111)) - return -} - -func SetExecutableBitsWithPaths(dest string, src string) (err error) { - fileToCopyInfo, err := os.Stat(src) - if err != nil { - return - } - - return SetExecutableBits(dest, fileToCopyInfo) -} diff --git a/utils/trace.go b/utils/trace.go deleted file mode 100644 index 4e342a5..0000000 --- a/utils/trace.go +++ /dev/null @@ -1,59 +0,0 @@ -package utils - -import ( - "io" - "log" - "os" -) - -const GOGOBOSH_TRACE = "GOGOBOSH_TRACE" - -type Printer interface { - Print(v ...interface{}) - Printf(format string, v ...interface{}) - Println(v ...interface{}) -} - -type nullLogger struct{} - -func (*nullLogger) Print(v ...interface{}) {} -func (*nullLogger) Printf(format string, v ...interface{}) {} -func (*nullLogger) Println(v ...interface{}) {} - -var stdOut io.Writer = os.Stdout -var Logger Printer - -func init() { - Logger = NewLogger() -} - -func SetStdout(s io.Writer) { - stdOut = s -} - -func NewLogger() Printer { - cf_trace := os.Getenv(GOGOBOSH_TRACE) - switch cf_trace { - case "", "false": - return new(nullLogger) - case "true": - return newStdoutLogger() - default: - return newFileLogger(cf_trace) - } -} - -func newStdoutLogger() Printer { - return log.New(stdOut, "", 0) -} - -func newFileLogger(path string) Printer { - file, err := OpenFile(path) - if err != nil { - logger := newStdoutLogger() - logger.Printf("CF_TRACE ERROR CREATING LOG FILE %s:\n%s", path, err) - return logger - } - - return log.New(file, "", 0) -}