Merge pull request #35 from skriss/server_config_validation

validate cloud-provider config at startup & make PVProvider optional
This commit is contained in:
Andy Goldstein
2017-08-14 16:03:15 -04:00
committed by GitHub
10 changed files with 653 additions and 7 deletions
+5
View File
@@ -29,6 +29,11 @@
"Comment": "v10.0.2-beta-2-g97210cf",
"Rev": "97210cf08b64533d54deb68ac5ca6bd9b8138ebb"
},
{
"ImportPath": "github.com/Azure/azure-sdk-for-go/arm/resources/subscriptions",
"Comment": "v10.0.2-beta-2-g97210cf",
"Rev": "97210cf08b64533d54deb68ac5ca6bd9b8138ebb"
},
{
"ImportPath": "github.com/Azure/azure-sdk-for-go/storage",
"Comment": "v10.0.2-beta-2-g97210cf",
+16 -1
View File
@@ -17,6 +17,8 @@ limitations under the License.
package aws
import (
"fmt"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/ec2"
@@ -42,9 +44,22 @@ func NewStorageAdapter(config *aws.Config, availabilityZone string, kmsKeyID str
return nil, err
}
// validate the availabilityZone
var (
ec2Client = ec2.New(sess)
azReq = &ec2.DescribeAvailabilityZonesInput{ZoneNames: []*string{&availabilityZone}}
)
res, err := ec2Client.DescribeAvailabilityZones(azReq)
if err != nil {
return nil, err
}
if len(res.AvailabilityZones) == 0 {
return nil, fmt.Errorf("availability zone %q not found", availabilityZone)
}
return &storageAdapter{
blockStorage: &blockStorageAdapter{
ec2: ec2.New(sess),
ec2: ec2Client,
az: availabilityZone,
},
objectStorage: &objectStorageAdapter{
@@ -17,12 +17,14 @@ limitations under the License.
package azure
import (
"errors"
"fmt"
"os"
"time"
"github.com/Azure/azure-sdk-for-go/arm/disk"
"github.com/Azure/azure-sdk-for-go/arm/examples/helpers"
"github.com/Azure/azure-sdk-for-go/arm/resources/subscriptions"
"github.com/Azure/azure-sdk-for-go/storage"
"github.com/Azure/go-autorest/autorest/azure"
@@ -79,6 +81,31 @@ func NewStorageAdapter(location string, apiTimeout time.Duration) (cloudprovider
apiTimeout = time.Minute
}
// validate the location
groupClient := subscriptions.NewGroupClient()
groupClient.Authorizer = spt
locs, err := groupClient.ListLocations(cfg[azureSubscriptionIDKey])
if err != nil {
return nil, err
}
if locs.Value == nil {
return nil, errors.New("no locations returned from Azure API")
}
locationExists := false
for _, loc := range *locs.Value {
if (loc.Name != nil && *loc.Name == location) || (loc.DisplayName != nil && *loc.DisplayName == location) {
locationExists = true
break
}
}
if !locationExists {
return nil, fmt.Errorf("location %q not found", location)
}
return &storageAdapter{
objectStorage: &objectStorageAdapter{
blobClient: &blobClient,
@@ -26,9 +26,7 @@ import (
)
type objectStorageAdapter struct {
project string
zone string
gcs *storage.Service
gcs *storage.Service
}
var _ cloudprovider.ObjectStorageAdapter = &objectStorageAdapter{}
+13 -3
View File
@@ -17,6 +17,8 @@ limitations under the License.
package gcp
import (
"fmt"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
"google.golang.org/api/compute/v0.beta"
@@ -44,6 +46,16 @@ func NewStorageAdapter(project string, zone string) (cloudprovider.StorageAdapte
return nil, err
}
// validate project & zone
res, err := gce.Zones.Get(project, zone).Do()
if err != nil {
return nil, err
}
if res == nil {
return nil, fmt.Errorf("zone %q not found for project %q", project, zone)
}
gcs, err := storage.New(client)
if err != nil {
return nil, err
@@ -51,9 +63,7 @@ func NewStorageAdapter(project string, zone string) (cloudprovider.StorageAdapte
return &storageAdapter{
objectStorage: &objectStorageAdapter{
gcs: gcs,
project: project,
zone: zone,
gcs: gcs,
},
blockStorage: &blockStorageAdapter{
gce: gce,
+54
View File
@@ -0,0 +1,54 @@
// Package subscriptions implements the Azure ARM Subscriptions service API
// version 2016-06-01.
//
// All resource groups and resources exist within subscriptions. These
// operation enable you get information about your subscriptions and tenants. A
// tenant is a dedicated instance of Azure Active Directory (Azure AD) for your
// organization.
package subscriptions
// Copyright (c) Microsoft and contributors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Code generated by Microsoft (R) AutoRest Code Generator 1.0.1.0
// Changes may cause incorrect behavior and will be lost if the code is
// regenerated.
import (
"github.com/Azure/go-autorest/autorest"
)
const (
// DefaultBaseURI is the default URI used for the service Subscriptions
DefaultBaseURI = "https://management.azure.com"
)
// ManagementClient is the base client for Subscriptions.
type ManagementClient struct {
autorest.Client
BaseURI string
}
// New creates an instance of the ManagementClient client.
func New() ManagementClient {
return NewWithBaseURI(DefaultBaseURI)
}
// NewWithBaseURI creates an instance of the ManagementClient client.
func NewWithBaseURI(baseURI string) ManagementClient {
return ManagementClient{
Client: autorest.NewClientWithUserAgent(UserAgent()),
BaseURI: baseURI,
}
}
+132
View File
@@ -0,0 +1,132 @@
package subscriptions
// Copyright (c) Microsoft and contributors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Code generated by Microsoft (R) AutoRest Code Generator 1.0.1.0
// Changes may cause incorrect behavior and will be lost if the code is
// regenerated.
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/to"
"net/http"
)
// SpendingLimit enumerates the values for spending limit.
type SpendingLimit string
const (
// CurrentPeriodOff specifies the current period off state for spending
// limit.
CurrentPeriodOff SpendingLimit = "CurrentPeriodOff"
// Off specifies the off state for spending limit.
Off SpendingLimit = "Off"
// On specifies the on state for spending limit.
On SpendingLimit = "On"
)
// State enumerates the values for state.
type State string
const (
// Deleted specifies the deleted state for state.
Deleted State = "Deleted"
// Disabled specifies the disabled state for state.
Disabled State = "Disabled"
// Enabled specifies the enabled state for state.
Enabled State = "Enabled"
// PastDue specifies the past due state for state.
PastDue State = "PastDue"
// Warned specifies the warned state for state.
Warned State = "Warned"
)
// ListResult is subscription list operation response.
type ListResult struct {
autorest.Response `json:"-"`
Value *[]Subscription `json:"value,omitempty"`
NextLink *string `json:"nextLink,omitempty"`
}
// ListResultPreparer prepares a request to retrieve the next set of results. It returns
// nil if no more results exist.
func (client ListResult) ListResultPreparer() (*http.Request, error) {
if client.NextLink == nil || len(to.String(client.NextLink)) <= 0 {
return nil, nil
}
return autorest.Prepare(&http.Request{},
autorest.AsJSON(),
autorest.AsGet(),
autorest.WithBaseURL(to.String(client.NextLink)))
}
// Location is location information.
type Location struct {
ID *string `json:"id,omitempty"`
SubscriptionID *string `json:"subscriptionId,omitempty"`
Name *string `json:"name,omitempty"`
DisplayName *string `json:"displayName,omitempty"`
Latitude *string `json:"latitude,omitempty"`
Longitude *string `json:"longitude,omitempty"`
}
// LocationListResult is location list operation response.
type LocationListResult struct {
autorest.Response `json:"-"`
Value *[]Location `json:"value,omitempty"`
}
// Policies is subscription policies.
type Policies struct {
LocationPlacementID *string `json:"locationPlacementId,omitempty"`
QuotaID *string `json:"quotaId,omitempty"`
SpendingLimit SpendingLimit `json:"spendingLimit,omitempty"`
}
// Subscription is subscription information.
type Subscription struct {
autorest.Response `json:"-"`
ID *string `json:"id,omitempty"`
SubscriptionID *string `json:"subscriptionId,omitempty"`
DisplayName *string `json:"displayName,omitempty"`
State State `json:"state,omitempty"`
SubscriptionPolicies *Policies `json:"subscriptionPolicies,omitempty"`
AuthorizationSource *string `json:"authorizationSource,omitempty"`
}
// TenantIDDescription is tenant Id information.
type TenantIDDescription struct {
ID *string `json:"id,omitempty"`
TenantID *string `json:"tenantId,omitempty"`
}
// TenantListResult is tenant Ids information.
type TenantListResult struct {
autorest.Response `json:"-"`
Value *[]TenantIDDescription `json:"value,omitempty"`
NextLink *string `json:"nextLink,omitempty"`
}
// TenantListResultPreparer prepares a request to retrieve the next set of results. It returns
// nil if no more results exist.
func (client TenantListResult) TenantListResultPreparer() (*http.Request, error) {
if client.NextLink == nil || len(to.String(client.NextLink)) <= 0 {
return nil, nil
}
return autorest.Prepare(&http.Request{},
autorest.AsJSON(),
autorest.AsGet(),
autorest.WithBaseURL(to.String(client.NextLink)))
}
@@ -0,0 +1,252 @@
package subscriptions
// Copyright (c) Microsoft and contributors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Code generated by Microsoft (R) AutoRest Code Generator 1.0.1.0
// Changes may cause incorrect behavior and will be lost if the code is
// regenerated.
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"net/http"
)
// GroupClient is the all resource groups and resources exist within
// subscriptions. These operation enable you get information about your
// subscriptions and tenants. A tenant is a dedicated instance of Azure Active
// Directory (Azure AD) for your organization.
type GroupClient struct {
ManagementClient
}
// NewGroupClient creates an instance of the GroupClient client.
func NewGroupClient() GroupClient {
return NewGroupClientWithBaseURI(DefaultBaseURI)
}
// NewGroupClientWithBaseURI creates an instance of the GroupClient client.
func NewGroupClientWithBaseURI(baseURI string) GroupClient {
return GroupClient{NewWithBaseURI(baseURI)}
}
// Get gets details about a specified subscription.
//
// subscriptionID is the ID of the target subscription.
func (client GroupClient) Get(subscriptionID string) (result Subscription, err error) {
req, err := client.GetPreparer(subscriptionID)
if err != nil {
err = autorest.NewErrorWithError(err, "subscriptions.GroupClient", "Get", nil, "Failure preparing request")
return
}
resp, err := client.GetSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "subscriptions.GroupClient", "Get", resp, "Failure sending request")
return
}
result, err = client.GetResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "subscriptions.GroupClient", "Get", resp, "Failure responding to request")
}
return
}
// GetPreparer prepares the Get request.
func (client GroupClient) GetPreparer(subscriptionID string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"subscriptionId": autorest.Encode("path", subscriptionID),
}
const APIVersion = "2016-06-01"
queryParameters := map[string]interface{}{
"api-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsGet(),
autorest.WithBaseURL(client.BaseURI),
autorest.WithPathParameters("/subscriptions/{subscriptionId}", pathParameters),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare(&http.Request{})
}
// GetSender sends the Get request. The method will close the
// http.Response Body if it receives an error.
func (client GroupClient) GetSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req)
}
// GetResponder handles the response to the Get request. The method always
// closes the http.Response Body.
func (client GroupClient) GetResponder(resp *http.Response) (result Subscription, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingJSON(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
// List gets all subscriptions for a tenant.
func (client GroupClient) List() (result ListResult, err error) {
req, err := client.ListPreparer()
if err != nil {
err = autorest.NewErrorWithError(err, "subscriptions.GroupClient", "List", nil, "Failure preparing request")
return
}
resp, err := client.ListSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "subscriptions.GroupClient", "List", resp, "Failure sending request")
return
}
result, err = client.ListResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "subscriptions.GroupClient", "List", resp, "Failure responding to request")
}
return
}
// ListPreparer prepares the List request.
func (client GroupClient) ListPreparer() (*http.Request, error) {
const APIVersion = "2016-06-01"
queryParameters := map[string]interface{}{
"api-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsGet(),
autorest.WithBaseURL(client.BaseURI),
autorest.WithPath("/subscriptions"),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare(&http.Request{})
}
// ListSender sends the List request. The method will close the
// http.Response Body if it receives an error.
func (client GroupClient) ListSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req)
}
// ListResponder handles the response to the List request. The method always
// closes the http.Response Body.
func (client GroupClient) ListResponder(resp *http.Response) (result ListResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingJSON(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
// ListNextResults retrieves the next set of results, if any.
func (client GroupClient) ListNextResults(lastResults ListResult) (result ListResult, err error) {
req, err := lastResults.ListResultPreparer()
if err != nil {
return result, autorest.NewErrorWithError(err, "subscriptions.GroupClient", "List", nil, "Failure preparing next results request")
}
if req == nil {
return
}
resp, err := client.ListSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
return result, autorest.NewErrorWithError(err, "subscriptions.GroupClient", "List", resp, "Failure sending next results request")
}
result, err = client.ListResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "subscriptions.GroupClient", "List", resp, "Failure responding to next results request")
}
return
}
// ListLocations this operation provides all the locations that are available
// for resource providers; however, each resource provider may support a subset
// of this list.
//
// subscriptionID is the ID of the target subscription.
func (client GroupClient) ListLocations(subscriptionID string) (result LocationListResult, err error) {
req, err := client.ListLocationsPreparer(subscriptionID)
if err != nil {
err = autorest.NewErrorWithError(err, "subscriptions.GroupClient", "ListLocations", nil, "Failure preparing request")
return
}
resp, err := client.ListLocationsSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "subscriptions.GroupClient", "ListLocations", resp, "Failure sending request")
return
}
result, err = client.ListLocationsResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "subscriptions.GroupClient", "ListLocations", resp, "Failure responding to request")
}
return
}
// ListLocationsPreparer prepares the ListLocations request.
func (client GroupClient) ListLocationsPreparer(subscriptionID string) (*http.Request, error) {
pathParameters := map[string]interface{}{
"subscriptionId": autorest.Encode("path", subscriptionID),
}
const APIVersion = "2016-06-01"
queryParameters := map[string]interface{}{
"api-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsGet(),
autorest.WithBaseURL(client.BaseURI),
autorest.WithPathParameters("/subscriptions/{subscriptionId}/locations", pathParameters),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare(&http.Request{})
}
// ListLocationsSender sends the ListLocations request. The method will close the
// http.Response Body if it receives an error.
func (client GroupClient) ListLocationsSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req)
}
// ListLocationsResponder handles the response to the ListLocations request. The method always
// closes the http.Response Body.
func (client GroupClient) ListLocationsResponder(resp *http.Response) (result LocationListResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingJSON(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
+124
View File
@@ -0,0 +1,124 @@
package subscriptions
// Copyright (c) Microsoft and contributors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Code generated by Microsoft (R) AutoRest Code Generator 1.0.1.0
// Changes may cause incorrect behavior and will be lost if the code is
// regenerated.
import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"net/http"
)
// TenantsClient is the all resource groups and resources exist within
// subscriptions. These operation enable you get information about your
// subscriptions and tenants. A tenant is a dedicated instance of Azure Active
// Directory (Azure AD) for your organization.
type TenantsClient struct {
ManagementClient
}
// NewTenantsClient creates an instance of the TenantsClient client.
func NewTenantsClient() TenantsClient {
return NewTenantsClientWithBaseURI(DefaultBaseURI)
}
// NewTenantsClientWithBaseURI creates an instance of the TenantsClient client.
func NewTenantsClientWithBaseURI(baseURI string) TenantsClient {
return TenantsClient{NewWithBaseURI(baseURI)}
}
// List gets the tenants for your account.
func (client TenantsClient) List() (result TenantListResult, err error) {
req, err := client.ListPreparer()
if err != nil {
err = autorest.NewErrorWithError(err, "subscriptions.TenantsClient", "List", nil, "Failure preparing request")
return
}
resp, err := client.ListSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
err = autorest.NewErrorWithError(err, "subscriptions.TenantsClient", "List", resp, "Failure sending request")
return
}
result, err = client.ListResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "subscriptions.TenantsClient", "List", resp, "Failure responding to request")
}
return
}
// ListPreparer prepares the List request.
func (client TenantsClient) ListPreparer() (*http.Request, error) {
const APIVersion = "2016-06-01"
queryParameters := map[string]interface{}{
"api-version": APIVersion,
}
preparer := autorest.CreatePreparer(
autorest.AsGet(),
autorest.WithBaseURL(client.BaseURI),
autorest.WithPath("/tenants"),
autorest.WithQueryParameters(queryParameters))
return preparer.Prepare(&http.Request{})
}
// ListSender sends the List request. The method will close the
// http.Response Body if it receives an error.
func (client TenantsClient) ListSender(req *http.Request) (*http.Response, error) {
return autorest.SendWithSender(client, req)
}
// ListResponder handles the response to the List request. The method always
// closes the http.Response Body.
func (client TenantsClient) ListResponder(resp *http.Response) (result TenantListResult, err error) {
err = autorest.Respond(
resp,
client.ByInspecting(),
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingJSON(&result),
autorest.ByClosing())
result.Response = autorest.Response{Response: resp}
return
}
// ListNextResults retrieves the next set of results, if any.
func (client TenantsClient) ListNextResults(lastResults TenantListResult) (result TenantListResult, err error) {
req, err := lastResults.TenantListResultPreparer()
if err != nil {
return result, autorest.NewErrorWithError(err, "subscriptions.TenantsClient", "List", nil, "Failure preparing next results request")
}
if req == nil {
return
}
resp, err := client.ListSender(req)
if err != nil {
result.Response = autorest.Response{Response: resp}
return result, autorest.NewErrorWithError(err, "subscriptions.TenantsClient", "List", resp, "Failure sending next results request")
}
result, err = client.ListResponder(resp)
if err != nil {
err = autorest.NewErrorWithError(err, "subscriptions.TenantsClient", "List", resp, "Failure responding to next results request")
}
return
}
+29
View File
@@ -0,0 +1,29 @@
package subscriptions
// Copyright (c) Microsoft and contributors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Code generated by Microsoft (R) AutoRest Code Generator 1.0.1.0
// Changes may cause incorrect behavior and will be lost if the code is
// regenerated.
// UserAgent returns the UserAgent string to use when sending http.Requests.
func UserAgent() string {
return "Azure-SDK-For-Go/v10.0.2-beta arm-subscriptions/2016-06-01"
}
// Version returns the semantic version (see http://semver.org) of the client.
func Version() string {
return "v10.0.2-beta"
}