mirror of https://github.com/docker/docs.git
294 lines
6.4 KiB
Go
294 lines
6.4 KiB
Go
package azureSdkForGo
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/rand"
|
|
"encoding/xml"
|
|
"errors"
|
|
"fmt"
|
|
"github.com/MSOpenTech/azure-sdk-for-go/core/http"
|
|
"github.com/MSOpenTech/azure-sdk-for-go/core/tls"
|
|
"io"
|
|
"os/exec"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
const (
|
|
ParamNotSpecifiedError = "Parameter %s is not specified."
|
|
|
|
azureManagementDnsName = "https://management.core.windows.net"
|
|
msVersionHeader = "x-ms-version"
|
|
msVersionHeaderValue = "2014-05-01"
|
|
contentHeader = "Content-Type"
|
|
contentHeaderValue = "application/xml"
|
|
requestIdHeader = "X-Ms-Request-Id"
|
|
)
|
|
|
|
//Region public methods starts
|
|
|
|
func SendAzureGetRequest(url string) ([]byte, error) {
|
|
if len(url) == 0 {
|
|
return nil, fmt.Errorf(ParamNotSpecifiedError, "url")
|
|
}
|
|
|
|
response, err := SendAzureRequest(url, "GET", nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
responseContent := getResponseBody(response)
|
|
return responseContent, nil
|
|
}
|
|
|
|
func SendAzurePostRequest(url string, data []byte) (string, error) {
|
|
if len(url) == 0 {
|
|
return "", fmt.Errorf(ParamNotSpecifiedError, "url")
|
|
}
|
|
|
|
response, err := SendAzureRequest(url, "POST", data)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
requestId := response.Header[requestIdHeader]
|
|
return requestId[0], nil
|
|
}
|
|
|
|
func SendAzureDeleteRequest(url string) (string, error) {
|
|
if len(url) == 0 {
|
|
return "", fmt.Errorf(ParamNotSpecifiedError, "url")
|
|
}
|
|
|
|
response, err := SendAzureRequest(url, "DELETE", nil)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
requestId := response.Header[requestIdHeader]
|
|
return requestId[0], nil
|
|
}
|
|
|
|
func SendAzureRequest(url string, requestType string, data []byte) (*http.Response, error) {
|
|
if len(url) == 0 {
|
|
return nil, fmt.Errorf(ParamNotSpecifiedError, "url")
|
|
}
|
|
if len(requestType) == 0 {
|
|
return nil, fmt.Errorf(ParamNotSpecifiedError, "requestType")
|
|
}
|
|
|
|
client := createHttpClient()
|
|
|
|
response, err := sendRequest(client, url, requestType, data, 7)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return response, nil
|
|
}
|
|
|
|
func ExecuteCommand(command string, input []byte) ([]byte, error) {
|
|
if len(command) == 0 {
|
|
return nil, fmt.Errorf(ParamNotSpecifiedError, "command")
|
|
}
|
|
|
|
parts := strings.Fields(command)
|
|
head := parts[0]
|
|
parts = parts[1:len(parts)]
|
|
|
|
cmd := exec.Command(head, parts...)
|
|
if input != nil {
|
|
cmd.Stdin = bytes.NewReader(input)
|
|
}
|
|
|
|
out, err := cmd.Output()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return out, nil
|
|
}
|
|
|
|
func GetOperationStatus(operationId string) (*Operation, error) {
|
|
if len(operationId) == 0 {
|
|
return nil, fmt.Errorf(ParamNotSpecifiedError, "operationId")
|
|
}
|
|
|
|
operation := new(Operation)
|
|
url := "operations/" + operationId
|
|
response, azureErr := SendAzureGetRequest(url)
|
|
if azureErr != nil {
|
|
return nil, azureErr
|
|
}
|
|
|
|
err := xml.Unmarshal(response, operation)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return operation, nil
|
|
}
|
|
|
|
func WaitAsyncOperation(operationId string) error {
|
|
if len(operationId) == 0 {
|
|
return fmt.Errorf(ParamNotSpecifiedError, "operationId")
|
|
}
|
|
|
|
status := "InProgress"
|
|
operation := new(Operation)
|
|
err := errors.New("")
|
|
for status == "InProgress" {
|
|
time.Sleep(2000 * time.Millisecond)
|
|
operation, err = GetOperationStatus(operationId)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
status = operation.Status
|
|
}
|
|
|
|
if status == "Failed" {
|
|
return errors.New(operation.Error.Message)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func CheckStringParams(url string) ([]byte, error) {
|
|
if len(url) == 0 {
|
|
return nil, fmt.Errorf(ParamNotSpecifiedError, "url")
|
|
}
|
|
|
|
response, err := SendAzureRequest(url, "GET", nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
responseContent := getResponseBody(response)
|
|
return responseContent, nil
|
|
}
|
|
|
|
// NewUUID generates a random UUID according to RFC 4122
|
|
func NewUUID() (string, error) {
|
|
uuid := make([]byte, 16)
|
|
n, err := io.ReadFull(rand.Reader, uuid)
|
|
if n != len(uuid) || err != nil {
|
|
return "", err
|
|
}
|
|
// variant bits; see section 4.1.1
|
|
uuid[8] = uuid[8]&^0xc0 | 0x80
|
|
// version 4 (pseudo-random); see section 4.1.3
|
|
uuid[6] = uuid[6]&^0xf0 | 0x40
|
|
|
|
//return fmt.Sprintf("%x-%x-%x-%x-%x", uuid[0:4], uuid[4:6], uuid[6:8], uuid[8:10], uuid[10:]), nil
|
|
return fmt.Sprintf("%x", uuid[10:]), nil
|
|
}
|
|
|
|
//Region public methods ends
|
|
|
|
//Region private methods starts
|
|
|
|
func sendRequest(client *http.Client, url string, requestType string, data []byte, numberOfRetries int) (*http.Response, error) {
|
|
request, reqErr := createAzureRequest(url, requestType, data)
|
|
if reqErr != nil {
|
|
return nil, reqErr
|
|
}
|
|
|
|
response, err := client.Do(request)
|
|
if err != nil {
|
|
if numberOfRetries == 0 {
|
|
return nil, err
|
|
}
|
|
|
|
return sendRequest(client, url, requestType, data, numberOfRetries-1)
|
|
}
|
|
|
|
if response.StatusCode > 299 {
|
|
responseContent := getResponseBody(response)
|
|
azureErr := getAzureError(responseContent)
|
|
if azureErr != nil {
|
|
if numberOfRetries == 0 {
|
|
return nil, azureErr
|
|
}
|
|
|
|
return sendRequest(client, url, requestType, data, numberOfRetries-1)
|
|
}
|
|
}
|
|
|
|
return response, nil
|
|
}
|
|
|
|
func getAzureError(responseBody []byte) error {
|
|
error := new(AzureError)
|
|
err := xml.Unmarshal(responseBody, error)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return error
|
|
}
|
|
|
|
func createAzureRequest(url string, requestType string, data []byte) (*http.Request, error) {
|
|
var request *http.Request
|
|
var err error
|
|
|
|
url = fmt.Sprintf("%s/%s/%s", azureManagementDnsName, GetPublishSettings().SubscriptionID, url)
|
|
if data != nil {
|
|
body := bytes.NewBuffer(data)
|
|
request, err = http.NewRequest(requestType, url, body)
|
|
} else {
|
|
request, err = http.NewRequest(requestType, url, nil)
|
|
}
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
request.Header.Add(msVersionHeader, msVersionHeaderValue)
|
|
request.Header.Add(contentHeader, contentHeaderValue)
|
|
|
|
return request, nil
|
|
}
|
|
|
|
func createHttpClient() *http.Client {
|
|
cert, _ := tls.X509KeyPair(GetPublishSettings().SubscriptionCert, GetPublishSettings().SubscriptionKey)
|
|
|
|
ssl := &tls.Config{}
|
|
ssl.Certificates = []tls.Certificate{cert}
|
|
|
|
client := &http.Client{
|
|
Transport: &http.Transport{
|
|
TLSClientConfig: ssl,
|
|
},
|
|
}
|
|
|
|
return client
|
|
}
|
|
|
|
func getResponseBody(response *http.Response) []byte {
|
|
|
|
responseBody := make([]byte, response.ContentLength)
|
|
io.ReadFull(response.Body, responseBody)
|
|
return responseBody
|
|
}
|
|
|
|
//Region private methods ends
|
|
|
|
type AzureError struct {
|
|
XMLName xml.Name `xml:"Error"`
|
|
Code string
|
|
Message string
|
|
}
|
|
|
|
func (e *AzureError) Error() string {
|
|
return fmt.Sprintf("Code: %s, Message: %s", e.Code, e.Message)
|
|
}
|
|
|
|
type Operation struct {
|
|
XMLName xml.Name `xml:"Operation"`
|
|
ID string
|
|
Status string
|
|
HttpStatusCode string
|
|
Error AzureError
|
|
}
|