Skip to content

Commit

Permalink
Merge pull request #33 from jen20/virtual-network-client
Browse files Browse the repository at this point in the history
Add a client for Virtual Network management
  • Loading branch information
ruslangabitov committed Feb 4, 2015
2 parents af6985d + c95e423 commit 0fbd371
Show file tree
Hide file tree
Showing 3 changed files with 166 additions and 18 deletions.
81 changes: 81 additions & 0 deletions clients/vnetClient/entities.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package vnetClient

import (
"encoding/xml"
)

const xmlNamespace = "http://schemas.microsoft.com/ServiceHosting/2011/07/NetworkConfiguration"
const xmlNamespaceXsd = "http://www.w3.org/2001/XMLSchema"
const xmlNamespaceXsi = "http://www.w3.org/2001/XMLSchema-instance"

//NetworkConfiguration represents the network configuration for an entire Azure
//subscription. TODO: Nicer builder methods for these that abstract away the
//underlying structure
type NetworkConfiguration struct {
XMLName xml.Name `xml:"NetworkConfiguration"`
XmlNamespaceXsd string `xml:"xmlns:xsd,attr"`
XmlNamespaceXsi string `xml:"xmlns:xsi,attr"`
Xmlns string `xml:"xmlns,attr"`
Configuration VirtualNetworkConfiguration `xml:"VirtualNetworkConfiguration"`
}

//NewNetworkConfiguration creates a new empty NetworkConfiguration structure for
//further configuration. The XML namespaces are set correctly.
func NewNetworkConfiguration() NetworkConfiguration {
networkConfiguration := NetworkConfiguration{}
networkConfiguration.setXmlNamespaces()
return networkConfiguration
}

//setXmlNamespaces ensure that all of the required namespaces are set. It should
//be called prior to marshalling the structure to XML for use with the Azure REST
//endpoint. It is used internally prior to submitting requests, but since it is
//idempotent there is no harm in repeat calls.
func (self *NetworkConfiguration) setXmlNamespaces() {
self.XmlNamespaceXsd = xmlNamespaceXsd
self.XmlNamespaceXsi = xmlNamespaceXsi
self.Xmlns = xmlNamespace
}

type VirtualNetworkConfiguration struct {
Dns Dns `xml:"Dns,omitempty"`
LocalNetworkSites []LocalNetworkSite `xml:"LocalNetworkSites>LocalNetworkSite"`
VirtualNetworkSites []VirtualNetworkSite `xml:"VirtualNetworkSites>VirtualNetworkSite"`
}

type Dns struct {
DnsServers []DnsServer `xml:"DnsServers,omitempty>DnsServer,omitempty"`
}

type DnsServer struct {
XMLName xml.Name `xml:"DnsServer"`
Name string `xml:"name,attr"`
IPAddress string `xml:"IPAddress,attr"`
}

type DnsServerRef struct {
Name string `xml:"name,attr"`
}

type VirtualNetworkSite struct {
Name string `xml:"name,attr"`
Location string `xml:"Location,attr"`
AddressSpace AddressSpace `xml:"AddressSpace"`
Subnets []Subnet `xml:"Subnets>Subnet"`
DnsServersRef []DnsServerRef `xml:"DnsServersRef,omitempty>DnsServerRef"`
}

type LocalNetworkSite struct {
Name string `xml:"name,attr"`
VPNGatewayAddress string
AddressSpace AddressSpace
}

type AddressSpace struct {
AddressPrefix []string
}

type Subnet struct {
Name string `xml:"name,attr"`
AddressPrefix string
}
49 changes: 49 additions & 0 deletions clients/vnetClient/vnetClient.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package vnetClient

import (
"encoding/xml"
azure "github.com/MSOpenTech/azure-sdk-for-go"
)

const (
azureNetworkConfigurationURL = "services/networking/media"
)

//GetVirtualNetworkConfiguration retreives the current virtual network
//configuration for the currently active subscription. Note that the
//underlying Azure API means that network related operations are not safe
//for running concurrently.
func GetVirtualNetworkConfiguration() (NetworkConfiguration, error) {
networkConfiguration := NewNetworkConfiguration()
response, err := azure.SendAzureGetRequest(azureNetworkConfigurationURL)
if err != nil {
return networkConfiguration, err
}

err = xml.Unmarshal(response, &networkConfiguration)
if err != nil {
return networkConfiguration, err
}

return networkConfiguration, nil
}

//SetVirtualNetworkConfiguration configures the virtual networks for the
//currently active subscription according to the NetworkConfiguration given.
//Note that the underlying Azure API means that network related operations
//are not safe for running concurrently.
func SetVirtualNetworkConfiguration(networkConfiguration NetworkConfiguration) error {
networkConfiguration.setXmlNamespaces()
networkConfigurationBytes, err := xml.Marshal(networkConfiguration)
if err != nil {
return err
}

requestId, err := azure.SendAzurePutRequest(azureNetworkConfigurationURL, "text/plain", networkConfigurationBytes)
if err != nil {
return err
}

err = azure.WaitAsyncOperation(requestId)
return err
}
54 changes: 36 additions & 18 deletions common.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ import (
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"
azureManagementDnsName = "https://management.core.windows.net"
msVersionHeader = "x-ms-version"
msVersionHeaderValue = "2014-05-01"
contentHeader = "Content-Type"
defaultContentHeaderValue = "application/xml"
requestIdHeader = "X-Ms-Request-Id"
)

//Region public methods starts
Expand All @@ -32,7 +32,7 @@ func SendAzureGetRequest(url string) ([]byte, error) {
return nil, fmt.Errorf(paramNotSpecifiedError, "url")
}

response, err := SendAzureRequest(url, "GET", nil)
response, err := SendAzureRequest(url, "GET", "", nil)
if err != nil {
return nil, err
}
Expand All @@ -46,7 +46,21 @@ func SendAzurePostRequest(url string, data []byte) (string, error) {
return "", fmt.Errorf(paramNotSpecifiedError, "url")
}

response, err := SendAzureRequest(url, "POST", data)
response, err := SendAzureRequest(url, "POST", "", data)
if err != nil {
return "", err
}

requestId := response.Header[requestIdHeader]
return requestId[0], nil
}

func SendAzurePutRequest(url string, contentType string, data []byte) (string, error) {
if len(url) == 0 {
return "", fmt.Errorf(paramNotSpecifiedError, contentType, "url")
}

response, err := SendAzureRequest(url, "PUT", contentType, data)
if err != nil {
return "", err
}
Expand All @@ -60,7 +74,7 @@ func SendAzureDeleteRequest(url string) (string, error) {
return "", fmt.Errorf(paramNotSpecifiedError, "url")
}

response, err := SendAzureRequest(url, "DELETE", nil)
response, err := SendAzureRequest(url, "DELETE", "", nil)
if err != nil {
return "", err
}
Expand All @@ -69,7 +83,7 @@ func SendAzureDeleteRequest(url string) (string, error) {
return requestId[0], nil
}

func SendAzureRequest(url string, requestType string, data []byte) (*http.Response, error) {
func SendAzureRequest(url string, requestType string, contentType string, data []byte) (*http.Response, error) {
if len(url) == 0 {
return nil, fmt.Errorf(paramNotSpecifiedError, "url")
}
Expand All @@ -79,7 +93,7 @@ func SendAzureRequest(url string, requestType string, data []byte) (*http.Respon

client := createHttpClient()

response, err := sendRequest(client, url, requestType, data, 7)
response, err := sendRequest(client, url, requestType, contentType, data, 7)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -159,7 +173,7 @@ func CheckStringParams(url string) ([]byte, error) {
return nil, fmt.Errorf(paramNotSpecifiedError, "url")
}

response, err := SendAzureRequest(url, "GET", nil)
response, err := SendAzureRequest(url, "GET", "", nil)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -188,8 +202,8 @@ func NewUUID() (string, error) {

//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)
func sendRequest(client *http.Client, url string, requestType string, contentType string, data []byte, numberOfRetries int) (*http.Response, error) {
request, reqErr := createAzureRequest(url, requestType, contentType, data)
if reqErr != nil {
return nil, reqErr
}
Expand All @@ -200,7 +214,7 @@ func sendRequest(client *http.Client, url string, requestType string, data []byt
return nil, err
}

return sendRequest(client, url, requestType, data, numberOfRetries-1)
return sendRequest(client, url, requestType, contentType, data, numberOfRetries-1)
}

if response.StatusCode > 299 {
Expand All @@ -211,7 +225,7 @@ func sendRequest(client *http.Client, url string, requestType string, data []byt
return nil, azureErr
}

return sendRequest(client, url, requestType, data, numberOfRetries-1)
return sendRequest(client, url, requestType, contentType, data, numberOfRetries-1)
}
}

Expand All @@ -228,7 +242,7 @@ func getAzureError(responseBody []byte) error {
return error
}

func createAzureRequest(url string, requestType string, data []byte) (*http.Request, error) {
func createAzureRequest(url string, requestType string, contentType string, data []byte) (*http.Request, error) {
var request *http.Request
var err error

Expand All @@ -245,7 +259,11 @@ func createAzureRequest(url string, requestType string, data []byte) (*http.Requ
}

request.Header.Add(msVersionHeader, msVersionHeaderValue)
request.Header.Add(contentHeader, contentHeaderValue)
if len(contentType) > 0 {
request.Header.Add(contentHeader, contentType)
} else {
request.Header.Add(contentHeader, defaultContentHeaderValue)
}

return request, nil
}
Expand Down

0 comments on commit 0fbd371

Please sign in to comment.