<commit_before>package server

import (
	"bytes"
	"encoding/json"
	"log"
	"net/http"
	"net/http/httptest"
	"net/url"
	"os"
	"testing"

	"github.com/namely/broadway/instance"
	"github.com/namely/broadway/playbook"
	"github.com/namely/broadway/services"
	"github.com/namely/broadway/store"

	"github.com/stretchr/testify/assert"
)

var testToken = "BroadwayTestToken"

func TestServerNew(t *testing.T) {
	err := os.Setenv(slackTokenENV, testToken)
	if err != nil {
		t.Fatal(err)
	}
	actualToken, exists := os.LookupEnv(slackTokenENV)
	assert.True(t, exists, "Expected ENV to exist")
	assert.Equal(t, testToken, actualToken, "Unexpected ENV value")

	mem := store.New()

	s := New(mem)
	assert.Equal(t, testToken, s.slackToken, "Expected server.slackToken to match existing ENV value")

	err = os.Unsetenv(slackTokenENV)
	if err != nil {
		t.Fatal(err)
	}
	actualToken, exists = os.LookupEnv(slackTokenENV)
	assert.False(t, exists, "Expected ENV to not exist")
	assert.Equal(t, "", actualToken, "Unexpected ENV value")
	s = New(mem)
	assert.Equal(t, "", s.slackToken, "Expected server.slackToken to be empty string for missing ENV value")

}

func TestInstanceCreateWithValidAttributes(t *testing.T) {
	w := httptest.NewRecorder()

	i := map[string]interface{}{
		"playbook_id": "test",
		"id":          "test",
		"vars": map[string]string{
			"version": "ok",
		},
	}

	rbody, err := json.Marshal(i)
	if err != nil {
		t.Error(err)
		return
	}

	req, err := http.NewRequest("POST", "/instances", bytes.NewBuffer(rbody))
	if err != nil {
		t.Error(err)
		return
	}
	req.Header.Add("Content-Type", "application/json")

	mem := store.New()

	server := New(mem).Handler()
	server.ServeHTTP(w, req)

	assert.Equal(t, http.StatusCreated, w.Code, "Response code should be 201")

	var response instance.Attributes
	err = json.Unmarshal(w.Body.Bytes(), &response)
	if err != nil {
		t.Error(err)
		return
	}
	assert.Equal(t, response.PlaybookID, "test")

	service := services.NewInstanceService(mem)
	ii, err := service.Show("test", "test")
	assert.Nil(t, err)
	assert.Equal(t, "test", ii.ID, "New instance was created")

}

func TestCreateInstanceWithInvalidAttributes(t *testing.T) {

	invalidRequests := map[string]map[string]interface{}{
		"playbook_id": {
			"id": "test",
			"vars": map[string]string{
				"version": "ok",
			},
		},
	}

	for _, i := range invalidRequests {
		w := httptest.NewRecorder()
		rbody, err := json.Marshal(i)
		if err != nil {
			t.Error(err)
			return
		}

		req, err := http.NewRequest("POST", "/instances", bytes.NewBuffer(rbody))
		if err != nil {
			t.Error(err)
			return
		}

		req.Header.Add("Content-Type", "application/json")

		mem := store.New()

		server := New(mem).Handler()
		server.ServeHTTP(w, req)

		assert.Equal(t, http.StatusBadRequest, w.Code, "Expected POST /instances with wrong attributes to be 400")

		var errorResponse map[string]string

		err = json.Unmarshal(w.Body.Bytes(), &errorResponse)
		if err != nil {
			t.Error(err)
			return
		}
		assert.Contains(t, errorResponse["error"], "Missing")
	}

}

func TestGetInstanceWithValidPath(t *testing.T) {
	w := httptest.NewRecorder()
	mem := store.New()

	i := instance.New(mem, &instance.Attributes{
		PlaybookID: "foo",
		ID:         "doesExist",
	})
	err := i.Save()
	if err != nil {
		t.Error(err)
		return
	}

	req, err := http.NewRequest("GET", "/instance/foo/doesExist", nil)
	if err != nil {
		t.Error(err)
		return
	}

	server := New(mem).Handler()
	server.ServeHTTP(w, req)

	assert.Equal(t, w.Code, http.StatusOK)

	var iResponse map[string]string

	err = json.Unmarshal(w.Body.Bytes(), &iResponse)
	if err != nil {
		t.Error(err)
		return
	}
	assert.Contains(t, iResponse["id"], "doesExist")
}

func TestGetInstanceWithInvalidPath(t *testing.T) {
	w := httptest.NewRecorder()

	req, err := http.NewRequest("GET", "/instance/foo/bar", nil)
	if err != nil {
		t.Error(err)
		return
	}

	mem := store.New()

	server := New(mem).Handler()
	server.ServeHTTP(w, req)

	assert.Equal(t, http.StatusNotFound, w.Code)

	var errorResponse map[string]string

	err = json.Unmarshal(w.Body.Bytes(), &errorResponse)
	if err != nil {
		t.Error(err)
		return
	}
	assert.Contains(t, errorResponse["error"], "Not Found")
}

func TestGetInstancesWithFullPlaybook(t *testing.T) {
	w := httptest.NewRecorder()
	mem := store.New()

	testInstance1 := instance.New(mem, &instance.Attributes{
		PlaybookID: "testPlaybookFull",
		ID:         "testInstance1",
	})
	err := testInstance1.Save()
	if err != nil {
		t.Error(err)
		return
	}
	testInstance2 := instance.New(mem, &instance.Attributes{
		PlaybookID: "testPlaybookFull",
		ID:         "testInstance2",
	})
	err = testInstance2.Save()
	if err != nil {
		t.Error(err)
		return
	}
	req, err := http.NewRequest("GET", "/instances/testPlaybookFull", nil)
	if err != nil {
		t.Error(err)
		return
	}

	server := New(mem).Handler()
	server.ServeHTTP(w, req)

	assert.Equal(t, http.StatusOK, w.Code, "Response code should be 200 OK")

	log.Println(w.Body.String())
	var okResponse []instance.Attributes

	err = json.Unmarshal(w.Body.Bytes(), &okResponse)
	if err != nil {
		t.Error(err)
		return
	}
	if len(okResponse) != 2 {
		t.Errorf("Expected 2 instances matching playbook testPlaybookFull, actual %v\n", len(okResponse))
	}
}

func TestGetInstancesWithEmptyPlaybook(t *testing.T) {
	w := httptest.NewRecorder()

	req, err := http.NewRequest("GET", "/instances/testPlaybookEmpty", nil)
	if err != nil {
		t.Error(err)
		return
	}

	mem := store.New()

	server := New(mem).Handler()
	server.ServeHTTP(w, req)

	assert.Equal(t, http.StatusNoContent, w.Code, "Response code should be 204 No Content")

	var okResponse []instance.Attributes

	err = json.Unmarshal(w.Body.Bytes(), &okResponse)
	if err != nil {
		t.Error(err)
		return
	}
	if len(okResponse) != 0 {
		t.Errorf("Expected 0 instances matching playbook testPlaybookEmpty, actual %v\n", len(okResponse))
	}
}

func TestGetStatusFailures(t *testing.T) {
	invalidRequests := []struct {
		method  string
		path    string
		errCode int
		errMsg  string
	}{
		{
			"GET",
			"/status",
			400,
			"Use GET /status/yourPlaybookId/yourInstanceId",
		},
		{
			"GET",
			"/status/goodPlaybook",
			400,
			"Use GET /status/yourPlaybookId/yourInstanceId",
		},
		/* TODO: Store and look up playbooks
		{
			"GET",
			"/status/badPlaybook/goodInstance",
			404,
			"Playbook badPlaybook not found",
		},
		*/
		{
			"GET",
			"/status/goodPlaybook/badInstance",
			404,
			"Not Found",
		},
	}

	mem := store.New()
	server := New(mem).Handler()

	for _, i := range invalidRequests {
		w := httptest.NewRecorder()
		req, err := http.NewRequest("GET", i.path, nil)
		assert.Nil(t, err)

		server.ServeHTTP(w, req)

		assert.Equal(t, i.errCode, w.Code)

		var errorResponse map[string]string

		err = json.Unmarshal(w.Body.Bytes(), &errorResponse)
		assert.Nil(t, err)
		assert.Contains(t, errorResponse["error"], i.errMsg)
	}

}
func TestGetStatusWithGoodPath(t *testing.T) {
	mem := store.New()
	testInstance1 := instance.New(mem, &instance.Attributes{
		PlaybookID: "goodPlaybook",
		ID:         "goodInstance",
		Status:     instance.StatusDeployed,
	})
	err := testInstance1.Save()
	if err != nil {
		t.Error(err)
		return
	}
	w := httptest.NewRecorder()

	req, err := http.NewRequest("GET", "/status/goodPlaybook/goodInstance", nil)
	assert.Nil(t, err)

	server := New(mem).Handler()
	server.ServeHTTP(w, req)

	assert.Equal(t, http.StatusOK, w.Code)

	var statusResponse map[string]string

	err = json.Unmarshal(w.Body.Bytes(), &statusResponse)
	assert.Nil(t, err)
	assert.Contains(t, statusResponse["status"], "deployed")
}

func helperSetupServer() (*httptest.ResponseRecorder, http.Handler) {
	w := httptest.NewRecorder()
	mem := store.New()
	server := New(mem).Handler()
	return w, server
}

func TestGetCommand400(t *testing.T) {
	w, server := helperSetupServer()
	req, err := http.NewRequest("GET", "/command", nil)
	if err != nil {
		t.Fatal(err)
	}

	server.ServeHTTP(w, req)
	assert.Equal(t, http.StatusBadRequest, w.Code, "Expected GET /command to be 400")
}

func TestGetCommand200(t *testing.T) {
	w, server := helperSetupServer()
	req, _ := http.NewRequest("GET", "/command?ssl_check=1", nil)

	server.ServeHTTP(w, req)
	assert.Equal(t, http.StatusOK, w.Code, "Expected GET /command?ssl_check=1 to be 200")
}
func TestPostCommandMissingToken(t *testing.T) {
	if err := os.Setenv(slackTokenENV, testToken); err != nil {
		t.Fatal(err)
	}
	w, server := helperSetupServer()
	formBytes := bytes.NewBufferString("not a form")
	req, _ := http.NewRequest("POST", "/command", formBytes)
	req.Header.Add("Content-Type", "application/x-www-form-urlencoded")

	server.ServeHTTP(w, req)
	assert.Equal(t, http.StatusUnauthorized, w.Code, "Expected POST /command with bad body to be 401")
}
func TestPostCommandWrongToken(t *testing.T) {
	if err := os.Setenv(slackTokenENV, testToken); err != nil {
		t.Fatal(err)
	}
	w, server := helperSetupServer()
	req, _ := http.NewRequest("POST", "/command", nil)
	req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
	form := url.Values{}
	form.Set("token", "wrongtoken")
	req.PostForm = form

	server.ServeHTTP(w, req)
	assert.Equal(t, http.StatusUnauthorized, w.Code, "Expected POST /command with wrong token to be 401")
}
func TestPostCommandHelp(t *testing.T) {
	if err := os.Setenv(slackTokenENV, testToken); err != nil {
		t.Fatal(err)
	}
	w, server := helperSetupServer()
	req, _ := http.NewRequest("POST", "/command", nil)
	req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
	form := url.Values{}
	form.Set("token", testToken)
	form.Set("command", "/broadway")
	form.Set("text", "help")
	req.PostForm = form

	server.ServeHTTP(w, req)
	assert.Equal(t, http.StatusOK, w.Code, "Expected /broadway help to be 200")
	assert.Contains(t, w.Body.String(), "/broadway", "Expected help message to contain /broadway")
}

func TestDeployMissing(t *testing.T) {
	mem := store.New()
	w := httptest.NewRecorder()

	req, err := http.NewRequest("POST", "/deploy/missingPlaybook/missingInstance", nil)
	assert.Nil(t, err)

	server := New(mem).Handler()
	server.ServeHTTP(w, req)

	assert.Equal(t, http.StatusNotFound, w.Code)

	var errorResponse map[string]string
	log.Println(w.Body.String())
	err = json.Unmarshal(w.Body.Bytes(), &errorResponse)
	assert.Nil(t, err)
	assert.Contains(t, errorResponse["error"], "Not Found")
}

func TestDeployGood(t *testing.T) {
	task := playbook.Task{
		Name: "First step",
		Manifests: []string{
			"test",
		},
	}
	// Ensure playbook is in memory
	p := &playbook.Playbook{
		ID:    "test",
		Name:  "Test deployment",
		Meta:  playbook.Meta{},
		Vars:  []string{"test"},
		Tasks: []playbook.Task{task},
	}

	// Ensure manifest "test.yml" present in manifests folder
	// Setup server
	mem := store.New()
	server := New(mem)
	server.playbooks = map[string]*playbook.Playbook{p.ID: p}
	// engine := server.Handler()

	// Ensure instance present in etcd
	// Call endpoint
	// Assert successful deploy
	// Teardown kubernetes topography
}
<commit_msg>Add a helper function for serializing a map into a json<commit_after>package server

import (
	"bytes"
	"encoding/json"
	"log"
	"net/http"
	"net/http/httptest"
	"net/url"
	"os"
	"testing"

	"github.com/namely/broadway/instance"
	"github.com/namely/broadway/playbook"
	"github.com/namely/broadway/store"

	"github.com/stretchr/testify/assert"
)

var testToken = "BroadwayTestToken"

func TestServerNew(t *testing.T) {
	err := os.Setenv(slackTokenENV, testToken)
	if err != nil {
		t.Fatal(err)
	}
	actualToken, exists := os.LookupEnv(slackTokenENV)
	assert.True(t, exists, "Expected ENV to exist")
	assert.Equal(t, testToken, actualToken, "Unexpected ENV value")

	mem := store.New()

	s := New(mem)
	assert.Equal(t, testToken, s.slackToken, "Expected server.slackToken to match existing ENV value")

	err = os.Unsetenv(slackTokenENV)
	if err != nil {
		t.Fatal(err)
	}
	actualToken, exists = os.LookupEnv(slackTokenENV)
	assert.False(t, exists, "Expected ENV to not exist")
	assert.Equal(t, "", actualToken, "Unexpected ENV value")
	s = New(mem)
	assert.Equal(t, "", s.slackToken, "Expected server.slackToken to be empty string for missing ENV value")

}

func jsonFromMap(t *testing.T, data map[string]interface{}) []byte {
	rbody, err := json.Marshal(data)
	if err != nil {
		t.Error(err)
		return []byte{}
	}
	return rbody
}

func TestInstanceCreateWithValidAttributes(t *testing.T) {
	w := httptest.NewRecorder()

	i := map[string]interface{}{
		"playbook_id": "test",
		"id":          "test",
		"vars": map[string]string{
			"version": "ok",
		},
	}

	rbody := jsonFromMap(t, i)

	req, err := http.NewRequest("POST", "/instances", bytes.NewBuffer(rbody))
	if err != nil {
		t.Error(err)
		return
	}
	req.Header.Add("Content-Type", "application/json")

	mem := store.New()

	server := New(mem).Handler()
	server.ServeHTTP(w, req)

	assert.Equal(t, http.StatusCreated, w.Code, "Response code should be 201")
}

func TestCreateInstanceWithInvalidAttributes(t *testing.T) {

	invalidRequests := map[string]map[string]interface{}{
		"playbook_id": {
			"id": "test",
			"vars": map[string]string{
				"version": "ok",
			},
		},
	}

	for _, i := range invalidRequests {
		w := httptest.NewRecorder()
		rbody, err := json.Marshal(i)
		if err != nil {
			t.Error(err)
			return
		}

		req, err := http.NewRequest("POST", "/instances", bytes.NewBuffer(rbody))
		if err != nil {
			t.Error(err)
			return
		}

		req.Header.Add("Content-Type", "application/json")

		mem := store.New()

		server := New(mem).Handler()
		server.ServeHTTP(w, req)

		assert.Equal(t, http.StatusBadRequest, w.Code, "Expected POST /instances with wrong attributes to be 400")

		var errorResponse map[string]string

		err = json.Unmarshal(w.Body.Bytes(), &errorResponse)
		if err != nil {
			t.Error(err)
			return
		}
		assert.Contains(t, errorResponse["error"], "Missing")
	}

}

func TestGetInstanceWithValidPath(t *testing.T) {
	w := httptest.NewRecorder()
	mem := store.New()

	i := instance.New(mem, &instance.Attributes{
		PlaybookID: "foo",
		ID:         "doesExist",
	})
	err := i.Save()
	if err != nil {
		t.Error(err)
		return
	}

	req, err := http.NewRequest("GET", "/instance/foo/doesExist", nil)
	if err != nil {
		t.Error(err)
		return
	}

	server := New(mem).Handler()
	server.ServeHTTP(w, req)

	assert.Equal(t, w.Code, http.StatusOK)

	var iResponse map[string]string

	err = json.Unmarshal(w.Body.Bytes(), &iResponse)
	if err != nil {
		t.Error(err)
		return
	}
	assert.Contains(t, iResponse["id"], "doesExist")
}

func TestGetInstanceWithInvalidPath(t *testing.T) {
	w := httptest.NewRecorder()

	req, err := http.NewRequest("GET", "/instance/foo/bar", nil)
	if err != nil {
		t.Error(err)
		return
	}

	mem := store.New()

	server := New(mem).Handler()
	server.ServeHTTP(w, req)

	assert.Equal(t, http.StatusNotFound, w.Code)

	var errorResponse map[string]string

	err = json.Unmarshal(w.Body.Bytes(), &errorResponse)
	if err != nil {
		t.Error(err)
		return
	}
	assert.Contains(t, errorResponse["error"], "Not Found")
}

func TestGetInstancesWithFullPlaybook(t *testing.T) {
	w := httptest.NewRecorder()
	mem := store.New()

	testInstance1 := instance.New(mem, &instance.Attributes{
		PlaybookID: "testPlaybookFull",
		ID:         "testInstance1",
	})
	err := testInstance1.Save()
	if err != nil {
		t.Error(err)
		return
	}
	testInstance2 := instance.New(mem, &instance.Attributes{
		PlaybookID: "testPlaybookFull",
		ID:         "testInstance2",
	})
	err = testInstance2.Save()
	if err != nil {
		t.Error(err)
		return
	}
	req, err := http.NewRequest("GET", "/instances/testPlaybookFull", nil)
	if err != nil {
		t.Error(err)
		return
	}

	server := New(mem).Handler()
	server.ServeHTTP(w, req)

	assert.Equal(t, http.StatusOK, w.Code, "Response code should be 200 OK")

	log.Println(w.Body.String())
	var okResponse []instance.Attributes

	err = json.Unmarshal(w.Body.Bytes(), &okResponse)
	if err != nil {
		t.Error(err)
		return
	}
	if len(okResponse) != 2 {
		t.Errorf("Expected 2 instances matching playbook testPlaybookFull, actual %v\n", len(okResponse))
	}
}

func TestGetInstancesWithEmptyPlaybook(t *testing.T) {
	w := httptest.NewRecorder()

	req, err := http.NewRequest("GET", "/instances/testPlaybookEmpty", nil)
	if err != nil {
		t.Error(err)
		return
	}

	mem := store.New()

	server := New(mem).Handler()
	server.ServeHTTP(w, req)

	assert.Equal(t, http.StatusNoContent, w.Code, "Response code should be 204 No Content")

	var okResponse []instance.Attributes

	err = json.Unmarshal(w.Body.Bytes(), &okResponse)
	if err != nil {
		t.Error(err)
		return
	}
	if len(okResponse) != 0 {
		t.Errorf("Expected 0 instances matching playbook testPlaybookEmpty, actual %v\n", len(okResponse))
	}
}

func TestGetStatusFailures(t *testing.T) {
	invalidRequests := []struct {
		method  string
		path    string
		errCode int
		errMsg  string
	}{
		{
			"GET",
			"/status",
			400,
			"Use GET /status/yourPlaybookId/yourInstanceId",
		},
		{
			"GET",
			"/status/goodPlaybook",
			400,
			"Use GET /status/yourPlaybookId/yourInstanceId",
		},
		/* TODO: Store and look up playbooks
		{
			"GET",
			"/status/badPlaybook/goodInstance",
			404,
			"Playbook badPlaybook not found",
		},
		*/
		{
			"GET",
			"/status/goodPlaybook/badInstance",
			404,
			"Not Found",
		},
	}

	mem := store.New()
	server := New(mem).Handler()

	for _, i := range invalidRequests {
		w := httptest.NewRecorder()
		req, err := http.NewRequest("GET", i.path, nil)
		assert.Nil(t, err)

		server.ServeHTTP(w, req)

		assert.Equal(t, i.errCode, w.Code)

		var errorResponse map[string]string

		err = json.Unmarshal(w.Body.Bytes(), &errorResponse)
		assert.Nil(t, err)
		assert.Contains(t, errorResponse["error"], i.errMsg)
	}

}
func TestGetStatusWithGoodPath(t *testing.T) {
	mem := store.New()
	testInstance1 := instance.New(mem, &instance.Attributes{
		PlaybookID: "goodPlaybook",
		ID:         "goodInstance",
		Status:     instance.StatusDeployed,
	})
	err := testInstance1.Save()
	if err != nil {
		t.Error(err)
		return
	}
	w := httptest.NewRecorder()

	req, err := http.NewRequest("GET", "/status/goodPlaybook/goodInstance", nil)
	assert.Nil(t, err)

	server := New(mem).Handler()
	server.ServeHTTP(w, req)

	assert.Equal(t, http.StatusOK, w.Code)

	var statusResponse map[string]string

	err = json.Unmarshal(w.Body.Bytes(), &statusResponse)
	assert.Nil(t, err)
	assert.Contains(t, statusResponse["status"], "deployed")
}

func helperSetupServer() (*httptest.ResponseRecorder, http.Handler) {
	w := httptest.NewRecorder()
	mem := store.New()
	server := New(mem).Handler()
	return w, server
}

func TestGetCommand400(t *testing.T) {
	w, server := helperSetupServer()
	req, err := http.NewRequest("GET", "/command", nil)
	if err != nil {
		t.Fatal(err)
	}

	server.ServeHTTP(w, req)
	assert.Equal(t, http.StatusBadRequest, w.Code, "Expected GET /command to be 400")
}

func TestGetCommand200(t *testing.T) {
	w, server := helperSetupServer()
	req, _ := http.NewRequest("GET", "/command?ssl_check=1", nil)

	server.ServeHTTP(w, req)
	assert.Equal(t, http.StatusOK, w.Code, "Expected GET /command?ssl_check=1 to be 200")
}
func TestPostCommandMissingToken(t *testing.T) {
	if err := os.Setenv(slackTokenENV, testToken); err != nil {
		t.Fatal(err)
	}
	w, server := helperSetupServer()
	formBytes := bytes.NewBufferString("not a form")
	req, _ := http.NewRequest("POST", "/command", formBytes)
	req.Header.Add("Content-Type", "application/x-www-form-urlencoded")

	server.ServeHTTP(w, req)
	assert.Equal(t, http.StatusUnauthorized, w.Code, "Expected POST /command with bad body to be 401")
}
func TestPostCommandWrongToken(t *testing.T) {
	if err := os.Setenv(slackTokenENV, testToken); err != nil {
		t.Fatal(err)
	}
	w, server := helperSetupServer()
	req, _ := http.NewRequest("POST", "/command", nil)
	req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
	form := url.Values{}
	form.Set("token", "wrongtoken")
	req.PostForm = form

	server.ServeHTTP(w, req)
	assert.Equal(t, http.StatusUnauthorized, w.Code, "Expected POST /command with wrong token to be 401")
}
func TestPostCommandHelp(t *testing.T) {
	if err := os.Setenv(slackTokenENV, testToken); err != nil {
		t.Fatal(err)
	}
	w, server := helperSetupServer()
	req, _ := http.NewRequest("POST", "/command", nil)
	req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
	form := url.Values{}
	form.Set("token", testToken)
	form.Set("command", "/broadway")
	form.Set("text", "help")
	req.PostForm = form

	server.ServeHTTP(w, req)
	assert.Equal(t, http.StatusOK, w.Code, "Expected /broadway help to be 200")
	assert.Contains(t, w.Body.String(), "/broadway", "Expected help message to contain /broadway")
}

func TestDeployMissing(t *testing.T) {
	mem := store.New()
	w := httptest.NewRecorder()

	req, err := http.NewRequest("POST", "/deploy/missingPlaybook/missingInstance", nil)
	assert.Nil(t, err)

	server := New(mem).Handler()
	server.ServeHTTP(w, req)

	assert.Equal(t, http.StatusNotFound, w.Code)

	var errorResponse map[string]string
	log.Println(w.Body.String())
	err = json.Unmarshal(w.Body.Bytes(), &errorResponse)
	assert.Nil(t, err)
	assert.Contains(t, errorResponse["error"], "Not Found")
}

func TestDeployGood(t *testing.T) {
	task := playbook.Task{
		Name: "First step",
		Manifests: []string{
			"test",
		},
	}
	// Ensure playbook is in memory
	p := &playbook.Playbook{
		ID:    "test",
		Name:  "Test deployment",
		Meta:  playbook.Meta{},
		Vars:  []string{"test"},
		Tasks: []playbook.Task{task},
	}

	// Ensure manifest "test.yml" present in manifests folder
	// Setup server
	mem := store.New()
	server := New(mem)
	server.playbooks = map[string]*playbook.Playbook{p.ID: p}
	// engine := server.Handler()

	// Ensure instance present in etcd
	// Call endpoint
	// Assert successful deploy
	// Teardown kubernetes topography
}
<|endoftext|>


<commit_before>package config

import (
	"bufio"
	"bytes"
	"errors"
	"fmt"
	"io"
	"os"
	"strconv"
	"strings"
	"sync"
)

var (
	DEFAULT_SECTION = "default"
	DEFAULT_COMMENT = []byte{'#'}
	DEFAULT_COMMENT_SEM = []byte{';'}
)

type ConfigInterface interface {
	String(key string) string
	Strings(key string) []string
	Bool(key string) (bool, error)
	Int(key string) (int, error)
	Int64(key string) (int64, error)
	Float64(key string) (float64, error)
	Set(key string, value string) error
}

type Config struct {
	// map is not safe.
	sync.RWMutex
	// Section:key=value
	data map[string]map[string]string

}

// NewConfig create an empty configuration representation.
func NewConfig(confName string) (ConfigInterface, error) {
	c := &Config{
		data: make(map[string]map[string]string),
	}
	err := c.parse(confName)
	return c, err
}
// AddConfig adds a new section->key:value to the configuration.
func (c *Config) AddConfig(section string, option string, value string) bool {
	if section == "" {
		section = DEFAULT_SECTION
	}

	if _, ok := c.data[section]; !ok {
		c.data[section] = make(map[string]string)
	}

	_, ok := c.data[section][option]
	c.data[section][option] = value

	return !ok
}

func (c *Config) parse(fname string) (err error) {
	c.Lock()
	f, err := os.Open(fname)
	if err != nil {
		return err
	}
	defer c.Unlock()
	defer f.Close()

	buf := bufio.NewReader(f)

	var section string
	var lineNum int

	for {
		lineNum++
		line, _, err := buf.ReadLine()
		if err == io.EOF {
			break
		} else if bytes.Equal(line, []byte{}) {
			continue
		} else if err != nil {
			return err
		}

		line = bytes.TrimSpace(line)
		switch {
		case bytes.HasPrefix(line, DEFAULT_COMMENT):
			continue
		case bytes.HasPrefix(line,DEFAULT_COMMENT_SEM):
			continue
		case bytes.HasPrefix(line, []byte{'['}) && bytes.HasSuffix(line, []byte{']'}):
			section = string(line[1 : len(line)-1])
		default:
			optionVal := bytes.SplitN(line, []byte{'='}, 2)
			if len(optionVal) != 2 {
				return fmt.Errorf("parse %s the content error : line %d , %s = ? ", fname, lineNum, optionVal[0])
			}
			option := bytes.TrimSpace(optionVal[0])
			value := bytes.TrimSpace(optionVal[1])
			c.AddConfig(section, string(option), string(value))
		}
	}

	return nil
}

func (c *Config) Bool(key string) (bool, error) {
	return strconv.ParseBool(c.get(key))
}

func (c *Config) Int(key string) (int, error) {
	return strconv.Atoi(c.get(key))
}

func (c *Config) Int64(key string) (int64, error) {
	return strconv.ParseInt(c.get(key), 10, 64)
}

func (c *Config) Float64(key string) (float64, error) {
	return strconv.ParseFloat(c.get(key), 64)
}

func (c *Config) String(key string) string {
	return c.get(key)
}

func (c *Config) Strings(key string) []string {
	v := c.get(key)
	if v == "" {
		return nil
	}
	return strings.Split(v, ",")
}

func (c *Config) Set(key string, value string) error {
	c.Lock()
	defer c.Unlock()
	if len(key) == 0 {
		return errors.New("key is empty.")
	}

	var (
		section string
		option  string
	)

	keys := strings.Split(strings.ToLower(key), ".")
	if len(keys) >= 2 {
		section = keys[0]
		option = keys[1]
	} else {
		option = keys[0]
	}

	c.AddConfig(section, option, value)
	return nil
}

// section.key or key
func (c *Config) get(key string) string {
	var (
		section string
		option  string
	)

	keys := strings.Split(strings.ToLower(key), "::")

	if len(keys) >= 2 {
		section = keys[0]
		option = keys[1]
	} else {
		section = DEFAULT_SECTION
		option = keys[0]
	}

	if value, ok := c.data[section][option]; ok {
		return value
	}

	return ""
}
<commit_msg>Fix the bug, APIS set bug<commit_after>package config

import (
	"bufio"
	"bytes"
	"errors"
	"fmt"
	"io"
	"os"
	"strconv"
	"strings"
	"sync"
)

var (
	DEFAULT_SECTION = "default"
	DEFAULT_COMMENT = []byte{'#'}
	DEFAULT_COMMENT_SEM = []byte{';'}
)

type ConfigInterface interface {
	String(key string) string
	Strings(key string) []string
	Bool(key string) (bool, error)
	Int(key string) (int, error)
	Int64(key string) (int64, error)
	Float64(key string) (float64, error)
	Set(key string, value string) error
}

type Config struct {
	// map is not safe.
	sync.RWMutex
	// Section:key=value
	data map[string]map[string]string

}

// NewConfig create an empty configuration representation.
func NewConfig(confName string) (ConfigInterface, error) {
	c := &Config{
		data: make(map[string]map[string]string),
	}
	err := c.parse(confName)
	return c, err
}
// AddConfig adds a new section->key:value to the configuration.
func (c *Config) AddConfig(section string, option string, value string) bool {
	if section == "" {
		section = DEFAULT_SECTION
	}

	if _, ok := c.data[section]; !ok {
		c.data[section] = make(map[string]string)
	}

	_, ok := c.data[section][option]
	c.data[section][option] = value

	return !ok
}

func (c *Config) parse(fname string) (err error) {
	c.Lock()
	f, err := os.Open(fname)
	if err != nil {
		return err
	}
	defer c.Unlock()
	defer f.Close()

	buf := bufio.NewReader(f)

	var section string
	var lineNum int

	for {
		lineNum++
		line, _, err := buf.ReadLine()
		if err == io.EOF {
			break
		} else if bytes.Equal(line, []byte{}) {
			continue
		} else if err != nil {
			return err
		}

		line = bytes.TrimSpace(line)
		switch {
		case bytes.HasPrefix(line, DEFAULT_COMMENT):
			continue
		case bytes.HasPrefix(line,DEFAULT_COMMENT_SEM):
			continue
		case bytes.HasPrefix(line, []byte{'['}) && bytes.HasSuffix(line, []byte{']'}):
			section = string(line[1 : len(line)-1])
		default:
			optionVal := bytes.SplitN(line, []byte{'='}, 2)
			if len(optionVal) != 2 {
				return fmt.Errorf("parse %s the content error : line %d , %s = ? ", fname, lineNum, optionVal[0])
			}
			option := bytes.TrimSpace(optionVal[0])
			value := bytes.TrimSpace(optionVal[1])
			c.AddConfig(section, string(option), string(value))
		}
	}

	return nil
}

func (c *Config) Bool(key string) (bool, error) {
	return strconv.ParseBool(c.get(key))
}

func (c *Config) Int(key string) (int, error) {
	return strconv.Atoi(c.get(key))
}

func (c *Config) Int64(key string) (int64, error) {
	return strconv.ParseInt(c.get(key), 10, 64)
}

func (c *Config) Float64(key string) (float64, error) {
	return strconv.ParseFloat(c.get(key), 64)
}

func (c *Config) String(key string) string {
	return c.get(key)
}

func (c *Config) Strings(key string) []string {
	v := c.get(key)
	if v == "" {
		return nil
	}
	return strings.Split(v, ",")
}

func (c *Config) Set(key string, value string) error {
	c.Lock()
	defer c.Unlock()
	if len(key) == 0 {
		return errors.New("key is empty.")
	}

	var (
		section string
		option  string
	)

	keys := strings.Split(strings.ToLower(key), "::")
	if len(keys) >= 2 {
		section = keys[0]
		option = keys[1]
	} else {
		option = keys[0]
	}

	c.AddConfig(section, option, value)
	return nil
}

// section.key or key
func (c *Config) get(key string) string {
	var (
		section string
		option  string
	)

	keys := strings.Split(strings.ToLower(key), "::")

	if len(keys) >= 2 {
		section = keys[0]
		option = keys[1]
	} else {
		section = DEFAULT_SECTION
		option = keys[0]
	}

	if value, ok := c.data[section][option]; ok {
		return value
	}

	return ""
}
<|endoftext|>


<commit_before>package lazy

import (
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"github.com/go-ini/ini"
	"log"
	"os"
	"path/filepath"
	"strings"
)

var outputPath string

func init() {
	flag.StringVar(&outputPath, "output", "_output", "Output path")
}

type iniConfig ini.File

func loadINIConfig(file string) (*iniConfig, error) {
	cfg, err := ini.Load(file)
	if err != nil {
		log.Println(err)
		return nil, err
	}
	cfg.NameMapper = ini.TitleUnderscore
	return (*iniConfig)(cfg), nil
}

func (cfg *iniConfig) newConfigFromSection(s string, v interface{}) (interface{}, error) {
	iniFile := (*ini.File)(cfg)
	sec, err := iniFile.GetSection(s)
	if err != nil {
		return v, nil
	}

	err = sec.MapTo(v)
	if err != nil {
		if len(s) == 0 {
			s = "DEFAULT"
		}
		log.Println("Parse session", s, "fail")
		return nil, err
	}
	return v, nil
}

func (cfg *iniConfig) newDefaultConfig() (*DefaultConfig, error) {
	v, err := cfg.newConfigFromSection("", &DefaultConfig{})
	if err != nil {
		return nil, err
	}
	return v.(*DefaultConfig), nil
}

func (cfg *iniConfig) newNodes(ids []string) ([]*Node, error) {
	nodes := make([]*Node, 0, len(ids))
	for _, id := range ids {
		if len(id) == 0 {
			continue
		}

		n, err := cfg.newConfigFromSection(id, &NodeConfig{})
		if err != nil {
			log.Println("New node config", id, "failed:", err)
			continue
		}
		nodes = append(nodes, &Node{NodeConfig: n.(*NodeConfig)})
	}
	return nodes, nil
}

func (cfg *iniConfig) newNetworkConfig() (*NetworkConfig, error) {
	v, err := cfg.newConfigFromSection("network", &NetworkConfig{})
	if err != nil {
		return nil, err
	}
	return v.(*NetworkConfig), nil
}

func (cfg *iniConfig) newMatchboxConfig() (*MatchboxConfig, error) {
	v, err := cfg.newConfigFromSection("matchbox", &MatchboxConfig{})
	if err != nil {
		return nil, err
	}
	return v.(*MatchboxConfig), nil
}

type Config struct {
	*DefaultConfig
	N     *NetworkConfig
	M     *MatchboxConfig
	Nodes []*Node
	Cls   *Cluster
}

type DefaultConfig struct {
	Version    string   `ini:"version"`
	Channel    string   `ini:"channel"`
	DomainBase string   `ini:"domain_base"`
	NodeIDs    []string `ini:"nodes"`
	Keys       []string `ini:"keys"`
}

type MatchboxConfig struct {
	URL    string `ini:"url"`
	IP     string `ini:"ip"`
	Domain string `ini:"domain"`
}

type NodeConfig struct {
	MAC     []string `ini:"mac"`
	Role    string   `ini:"role"`
	IP      []string `ini:"ip"`
	Profile string   `ini:"profile"`
}

type NetworkConfig struct {
	Gateway   string   `ini:"gateway"`
	IPs       string   `ini:"ips"`
	VIP       string   `ini:"vip"`
	DNS       []string `ini:"dns"`
	EnableVIP bool     `ini:"enable_vip"`
	VIPDomain string   `ini:"vip_domain"`
}

func Load(file string) (*Config, error) {
	cfg, err := loadINIConfig(file)
	if err != nil {
		log.Println("Load ini config failed:", err)
		return nil, err
	}

	c := &Config{}

	if c.DefaultConfig, err = cfg.newDefaultConfig(); err != nil {
		log.Println("Load config failed:", err)
		return nil, err
	}

	if c.N, err = cfg.newNetworkConfig(); err != nil {
		log.Println("Load network config failed:", err)
	}

	if c.M, err = cfg.newMatchboxConfig(); err != nil {
		log.Println("Load matchbox config failed:", err)
	}

	if c.Nodes, err = cfg.newNodes(c.NodeIDs); err != nil {
		log.Println("Load nodes failed:", err)
	}

	c.Cls = &Cluster{
		M: c.M,
		Network: &Network{
			NetworkConfig: c.N,
		},
	}

	if err = c.analyze(); err != nil {
		log.Println(err)
		return nil, err
	}
	return c, nil
}

func (c *Config) analyze() (err error) {
	if err = c.analyzeNetwork(); err != nil {
		return errors.New("Analyze network failed: " + err.Error())
	}
	if err = c.analyzeMatchbox(); err != nil {
		return errors.New("Analyze matchbox failed: " + err.Error())
	}
	if err = c.analyzeNodes(); err != nil {
		return errors.New("Analyze nodes failed: " + err.Error())
	}
	if err = c.analyzeCluster(); err != nil {
		return errors.New("Analyze cluster failed: " + err.Error())
	}
	return nil
}

func (c *Config) analyzeNetwork() error {
	// TODO: Implement network
	return nil
}

func (c *Config) analyzeMatchbox() error {
	// TODO: Implement network
	return nil
}

func (c *Config) analyzeNodes() error {
	for i, node := range c.Nodes {
		node.ID = c.NodeIDs[i]
		node.Domain = node.ID
		if len(c.DomainBase) == 0 {
			node.Domain = node.Domain + "." + c.DomainBase
		}
		if len(node.Profile) == 0 {
			node.Profile = "node"
		}

		nics := make(NodeInterfaces, 0, len(node.IP))
		for i, ip := range node.IP {
			var mac string
			if len(node.MAC) > i {
				mac = node.MAC[i]
			}
			nics = append(nics, NodeInterface{
				MAC:       mac,
				IP:        ip,
				Interface: fmt.Sprintf("eth%d", i),
			})
		}
		node.Nics = nics
		node.Cluster = c.Cls
	}
	return nil
}

func (c *Config) analyzeCluster() error {
	var controllerEndpoint string
	initialCluster := make([]string, 0, len(c.Nodes))
	endpoints := make([]string, 0, len(c.Nodes))

	for _, n := range c.Nodes {
		if n.Role == "master" {
			initialCluster = append(initialCluster, fmt.Sprintf("%s=http://%s:2380", n.ID, n.Domain))
			endpoints = append(endpoints, fmt.Sprintf("http://%s:2379", n.Domain))
			if len(controllerEndpoint) == 0 {
				controllerEndpoint = fmt.Sprintf("https://%s", n.Domain)
			}
		}
	}

	bs, err := json.Marshal(c.Keys)
	if err != nil {
		log.Println("Convert keys into json array failed: ", err)
		bs = []byte("[]")
	}

	c.Cls.InitialCluster = strings.Join(initialCluster, ",")
	c.Cls.Endpoints = strings.Join(endpoints, ",")
	c.Cls.ControllerEndpoint = controllerEndpoint
	c.Cls.AuthorizedKeys = string(bs)
	return nil
}

func (c *Config) Generate() error {
	err := os.MkdirAll(outputPath, 0744)
	if err != nil {
		log.Fatal("Make output path ", outputPath, "fail")
	}
	err = writeTemplateToFile(OS_INSTALL_TMPL, "install",
		filepath.Join(outputPath, "install.json"), c)
	if err != nil {
		log.Println("Write template install failed: ", err)
	}

	for _, n := range c.Nodes {
		var tmpl, name string
		switch n.Role {
		case "master":
			tmpl = K8S_CONTROLLER_TMPL
			name = "controller"
		case "minion":
			tmpl = K8S_WORKER_TMPL
			name = "worker"
		default:
			tmpl = NODE_TMPL
			name = "Node " + n.ID
		}

		err = writeTemplateToFile(tmpl, name,
			filepath.Join(outputPath, n.ID+".json"), n)
		if err != nil {
			log.Println("Write template install failed: ", err)
		}
	}

	err = writeTemplateToFile(DNSMASQ_TMPL, "dnsmasq",
		filepath.Join(outputPath, "dnsmasq.conf"), c)
	if err != nil {
		log.Println("Write dnsmasq config failed: ", err)
	}
	return nil
}
<commit_msg>Node domain do not contain base domain<commit_after>package lazy

import (
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"github.com/go-ini/ini"
	"log"
	"os"
	"path/filepath"
	"strings"
)

var outputPath string

func init() {
	flag.StringVar(&outputPath, "output", "_output", "Output path")
}

type iniConfig ini.File

func loadINIConfig(file string) (*iniConfig, error) {
	cfg, err := ini.Load(file)
	if err != nil {
		log.Println(err)
		return nil, err
	}
	cfg.NameMapper = ini.TitleUnderscore
	return (*iniConfig)(cfg), nil
}

func (cfg *iniConfig) newConfigFromSection(s string, v interface{}) (interface{}, error) {
	iniFile := (*ini.File)(cfg)
	sec, err := iniFile.GetSection(s)
	if err != nil {
		return v, nil
	}

	err = sec.MapTo(v)
	if err != nil {
		if len(s) == 0 {
			s = "DEFAULT"
		}
		log.Println("Parse session", s, "fail")
		return nil, err
	}
	return v, nil
}

func (cfg *iniConfig) newDefaultConfig() (*DefaultConfig, error) {
	v, err := cfg.newConfigFromSection("", &DefaultConfig{})
	if err != nil {
		return nil, err
	}
	return v.(*DefaultConfig), nil
}

func (cfg *iniConfig) newNodes(ids []string) ([]*Node, error) {
	nodes := make([]*Node, 0, len(ids))
	for _, id := range ids {
		if len(id) == 0 {
			continue
		}

		n, err := cfg.newConfigFromSection(id, &NodeConfig{})
		if err != nil {
			log.Println("New node config", id, "failed:", err)
			continue
		}
		nodes = append(nodes, &Node{NodeConfig: n.(*NodeConfig)})
	}
	return nodes, nil
}

func (cfg *iniConfig) newNetworkConfig() (*NetworkConfig, error) {
	v, err := cfg.newConfigFromSection("network", &NetworkConfig{})
	if err != nil {
		return nil, err
	}
	return v.(*NetworkConfig), nil
}

func (cfg *iniConfig) newMatchboxConfig() (*MatchboxConfig, error) {
	v, err := cfg.newConfigFromSection("matchbox", &MatchboxConfig{})
	if err != nil {
		return nil, err
	}
	return v.(*MatchboxConfig), nil
}

type Config struct {
	*DefaultConfig
	N     *NetworkConfig
	M     *MatchboxConfig
	Nodes []*Node
	Cls   *Cluster
}

type DefaultConfig struct {
	Version    string   `ini:"version"`
	Channel    string   `ini:"channel"`
	DomainBase string   `ini:"domain_base"`
	NodeIDs    []string `ini:"nodes"`
	Keys       []string `ini:"keys"`
}

type MatchboxConfig struct {
	URL    string `ini:"url"`
	IP     string `ini:"ip"`
	Domain string `ini:"domain"`
}

type NodeConfig struct {
	MAC     []string `ini:"mac"`
	Role    string   `ini:"role"`
	IP      []string `ini:"ip"`
	Profile string   `ini:"profile"`
}

type NetworkConfig struct {
	Gateway   string   `ini:"gateway"`
	IPs       string   `ini:"ips"`
	VIP       string   `ini:"vip"`
	DNS       []string `ini:"dns"`
	EnableVIP bool     `ini:"enable_vip"`
	VIPDomain string   `ini:"vip_domain"`
}

func Load(file string) (*Config, error) {
	cfg, err := loadINIConfig(file)
	if err != nil {
		log.Println("Load ini config failed:", err)
		return nil, err
	}

	c := &Config{}

	if c.DefaultConfig, err = cfg.newDefaultConfig(); err != nil {
		log.Println("Load config failed:", err)
		return nil, err
	}

	if c.N, err = cfg.newNetworkConfig(); err != nil {
		log.Println("Load network config failed:", err)
	}

	if c.M, err = cfg.newMatchboxConfig(); err != nil {
		log.Println("Load matchbox config failed:", err)
	}

	if c.Nodes, err = cfg.newNodes(c.NodeIDs); err != nil {
		log.Println("Load nodes failed:", err)
	}

	c.Cls = &Cluster{
		M: c.M,
		Network: &Network{
			NetworkConfig: c.N,
		},
	}

	if err = c.analyze(); err != nil {
		log.Println(err)
		return nil, err
	}
	return c, nil
}

func (c *Config) analyze() (err error) {
	if err = c.analyzeNetwork(); err != nil {
		return errors.New("Analyze network failed: " + err.Error())
	}
	if err = c.analyzeMatchbox(); err != nil {
		return errors.New("Analyze matchbox failed: " + err.Error())
	}
	if err = c.analyzeNodes(); err != nil {
		return errors.New("Analyze nodes failed: " + err.Error())
	}
	if err = c.analyzeCluster(); err != nil {
		return errors.New("Analyze cluster failed: " + err.Error())
	}
	return nil
}

func (c *Config) analyzeNetwork() error {
	// TODO: Implement network
	return nil
}

func (c *Config) analyzeMatchbox() error {
	// TODO: Implement network
	return nil
}

func (c *Config) analyzeNodes() error {
	for i, node := range c.Nodes {
		node.ID = c.NodeIDs[i]
		node.Domain = node.ID
		if len(c.DomainBase) != 0 {
			node.Domain = node.Domain + "." + c.DomainBase
		}

		if len(node.Profile) == 0 {
			node.Profile = "node"
		}

		nics := make(NodeInterfaces, 0, len(node.IP))
		for i, ip := range node.IP {
			var mac string
			if len(node.MAC) > i {
				mac = node.MAC[i]
			}
			nics = append(nics, NodeInterface{
				MAC:       mac,
				IP:        ip,
				Interface: fmt.Sprintf("eth%d", i),
			})
		}
		node.Nics = nics
		node.Cluster = c.Cls
	}
	return nil
}

func (c *Config) analyzeCluster() error {
	var controllerEndpoint string
	initialCluster := make([]string, 0, len(c.Nodes))
	endpoints := make([]string, 0, len(c.Nodes))

	for _, n := range c.Nodes {
		if n.Role == "master" {
			initialCluster = append(initialCluster, fmt.Sprintf("%s=http://%s:2380", n.ID, n.Domain))
			endpoints = append(endpoints, fmt.Sprintf("http://%s:2379", n.Domain))
			if len(controllerEndpoint) == 0 {
				controllerEndpoint = fmt.Sprintf("https://%s", n.Domain)
			}
		}
	}

	bs, err := json.Marshal(c.Keys)
	if err != nil {
		log.Println("Convert keys into json array failed: ", err)
		bs = []byte("[]")
	}

	c.Cls.InitialCluster = strings.Join(initialCluster, ",")
	c.Cls.Endpoints = strings.Join(endpoints, ",")
	c.Cls.ControllerEndpoint = controllerEndpoint
	c.Cls.AuthorizedKeys = string(bs)
	return nil
}

func (c *Config) Generate() error {
	err := os.MkdirAll(outputPath, 0744)
	if err != nil {
		log.Fatal("Make output path ", outputPath, "fail")
	}
	err = writeTemplateToFile(OS_INSTALL_TMPL, "install",
		filepath.Join(outputPath, "install.json"), c)
	if err != nil {
		log.Println("Write template install failed: ", err)
	}

	for _, n := range c.Nodes {
		var tmpl, name string
		switch n.Role {
		case "master":
			tmpl = K8S_CONTROLLER_TMPL
			name = "controller"
		case "minion":
			tmpl = K8S_WORKER_TMPL
			name = "worker"
		default:
			tmpl = NODE_TMPL
			name = "Node " + n.ID
		}

		err = writeTemplateToFile(tmpl, name,
			filepath.Join(outputPath, n.ID+".json"), n)
		if err != nil {
			log.Println("Write template install failed: ", err)
		}
	}

	err = writeTemplateToFile(DNSMASQ_TMPL, "dnsmasq",
		filepath.Join(outputPath, "dnsmasq.conf"), c)
	if err != nil {
		log.Println("Write dnsmasq config failed: ", err)
	}
	return nil
}
<|endoftext|>


<commit_before>package gogo

import (
	"encoding/json"
	"io/ioutil"

	"github.com/dolab/logger"
)

var (
	DefaultServerConfig = &ServerConfig{
		Addr:      "127.0.0.1",
		Port:      9090,
		Ssl:       false,
		RequestId: DefaultHttpRequestId,
	}

	DefaultLoggerConfig = &LoggerConfig{
		Output: "stderr",
		level:  "info",
	}

	DefaultSectionConfig = &SectionConfig{
		Server: DefaultServerConfig,
		Logger: DefaultLoggerConfig,
	}
)

type AppConfig struct {
	Mode     RunMode                      `json:"mode"`
	Name     string                       `json:"name"`
	Sections map[RunMode]*json.RawMessage `json:"sections"`
}

func NewAppConfig(filename string) (*AppConfig, error) {
	b, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}

	var config *AppConfig
	err = json.Unmarshal(b, &config)
	if err != nil {
		return nil, err
	}

	// default to Development mode
	if !config.Mode.IsValid() {
		config.Mode = Development
	}

	if config.Name == "" {
		config.Name = "GOGO"
	}

	return config, nil
}

// SetMode changes config mode
func (config *AppConfig) SetMode(mode RunMode) {
	if !mode.IsValid() {
		return
	}

	config.Mode = mode
}

// Section is shortcut of retreving app server and logger configurations at one time
// It returns SectionConfig if exists, otherwise returns DefaultSectionConfig instead
func (config *AppConfig) Section() *SectionConfig {
	var sconfig *SectionConfig

	err := config.UnmarshalJSON(&sconfig)
	if err != nil {
		return DefaultSectionConfig
	}

	return sconfig
}

// UnmarshalJSON parses JSON-encoded data of section and stores the result in the value pointed to by v.
// It returns ErrConfigSection error if section of the current mode does not exist.
func (config *AppConfig) UnmarshalJSON(v interface{}) error {
	section, ok := config.Sections[config.Mode]
	if !ok {
		return ErrConfigSection
	}

	return json.Unmarshal([]byte(*section), &v)
}

// app server and logger config
type SectionConfig struct {
	Server *ServerConfig `json:"server"`
	Logger *LoggerConfig `json:"logger"`
}

// server config spec
type ServerConfig struct {
	Addr           string `json:"addr"`
	Port           int    `json:"port"`
	RTimeout       int    `json:"request_timeout"`
	WTimeout       int    `json:"response_timeout"`
	MaxHeaderBytes int    `json:"max_header_bytes"`

	Ssl     bool   `json:"ssl"`
	SslCert string `json:"ssl_cert"`
	SslKey  string `json:"ssl_key"`

	RequestId string `json:"request_id"`
}

// logger config spec
type LoggerConfig struct {
	Output string `json:"output"` // valid values [stdout|stderr|null|path/to/file]
	level  string `json:"level"`  // valid values [debug|info|warn|error]
}

func (l *LoggerConfig) Level() logger.Level {
	return logger.ResolveLevelByName(l.level)
}
<commit_msg>new filter parameters for logger<commit_after>package gogo

import (
	"encoding/json"
	"io/ioutil"

	"github.com/dolab/logger"
)

var (
	DefaultServerConfig = &ServerConfig{
		Addr:      "127.0.0.1",
		Port:      9090,
		Ssl:       false,
		RequestId: DefaultHttpRequestId,
	}

	DefaultLoggerConfig = &LoggerConfig{
		Output: "stderr",
		level:  "info",
	}

	DefaultSectionConfig = &SectionConfig{
		Server: DefaultServerConfig,
		Logger: DefaultLoggerConfig,
	}
)

type AppConfig struct {
	Mode RunMode `json:"mode"`
	Name string  `json:"name"`

	Sections map[RunMode]*json.RawMessage `json:"sections"`
}

func NewAppConfig(filename string) (*AppConfig, error) {
	b, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}

	var config *AppConfig
	err = json.Unmarshal(b, &config)
	if err != nil {
		return nil, err
	}

	// default to Development mode
	if !config.Mode.IsValid() {
		config.Mode = Development
	}

	if config.Name == "" {
		config.Name = "GOGO"
	}

	return config, nil
}

// SetMode changes config mode
func (config *AppConfig) SetMode(mode RunMode) {
	if !mode.IsValid() {
		return
	}

	config.Mode = mode
}

// Section is shortcut of retreving app server and logger configurations at one time
// It returns SectionConfig if exists, otherwise returns DefaultSectionConfig instead
func (config *AppConfig) Section() *SectionConfig {
	var sconfig *SectionConfig

	err := config.UnmarshalJSON(&sconfig)
	if err != nil {
		return DefaultSectionConfig
	}

	return sconfig
}

// UnmarshalJSON parses JSON-encoded data of section and stores the result in the value pointed to by v.
// It returns ErrConfigSection error if section of the current mode does not exist.
func (config *AppConfig) UnmarshalJSON(v interface{}) error {
	section, ok := config.Sections[config.Mode]
	if !ok {
		return ErrConfigSection
	}

	return json.Unmarshal([]byte(*section), &v)
}

// app server and logger config
type SectionConfig struct {
	Server *ServerConfig `json:"server"`
	Logger *LoggerConfig `json:"logger"`
}

// server config spec
type ServerConfig struct {
	Addr           string `json:"addr"`
	Port           int    `json:"port"`
	RTimeout       int    `json:"request_timeout"`
	WTimeout       int    `json:"response_timeout"`
	MaxHeaderBytes int    `json:"max_header_bytes"`

	Ssl     bool   `json:"ssl"`
	SslCert string `json:"ssl_cert"`
	SslKey  string `json:"ssl_key"`

	RequestId string `json:"request_id"`
}

// logger config spec
type LoggerConfig struct {
	Output string `json:"output"` // valid values [stdout|stderr|null|path/to/file]
	level  string `json:"level"`  // valid values [debug|info|warn|error]

	FilterParams []string `json:"filter_params"`
}

func (l *LoggerConfig) Level() logger.Level {
	return logger.ResolveLevelByName(l.level)
}
<|endoftext|>


<commit_before>package peco

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

type Config struct {
	Keymap Keymap `json:"Keymap"`
}

func NewConfig() *Config {
	return &Config{
		Keymap: NewKeymap(),
	}
}

func (c *Config) ReadFilename(filename string) error {
	f, err := os.Open(filename)
	if err != nil {
		return err
	}
	defer f.Close()

	buf, err := ioutil.ReadAll(f)
	if err != nil {
		return err
	}

	err = json.Unmarshal(buf, c)
	if err != nil {
		return err
	}

	return nil
}
<commit_msg>Directly use NewDecoder(io.Reader).Decode()<commit_after>package peco

import (
	"encoding/json"
	"os"
)

type Config struct {
	Keymap Keymap `json:"Keymap"`
}

func NewConfig() *Config {
	return &Config{
		Keymap: NewKeymap(),
	}
}

func (c *Config) ReadFilename(filename string) error {
	f, err := os.Open(filename)
	if err != nil {
		return err
	}
	defer f.Close()

	err = json.NewDecoder(f).Decode(c)
	if err != nil {
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>package raftor

import "github.com/coreos/etcd/raft"

// RaftConfig helps to configure a RaftNode
type RaftConfig struct {
	Name    string
	Cluster Cluster
	Storage raft.Storage

	Raft raft.Config
}
<commit_msg>Rename RaftConfig and add ClusterChangeNotifier and Applier to config struct<commit_after>package raftor

import "github.com/coreos/etcd/raft"

// ClusterConfig helps to configure a RaftNode
type ClusterConfig struct {
	Name      string
	Raft      raft.Config
	Notifiers []ClusterChangeNotifier
	Applier   Applier
}
<|endoftext|>


<commit_before>package config

import (
	"fmt"
	"log"
	"os/user"
	"path/filepath"
	"strings"

	"os"

	"github.com/spf13/viper"
)

type TablesConf struct {
	Name        string   `mapstructure:"name"`
	Permissions []string `mapstructure:"permissions"`
	Fields      []string `mapstructure:"fields"`
}

type AccessConf struct {
	Restrict bool
	Tables   []TablesConf
}

// Prest basic config
type Prest struct {
	// HTTPPort Declare which http port the PREST used
	HTTPPort       int
	PGHost         string
	PGPort         int
	PGUser         string
	PGPass         string
	PGDatabase     string
	PGMaxIdleConn  int
	PGMAxOpenConn  int
	JWTKey         string
	MigrationsPath string
	QueriesPath    string
	AccessConf     AccessConf
}

var PREST_CONF *Prest

func init() {
	viperCfg()
}

func viperCfg() {
	filePath := os.Getenv("PREST_CONF")
	if filePath == "" {
		filePath = "prest.toml"
	}
	replacer := strings.NewReplacer(".", "_")
	viper.SetEnvPrefix("PREST")
	viper.AutomaticEnv()
	viper.SetEnvKeyReplacer(replacer)
	viper.SetConfigFile(filePath)
	viper.SetConfigType("toml")
	viper.SetDefault("http.port", 3000)
	viper.SetDefault("pg.host", "127.0.0.1")
	viper.SetDefault("pg.port", 5432)
	viper.SetDefault("pg.maxidleconn", 10)
	viper.SetDefault("pg.maxopenconn", 10)

	user, err := user.Current()
	if err != nil {
		log.Println("{viperCfg}", err)
	}

	viper.SetDefault("queries.location", filepath.Join(user.HomeDir, "queries"))
}

// Parse pREST config
func Parse(cfg *Prest) (err error) {
	err = viper.ReadInConfig()
	cfg.HTTPPort = viper.GetInt("http.port")
	cfg.PGHost = viper.GetString("pg.host")
	cfg.PGPort = viper.GetInt("pg.port")
	cfg.PGUser = viper.GetString("pg.user")
	cfg.PGPass = viper.GetString("pg.pass")
	cfg.PGDatabase = viper.GetString("pg.database")
	cfg.PGMaxIdleConn = viper.GetInt("pg.maxidleconn")
	cfg.PGMAxOpenConn = viper.GetInt("pg.maxopenconn")
	cfg.JWTKey = viper.GetString("jwt.key")
	cfg.MigrationsPath = viper.GetString("migrations")
	cfg.AccessConf.Restrict = viper.GetBool("access.restrict")
	cfg.QueriesPath = viper.GetString("queries.location")

	var t []TablesConf
	err = viper.UnmarshalKey("access.tables", &t)
	if err != nil {
		return err
	}

	cfg.AccessConf.Tables = t

	return
}

func InitConf() {
	viperCfg()
	prestConfig := Prest{}
	Parse(&prestConfig)
	PREST_CONF = &prestConfig

	if !prestConfig.AccessConf.Restrict {
		fmt.Println("You are running pREST in public mode.")
	}

	if _, err := os.Stat(PREST_CONF.QueriesPath); os.IsNotExist(err) {
		os.MkdirAll(PREST_CONF.QueriesPath, 0777)
	}
}
<commit_msg>added cors support<commit_after>package config

import (
	"fmt"
	"log"
	"os/user"
	"path/filepath"
	"strings"

	"os"

	"github.com/spf13/viper"
)

type TablesConf struct {
	Name        string   `mapstructure:"name"`
	Permissions []string `mapstructure:"permissions"`
	Fields      []string `mapstructure:"fields"`
}

type AccessConf struct {
	Restrict bool
	Tables   []TablesConf
}

// Prest basic config
type Prest struct {
	// HTTPPort Declare which http port the PREST used
	HTTPPort        int
	PGHost          string
	PGPort          int
	PGUser          string
	PGPass          string
	PGDatabase      string
	PGMaxIdleConn   int
	PGMAxOpenConn   int
	JWTKey          string
	MigrationsPath  string
	QueriesPath     string
	AccessConf      AccessConf
	CORSAllowOrigin []string
}

var PREST_CONF *Prest

func init() {
	viperCfg()
}

func viperCfg() {
	filePath := os.Getenv("PREST_CONF")
	if filePath == "" {
		filePath = "prest.toml"
	}
	replacer := strings.NewReplacer(".", "_")
	viper.SetEnvPrefix("PREST")
	viper.AutomaticEnv()
	viper.SetEnvKeyReplacer(replacer)
	viper.SetConfigFile(filePath)
	viper.SetConfigType("toml")
	viper.SetDefault("http.port", 3000)
	viper.SetDefault("pg.host", "127.0.0.1")
	viper.SetDefault("pg.port", 5432)
	viper.SetDefault("pg.maxidleconn", 10)
	viper.SetDefault("pg.maxopenconn", 10)

	user, err := user.Current()
	if err != nil {
		log.Println("{viperCfg}", err)
	}

	viper.SetDefault("queries.location", filepath.Join(user.HomeDir, "queries"))
}

// Parse pREST config
func Parse(cfg *Prest) (err error) {
	err = viper.ReadInConfig()
	cfg.HTTPPort = viper.GetInt("http.port")
	cfg.PGHost = viper.GetString("pg.host")
	cfg.PGPort = viper.GetInt("pg.port")
	cfg.PGUser = viper.GetString("pg.user")
	cfg.PGPass = viper.GetString("pg.pass")
	cfg.PGDatabase = viper.GetString("pg.database")
	cfg.PGMaxIdleConn = viper.GetInt("pg.maxidleconn")
	cfg.PGMAxOpenConn = viper.GetInt("pg.maxopenconn")
	cfg.JWTKey = viper.GetString("jwt.key")
	cfg.MigrationsPath = viper.GetString("migrations")
	cfg.AccessConf.Restrict = viper.GetBool("access.restrict")
	cfg.QueriesPath = viper.GetString("queries.location")
	cfg.CORSAllowOrigin = viper.GetStringSlice("cors.alloworigin")

	var t []TablesConf
	err = viper.UnmarshalKey("access.tables", &t)
	if err != nil {
		return err
	}

	cfg.AccessConf.Tables = t

	return
}

func InitConf() {
	viperCfg()
	prestConfig := Prest{}
	Parse(&prestConfig)
	PREST_CONF = &prestConfig

	if !prestConfig.AccessConf.Restrict {
		fmt.Println("You are running pREST in public mode.")
	}

	if _, err := os.Stat(PREST_CONF.QueriesPath); os.IsNotExist(err) {
		os.MkdirAll(PREST_CONF.QueriesPath, 0777)
	}
}
<|endoftext|>


<commit_before>package main
/*
*  File: config.go
*  Author: Bryan Matsuo [bmatsuo@soe.ucsc.edu]
*  Created: Sat Jul  2 23:09:50 PDT 2011
*/
import (
    //"goconf.googlecode.com/hg"    // This does not work for some reason.
    //"conf"
    "github.com/kless/goconfig/config"
    "os"
    "path/filepath"
)

var ConfigFilename = filepath.Join(os.Getenv("HOME"), ".gonewrc")

type GonewConfig struct {
    Name     string
    Email    string
    HostUser string
    Repo     RepoType
    Host     RepoHost
}

var AppConfig GonewConfig

func ReadConfig() os.Error {
    AppConfig = GonewConfig{"", "", "", NilRepoType, NilRepoHost}
    conf, err := config.ReadDefault(ConfigFilename)
    if err != nil {
        return err
    }
    var (
        repostr string
        hoststr string
    )
    AppConfig.Name, err = conf.String("variables", "name")
    AppConfig.Email, err = conf.String("variables", "email")
    AppConfig.HostUser, err = conf.String("general", "hostuser")
    repostr, err = conf.String("general", "repo")
    switch repostr {
    case "":
        AppConfig.Repo = NilRepoType
    case "git":
        AppConfig.Repo = GitType
    //case "mercurial":
    //...
    default:
        AppConfig.Repo = NilRepoType
    }
    hoststr, err = conf.String("general", "host")
    switch hoststr {
    case "":
        AppConfig.Host = NilRepoHost
    case "github":
        AppConfig.Host = GitHubHost
        AppConfig.Repo = GitType
    //case "googlecode":
    //...
    default:
        AppConfig.Host = NilRepoHost
    }
    return nil
}
<commit_msg>Add a function to collect config info and write it out (unused).<commit_after>package main
/*
*  File: config.go
*  Author: Bryan Matsuo [bmatsuo@soe.ucsc.edu]
*  Created: Sat Jul  2 23:09:50 PDT 2011
*/
import (
    "os"
    "fmt"
    "bytes"
    "bufio"
    "path/filepath"
    //"goconf.googlecode.com/hg"    // This does not work for some reason.
    //"conf"
    "github.com/kless/goconfig/config"
)

var ConfigFilename = filepath.Join(os.Getenv("HOME"), ".gonewrc")

type GonewConfig struct {
    Name     string
    Email    string
    HostUser string
    Repo     RepoType
    Host     RepoHost
}

var AppConfig GonewConfig

func ReadConfig() os.Error {
    AppConfig = GonewConfig{"", "", "", NilRepoType, NilRepoHost}
    conf, err := config.ReadDefault(ConfigFilename)
    if err != nil {
        return err
    }
    var (
        repostr string
        hoststr string
    )
    AppConfig.Name, err = conf.String("variables", "name")
    AppConfig.Email, err = conf.String("variables", "email")
    AppConfig.HostUser, err = conf.String("general", "hostuser")
    repostr, err = conf.String("general", "repo")
    switch repostr {
    case "":
        AppConfig.Repo = NilRepoType
    case "git":
        AppConfig.Repo = GitType
    //case "mercurial":
    //...
    default:
        AppConfig.Repo = NilRepoType
    }
    hoststr, err = conf.String("general", "host")
    switch hoststr {
    case "":
        AppConfig.Host = NilRepoHost
    case "github":
        AppConfig.Host = GitHubHost
        AppConfig.Repo = GitType
    //case "googlecode":
    //...
    default:
        AppConfig.Host = NilRepoHost
    }
    return nil
}

func MakeConfig() os.Error {
    var (
        c       = config.NewDefault()
        scanner = bufio.NewReader(os.Stdin)
        errScan os.Error
        buff    []byte
    )
    fmt.Printf("Enter your name: ")
    buff, _, errScan = scanner.ReadLine()
    if errScan != nil {
        return errScan
    }
    c.AddOption("variables", "name", string(bytes.TrimRight(buff, "\n")))
    fmt.Printf("Enter your email address: ")
    buff, _, errScan = scanner.ReadLine()
    if errScan != nil {
        return errScan
    }
    c.AddOption("variables", "email", string(bytes.TrimRight(buff, "\n")))
    var (
        repoName string
        repoOk   bool
    )
    for !repoOk {
        fmt.Printf("Enter a repository type ('git', or none): ")
        buff, _, errScan = scanner.ReadLine()
        if errScan != nil {
            return errScan
        }
        repoName = string(bytes.TrimRight(buff, "\n"))
        switch repoName {
        case "":
            fallthrough
        case "git":
            repoOk = true
        default:
            fmt.Printf("I didn't understand repo type %s\n", repoName)
        }
    }
    c.AddOption("general", "repo", repoName)
    var (
        hostName string
        hostOk   bool
    )
    for !hostOk {
        fmt.Printf("Enter a repo host ('github', or none): ")
        buff, _, errScan = scanner.ReadLine()
        if errScan != nil {
            return errScan
        }
        hostName = string(bytes.TrimRight(buff, "\n"))
        switch hostName {
        case "":
            fallthrough
        case "github":
            hostOk = true
        default:
            fmt.Printf("I didn't understand repo host %s\n", hostName)
        }
    }
    c.AddOption("general", "host", hostName)
    var hostuser = ""
    var hostuserOk = hostName != "github"
    for !hostuserOk {
        fmt.Printf("Enter a %s username: ", hostName)
        buff, _, errScan = scanner.ReadLine()
        if errScan != nil {
            return errScan
        }
        hostuser = string(bytes.TrimRight(buff, "\n"))
        if hostuser == "" {
            fmt.Printf("Invalid %s username '%s'\n", hostName, hostuser)
        } else {
            hostuserOk = true
        }
    }
    c.AddOption("general", "hostuser", hostuser)
    return c.WriteFile(ConfigFilename, FilePermissions, "Generated configuration for gonew.")
}
<|endoftext|>


<commit_before>package messages

// Github config
type Github struct {
	Token  string `json:"token"`
	Labels []string
}

// Config internal to be shared between services
type Config struct {
	Github *Github `json:"github, omitempty"`
}

// GetIssuesList request message to get an issue list
type GetIssuesList struct {
	Status string `json:"status"`
	Org    string `json:"org"`
	Repo   string `json:"repo,omitempty"`
	Config `json:"config"`
}

// IssuesDetails request message to get an issue
type GetIssue struct {
	Issue  *Issue `json:"issue"`
	Config `json:"config"`
}

// CreateIssue request message to create an issue
type CreateIssue struct {
	Issue  *Issue `json:issue`
	Config `json:"config"`
}

// Setup request message to setup issue tracker
type Setup struct {
	Org    string   `json:"org"`
	Repo   string   `json:"repo"`
	States []string `json:"states"`
	Config `json:"config"`
}

// UpdateIssue request message to update an issue
type UpdateIssue struct {
	Issue    *Issue `json:issue`
	Status   string `json:"state"`
	Config   `json:"config"`
	Workflow *[]Transition `json:"transitions"`
}

// Transition json representation
type Transition struct {
	From  string   `json:"from"`
	To    string   `json:"to"`
	Hooks []string `json:"hooks"`
}
<commit_msg>Workflow struct<commit_after>package messages

// Github config
type Github struct {
	Token  string `json:"token"`
	Labels []string
}

// Config internal to be shared between services
type Config struct {
	Github *Github `json:"github, omitempty"`
}

// GetIssuesList request message to get an issue list
type GetIssuesList struct {
	Status string `json:"status"`
	Org    string `json:"org"`
	Repo   string `json:"repo,omitempty"`
	Config `json:"config"`
}

// IssuesDetails request message to get an issue
type GetIssue struct {
	Issue  *Issue `json:"issue"`
	Config `json:"config"`
}

// CreateIssue request message to create an issue
type CreateIssue struct {
	Issue  *Issue `json:issue`
	Config `json:"config"`
}

// Setup request message to setup issue tracker
type Setup struct {
	Org    string   `json:"org"`
	Repo   string   `json:"repo"`
	States []string `json:"states"`
	Config `json:"config"`
}

// UpdateIssue request message to update an issue
type UpdateIssue struct {
	Issue    *Issue `json:issue`
	Status   string `json:"state"`
	Config   `json:"config"`
	Workflow `json:"workflow"`
}

// Workflow ...
type Workflow struct {
	Transitions []Transition `json:"transitions"`
}

// Transition json representation
type Transition struct {
	From  string   `json:"from"`
	To    string   `json:"to"`
	Hooks []string `json:"hooks"`
}
<|endoftext|>


<commit_before>package main

import (
	"path/filepath"

	"github.com/spf13/viper"
)

const CONFIG_DEPENDENCY_KEY = "dependency"

func init() {
	viper.AutomaticEnv()
	viper.SetConfigType("toml")
	viper.AddConfigPath(".")
	viper.SetConfigName("spacer")

	viper.SetDefault("listen", ":9064")
	viper.SetDefault("verbose", false)
	viper.SetDefault("prefix", "_services")

	err := viper.ReadInConfig()
	if err != nil {
		panic(err)
	}
}

func getDependencies() []Service {
	var deps []Service

	for _, serviceConfig := range viper.Get(CONFIG_DEPENDENCY_KEY).([]map[string]interface{}) {
		if v, ok := serviceConfig["local"]; ok {
			localPath := v.(string)
			deps = append(deps, Service{LocalPath: localPath,
				Name: filepath.Base(localPath),
				Path: viper.GetString("prefix") + "/",
			})
		}
	}
	return deps
}
<commit_msg>support remote path<commit_after>package main

import (
	"path/filepath"
	"strings"

	"github.com/spf13/viper"
)

const CONFIG_DEPENDENCY_KEY = "dependency"

func init() {
	viper.AutomaticEnv()

	viper.SetDefault("listen", ":9064")
	viper.SetDefault("prefix", "_services")
	viper.SetDefault("verbose", false)

	viper.AddConfigPath(".")
	viper.SetConfigType("toml")
	viper.SetConfigName("spacer")

	err := viper.ReadInConfig()
	if err != nil {
		panic(err)
	}
}

func getDependencies() []Service {
	var deps []Service

	for _, serviceConfig := range viper.Get(CONFIG_DEPENDENCY_KEY).([]map[string]interface{}) {
		if v, ok := serviceConfig["local"]; ok {
			localPath := v.(string)
			deps = append(deps, Service{
				LocalPath: localPath,
				Name:      filepath.Base(localPath),
				Path:      viper.GetString("prefix") + "/",
			})
			break
		}
		if v, ok := serviceConfig["github"]; ok {
			remotePath := v.(string)
			deps = append(deps, Service{
				RemotePath: remotePath,
				Name:       strings.Split(remotePath, "/")[1],
				Path:       viper.GetString("prefix") + "/",
			})
			break
		}
	}
	return deps
}
<|endoftext|>


<commit_before>package azurerm

import (
	"fmt"
	"log"
	"net/http"
	"net/http/httputil"

	"github.com/Azure/azure-sdk-for-go/arm/cdn"
	"github.com/Azure/azure-sdk-for-go/arm/compute"
	"github.com/Azure/azure-sdk-for-go/arm/network"
	"github.com/Azure/azure-sdk-for-go/arm/resources/resources"
	"github.com/Azure/azure-sdk-for-go/arm/scheduler"
	"github.com/Azure/azure-sdk-for-go/arm/storage"
	mainStorage "github.com/Azure/azure-sdk-for-go/storage"
	"github.com/Azure/go-autorest/autorest"
	"github.com/Azure/go-autorest/autorest/azure"
	"github.com/hashicorp/terraform/terraform"
	riviera "github.com/jen20/riviera/azure"
)

// ArmClient contains the handles to all the specific Azure Resource Manager
// resource classes' respective clients.
type ArmClient struct {
	rivieraClient *riviera.Client

	availSetClient         compute.AvailabilitySetsClient
	usageOpsClient         compute.UsageOperationsClient
	vmExtensionImageClient compute.VirtualMachineExtensionImagesClient
	vmExtensionClient      compute.VirtualMachineExtensionsClient
	vmScaleSetClient       compute.VirtualMachineScaleSetsClient
	vmImageClient          compute.VirtualMachineImagesClient
	vmClient               compute.VirtualMachinesClient

	appGatewayClient             network.ApplicationGatewaysClient
	ifaceClient                  network.InterfacesClient
	loadBalancerClient           network.LoadBalancersClient
	localNetConnClient           network.LocalNetworkGatewaysClient
	publicIPClient               network.PublicIPAddressesClient
	secGroupClient               network.SecurityGroupsClient
	secRuleClient                network.SecurityRulesClient
	subnetClient                 network.SubnetsClient
	netUsageClient               network.UsagesClient
	vnetGatewayConnectionsClient network.VirtualNetworkGatewayConnectionsClient
	vnetGatewayClient            network.VirtualNetworkGatewaysClient
	vnetClient                   network.VirtualNetworksClient
	routeTablesClient            network.RouteTablesClient
	routesClient                 network.RoutesClient

	cdnProfilesClient  cdn.ProfilesClient
	cdnEndpointsClient cdn.EndpointsClient

	providers           resources.ProvidersClient
	resourceGroupClient resources.GroupsClient
	tagsClient          resources.TagsClient

	jobsClient            scheduler.JobsClient
	jobsCollectionsClient scheduler.JobCollectionsClient

	storageServiceClient storage.AccountsClient
	storageUsageClient   storage.UsageOperationsClient

	deploymentsClient resources.DeploymentsClient
}

func withRequestLogging() autorest.SendDecorator {
	return func(s autorest.Sender) autorest.Sender {
		return autorest.SenderFunc(func(r *http.Request) (*http.Response, error) {
			// dump request to wire format
			if dump, err := httputil.DumpRequestOut(r, true); err == nil {
				log.Printf("[DEBUG] AzureRM Request: \n%s\n", dump)
			} else {
				// fallback to basic message
				log.Printf("[DEBUG] AzureRM Request: %s to %s\n", r.Method, r.URL)
			}

			resp, err := s.Do(r)
			if resp != nil {
				// dump response to wire format
				if dump, err := httputil.DumpResponse(resp, true); err == nil {
					log.Printf("[DEBUG] AzureRM Response for %s: \n%s\n", r.URL, dump)
				} else {
					// fallback to basic message
					log.Printf("[DEBUG] AzureRM Response: %s for %s\n", resp.Status, r.URL)
				}
			} else {
				log.Printf("[DEBUG] Request to %s completed with no response", r.URL)
			}
			return resp, err
		})
	}
}

func setUserAgent(client *autorest.Client) {
	var version string
	if terraform.VersionPrerelease != "" {
		version = fmt.Sprintf("%s-%s", terraform.Version, terraform.VersionPrerelease)
	} else {
		version = terraform.Version
	}

	client.UserAgent = fmt.Sprintf("HashiCorp-Terraform-v%s", version)
}

// getArmClient is a helper method which returns a fully instantiated
// *ArmClient based on the Config's current settings.
func (c *Config) getArmClient() (*ArmClient, error) {
	// client declarations:
	client := ArmClient{}

	rivieraClient, err := riviera.NewClient(&riviera.AzureResourceManagerCredentials{
		ClientID:       c.ClientID,
		ClientSecret:   c.ClientSecret,
		TenantID:       c.TenantID,
		SubscriptionID: c.SubscriptionID,
	})
	if err != nil {
		return nil, fmt.Errorf("Error creating Riviera client: %s", err)
	}

	// validate that the credentials are correct using Riviera. Note that this must be
	// done _before_ using the Microsoft SDK, because Riviera handles errors. Using a
	// namespace registration instead of a simple OAuth token refresh guarantees that
	// service delegation is correct. This has the effect of registering Microsoft.Compute
	// which is neccessary anyway.
	if err := registerProviderWithSubscription("Microsoft.Compute", rivieraClient); err != nil {
		return nil, err
	}
	client.rivieraClient = rivieraClient

	oauthConfig, err := azure.PublicCloud.OAuthConfigForTenant(c.TenantID)
	if err != nil {
		return nil, err
	}

	// This is necessary because no-one thought about API usability. OAuthConfigForTenant
	// returns a pointer, which can be nil. NewServicePrincipalToken does not take a pointer.
	// Consequently we have to nil check this and do _something_ if it is nil, which should
	// be either an invariant of OAuthConfigForTenant (guarantee the token is not nil if
	// there is no error), or NewServicePrincipalToken should error out if the configuration
	// is required and is nil. This is the worst of all worlds, however.
	if oauthConfig == nil {
		return nil, fmt.Errorf("Unable to configure OAuthConfig for tenant %s", c.TenantID)
	}

	spt, err := azure.NewServicePrincipalToken(*oauthConfig, c.ClientID, c.ClientSecret,
		azure.PublicCloud.ResourceManagerEndpoint)
	if err != nil {
		return nil, err
	}

	// NOTE: these declarations should be left separate for clarity should the
	// clients be wished to be configured with custom Responders/PollingModess etc...
	asc := compute.NewAvailabilitySetsClient(c.SubscriptionID)
	setUserAgent(&asc.Client)
	asc.Authorizer = spt
	asc.Sender = autorest.CreateSender(withRequestLogging())
	client.availSetClient = asc

	uoc := compute.NewUsageOperationsClient(c.SubscriptionID)
	setUserAgent(&uoc.Client)
	uoc.Authorizer = spt
	uoc.Sender = autorest.CreateSender(withRequestLogging())
	client.usageOpsClient = uoc

	vmeic := compute.NewVirtualMachineExtensionImagesClient(c.SubscriptionID)
	setUserAgent(&vmeic.Client)
	vmeic.Authorizer = spt
	vmeic.Sender = autorest.CreateSender(withRequestLogging())
	client.vmExtensionImageClient = vmeic

	vmec := compute.NewVirtualMachineExtensionsClient(c.SubscriptionID)
	setUserAgent(&vmec.Client)
	vmec.Authorizer = spt
	vmec.Sender = autorest.CreateSender(withRequestLogging())
	client.vmExtensionClient = vmec

	vmic := compute.NewVirtualMachineImagesClient(c.SubscriptionID)
	setUserAgent(&vmic.Client)
	vmic.Authorizer = spt
	vmic.Sender = autorest.CreateSender(withRequestLogging())
	client.vmImageClient = vmic

	vmssc := compute.NewVirtualMachineScaleSetsClient(c.SubscriptionID)
	setUserAgent(&vmssc.Client)
	vmssc.Authorizer = spt
	vmssc.Sender = autorest.CreateSender(withRequestLogging())
	client.vmScaleSetClient = vmssc

	vmc := compute.NewVirtualMachinesClient(c.SubscriptionID)
	setUserAgent(&vmc.Client)
	vmc.Authorizer = spt
	vmc.Sender = autorest.CreateSender(withRequestLogging())
	client.vmClient = vmc

	agc := network.NewApplicationGatewaysClient(c.SubscriptionID)
	setUserAgent(&agc.Client)
	agc.Authorizer = spt
	agc.Sender = autorest.CreateSender(withRequestLogging())
	client.appGatewayClient = agc

	ifc := network.NewInterfacesClient(c.SubscriptionID)
	setUserAgent(&ifc.Client)
	ifc.Authorizer = spt
	ifc.Sender = autorest.CreateSender(withRequestLogging())
	client.ifaceClient = ifc

	lbc := network.NewLoadBalancersClient(c.SubscriptionID)
	setUserAgent(&lbc.Client)
	lbc.Authorizer = spt
	lbc.Sender = autorest.CreateSender(withRequestLogging())
	client.loadBalancerClient = lbc

	lgc := network.NewLocalNetworkGatewaysClient(c.SubscriptionID)
	setUserAgent(&lgc.Client)
	lgc.Authorizer = spt
	lgc.Sender = autorest.CreateSender(withRequestLogging())
	client.localNetConnClient = lgc

	pipc := network.NewPublicIPAddressesClient(c.SubscriptionID)
	setUserAgent(&pipc.Client)
	pipc.Authorizer = spt
	pipc.Sender = autorest.CreateSender(withRequestLogging())
	client.publicIPClient = pipc

	sgc := network.NewSecurityGroupsClient(c.SubscriptionID)
	setUserAgent(&sgc.Client)
	sgc.Authorizer = spt
	sgc.Sender = autorest.CreateSender(withRequestLogging())
	client.secGroupClient = sgc

	src := network.NewSecurityRulesClient(c.SubscriptionID)
	setUserAgent(&src.Client)
	src.Authorizer = spt
	src.Sender = autorest.CreateSender(withRequestLogging())
	client.secRuleClient = src

	snc := network.NewSubnetsClient(c.SubscriptionID)
	setUserAgent(&snc.Client)
	snc.Authorizer = spt
	snc.Sender = autorest.CreateSender(withRequestLogging())
	client.subnetClient = snc

	vgcc := network.NewVirtualNetworkGatewayConnectionsClient(c.SubscriptionID)
	setUserAgent(&vgcc.Client)
	vgcc.Authorizer = spt
	vgcc.Sender = autorest.CreateSender(withRequestLogging())
	client.vnetGatewayConnectionsClient = vgcc

	vgc := network.NewVirtualNetworkGatewaysClient(c.SubscriptionID)
	setUserAgent(&vgc.Client)
	vgc.Authorizer = spt
	vgc.Sender = autorest.CreateSender(withRequestLogging())
	client.vnetGatewayClient = vgc

	vnc := network.NewVirtualNetworksClient(c.SubscriptionID)
	setUserAgent(&vnc.Client)
	vnc.Authorizer = spt
	vnc.Sender = autorest.CreateSender(withRequestLogging())
	client.vnetClient = vnc

	rtc := network.NewRouteTablesClient(c.SubscriptionID)
	setUserAgent(&rtc.Client)
	rtc.Authorizer = spt
	rtc.Sender = autorest.CreateSender(withRequestLogging())
	client.routeTablesClient = rtc

	rc := network.NewRoutesClient(c.SubscriptionID)
	setUserAgent(&rc.Client)
	rc.Authorizer = spt
	rc.Sender = autorest.CreateSender(withRequestLogging())
	client.routesClient = rc

	rgc := resources.NewGroupsClient(c.SubscriptionID)
	setUserAgent(&rgc.Client)
	rgc.Authorizer = spt
	rgc.Sender = autorest.CreateSender(withRequestLogging())
	client.resourceGroupClient = rgc

	pc := resources.NewProvidersClient(c.SubscriptionID)
	setUserAgent(&pc.Client)
	pc.Authorizer = spt
	pc.Sender = autorest.CreateSender(withRequestLogging())
	client.providers = pc

	tc := resources.NewTagsClient(c.SubscriptionID)
	setUserAgent(&tc.Client)
	tc.Authorizer = spt
	tc.Sender = autorest.CreateSender(withRequestLogging())
	client.tagsClient = tc

	jc := scheduler.NewJobsClient(c.SubscriptionID)
	setUserAgent(&jc.Client)
	jc.Authorizer = spt
	jc.Sender = autorest.CreateSender(withRequestLogging())
	client.jobsClient = jc

	jcc := scheduler.NewJobCollectionsClient(c.SubscriptionID)
	setUserAgent(&jcc.Client)
	jcc.Authorizer = spt
	jcc.Sender = autorest.CreateSender(withRequestLogging())
	client.jobsCollectionsClient = jcc

	ssc := storage.NewAccountsClient(c.SubscriptionID)
	setUserAgent(&ssc.Client)
	ssc.Authorizer = spt
	ssc.Sender = autorest.CreateSender(withRequestLogging())
	client.storageServiceClient = ssc

	suc := storage.NewUsageOperationsClient(c.SubscriptionID)
	setUserAgent(&suc.Client)
	suc.Authorizer = spt
	suc.Sender = autorest.CreateSender(withRequestLogging())
	client.storageUsageClient = suc

	cpc := cdn.NewProfilesClient(c.SubscriptionID)
	setUserAgent(&cpc.Client)
	cpc.Authorizer = spt
	cpc.Sender = autorest.CreateSender(withRequestLogging())
	client.cdnProfilesClient = cpc

	cec := cdn.NewEndpointsClient(c.SubscriptionID)
	setUserAgent(&cec.Client)
	cec.Authorizer = spt
	cec.Sender = autorest.CreateSender(withRequestLogging())
	client.cdnEndpointsClient = cec

	dc := resources.NewDeploymentsClient(c.SubscriptionID)
	setUserAgent(&dc.Client)
	dc.Authorizer = spt
	dc.Sender = autorest.CreateSender(withRequestLogging())
	client.deploymentsClient = dc

	return &client, nil
}

func (armClient *ArmClient) getKeyForStorageAccount(resourceGroupName, storageAccountName string) (string, bool, error) {
	accountKeys, err := armClient.storageServiceClient.ListKeys(resourceGroupName, storageAccountName)
	if accountKeys.StatusCode == http.StatusNotFound {
		return "", false, nil
	}
	if err != nil {
		// We assume this is a transient error rather than a 404 (which is caught above),  so assume the
		// account still exists.
		return "", true, fmt.Errorf("Error retrieving keys for storage account %q: %s", storageAccountName, err)
	}

	if accountKeys.Keys == nil {
		return "", false, fmt.Errorf("Nil key returned for storage account %q", storageAccountName)
	}

	keys := *accountKeys.Keys
	return *keys[0].Value, true, nil
}

func (armClient *ArmClient) getBlobStorageClientForStorageAccount(resourceGroupName, storageAccountName string) (*mainStorage.BlobStorageClient, bool, error) {
	key, accountExists, err := armClient.getKeyForStorageAccount(resourceGroupName, storageAccountName)
	if err != nil {
		return nil, accountExists, err
	}
	if accountExists == false {
		return nil, false, nil
	}

	storageClient, err := mainStorage.NewBasicClient(storageAccountName, key)
	if err != nil {
		return nil, true, fmt.Errorf("Error creating storage client for storage account %q: %s", storageAccountName, err)
	}

	blobClient := storageClient.GetBlobService()
	return &blobClient, true, nil
}

func (armClient *ArmClient) getQueueServiceClientForStorageAccount(resourceGroupName, storageAccountName string) (*mainStorage.QueueServiceClient, bool, error) {
	key, accountExists, err := armClient.getKeyForStorageAccount(resourceGroupName, storageAccountName)
	if err != nil {
		return nil, accountExists, err
	}
	if accountExists == false {
		return nil, false, nil
	}

	storageClient, err := mainStorage.NewBasicClient(storageAccountName, key)
	if err != nil {
		return nil, true, fmt.Errorf("Error creating storage client for storage account %q: %s", storageAccountName, err)
	}

	queueClient := storageClient.GetQueueService()
	return &queueClient, true, nil
}
<commit_msg>Add VersionString<commit_after>package azurerm

import (
	"fmt"
	"log"
	"net/http"
	"net/http/httputil"

	"github.com/Azure/azure-sdk-for-go/arm/cdn"
	"github.com/Azure/azure-sdk-for-go/arm/compute"
	"github.com/Azure/azure-sdk-for-go/arm/network"
	"github.com/Azure/azure-sdk-for-go/arm/resources/resources"
	"github.com/Azure/azure-sdk-for-go/arm/scheduler"
	"github.com/Azure/azure-sdk-for-go/arm/storage"
	mainStorage "github.com/Azure/azure-sdk-for-go/storage"
	"github.com/Azure/go-autorest/autorest"
	"github.com/Azure/go-autorest/autorest/azure"
	"github.com/hashicorp/terraform/terraform"
	riviera "github.com/jen20/riviera/azure"
)

// ArmClient contains the handles to all the specific Azure Resource Manager
// resource classes' respective clients.
type ArmClient struct {
	rivieraClient *riviera.Client

	availSetClient         compute.AvailabilitySetsClient
	usageOpsClient         compute.UsageOperationsClient
	vmExtensionImageClient compute.VirtualMachineExtensionImagesClient
	vmExtensionClient      compute.VirtualMachineExtensionsClient
	vmScaleSetClient       compute.VirtualMachineScaleSetsClient
	vmImageClient          compute.VirtualMachineImagesClient
	vmClient               compute.VirtualMachinesClient

	appGatewayClient             network.ApplicationGatewaysClient
	ifaceClient                  network.InterfacesClient
	loadBalancerClient           network.LoadBalancersClient
	localNetConnClient           network.LocalNetworkGatewaysClient
	publicIPClient               network.PublicIPAddressesClient
	secGroupClient               network.SecurityGroupsClient
	secRuleClient                network.SecurityRulesClient
	subnetClient                 network.SubnetsClient
	netUsageClient               network.UsagesClient
	vnetGatewayConnectionsClient network.VirtualNetworkGatewayConnectionsClient
	vnetGatewayClient            network.VirtualNetworkGatewaysClient
	vnetClient                   network.VirtualNetworksClient
	routeTablesClient            network.RouteTablesClient
	routesClient                 network.RoutesClient

	cdnProfilesClient  cdn.ProfilesClient
	cdnEndpointsClient cdn.EndpointsClient

	providers           resources.ProvidersClient
	resourceGroupClient resources.GroupsClient
	tagsClient          resources.TagsClient

	jobsClient            scheduler.JobsClient
	jobsCollectionsClient scheduler.JobCollectionsClient

	storageServiceClient storage.AccountsClient
	storageUsageClient   storage.UsageOperationsClient

	deploymentsClient resources.DeploymentsClient
}

func withRequestLogging() autorest.SendDecorator {
	return func(s autorest.Sender) autorest.Sender {
		return autorest.SenderFunc(func(r *http.Request) (*http.Response, error) {
			// dump request to wire format
			if dump, err := httputil.DumpRequestOut(r, true); err == nil {
				log.Printf("[DEBUG] AzureRM Request: \n%s\n", dump)
			} else {
				// fallback to basic message
				log.Printf("[DEBUG] AzureRM Request: %s to %s\n", r.Method, r.URL)
			}

			resp, err := s.Do(r)
			if resp != nil {
				// dump response to wire format
				if dump, err := httputil.DumpResponse(resp, true); err == nil {
					log.Printf("[DEBUG] AzureRM Response for %s: \n%s\n", r.URL, dump)
				} else {
					// fallback to basic message
					log.Printf("[DEBUG] AzureRM Response: %s for %s\n", resp.Status, r.URL)
				}
			} else {
				log.Printf("[DEBUG] Request to %s completed with no response", r.URL)
			}
			return resp, err
		})
	}
}

func setUserAgent(client *autorest.Client) {
	version := terraform.VersionString()
	client.UserAgent = fmt.Sprintf("HashiCorp-Terraform-v%s", version)
}

// getArmClient is a helper method which returns a fully instantiated
// *ArmClient based on the Config's current settings.
func (c *Config) getArmClient() (*ArmClient, error) {
	// client declarations:
	client := ArmClient{}

	rivieraClient, err := riviera.NewClient(&riviera.AzureResourceManagerCredentials{
		ClientID:       c.ClientID,
		ClientSecret:   c.ClientSecret,
		TenantID:       c.TenantID,
		SubscriptionID: c.SubscriptionID,
	})
	if err != nil {
		return nil, fmt.Errorf("Error creating Riviera client: %s", err)
	}

	// validate that the credentials are correct using Riviera. Note that this must be
	// done _before_ using the Microsoft SDK, because Riviera handles errors. Using a
	// namespace registration instead of a simple OAuth token refresh guarantees that
	// service delegation is correct. This has the effect of registering Microsoft.Compute
	// which is neccessary anyway.
	if err := registerProviderWithSubscription("Microsoft.Compute", rivieraClient); err != nil {
		return nil, err
	}
	client.rivieraClient = rivieraClient

	oauthConfig, err := azure.PublicCloud.OAuthConfigForTenant(c.TenantID)
	if err != nil {
		return nil, err
	}

	// This is necessary because no-one thought about API usability. OAuthConfigForTenant
	// returns a pointer, which can be nil. NewServicePrincipalToken does not take a pointer.
	// Consequently we have to nil check this and do _something_ if it is nil, which should
	// be either an invariant of OAuthConfigForTenant (guarantee the token is not nil if
	// there is no error), or NewServicePrincipalToken should error out if the configuration
	// is required and is nil. This is the worst of all worlds, however.
	if oauthConfig == nil {
		return nil, fmt.Errorf("Unable to configure OAuthConfig for tenant %s", c.TenantID)
	}

	spt, err := azure.NewServicePrincipalToken(*oauthConfig, c.ClientID, c.ClientSecret,
		azure.PublicCloud.ResourceManagerEndpoint)
	if err != nil {
		return nil, err
	}

	// NOTE: these declarations should be left separate for clarity should the
	// clients be wished to be configured with custom Responders/PollingModess etc...
	asc := compute.NewAvailabilitySetsClient(c.SubscriptionID)
	setUserAgent(&asc.Client)
	asc.Authorizer = spt
	asc.Sender = autorest.CreateSender(withRequestLogging())
	client.availSetClient = asc

	uoc := compute.NewUsageOperationsClient(c.SubscriptionID)
	setUserAgent(&uoc.Client)
	uoc.Authorizer = spt
	uoc.Sender = autorest.CreateSender(withRequestLogging())
	client.usageOpsClient = uoc

	vmeic := compute.NewVirtualMachineExtensionImagesClient(c.SubscriptionID)
	setUserAgent(&vmeic.Client)
	vmeic.Authorizer = spt
	vmeic.Sender = autorest.CreateSender(withRequestLogging())
	client.vmExtensionImageClient = vmeic

	vmec := compute.NewVirtualMachineExtensionsClient(c.SubscriptionID)
	setUserAgent(&vmec.Client)
	vmec.Authorizer = spt
	vmec.Sender = autorest.CreateSender(withRequestLogging())
	client.vmExtensionClient = vmec

	vmic := compute.NewVirtualMachineImagesClient(c.SubscriptionID)
	setUserAgent(&vmic.Client)
	vmic.Authorizer = spt
	vmic.Sender = autorest.CreateSender(withRequestLogging())
	client.vmImageClient = vmic

	vmssc := compute.NewVirtualMachineScaleSetsClient(c.SubscriptionID)
	setUserAgent(&vmssc.Client)
	vmssc.Authorizer = spt
	vmssc.Sender = autorest.CreateSender(withRequestLogging())
	client.vmScaleSetClient = vmssc

	vmc := compute.NewVirtualMachinesClient(c.SubscriptionID)
	setUserAgent(&vmc.Client)
	vmc.Authorizer = spt
	vmc.Sender = autorest.CreateSender(withRequestLogging())
	client.vmClient = vmc

	agc := network.NewApplicationGatewaysClient(c.SubscriptionID)
	setUserAgent(&agc.Client)
	agc.Authorizer = spt
	agc.Sender = autorest.CreateSender(withRequestLogging())
	client.appGatewayClient = agc

	ifc := network.NewInterfacesClient(c.SubscriptionID)
	setUserAgent(&ifc.Client)
	ifc.Authorizer = spt
	ifc.Sender = autorest.CreateSender(withRequestLogging())
	client.ifaceClient = ifc

	lbc := network.NewLoadBalancersClient(c.SubscriptionID)
	setUserAgent(&lbc.Client)
	lbc.Authorizer = spt
	lbc.Sender = autorest.CreateSender(withRequestLogging())
	client.loadBalancerClient = lbc

	lgc := network.NewLocalNetworkGatewaysClient(c.SubscriptionID)
	setUserAgent(&lgc.Client)
	lgc.Authorizer = spt
	lgc.Sender = autorest.CreateSender(withRequestLogging())
	client.localNetConnClient = lgc

	pipc := network.NewPublicIPAddressesClient(c.SubscriptionID)
	setUserAgent(&pipc.Client)
	pipc.Authorizer = spt
	pipc.Sender = autorest.CreateSender(withRequestLogging())
	client.publicIPClient = pipc

	sgc := network.NewSecurityGroupsClient(c.SubscriptionID)
	setUserAgent(&sgc.Client)
	sgc.Authorizer = spt
	sgc.Sender = autorest.CreateSender(withRequestLogging())
	client.secGroupClient = sgc

	src := network.NewSecurityRulesClient(c.SubscriptionID)
	setUserAgent(&src.Client)
	src.Authorizer = spt
	src.Sender = autorest.CreateSender(withRequestLogging())
	client.secRuleClient = src

	snc := network.NewSubnetsClient(c.SubscriptionID)
	setUserAgent(&snc.Client)
	snc.Authorizer = spt
	snc.Sender = autorest.CreateSender(withRequestLogging())
	client.subnetClient = snc

	vgcc := network.NewVirtualNetworkGatewayConnectionsClient(c.SubscriptionID)
	setUserAgent(&vgcc.Client)
	vgcc.Authorizer = spt
	vgcc.Sender = autorest.CreateSender(withRequestLogging())
	client.vnetGatewayConnectionsClient = vgcc

	vgc := network.NewVirtualNetworkGatewaysClient(c.SubscriptionID)
	setUserAgent(&vgc.Client)
	vgc.Authorizer = spt
	vgc.Sender = autorest.CreateSender(withRequestLogging())
	client.vnetGatewayClient = vgc

	vnc := network.NewVirtualNetworksClient(c.SubscriptionID)
	setUserAgent(&vnc.Client)
	vnc.Authorizer = spt
	vnc.Sender = autorest.CreateSender(withRequestLogging())
	client.vnetClient = vnc

	rtc := network.NewRouteTablesClient(c.SubscriptionID)
	setUserAgent(&rtc.Client)
	rtc.Authorizer = spt
	rtc.Sender = autorest.CreateSender(withRequestLogging())
	client.routeTablesClient = rtc

	rc := network.NewRoutesClient(c.SubscriptionID)
	setUserAgent(&rc.Client)
	rc.Authorizer = spt
	rc.Sender = autorest.CreateSender(withRequestLogging())
	client.routesClient = rc

	rgc := resources.NewGroupsClient(c.SubscriptionID)
	setUserAgent(&rgc.Client)
	rgc.Authorizer = spt
	rgc.Sender = autorest.CreateSender(withRequestLogging())
	client.resourceGroupClient = rgc

	pc := resources.NewProvidersClient(c.SubscriptionID)
	setUserAgent(&pc.Client)
	pc.Authorizer = spt
	pc.Sender = autorest.CreateSender(withRequestLogging())
	client.providers = pc

	tc := resources.NewTagsClient(c.SubscriptionID)
	setUserAgent(&tc.Client)
	tc.Authorizer = spt
	tc.Sender = autorest.CreateSender(withRequestLogging())
	client.tagsClient = tc

	jc := scheduler.NewJobsClient(c.SubscriptionID)
	setUserAgent(&jc.Client)
	jc.Authorizer = spt
	jc.Sender = autorest.CreateSender(withRequestLogging())
	client.jobsClient = jc

	jcc := scheduler.NewJobCollectionsClient(c.SubscriptionID)
	setUserAgent(&jcc.Client)
	jcc.Authorizer = spt
	jcc.Sender = autorest.CreateSender(withRequestLogging())
	client.jobsCollectionsClient = jcc

	ssc := storage.NewAccountsClient(c.SubscriptionID)
	setUserAgent(&ssc.Client)
	ssc.Authorizer = spt
	ssc.Sender = autorest.CreateSender(withRequestLogging())
	client.storageServiceClient = ssc

	suc := storage.NewUsageOperationsClient(c.SubscriptionID)
	setUserAgent(&suc.Client)
	suc.Authorizer = spt
	suc.Sender = autorest.CreateSender(withRequestLogging())
	client.storageUsageClient = suc

	cpc := cdn.NewProfilesClient(c.SubscriptionID)
	setUserAgent(&cpc.Client)
	cpc.Authorizer = spt
	cpc.Sender = autorest.CreateSender(withRequestLogging())
	client.cdnProfilesClient = cpc

	cec := cdn.NewEndpointsClient(c.SubscriptionID)
	setUserAgent(&cec.Client)
	cec.Authorizer = spt
	cec.Sender = autorest.CreateSender(withRequestLogging())
	client.cdnEndpointsClient = cec

	dc := resources.NewDeploymentsClient(c.SubscriptionID)
	setUserAgent(&dc.Client)
	dc.Authorizer = spt
	dc.Sender = autorest.CreateSender(withRequestLogging())
	client.deploymentsClient = dc

	return &client, nil
}

func (armClient *ArmClient) getKeyForStorageAccount(resourceGroupName, storageAccountName string) (string, bool, error) {
	accountKeys, err := armClient.storageServiceClient.ListKeys(resourceGroupName, storageAccountName)
	if accountKeys.StatusCode == http.StatusNotFound {
		return "", false, nil
	}
	if err != nil {
		// We assume this is a transient error rather than a 404 (which is caught above),  so assume the
		// account still exists.
		return "", true, fmt.Errorf("Error retrieving keys for storage account %q: %s", storageAccountName, err)
	}

	if accountKeys.Keys == nil {
		return "", false, fmt.Errorf("Nil key returned for storage account %q", storageAccountName)
	}

	keys := *accountKeys.Keys
	return *keys[0].Value, true, nil
}

func (armClient *ArmClient) getBlobStorageClientForStorageAccount(resourceGroupName, storageAccountName string) (*mainStorage.BlobStorageClient, bool, error) {
	key, accountExists, err := armClient.getKeyForStorageAccount(resourceGroupName, storageAccountName)
	if err != nil {
		return nil, accountExists, err
	}
	if accountExists == false {
		return nil, false, nil
	}

	storageClient, err := mainStorage.NewBasicClient(storageAccountName, key)
	if err != nil {
		return nil, true, fmt.Errorf("Error creating storage client for storage account %q: %s", storageAccountName, err)
	}

	blobClient := storageClient.GetBlobService()
	return &blobClient, true, nil
}

func (armClient *ArmClient) getQueueServiceClientForStorageAccount(resourceGroupName, storageAccountName string) (*mainStorage.QueueServiceClient, bool, error) {
	key, accountExists, err := armClient.getKeyForStorageAccount(resourceGroupName, storageAccountName)
	if err != nil {
		return nil, accountExists, err
	}
	if accountExists == false {
		return nil, false, nil
	}

	storageClient, err := mainStorage.NewBasicClient(storageAccountName, key)
	if err != nil {
		return nil, true, fmt.Errorf("Error creating storage client for storage account %q: %s", storageAccountName, err)
	}

	queueClient := storageClient.GetQueueService()
	return &queueClient, true, nil
}
<|endoftext|>


<commit_before>package crane

import (
	"errors"
	"fmt"
	"github.com/michaelsauter/crane/print"
	"os"
	"os/exec"
	"regexp"
	"strconv"
	"strings"
	"syscall"
)

type StatusError struct {
	error  error
	status int
}

var (
	minimalDockerVersion     = []int{1, 0}
	recommendedDockerVersion = []int{1, 2}
)

func RealMain() {
	// On panic, recover the error, display it and return the given status code if any
	defer func() {
		var statusError StatusError

		switch err := recover().(type) {
		case StatusError:
			statusError = err
		case error:
			statusError = StatusError{err, 1}
		case string:
			statusError = StatusError{errors.New(err), 1}
		default:
			statusError = StatusError{}
		}

		if statusError.error != nil {
			print.Errorf("ERROR: %s\n", statusError.error)
		}
		os.Exit(statusError.status)
	}()
	checkDockerClient()
	handleCmd()
}

// Ensure there is a docker binary in the path, panicking if its version
// is below the minimal requirement, and printing a warning if its version
// is below the recommended requirement.
func checkDockerClient() {
	dockerCmd := []string{"docker", "--version"}
	sedCmd := []string{"sed", "-e", "s/[^0-9]*\\([0-9.]\\+\\).*/\\1/"}
	output, err := pipedCommandOutput(dockerCmd, sedCmd)
	if err != nil {
		panic(StatusError{errors.New("Error when probing Docker's client version. Is docker installed and within the $PATH?"), 69})
	}

	re := regexp.MustCompile("([0-9]+)\\.([0-9]+)\\.?([0-9]+)?")
	rawVersions := re.FindStringSubmatch(string(output))
	var versions []int
	for _, rawVersion := range rawVersions[1:] {
		version, err := strconv.Atoi(rawVersion)
		if err != nil {
			panic(StatusError{fmt.Errorf("Error when parsing Docker's version %v: %v", rawVersion, err), 69})
		}
		versions = append(versions, version)
	}

	for i, expectedVersion := range minimalDockerVersion {
		if versions[i] > expectedVersion {
			break
		}
		if versions[i] < expectedVersion {
			panic(StatusError{fmt.Errorf("Unsupported client version. Please upgrade to Docker %v or later.", intJoin(recommendedDockerVersion, ".")), 69})
		}
	}
	for i, expectedVersion := range recommendedDockerVersion {
		if versions[i] > expectedVersion {
			break
		}
		if versions[i] < expectedVersion {
			print.Noticef("WARNING: outdated Docker client, behavior might not be optimal. Please upgrade to Docker %v or later.\n", intJoin(recommendedDockerVersion, "."))
			break
		}
	}
}

// Similar to strings.Join() for int slices.
func intJoin(intSlice []int, sep string) string {
	var stringSlice []string
	for _, v := range intSlice {
		stringSlice = append(stringSlice, fmt.Sprint(v))
	}
	return strings.Join(stringSlice, ".")
}

func executeCommand(name string, args []string) {
	if isVerbose() {
		fmt.Printf("\n--> %s %s\n", name, strings.Join(args, " "))
	}
	cmd := exec.Command(name, args...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	cmd.Stdin = os.Stdin
	cmd.Run()
	if !cmd.ProcessState.Success() {
		status := cmd.ProcessState.Sys().(syscall.WaitStatus).ExitStatus()
		panic(StatusError{errors.New(cmd.ProcessState.String()), status})
	}
}

func commandOutput(name string, args []string) (string, error) {
	out, err := exec.Command(name, args...).CombinedOutput()
	return strings.TrimSpace(string(out)), err
}

// From https://gist.github.com/dagoof/1477401
func pipedCommandOutput(pipedCommandArgs ...[]string) ([]byte, error) {
	var commands []exec.Cmd
	for _, commandArgs := range pipedCommandArgs {
		cmd := exec.Command(commandArgs[0], commandArgs[1:]...)
		commands = append(commands, *cmd)
	}
	for i, command := range commands[:len(commands)-1] {
		out, err := command.StdoutPipe()
		if err != nil {
			return nil, err
		}
		command.Start()
		commands[i+1].Stdin = out
	}
	final, err := commands[len(commands)-1].Output()
	if err != nil {
		return nil, err
	}
	return final, nil
}
<commit_msg>remove unecessary sed hiding proper error if docker not found<commit_after>package crane

import (
	"errors"
	"fmt"
	"github.com/michaelsauter/crane/print"
	"os"
	"os/exec"
	"regexp"
	"strconv"
	"strings"
	"syscall"
)

type StatusError struct {
	error  error
	status int
}

var (
	minimalDockerVersion     = []int{1, 0}
	recommendedDockerVersion = []int{1, 2}
)

func RealMain() {
	// On panic, recover the error, display it and return the given status code if any
	defer func() {
		var statusError StatusError

		switch err := recover().(type) {
		case StatusError:
			statusError = err
		case error:
			statusError = StatusError{err, 1}
		case string:
			statusError = StatusError{errors.New(err), 1}
		default:
			statusError = StatusError{}
		}

		if statusError.error != nil {
			print.Errorf("ERROR: %s\n", statusError.error)
		}
		os.Exit(statusError.status)
	}()
	checkDockerClient()
	handleCmd()
}

// Ensure there is a docker binary in the path, panicking if its version
// is below the minimal requirement, and printing a warning if its version
// is below the recommended requirement.
func checkDockerClient() {
	output, err := commandOutput("docker", []string{"--version"})
	if err != nil {
		panic(StatusError{errors.New("Error when probing Docker's client version. Is docker installed and within the $PATH?"), 69})
	}

	re := regexp.MustCompile("([0-9]+)\\.([0-9]+)\\.?([0-9]+)?")
	rawVersions := re.FindStringSubmatch(string(output))
	var versions []int
	for _, rawVersion := range rawVersions[1:] {
		version, err := strconv.Atoi(rawVersion)
		if err != nil {
			panic(StatusError{fmt.Errorf("Error when parsing Docker's version %v: %v", rawVersion, err), 69})
		}
		versions = append(versions, version)
	}

	for i, expectedVersion := range minimalDockerVersion {
		if versions[i] > expectedVersion {
			break
		}
		if versions[i] < expectedVersion {
			panic(StatusError{fmt.Errorf("Unsupported client version. Please upgrade to Docker %v or later.", intJoin(recommendedDockerVersion, ".")), 69})
		}
	}
	for i, expectedVersion := range recommendedDockerVersion {
		if versions[i] > expectedVersion {
			break
		}
		if versions[i] < expectedVersion {
			print.Noticef("WARNING: outdated Docker client, behavior might not be optimal. Please upgrade to Docker %v or later.\n", intJoin(recommendedDockerVersion, "."))
			break
		}
	}
}

// Similar to strings.Join() for int slices.
func intJoin(intSlice []int, sep string) string {
	var stringSlice []string
	for _, v := range intSlice {
		stringSlice = append(stringSlice, fmt.Sprint(v))
	}
	return strings.Join(stringSlice, ".")
}

func executeCommand(name string, args []string) {
	if isVerbose() {
		fmt.Printf("\n--> %s %s\n", name, strings.Join(args, " "))
	}
	cmd := exec.Command(name, args...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	cmd.Stdin = os.Stdin
	cmd.Run()
	if !cmd.ProcessState.Success() {
		status := cmd.ProcessState.Sys().(syscall.WaitStatus).ExitStatus()
		panic(StatusError{errors.New(cmd.ProcessState.String()), status})
	}
}

func commandOutput(name string, args []string) (string, error) {
	out, err := exec.Command(name, args...).CombinedOutput()
	return strings.TrimSpace(string(out)), err
}

// From https://gist.github.com/dagoof/1477401
func pipedCommandOutput(pipedCommandArgs ...[]string) ([]byte, error) {
	var commands []exec.Cmd
	for _, commandArgs := range pipedCommandArgs {
		cmd := exec.Command(commandArgs[0], commandArgs[1:]...)
		commands = append(commands, *cmd)
	}
	for i, command := range commands[:len(commands)-1] {
		out, err := command.StdoutPipe()
		if err != nil {
			return nil, err
		}
		command.Start()
		commands[i+1].Stdin = out
	}
	final, err := commands[len(commands)-1].Output()
	if err != nil {
		return nil, err
	}
	return final, nil
}
<|endoftext|>