<commit_before>package state

import (
	"fmt"

	"github.com/hashicorp/go-memdb"
	"github.com/hashicorp/nomad/nomad/structs"
)

// stateStoreSchema is used to return the schema for the state store
func stateStoreSchema() *memdb.DBSchema {
	// Create the root DB schema
	db := &memdb.DBSchema{
		Tables: make(map[string]*memdb.TableSchema),
	}

	// Collect all the schemas that are needed
	schemas := []func() *memdb.TableSchema{
		indexTableSchema,
		nodeTableSchema,
		jobTableSchema,
		jobSummarySchema,
		periodicLaunchTableSchema,
		evalTableSchema,
		allocTableSchema,
		vaultAccessorTableSchema,
	}

	// Add each of the tables
	for _, schemaFn := range schemas {
		schema := schemaFn()
		if _, ok := db.Tables[schema.Name]; ok {
			panic(fmt.Sprintf("duplicate table name: %s", schema.Name))
		}
		db.Tables[schema.Name] = schema
	}
	return db
}

// indexTableSchema is used for
func indexTableSchema() *memdb.TableSchema {
	return &memdb.TableSchema{
		Name: "index",
		Indexes: map[string]*memdb.IndexSchema{
			"id": &memdb.IndexSchema{
				Name:         "id",
				AllowMissing: false,
				Unique:       true,
				Indexer: &memdb.StringFieldIndex{
					Field:     "Key",
					Lowercase: true,
				},
			},
		},
	}
}

// nodeTableSchema returns the MemDB schema for the nodes table.
// This table is used to store all the client nodes that are registered.
func nodeTableSchema() *memdb.TableSchema {
	return &memdb.TableSchema{
		Name: "nodes",
		Indexes: map[string]*memdb.IndexSchema{
			// Primary index is used for node management
			// and simple direct lookup. ID is required to be
			// unique.
			"id": &memdb.IndexSchema{
				Name:         "id",
				AllowMissing: false,
				Unique:       true,
				Indexer: &memdb.UUIDFieldIndex{
					Field: "ID",
				},
			},
		},
	}
}

// jobTableSchema returns the MemDB schema for the jobs table.
// This table is used to store all the jobs that have been submitted.
func jobTableSchema() *memdb.TableSchema {
	return &memdb.TableSchema{
		Name: "jobs",
		Indexes: map[string]*memdb.IndexSchema{
			// Primary index is used for job management
			// and simple direct lookup. ID is required to be
			// unique.
			"id": &memdb.IndexSchema{
				Name:         "id",
				AllowMissing: false,
				Unique:       true,
				Indexer: &memdb.StringFieldIndex{
					Field:     "ID",
					Lowercase: true,
				},
			},
			"type": &memdb.IndexSchema{
				Name:         "type",
				AllowMissing: false,
				Unique:       false,
				Indexer: &memdb.StringFieldIndex{
					Field:     "Type",
					Lowercase: false,
				},
			},
			"gc": &memdb.IndexSchema{
				Name:         "gc",
				AllowMissing: false,
				Unique:       false,
				Indexer: &memdb.ConditionalIndex{
					Conditional: jobIsGCable,
				},
			},
			"periodic": &memdb.IndexSchema{
				Name:         "periodic",
				AllowMissing: false,
				Unique:       false,
				Indexer: &memdb.ConditionalIndex{
					Conditional: jobIsPeriodic,
				},
			},
		},
	}
}

// jobSummarySchema returns the memdb schema for the job summary table
func jobSummarySchema() *memdb.TableSchema {
	return &memdb.TableSchema{
		Name: "job_summary",
		Indexes: map[string]*memdb.IndexSchema{
			"id": &memdb.IndexSchema{
				Name:         "id",
				AllowMissing: false,
				Unique:       true,
				Indexer: &memdb.StringFieldIndex{
					Field:     "JobID",
					Lowercase: true,
				},
			},
		},
	}
}

// jobIsGCable satisfies the ConditionalIndexFunc interface and creates an index
// on whether a job is eligible for garbage collection.
func jobIsGCable(obj interface{}) (bool, error) {
	j, ok := obj.(*structs.Job)
	if !ok {
		return false, fmt.Errorf("Unexpected type: %v", obj)
	}

	// The job is GCable if it is batch, it is not periodic and is not a
	// parameterized job.
	periodic := j.Periodic != nil && j.Periodic.Enabled
	gcable := j.Type == structs.JobTypeBatch && !periodic && !j.IsParameterized()
	return gcable, nil
}

// jobIsPeriodic satisfies the ConditionalIndexFunc interface and creates an index
// on whether a job is periodic.
func jobIsPeriodic(obj interface{}) (bool, error) {
	j, ok := obj.(*structs.Job)
	if !ok {
		return false, fmt.Errorf("Unexpected type: %v", obj)
	}

	if j.Periodic != nil && j.Periodic.Enabled == true {
		return true, nil
	}

	return false, nil
}

// periodicLaunchTableSchema returns the MemDB schema tracking the most recent
// launch time for a perioidic job.
func periodicLaunchTableSchema() *memdb.TableSchema {
	return &memdb.TableSchema{
		Name: "periodic_launch",
		Indexes: map[string]*memdb.IndexSchema{
			// Primary index is used for job management
			// and simple direct lookup. ID is required to be
			// unique.
			"id": &memdb.IndexSchema{
				Name:         "id",
				AllowMissing: false,
				Unique:       true,
				Indexer: &memdb.StringFieldIndex{
					Field:     "ID",
					Lowercase: true,
				},
			},
		},
	}
}

// evalTableSchema returns the MemDB schema for the eval table.
// This table is used to store all the evaluations that are pending
// or recently completed.
func evalTableSchema() *memdb.TableSchema {
	return &memdb.TableSchema{
		Name: "evals",
		Indexes: map[string]*memdb.IndexSchema{
			// Primary index is used for direct lookup.
			"id": &memdb.IndexSchema{
				Name:         "id",
				AllowMissing: false,
				Unique:       true,
				Indexer: &memdb.UUIDFieldIndex{
					Field: "ID",
				},
			},

			// Job index is used to lookup allocations by job
			"job": &memdb.IndexSchema{
				Name:         "job",
				AllowMissing: false,
				Unique:       false,
				Indexer: &memdb.CompoundIndex{
					Indexes: []memdb.Indexer{
						&memdb.StringFieldIndex{
							Field:     "JobID",
							Lowercase: true,
						},
						&memdb.StringFieldIndex{
							Field:     "Status",
							Lowercase: true,
						},
					},
				},
			},
		},
	}
}

// allocTableSchema returns the MemDB schema for the allocation table.
// This table is used to store all the task allocations between task groups
// and nodes.
func allocTableSchema() *memdb.TableSchema {
	return &memdb.TableSchema{
		Name: "allocs",
		Indexes: map[string]*memdb.IndexSchema{
			// Primary index is a UUID
			"id": &memdb.IndexSchema{
				Name:         "id",
				AllowMissing: false,
				Unique:       true,
				Indexer: &memdb.UUIDFieldIndex{
					Field: "ID",
				},
			},

			// Node index is used to lookup allocations by node
			"node": &memdb.IndexSchema{
				Name:         "node",
				AllowMissing: true, // Missing is allow for failed allocations
				Unique:       false,
				Indexer: &memdb.CompoundIndex{
					Indexes: []memdb.Indexer{
						&memdb.StringFieldIndex{
							Field:     "NodeID",
							Lowercase: true,
						},

						// Conditional indexer on if allocation is terminal
						&memdb.ConditionalIndex{
							Conditional: func(obj interface{}) (bool, error) {
								// Cast to allocation
								alloc, ok := obj.(*structs.Allocation)
								if !ok {
									return false, fmt.Errorf("wrong type, got %t should be Allocation", obj)
								}

								// Check if the allocation is terminal
								return alloc.TerminalStatus(), nil
							},
						},
					},
				},
			},

			// Job index is used to lookup allocations by job
			"job": &memdb.IndexSchema{
				Name:         "job",
				AllowMissing: false,
				Unique:       false,
				Indexer: &memdb.StringFieldIndex{
					Field:     "JobID",
					Lowercase: true,
				},
			},

			// Eval index is used to lookup allocations by eval
			"eval": &memdb.IndexSchema{
				Name:         "eval",
				AllowMissing: false,
				Unique:       false,
				Indexer: &memdb.UUIDFieldIndex{
					Field: "EvalID",
				},
			},
		},
	}
}

// vaultAccessorTableSchema returns the MemDB schema for the Vault Accessor
// Table. This table tracks Vault accessors for tokens created on behalf of
// allocations required Vault tokens.
func vaultAccessorTableSchema() *memdb.TableSchema {
	return &memdb.TableSchema{
		Name: "vault_accessors",
		Indexes: map[string]*memdb.IndexSchema{
			// The primary index is the accessor id
			"id": &memdb.IndexSchema{
				Name:         "id",
				AllowMissing: false,
				Unique:       true,
				Indexer: &memdb.StringFieldIndex{
					Field: "Accessor",
				},
			},

			"alloc_id": &memdb.IndexSchema{
				Name:         "alloc_id",
				AllowMissing: false,
				Unique:       false,
				Indexer: &memdb.StringFieldIndex{
					Field: "AllocID",
				},
			},

			"node_id": &memdb.IndexSchema{
				Name:         "node_id",
				AllowMissing: false,
				Unique:       false,
				Indexer: &memdb.StringFieldIndex{
					Field: "NodeID",
				},
			},
		},
	}
}
<commit_msg>Job History schema<commit_after>package state

import (
	"fmt"

	"github.com/hashicorp/go-memdb"
	"github.com/hashicorp/nomad/nomad/structs"
)

// stateStoreSchema is used to return the schema for the state store
func stateStoreSchema() *memdb.DBSchema {
	// Create the root DB schema
	db := &memdb.DBSchema{
		Tables: make(map[string]*memdb.TableSchema),
	}

	// Collect all the schemas that are needed
	schemas := []func() *memdb.TableSchema{
		indexTableSchema,
		nodeTableSchema,
		jobTableSchema,
		jobSummarySchema,
		jobHistorySchema,
		periodicLaunchTableSchema,
		evalTableSchema,
		allocTableSchema,
		vaultAccessorTableSchema,
	}

	// Add each of the tables
	for _, schemaFn := range schemas {
		schema := schemaFn()
		if _, ok := db.Tables[schema.Name]; ok {
			panic(fmt.Sprintf("duplicate table name: %s", schema.Name))
		}
		db.Tables[schema.Name] = schema
	}
	return db
}

// indexTableSchema is used for
func indexTableSchema() *memdb.TableSchema {
	return &memdb.TableSchema{
		Name: "index",
		Indexes: map[string]*memdb.IndexSchema{
			"id": &memdb.IndexSchema{
				Name:         "id",
				AllowMissing: false,
				Unique:       true,
				Indexer: &memdb.StringFieldIndex{
					Field:     "Key",
					Lowercase: true,
				},
			},
		},
	}
}

// nodeTableSchema returns the MemDB schema for the nodes table.
// This table is used to store all the client nodes that are registered.
func nodeTableSchema() *memdb.TableSchema {
	return &memdb.TableSchema{
		Name: "nodes",
		Indexes: map[string]*memdb.IndexSchema{
			// Primary index is used for node management
			// and simple direct lookup. ID is required to be
			// unique.
			"id": &memdb.IndexSchema{
				Name:         "id",
				AllowMissing: false,
				Unique:       true,
				Indexer: &memdb.UUIDFieldIndex{
					Field: "ID",
				},
			},
		},
	}
}

// jobTableSchema returns the MemDB schema for the jobs table.
// This table is used to store all the jobs that have been submitted.
func jobTableSchema() *memdb.TableSchema {
	return &memdb.TableSchema{
		Name: "jobs",
		Indexes: map[string]*memdb.IndexSchema{
			// Primary index is used for job management
			// and simple direct lookup. ID is required to be
			// unique.
			"id": &memdb.IndexSchema{
				Name:         "id",
				AllowMissing: false,
				Unique:       true,
				Indexer: &memdb.StringFieldIndex{
					Field:     "ID",
					Lowercase: true,
				},
			},
			"type": &memdb.IndexSchema{
				Name:         "type",
				AllowMissing: false,
				Unique:       false,
				Indexer: &memdb.StringFieldIndex{
					Field:     "Type",
					Lowercase: false,
				},
			},
			"gc": &memdb.IndexSchema{
				Name:         "gc",
				AllowMissing: false,
				Unique:       false,
				Indexer: &memdb.ConditionalIndex{
					Conditional: jobIsGCable,
				},
			},
			"periodic": &memdb.IndexSchema{
				Name:         "periodic",
				AllowMissing: false,
				Unique:       false,
				Indexer: &memdb.ConditionalIndex{
					Conditional: jobIsPeriodic,
				},
			},
		},
	}
}

// jobSummarySchema returns the memdb schema for the job summary table
func jobSummarySchema() *memdb.TableSchema {
	return &memdb.TableSchema{
		Name: "job_summary",
		Indexes: map[string]*memdb.IndexSchema{
			"id": &memdb.IndexSchema{
				Name:         "id",
				AllowMissing: false,
				Unique:       true,
				Indexer: &memdb.StringFieldIndex{
					Field:     "JobID",
					Lowercase: true,
				},
			},
		},
	}
}

// jobHistorySchema returns the memdb schema for the job history table which
// keeps a historical view of jobs.
func jobHistorySchema() *memdb.TableSchema {
	return &memdb.TableSchema{
		Name: "job_histories",
		Indexes: map[string]*memdb.IndexSchema{
			"id": &memdb.IndexSchema{
				Name:         "id",
				AllowMissing: false,
				Unique:       true,

				// Use a compound index so the tuple of (JobID, Version) is
				// uniquely identifying
				Indexer: &memdb.CompoundIndex{
					Indexes: []memdb.Indexer{
						&memdb.StringFieldIndex{
							Field:     "JobID",
							Lowercase: true,
						},

						// Will need to create a new indexer
						&memdb.UintFieldIndex{
							Field: "Version",
						},
					},
				},
			},
		},
	}
}

// jobIsGCable satisfies the ConditionalIndexFunc interface and creates an index
// on whether a job is eligible for garbage collection.
func jobIsGCable(obj interface{}) (bool, error) {
	j, ok := obj.(*structs.Job)
	if !ok {
		return false, fmt.Errorf("Unexpected type: %v", obj)
	}

	// The job is GCable if it is batch, it is not periodic and is not a
	// parameterized job.
	periodic := j.Periodic != nil && j.Periodic.Enabled
	gcable := j.Type == structs.JobTypeBatch && !periodic && !j.IsParameterized()
	return gcable, nil
}

// jobIsPeriodic satisfies the ConditionalIndexFunc interface and creates an index
// on whether a job is periodic.
func jobIsPeriodic(obj interface{}) (bool, error) {
	j, ok := obj.(*structs.Job)
	if !ok {
		return false, fmt.Errorf("Unexpected type: %v", obj)
	}

	if j.Periodic != nil && j.Periodic.Enabled == true {
		return true, nil
	}

	return false, nil
}

// periodicLaunchTableSchema returns the MemDB schema tracking the most recent
// launch time for a perioidic job.
func periodicLaunchTableSchema() *memdb.TableSchema {
	return &memdb.TableSchema{
		Name: "periodic_launch",
		Indexes: map[string]*memdb.IndexSchema{
			// Primary index is used for job management
			// and simple direct lookup. ID is required to be
			// unique.
			"id": &memdb.IndexSchema{
				Name:         "id",
				AllowMissing: false,
				Unique:       true,
				Indexer: &memdb.StringFieldIndex{
					Field:     "ID",
					Lowercase: true,
				},
			},
		},
	}
}

// evalTableSchema returns the MemDB schema for the eval table.
// This table is used to store all the evaluations that are pending
// or recently completed.
func evalTableSchema() *memdb.TableSchema {
	return &memdb.TableSchema{
		Name: "evals",
		Indexes: map[string]*memdb.IndexSchema{
			// Primary index is used for direct lookup.
			"id": &memdb.IndexSchema{
				Name:         "id",
				AllowMissing: false,
				Unique:       true,
				Indexer: &memdb.UUIDFieldIndex{
					Field: "ID",
				},
			},

			// Job index is used to lookup allocations by job
			"job": &memdb.IndexSchema{
				Name:         "job",
				AllowMissing: false,
				Unique:       false,
				Indexer: &memdb.CompoundIndex{
					Indexes: []memdb.Indexer{
						&memdb.StringFieldIndex{
							Field:     "JobID",
							Lowercase: true,
						},
						&memdb.StringFieldIndex{
							Field:     "Status",
							Lowercase: true,
						},
					},
				},
			},
		},
	}
}

// allocTableSchema returns the MemDB schema for the allocation table.
// This table is used to store all the task allocations between task groups
// and nodes.
func allocTableSchema() *memdb.TableSchema {
	return &memdb.TableSchema{
		Name: "allocs",
		Indexes: map[string]*memdb.IndexSchema{
			// Primary index is a UUID
			"id": &memdb.IndexSchema{
				Name:         "id",
				AllowMissing: false,
				Unique:       true,
				Indexer: &memdb.UUIDFieldIndex{
					Field: "ID",
				},
			},

			// Node index is used to lookup allocations by node
			"node": &memdb.IndexSchema{
				Name:         "node",
				AllowMissing: true, // Missing is allow for failed allocations
				Unique:       false,
				Indexer: &memdb.CompoundIndex{
					Indexes: []memdb.Indexer{
						&memdb.StringFieldIndex{
							Field:     "NodeID",
							Lowercase: true,
						},

						// Conditional indexer on if allocation is terminal
						&memdb.ConditionalIndex{
							Conditional: func(obj interface{}) (bool, error) {
								// Cast to allocation
								alloc, ok := obj.(*structs.Allocation)
								if !ok {
									return false, fmt.Errorf("wrong type, got %t should be Allocation", obj)
								}

								// Check if the allocation is terminal
								return alloc.TerminalStatus(), nil
							},
						},
					},
				},
			},

			// Job index is used to lookup allocations by job
			"job": &memdb.IndexSchema{
				Name:         "job",
				AllowMissing: false,
				Unique:       false,
				Indexer: &memdb.StringFieldIndex{
					Field:     "JobID",
					Lowercase: true,
				},
			},

			// Eval index is used to lookup allocations by eval
			"eval": &memdb.IndexSchema{
				Name:         "eval",
				AllowMissing: false,
				Unique:       false,
				Indexer: &memdb.UUIDFieldIndex{
					Field: "EvalID",
				},
			},
		},
	}
}

// vaultAccessorTableSchema returns the MemDB schema for the Vault Accessor
// Table. This table tracks Vault accessors for tokens created on behalf of
// allocations required Vault tokens.
func vaultAccessorTableSchema() *memdb.TableSchema {
	return &memdb.TableSchema{
		Name: "vault_accessors",
		Indexes: map[string]*memdb.IndexSchema{
			// The primary index is the accessor id
			"id": &memdb.IndexSchema{
				Name:         "id",
				AllowMissing: false,
				Unique:       true,
				Indexer: &memdb.StringFieldIndex{
					Field: "Accessor",
				},
			},

			"alloc_id": &memdb.IndexSchema{
				Name:         "alloc_id",
				AllowMissing: false,
				Unique:       false,
				Indexer: &memdb.StringFieldIndex{
					Field: "AllocID",
				},
			},

			"node_id": &memdb.IndexSchema{
				Name:         "node_id",
				AllowMissing: false,
				Unique:       false,
				Indexer: &memdb.StringFieldIndex{
					Field: "NodeID",
				},
			},
		},
	}
}
<|endoftext|>


<commit_before>package capabilities

import (
	"context"
	"encoding/json"
	"fmt"
	"net/http"
	"sort"

	"github.com/Azure/azure-sdk-for-go/services/containerservice/mgmt/2017-09-30/containerservice"
	"github.com/Azure/go-autorest/autorest"
	"github.com/Azure/go-autorest/autorest/adal"
	"github.com/Azure/go-autorest/autorest/azure"
	"github.com/mcuadros/go-version"
)

func NewAKSVersionsHandler() *AKSVersionHandler {
	return &AKSVersionHandler{}
}

type AKSVersionHandler struct {
}

type regionCapabilitiesRequestBody struct {
	// BaseURL specifies the Azure Resource management endpoint, it defaults "https://management.azure.com/".
	BaseURL string `json:"baseUrl"`
	// AuthBaseURL specifies the Azure OAuth 2.0 authentication endpoint, it defaults "https://login.microsoftonline.com/".
	AuthBaseURL string `json:"authBaseUrl"`
	// credentials
	ClientID       string `json:"clientId"`
	ClientSecret   string `json:"clientSecret"`
	SubscriptionID string `json:"subscriptionId"`
	TenantID       string `json:"tenantId"`

	Region string `json:"region"`
}

func (g *AKSVersionHandler) ServeHTTP(writer http.ResponseWriter, req *http.Request) {
	if req.Method != http.MethodPost {
		writer.WriteHeader(http.StatusMethodNotAllowed)
		return
	}

	writer.Header().Set("Content-Type", "application/json")

	var body regionCapabilitiesRequestBody
	if err := extractRequestBody(writer, req, &body); err != nil {
		handleErr(writer, err)
		return
	}

	if err := validateRegionRequestBody(writer, &body); err != nil {
		handleErr(writer, err)
		return
	}

	region := body.Region

	clientID := body.ClientID
	clientSecret := body.ClientSecret
	subscriptionID := body.SubscriptionID
	tenantID := body.TenantID

	baseURL := body.BaseURL
	authBaseURL := body.AuthBaseURL
	if baseURL == "" {
		baseURL = azure.PublicCloud.ResourceManagerEndpoint
	}
	if authBaseURL == "" {
		authBaseURL = azure.PublicCloud.ActiveDirectoryEndpoint
	}

	oAuthConfig, err := adal.NewOAuthConfig(authBaseURL, tenantID)
	if err != nil {
		writer.WriteHeader(http.StatusBadRequest)
		handleErr(writer, fmt.Errorf("failed to configure azure oaith: %v", err))
		return
	}

	spToken, err := adal.NewServicePrincipalToken(*oAuthConfig, clientID, clientSecret, baseURL)
	if err != nil {
		writer.WriteHeader(http.StatusBadRequest)
		handleErr(writer, fmt.Errorf("failed to create token: %v", err))
		return
	}

	authorizer := autorest.NewBearerAuthorizer(spToken)

	client := containerservice.NewContainerServicesClientWithBaseURI(baseURL, subscriptionID)
	client.Authorizer = authorizer

	orchestrators, err := client.ListOrchestrators(context.Background(), region, "managedClusters")
	if err != nil {
		writer.WriteHeader(http.StatusBadRequest)
		handleErr(writer, fmt.Errorf("failed to get orchestrators: %v", err))
		return
	}

	if orchestrators.Orchestrators == nil {
		writer.WriteHeader(http.StatusBadRequest)
		handleErr(writer, fmt.Errorf("no version profiles returned: %v", err))
		return
	}

	var kubernetesVersions []string

	for _, profile := range *orchestrators.Orchestrators {
		if profile.OrchestratorType == nil || profile.OrchestratorVersion == nil {
			writer.WriteHeader(http.StatusInternalServerError)
			handleErr(writer, fmt.Errorf("unexpected nil orchestrator type or version"))
			return
		}

		if *profile.OrchestratorType == "Kubernetes" {
			kubernetesVersions = append(kubernetesVersions, *profile.OrchestratorVersion)
		}
	}

	sort.Sort(sortableVersion(kubernetesVersions))

	serialized, err := json.Marshal(kubernetesVersions)
	if err != nil {
		writer.WriteHeader(http.StatusInternalServerError)
		handleErr(writer, err)
		return
	}

	writer.Write(serialized)
}

type sortableVersion []string

func (s sortableVersion) Len() int {
	return len(s)
}

func (s sortableVersion) Swap(a, b int) {
	s[a], s[b] = s[b], s[a]
}

func (s sortableVersion) Less(a, b int) bool {
	return version.Compare(s[a], s[b], "<")
}

func validateRegionRequestBody(writer http.ResponseWriter, body *regionCapabilitiesRequestBody) error {
	region := body.Region

	clientID := body.ClientID
	clientSecret := body.ClientSecret
	subscriptionID := body.SubscriptionID
	tenantID := body.TenantID

	if region == "" {
		writer.WriteHeader(http.StatusBadRequest)
		return fmt.Errorf("invalid region")
	}

	if clientID == "" {
		writer.WriteHeader(http.StatusBadRequest)
		return fmt.Errorf("invalid clientID")
	}

	if clientSecret == "" {
		writer.WriteHeader(http.StatusBadRequest)
		return fmt.Errorf("invalid clientSecret")
	}

	if subscriptionID == "" {
		writer.WriteHeader(http.StatusBadRequest)
		return fmt.Errorf("invalid subscriptionID")
	}

	if tenantID == "" {
		writer.WriteHeader(http.StatusBadRequest)
		return fmt.Errorf("invalid tenantID")
	}

	return nil
}
<commit_msg>Simple refactor validateRegionRequestBody<commit_after>package capabilities

import (
	"context"
	"encoding/json"
	"fmt"
	"net/http"
	"sort"

	"github.com/Azure/azure-sdk-for-go/services/containerservice/mgmt/2017-09-30/containerservice"
	"github.com/Azure/go-autorest/autorest"
	"github.com/Azure/go-autorest/autorest/adal"
	"github.com/Azure/go-autorest/autorest/azure"
	"github.com/mcuadros/go-version"
)

func NewAKSVersionsHandler() *AKSVersionHandler {
	return &AKSVersionHandler{}
}

type AKSVersionHandler struct {
}

type regionCapabilitiesRequestBody struct {
	// BaseURL specifies the Azure Resource management endpoint, it defaults "https://management.azure.com/".
	BaseURL string `json:"baseUrl"`
	// AuthBaseURL specifies the Azure OAuth 2.0 authentication endpoint, it defaults "https://login.microsoftonline.com/".
	AuthBaseURL string `json:"authBaseUrl"`
	// credentials
	ClientID       string `json:"clientId"`
	ClientSecret   string `json:"clientSecret"`
	SubscriptionID string `json:"subscriptionId"`
	TenantID       string `json:"tenantId"`

	Region string `json:"region"`
}

func (g *AKSVersionHandler) ServeHTTP(writer http.ResponseWriter, req *http.Request) {
	if req.Method != http.MethodPost {
		writer.WriteHeader(http.StatusMethodNotAllowed)
		return
	}

	writer.Header().Set("Content-Type", "application/json")

	var body regionCapabilitiesRequestBody
	if err := extractRequestBody(writer, req, &body); err != nil {
		handleErr(writer, err)
		return
	}

	if err := validateRegionRequestBody(writer, &body); err != nil {
		handleErr(writer, err)
		return
	}

	region := body.Region

	clientID := body.ClientID
	clientSecret := body.ClientSecret
	subscriptionID := body.SubscriptionID
	tenantID := body.TenantID

	baseURL := body.BaseURL
	authBaseURL := body.AuthBaseURL
	if baseURL == "" {
		baseURL = azure.PublicCloud.ResourceManagerEndpoint
	}
	if authBaseURL == "" {
		authBaseURL = azure.PublicCloud.ActiveDirectoryEndpoint
	}

	oAuthConfig, err := adal.NewOAuthConfig(authBaseURL, tenantID)
	if err != nil {
		writer.WriteHeader(http.StatusBadRequest)
		handleErr(writer, fmt.Errorf("failed to configure azure oaith: %v", err))
		return
	}

	spToken, err := adal.NewServicePrincipalToken(*oAuthConfig, clientID, clientSecret, baseURL)
	if err != nil {
		writer.WriteHeader(http.StatusBadRequest)
		handleErr(writer, fmt.Errorf("failed to create token: %v", err))
		return
	}

	authorizer := autorest.NewBearerAuthorizer(spToken)

	client := containerservice.NewContainerServicesClientWithBaseURI(baseURL, subscriptionID)
	client.Authorizer = authorizer

	orchestrators, err := client.ListOrchestrators(context.Background(), region, "managedClusters")
	if err != nil {
		writer.WriteHeader(http.StatusBadRequest)
		handleErr(writer, fmt.Errorf("failed to get orchestrators: %v", err))
		return
	}

	if orchestrators.Orchestrators == nil {
		writer.WriteHeader(http.StatusBadRequest)
		handleErr(writer, fmt.Errorf("no version profiles returned: %v", err))
		return
	}

	var kubernetesVersions []string

	for _, profile := range *orchestrators.Orchestrators {
		if profile.OrchestratorType == nil || profile.OrchestratorVersion == nil {
			writer.WriteHeader(http.StatusInternalServerError)
			handleErr(writer, fmt.Errorf("unexpected nil orchestrator type or version"))
			return
		}

		if *profile.OrchestratorType == "Kubernetes" {
			kubernetesVersions = append(kubernetesVersions, *profile.OrchestratorVersion)
		}
	}

	sort.Sort(sortableVersion(kubernetesVersions))

	serialized, err := json.Marshal(kubernetesVersions)
	if err != nil {
		writer.WriteHeader(http.StatusInternalServerError)
		handleErr(writer, err)
		return
	}

	writer.Write(serialized)
}

type sortableVersion []string

func (s sortableVersion) Len() int {
	return len(s)
}

func (s sortableVersion) Swap(a, b int) {
	s[a], s[b] = s[b], s[a]
}

func (s sortableVersion) Less(a, b int) bool {
	return version.Compare(s[a], s[b], "<")
}

func validateRegionRequestBody(writer http.ResponseWriter, body *regionCapabilitiesRequestBody) error {
	toCheck := map[string]string{
		"region":         body.Region,
		"clientID":       body.ClientID,
		"clientSecret":   body.ClientSecret,
		"subscriptionID": body.SubscriptionID,
		"tenantID":       body.TenantID,
	}
	for k, v := range toCheck {
		if v == "" {
			writer.WriteHeader(http.StatusBadRequest)
			return fmt.Errorf("invalid %s", k)
		}
	}

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
	"log"
	"math/rand"
	"net/http"
	"runtime"
	"strconv"
)

const (
	connectionString = "localhost"
	helloWorldString = "Hello, world!"
	worldRowCount    = 10000
)

var (
	collection *mgo.Collection
	database   *mgo.Database
)

type Message struct {
	Message string `json:"message"`
}

type World struct {
	Id           uint16 `json:"id"`
	RandomNumber uint16 `json:"randomNumber"`
}

type Fortune struct {
	Id      uint16 `json:"id"`
	Message string `json:"message"`
}

func main() {
	port := ":8228"
	runtime.GOMAXPROCS(runtime.NumCPU())
	if session, err := mgo.Dial(connectionString); err != nil {
		log.Fatalf("Error opening database: %v", err)
	} else {
		defer session.Close()
		session.SetPoolLimit(5)
		database = session.DB("hello_world")
		collection = database.C("world")
		http.HandleFunc("/json", jsonHandler)
		http.HandleFunc("/db", dbHandler)
		http.HandleFunc("queries", queriesHandler)
		http.HandleFunc("/update", updateHandler)
		http.HandleFunc("/plaintext", plaintextHandler)
		fmt.Println("Serving on http://localhost" + port)
		http.ListenAndServe(port, nil)
	}
}

// Helper for random numbers
func getRandomNumber() int {
	return rand.Intn(worldRowCount) + 1
}

// Test 1: JSON serialization
func jsonHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/javascript")
	json.NewEncoder(w).Encode(&Message{helloWorldString})
}

func dbHandler(w http.ResponseWriter, r *http.Request) {
	var world World
	query := bson.M{"id": getRandomNumber()}
	if collection != nil {
		if err := collection.Find(query).One(&world); err != nil {
			log.Fatalf("Error finding world with id: %s", err.Error())
			return
		} else {
			w.Header().Set("Content-Type", "application/json")
			json.NewEncoder(w).Encode(&world)
			return
		}
	} else {
		log.Fatal("Collection not initialized properly")
	}
}

func queriesHandler(w http.ResponseWriter, r *http.Request) {
	n := 1
	if nStr := r.URL.Query().Get("queries"); len(nStr) > 0 {
		n, _ = strconv.Atoi(nStr)
	}

	if n <= 1 {
		dbHandler(w, r)
		return
	} else if n > 500 {
		n = 500
	}

	worlds := make([]World, n)
	for _, world := range worlds {
		query := bson.M{"id": getRandomNumber()}
		if err := collection.Find(query).One(&world); err != nil {
			log.Fatalf("Error finding world with id: %s", err.Error())
			return
		}
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(worlds)
}

func updateHandler(w http.ResponseWriter, r *http.Request) {
	n := 1
	if nStr := r.URL.Query().Get("queries"); len(nStr) > 0 {
		n, _ = strconv.Atoi(nStr)
	}

	w.Header().Set("Content-Type", "application/json")
	encoder := json.NewEncoder(w)

	if n <= 1 {
		var world World
		colQuery := bson.M{"id": getRandomNumber()}
		update := bson.M{"$set": bson.M{"randomNumber": getRandomNumber()}}
		if err := collection.Update(colQuery, update); err != nil {
			log.Fatalf("Error updating world with id: %s", err.Error())
		} else {
			world.Id = colQuery["id"]
			world.RandomNumber = update["$set"].(bson.M)["randomNumber"]
		}
		encoder.Encode(world)
	} else {
		if n > 500 {
			n = 500
		}
		worlds := make([]World, n)
		for _, world := range worlds {
			colQuery := bson.M{"id": getRandomNumber()}
			update := bson.M{"$set": bson.M{"randomNumber": getRandomNumber()}}
			if err := collection.Update(colQuery, update); err != nil {
				log.Fatalf("Error updating world with id: %s", err.Error())
			} else {
				world.Id = colQuery["id"]
				world.RandomNumber = update["$set"].(bson.M)["randomNumber"]
			}
		}
		encoder.Encode(worlds)
	}
}

func plaintextHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "text/plain")
	w.Write([]byte("Hello, World!"))
}
<commit_msg>Added uint16 type assertion<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
	"log"
	"math/rand"
	"net/http"
	"runtime"
	"strconv"
)

const (
	connectionString = "localhost"
	helloWorldString = "Hello, world!"
	worldRowCount    = 10000
)

var (
	collection *mgo.Collection
	database   *mgo.Database
)

type Message struct {
	Message string `json:"message"`
}

type World struct {
	Id           uint16 `json:"id"`
	RandomNumber uint16 `json:"randomNumber"`
}

type Fortune struct {
	Id      uint16 `json:"id"`
	Message string `json:"message"`
}

func main() {
	port := ":8228"
	runtime.GOMAXPROCS(runtime.NumCPU())
	if session, err := mgo.Dial(connectionString); err != nil {
		log.Fatalf("Error opening database: %v", err)
	} else {
		defer session.Close()
		session.SetPoolLimit(5)
		database = session.DB("hello_world")
		collection = database.C("world")
		http.HandleFunc("/json", jsonHandler)
		http.HandleFunc("/db", dbHandler)
		http.HandleFunc("queries", queriesHandler)
		http.HandleFunc("/update", updateHandler)
		http.HandleFunc("/plaintext", plaintextHandler)
		fmt.Println("Serving on http://localhost" + port)
		http.ListenAndServe(port, nil)
	}
}

// Helper for random numbers
func getRandomNumber() int {
	return rand.Intn(worldRowCount) + 1
}

// Test 1: JSON serialization
func jsonHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/javascript")
	json.NewEncoder(w).Encode(&Message{helloWorldString})
}

func dbHandler(w http.ResponseWriter, r *http.Request) {
	var world World
	query := bson.M{"id": getRandomNumber()}
	if collection != nil {
		if err := collection.Find(query).One(&world); err != nil {
			log.Fatalf("Error finding world with id: %s", err.Error())
			return
		} else {
			w.Header().Set("Content-Type", "application/json")
			json.NewEncoder(w).Encode(&world)
			return
		}
	} else {
		log.Fatal("Collection not initialized properly")
	}
}

func queriesHandler(w http.ResponseWriter, r *http.Request) {
	n := 1
	if nStr := r.URL.Query().Get("queries"); len(nStr) > 0 {
		n, _ = strconv.Atoi(nStr)
	}

	if n <= 1 {
		dbHandler(w, r)
		return
	} else if n > 500 {
		n = 500
	}

	worlds := make([]World, n)
	for _, world := range worlds {
		query := bson.M{"id": getRandomNumber()}
		if err := collection.Find(query).One(&world); err != nil {
			log.Fatalf("Error finding world with id: %s", err.Error())
			return
		}
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(worlds)
}

func updateHandler(w http.ResponseWriter, r *http.Request) {
	n := 1
	if nStr := r.URL.Query().Get("queries"); len(nStr) > 0 {
		n, _ = strconv.Atoi(nStr)
	}

	w.Header().Set("Content-Type", "application/json")
	encoder := json.NewEncoder(w)

	if n <= 1 {
		var world World
		colQuery := bson.M{"id": getRandomNumber()}
		update := bson.M{"$set": bson.M{"randomNumber": getRandomNumber()}}
		if err := collection.Update(colQuery, update); err != nil {
			log.Fatalf("Error updating world with id: %s", err.Error())
		} else {
			world.Id = colQuery["id"].(uint16)
			world.RandomNumber = update["$set"].(bson.M)["randomNumber"].(uint16)
		}
		encoder.Encode(world)
	} else {
		if n > 500 {
			n = 500
		}
		worlds := make([]World, n)
		for _, world := range worlds {
			colQuery := bson.M{"id": getRandomNumber()}
			update := bson.M{"$set": bson.M{"randomNumber": getRandomNumber()}}
			if err := collection.Update(colQuery, update); err != nil {
				log.Fatalf("Error updating world with id: %s", err.Error())
			} else {
				world.Id = colQuery["id"].(uint16)
				world.RandomNumber = update["$set"].(bson.M)["randomNumber"].(uint16)
			}
		}
		encoder.Encode(worlds)
	}
}

func plaintextHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "text/plain")
	w.Write([]byte("Hello, World!"))
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
	"html/template"
	"log"
	"math/rand"
	"net/http"
	"runtime"
	"sort"
	"strconv"
)

const (
	connectionString = "localhost"
	helloWorldString = "Hello, world!"
	worldRowCount    = 10000
)

var (
	tmpl = template.Must(template.ParseFiles("templates/layout.html", "templates/fortune.html"))

	database *mgo.Database
	fortunes *mgo.Collection
	worlds   *mgo.Collection
)

type Message struct {
	Message string `json:"message"`
}

type World struct {
	Id           uint16 `json:"id"`
	RandomNumber uint16 `json:"randomNumber"`
}

type Fortune struct {
	Id      uint16 `json:"id"`
	Message string `json:"message"`
}

type Fortunes []Fortune

func (s Fortunes) Len() int {
	return len(s)
}

func (s Fortunes) Swap(i, j int) {
	s[i], s[j] = s[j], s[i]
}

type ByMessage struct{ Fortunes }

func (s ByMessage) Less(i, j int) bool {
	return s.Fortunes[i].Message < s.Fortunes[j].Message
}

func main() {
	port := ":8228"
	runtime.GOMAXPROCS(runtime.NumCPU())
	if session, err := mgo.Dial(connectionString); err != nil {
		log.Fatalf("Error opening database: %v", err)
	} else {
		defer session.Close()
		session.SetPoolLimit(5)
		database = session.DB("hello_world")
		worlds = database.C("world")
		fortunes = database.C("fortune")
		http.HandleFunc("/json", jsonHandler)
		http.HandleFunc("/db", dbHandler)
		http.HandleFunc("queries", queriesHandler)
		http.HandleFunc("/update", updateHandler)
		http.HandleFunc("/plaintext", plaintextHandler)
		fmt.Println("Serving on http://localhost" + port)
		http.ListenAndServe(port, nil)
	}
}

// Helper for random numbers
func getRandomNumber() int {
	return rand.Intn(worldRowCount) + 1
}

// Test 1: JSON serialization
func jsonHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/javascript")
	json.NewEncoder(w).Encode(&Message{helloWorldString})
}

func dbHandler(w http.ResponseWriter, r *http.Request) {
	var world World
	query := bson.M{"id": getRandomNumber()}
	if worlds != nil {
		if err := worlds.Find(query).One(&world); err != nil {
			log.Fatalf("Error finding world with id: %s", err.Error())
			return
		} else {
			w.Header().Set("Content-Type", "application/json")
			json.NewEncoder(w).Encode(&world)
			return
		}
	} else {
		log.Fatal("Collection not initialized properly")
	}
}

func queriesHandler(w http.ResponseWriter, r *http.Request) {
	n := 1
	if nStr := r.URL.Query().Get("queries"); len(nStr) > 0 {
		n, _ = strconv.Atoi(nStr)
	}

	if n <= 1 {
		dbHandler(w, r)
		return
	} else if n > 500 {
		n = 500
	}

	result := make([]World, n)
	for _, world := range result {
		query := bson.M{"id": getRandomNumber()}
		if err := worlds.Find(query).One(&world); err != nil {
			log.Fatalf("Error finding world with id: %s", err.Error())
			return
		}
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(result)
}

func fortuneHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "text/html")
	f := make(Fortunes, 16)
	if err := fortunes.Find(nil).All(&f); err == nil {
		f = append(f, Fortune{
			Message: "Additional fortune added at request time.",
		})
		sort.Sort(ByMessage{f})
		if err := tmpl.Execute(w, f); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
		}
	}

}

func updateHandler(w http.ResponseWriter, r *http.Request) {
	n := 1
	if nStr := r.URL.Query().Get("queries"); len(nStr) > 0 {
		n, _ = strconv.Atoi(nStr)
	}

	w.Header().Set("Content-Type", "application/json")
	encoder := json.NewEncoder(w)

	if n <= 1 {
		var world World
		colQuery := bson.M{"id": getRandomNumber()}
		update := bson.M{"$set": bson.M{"randomNumber": getRandomNumber()}}
		if err := worlds.Update(colQuery, update); err != nil {
			log.Fatalf("Error updating world with id: %s", err.Error())
		} else {
			world.Id = colQuery["id"].(uint16)
			world.RandomNumber = update["$set"].(bson.M)["randomNumber"].(uint16)
		}
		encoder.Encode(world)
	} else {
		if n > 500 {
			n = 500
		}
		worlds := make([]World, n)
		for _, world := range worlds {
			colQuery := bson.M{"id": getRandomNumber()}
			update := bson.M{"$set": bson.M{"randomNumber": getRandomNumber()}}
			if err := worlds.Update(colQuery, update); err != nil {
				log.Fatalf("Error updating world with id: %s", err.Error())
			} else {
				world.Id = colQuery["id"].(uint16)
				world.RandomNumber = update["$set"].(bson.M)["randomNumber"].(uint16)
			}
		}
		encoder.Encode(worlds)
	}
}

func plaintextHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "text/plain")
	w.Write([]byte("Hello, World!"))
}
<commit_msg>Some more cleanup<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
	"html/template"
	"log"
	"math/rand"
	"net/http"
	"runtime"
	"sort"
	"strconv"
)

const (
	connectionString = "localhost"
	helloWorldString = "Hello, world!"
	worldRowCount    = 10000
)

var (
	tmpl = template.Must(template.ParseFiles("templates/layout.html", "templates/fortune.html"))

	database *mgo.Database
	fortunes *mgo.Collection
	worlds   *mgo.Collection
)

type Message struct {
	Message string `json:"message"`
}

type World struct {
	Id           uint16 `json:"id"`
	RandomNumber uint16 `json:"randomNumber"`
}

type Fortune struct {
	Id      uint16 `json:"id"`
	Message string `json:"message"`
}

type Fortunes []Fortune

func (s Fortunes) Len() int {
	return len(s)
}

func (s Fortunes) Swap(i, j int) {
	s[i], s[j] = s[j], s[i]
}

type ByMessage struct{ Fortunes }

func (s ByMessage) Less(i, j int) bool {
	return s.Fortunes[i].Message < s.Fortunes[j].Message
}

func main() {
	port := ":8228"
	runtime.GOMAXPROCS(runtime.NumCPU())
	if session, err := mgo.Dial(connectionString); err != nil {
		log.Fatalf("Error opening database: %v", err)
	} else {
		defer session.Close()
		session.SetPoolLimit(5)
		database = session.DB("hello_world")
		worlds = database.C("world")
		fortunes = database.C("fortune")
		http.HandleFunc("/json", jsonHandler)
		http.HandleFunc("/db", dbHandler)
		http.HandleFunc("queries", queriesHandler)
		http.HandleFunc("/update", updateHandler)
		http.HandleFunc("/plaintext", plaintextHandler)
		fmt.Println("Serving on http://localhost" + port)
		http.ListenAndServe(port, nil)
	}
}

// Helper for random numbers
func getRandomNumber() int {
	return rand.Intn(worldRowCount) + 1
}

// Test 1: JSON serialization
func jsonHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/javascript")
	json.NewEncoder(w).Encode(&Message{helloWorldString})
}

func dbHandler(w http.ResponseWriter, r *http.Request) {
	var world World
	query := bson.M{"id": getRandomNumber()}
	if worlds != nil {
		if err := worlds.Find(query).One(&world); err != nil {
			log.Fatalf("Error finding world with id: %s", err.Error())
			return
		} else {
			w.Header().Set("Content-Type", "application/json")
			json.NewEncoder(w).Encode(&world)
			return
		}
	} else {
		log.Fatal("Collection not initialized properly")
	}
}

func queriesHandler(w http.ResponseWriter, r *http.Request) {
	n := 1
	if nStr := r.URL.Query().Get("queries"); len(nStr) > 0 {
		n, _ = strconv.Atoi(nStr)
	}

	if n <= 1 {
		dbHandler(w, r)
		return
	} else if n > 500 {
		n = 500
	}

	result := make([]World, n)
	for _, world := range result {
		query := bson.M{"id": getRandomNumber()}
		if err := worlds.Find(query).One(&world); err != nil {
			log.Fatalf("Error finding world with id: %s", err.Error())
			return
		}
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(result)
}

func fortuneHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "text/html")
	f := make(Fortunes, 16)
	if err := fortunes.Find(nil).All(&f); err == nil {
		f = append(f, Fortune{
			Message: "Additional fortune added at request time.",
		})
		sort.Sort(ByMessage{f})
		if err := tmpl.Execute(w, f); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
		}
	}

}

func updateHandler(w http.ResponseWriter, r *http.Request) {
	n := 1
	if nStr := r.URL.Query().Get("queries"); len(nStr) > 0 {
		n, _ = strconv.Atoi(nStr)
	}

	w.Header().Set("Content-Type", "application/json")
	encoder := json.NewEncoder(w)

	if n <= 1 {
		var world World
		colQuery := bson.M{"id": getRandomNumber()}
		update := bson.M{"$set": bson.M{"randomNumber": getRandomNumber()}}
		if err := worlds.Update(colQuery, update); err != nil {
			log.Fatalf("Error updating world with id: %s", err.Error())
		} else {
			world.Id = colQuery["id"].(uint16)
			world.RandomNumber = update["$set"].(bson.M)["randomNumber"].(uint16)
		}
		encoder.Encode(world)
	} else {
		if n > 500 {
			n = 500
		}
		result := make([]World, n)
		for _, world := range result {
			colQuery := bson.M{"id": getRandomNumber()}
			update := bson.M{"$set": bson.M{"randomNumber": getRandomNumber()}}
			if err := worlds.Update(colQuery, update); err != nil {
				log.Fatalf("Error updating world with id: %s", err.Error())
			} else {
				world.Id = colQuery["id"].(uint16)
				world.RandomNumber = update["$set"].(bson.M)["randomNumber"].(uint16)
			}
		}
		encoder.Encode(result)
	}
}

func plaintextHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "text/plain")
	w.Write([]byte(helloWorldString))
}
<|endoftext|>


<commit_before>package xsdgen

import (
	"io/ioutil"
	"os"
	"path/filepath"
	"testing"
)

func glob(dir ...string) []string {
	files, err := filepath.Glob(filepath.Join(dir...))
	if err != nil {
		panic("error in glob util function: " + err.Error())
	}
	return files
}

type testLogger testing.T

func (t *testLogger) Printf(format string, v ...interface{}) {
	t.Logf(format, v...)
}

func TestLibrarySchema(t *testing.T) {
	testGen(t, "http://dyomedea.com/ns/library", "testdata/library.xsd")
}
func TestPurchasOrderSchema(t *testing.T) {
	testGen(t, "http://www.example.com/PO1", "testdata/po1.xsd")
}
func TestUSTreasureSDN(t *testing.T) {
	testGen(t, "http://tempuri.org/sdnList.xsd", "testdata/sdn.xsd")
}

func testGen(t *testing.T, ns string, files ...string) {
	file, err := ioutil.TempFile("", "xsdgen")
	if err != nil {
		t.Fatal(err)
	}
	defer os.Remove(file.Name())

	var cfg Config
	cfg.Option(DefaultOptions...)
	cfg.Option(LogOutput((*testLogger)(t)))

	args := []string{"-v", "-o", file.Name(), "-ns", ns}
	err = cfg.GenCLI(append(args, files...)...)
	if err != nil {
		t.Error(err)
	}
	if data, err := ioutil.ReadFile(file.Name()); err != nil {
		t.Error(err)
	} else {
		t.Logf("\n%s\n", data)
	}
}
<commit_msg>Add test case for SOAP 1.1 schema<commit_after>package xsdgen

import (
	"io/ioutil"
	"os"
	"path/filepath"
	"testing"
)

func glob(dir ...string) []string {
	files, err := filepath.Glob(filepath.Join(dir...))
	if err != nil {
		panic("error in glob util function: " + err.Error())
	}
	return files
}

type testLogger testing.T

func (t *testLogger) Printf(format string, v ...interface{}) {
	t.Logf(format, v...)
}

func TestLibrarySchema(t *testing.T) {
	testGen(t, "http://dyomedea.com/ns/library", "testdata/library.xsd")
}
func TestPurchasOrderSchema(t *testing.T) {
	testGen(t, "http://www.example.com/PO1", "testdata/po1.xsd")
}
func TestUSTreasureSDN(t *testing.T) {
	testGen(t, "http://tempuri.org/sdnList.xsd", "testdata/sdn.xsd")
}
func TestSoap(t *testing.T) {
	testGen(t, "http://schemas.xmlsoap.org/soap/encoding/", "testdata/soap11.xsd")
}

func testGen(t *testing.T, ns string, files ...string) {
	file, err := ioutil.TempFile("", "xsdgen")
	if err != nil {
		t.Fatal(err)
	}
	defer os.Remove(file.Name())

	var cfg Config
	cfg.Option(DefaultOptions...)
	cfg.Option(LogOutput((*testLogger)(t)))

	args := []string{"-v", "-o", file.Name(), "-ns", ns}
	err = cfg.GenCLI(append(args, files...)...)
	if err != nil {
		t.Error(err)
	}
	if data, err := ioutil.ReadFile(file.Name()); err != nil {
		t.Error(err)
	} else {
		t.Logf("\n%s\n", data)
	}
}
<|endoftext|>


<commit_before>package brightbox

import (
	"fmt"
	"log"
	"strings"
	"time"

	"github.com/brightbox/gobrightbox"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/helper/schema"
)

const (
	mapped   = "mapped"
	unmapped = "unmapped"
)

func resourceBrightboxCloudip() *schema.Resource {
	return &schema.Resource{
		Create: resourceBrightboxCloudipCreate,
		Read:   resourceBrightboxCloudipRead,
		Update: resourceBrightboxCloudipUpdate,
		Delete: resourceBrightboxCloudipDelete,
		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},

		Schema: map[string]*schema.Schema{
			"name": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
			},

			"target": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
			},

			"status": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},

			"locked": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},

			"public_ip": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},

			"fqdn": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},

			"reverse_dns": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},
		},
	}
}

func resourceBrightboxCloudipCreate(
	d *schema.ResourceData,
	meta interface{},
) error {
	client := meta.(*CompositeClient).ApiClient

	log.Printf("[INFO] Creating CloudIP")
	cloudip_opts := &brightbox.CloudIPOptions{}
	err := addUpdateableCloudipOptions(d, cloudip_opts)
	if err != nil {
		return err
	}

	cloudip, err := client.CreateCloudIP(cloudip_opts)
	if err != nil {
		return fmt.Errorf("Error creating Cloud IP: %s", err)
	}

	d.SetId(cloudip.Id)

	if target_id, ok := d.GetOk("target"); ok {
		cloudip, err = assignCloudIP(client, cloudip.Id, target_id.(string))
		if err != nil {
			return err
		}
	}

	setCloudipAttributes(d, cloudip)

	return nil
}

func assignCloudIP(
	client *brightbox.Client,
	cloudip_id string,
	target_id string,
) (*brightbox.CloudIP, error) {
	log.Printf("[INFO] Assigning Cloud IP %s to target %s", cloudip_id, target_id)
	err := client.MapCloudIP(cloudip_id, target_id)
	if err != nil {
		return nil, fmt.Errorf("Error assigning Cloud IP %s to target %s: %s", cloudip_id, target_id, err)
	}
	cloudip, err := waitForMappedCloudIp(client, cloudip_id)
	if err != nil {
		return nil, err
	}
	return cloudip, err
}

func unmapCloudIP(
	client *brightbox.Client,
	cloudip_id string,
) error {
	log.Printf("[INFO] Checking mapping of Cloud IP %s", cloudip_id)
	cloudip, err := client.CloudIP(cloudip_id)
	if err != nil {
		return fmt.Errorf("Error retrieving details of Cloud IP %s: %s", cloudip_id, err)
	}
	if cloudip.Status == mapped {
		log.Printf("[INFO] Unmapping Cloud IP %s", cloudip_id)
		err := client.UnMapCloudIP(cloudip_id)
		if err != nil {
			return fmt.Errorf("Error unmapping Cloud IP %s: %s", cloudip_id, err)
		}
		_, err = waitForUnmappedCloudIp(client, cloudip_id)
		if err != nil {
			return err
		}
	} else {
		log.Printf("[DEBUG] Cloud IP %s is already unmapped", cloudip_id)
	}
	return nil
}

func waitForCloudip(
	client *brightbox.Client,
	cloudip_id string,
	pending string,
	target string,
) (*brightbox.CloudIP, error) {
	stateConf := resource.StateChangeConf{
		Pending:    []string{pending},
		Target:     []string{target},
		Refresh:    cloudipStateRefresh(client, cloudip_id),
		Timeout:    5 * time.Minute,
		MinTimeout: 3 * time.Second,
	}

	active_cloudip, err := stateConf.WaitForState()
	if err != nil {
		return nil, err
	}

	return active_cloudip.(*brightbox.CloudIP), err
}

func waitForMappedCloudIp(
	client *brightbox.Client,
	cloudip_id string,
) (*brightbox.CloudIP, error) {
	return waitForCloudip(client, cloudip_id, unmapped, mapped)
}

func waitForUnmappedCloudIp(
	client *brightbox.Client,
	cloudip_id string,
) (*brightbox.CloudIP, error) {
	return waitForCloudip(client, cloudip_id, mapped, unmapped)
}

func cloudipStateRefresh(client *brightbox.Client, cloudip_id string) resource.StateRefreshFunc {
	return func() (interface{}, string, error) {
		cloudip, err := client.CloudIP(cloudip_id)
		if err != nil {
			log.Printf("Error on Cloud IP State Refresh: %s", err)
			return nil, "", err
		}
		return cloudip, cloudip.Status, nil
	}
}

func setCloudipAttributes(
	d *schema.ResourceData,
	cloudip *brightbox.CloudIP,
) {
	d.Set("name", cloudip.Name)
	d.Set("public_ip", cloudip.PublicIP)
	d.Set("status", cloudip.Status)
	d.Set("locked", cloudip.Locked)
	d.Set("reverse_dns", cloudip.ReverseDns)
	d.Set("fqdn", cloudip.Fqdn)

}

func resourceBrightboxCloudipRead(
	d *schema.ResourceData,
	meta interface{},
) error {
	client := meta.(*CompositeClient).ApiClient

	cloudip, err := client.CloudIP(d.Id())
	if err != nil {
		if strings.HasPrefix(err.Error(), "missing_resource:") {
			log.Printf("[WARN] CloudIP not found, removing from state: %s", d.Id())
			d.SetId("")
			return nil
		}
		return fmt.Errorf("Error retrieving Cloud IP details: %s", err)
	}

	setCloudipAttributes(d, cloudip)

	return nil
}

func resourceBrightboxCloudipDelete(
	d *schema.ResourceData,
	meta interface{},
) error {
	client := meta.(*CompositeClient).ApiClient
	return removeCloudIP(client, d.Id())
}

func removeCloudIP(client *brightbox.Client, id string) error {
	log.Printf("[DEBUG] Unmapping Cloud IP %s", id)
	err := unmapCloudIP(client, id)
	if err != nil {
		return err
	}
	log.Printf("[INFO] Deleting Cloud IP %s", id)
	err = client.DestroyCloudIP(id)
	if err != nil {
		return fmt.Errorf("Error deleting Cloud IP (%s): %s", id, err)
	}
	return nil
}

func resourceBrightboxCloudipUpdate(
	d *schema.ResourceData,
	meta interface{},
) error {
	client := meta.(*CompositeClient).ApiClient

	d.Partial(true)

	if d.HasChange("target") {
		err := unmapCloudIP(client, d.Id())
		if err != nil {
			return err
		}
		if target_id, ok := d.GetOk("target"); ok {
			_, err := assignCloudIP(client, d.Id(), target_id.(string))
			if err != nil {
				return err
			}
		}
		d.SetPartial("target")
	}

	cloudip_opts := &brightbox.CloudIPOptions{
		Id: d.Id(),
	}
	err := addUpdateableCloudipOptions(d, cloudip_opts)
	if err != nil {
		return err
	}
	log.Printf("[DEBUG] Cloud IP update configuration: %#v", cloudip_opts)

	cloudip, err := client.UpdateCloudIP(cloudip_opts)
	if err != nil {
		return fmt.Errorf("Error updating Cloud IP (%s): %s", cloudip_opts.Id, err)
	}

	setCloudipAttributes(d, cloudip)
	d.Partial(false)
	return nil
}

func addUpdateableCloudipOptions(
	d *schema.ResourceData,
	opts *brightbox.CloudIPOptions,
) error {
	assign_string(d, &opts.Name, "name")
	assign_string(d, &opts.ReverseDns, "reverse_dns")
	return nil
}
<commit_msg>Refactor Cloud Ip<commit_after>package brightbox

import (
	"fmt"
	"log"
	"strings"
	"time"

	"github.com/brightbox/gobrightbox"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/helper/schema"
)

const (
	mapped   = "mapped"
	unmapped = "unmapped"
)

func resourceBrightboxCloudip() *schema.Resource {
	return &schema.Resource{
		Create: resourceBrightboxCloudipCreate,
		Read:   resourceBrightboxCloudipRead,
		Update: resourceBrightboxCloudipUpdate,
		Delete: resourceBrightboxCloudipDelete,
		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},

		Schema: map[string]*schema.Schema{
			"name": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
			},

			"target": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
			},

			"status": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},

			"locked": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},

			"public_ip": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},

			"fqdn": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},

			"reverse_dns": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},
		},
	}
}

func resourceBrightboxCloudipCreate(
	d *schema.ResourceData,
	meta interface{},
) error {
	client := meta.(*CompositeClient).ApiClient

	log.Printf("[INFO] Creating CloudIP")
	cloudip_opts := &brightbox.CloudIPOptions{}
	err := addUpdateableCloudipOptions(d, cloudip_opts)
	if err != nil {
		return err
	}

	cloudip, err := client.CreateCloudIP(cloudip_opts)
	if err != nil {
		return fmt.Errorf("Error creating Cloud IP: %s", err)
	}

	d.SetId(cloudip.Id)

	if target_id, ok := d.GetOk("target"); ok {
		cloudip, err = assignCloudIP(client, cloudip.Id, target_id.(string))
		if err != nil {
			return err
		}
	}

	return setCloudipAttributes(d, cloudip)
}

func resourceBrightboxCloudipRead(
	d *schema.ResourceData,
	meta interface{},
) error {
	client := meta.(*CompositeClient).ApiClient

	cloudip, err := client.CloudIP(d.Id())
	if err != nil {
		if strings.HasPrefix(err.Error(), "missing_resource:") {
			log.Printf("[WARN] CloudIP not found, removing from state: %s", d.Id())
			d.SetId("")
			return nil
		}
		return fmt.Errorf("Error retrieving Cloud IP details: %s", err)
	}

	return setCloudipAttributes(d, cloudip)
}

func resourceBrightboxCloudipDelete(
	d *schema.ResourceData,
	meta interface{},
) error {
	client := meta.(*CompositeClient).ApiClient
	return removeCloudIP(client, d.Id())
}

func resourceBrightboxCloudipUpdate(
	d *schema.ResourceData,
	meta interface{},
) error {
	client := meta.(*CompositeClient).ApiClient

	d.Partial(true)

	if d.HasChange("target") {
		err := unmapCloudIP(client, d.Id())
		if err != nil {
			return err
		}
		if target_id, ok := d.GetOk("target"); ok {
			_, err := assignCloudIP(client, d.Id(), target_id.(string))
			if err != nil {
				return err
			}
		}
		d.SetPartial("target")
	}

	cloudip_opts := &brightbox.CloudIPOptions{
		Id: d.Id(),
	}
	err := addUpdateableCloudipOptions(d, cloudip_opts)
	if err != nil {
		return err
	}
	log.Printf("[DEBUG] Cloud IP update configuration: %#v", cloudip_opts)

	cloudip, err := client.UpdateCloudIP(cloudip_opts)
	if err != nil {
		return fmt.Errorf("Error updating Cloud IP (%s): %s", cloudip_opts.Id, err)
	}

	return setCloudipAttributes(d, cloudip)
}

func assignCloudIP(
	client *brightbox.Client,
	cloudip_id string,
	target_id string,
) (*brightbox.CloudIP, error) {
	log.Printf("[INFO] Assigning Cloud IP %s to target %s", cloudip_id, target_id)
	err := client.MapCloudIP(cloudip_id, target_id)
	if err != nil {
		return nil, fmt.Errorf("Error assigning Cloud IP %s to target %s: %s", cloudip_id, target_id, err)
	}
	cloudip, err := waitForMappedCloudIp(client, cloudip_id)
	if err != nil {
		return nil, err
	}
	return cloudip, err
}

func unmapCloudIP(
	client *brightbox.Client,
	cloudip_id string,
) error {
	log.Printf("[INFO] Checking mapping of Cloud IP %s", cloudip_id)
	cloudip, err := client.CloudIP(cloudip_id)
	if err != nil {
		return fmt.Errorf("Error retrieving details of Cloud IP %s: %s", cloudip_id, err)
	}
	if cloudip.Status == mapped {
		log.Printf("[INFO] Unmapping Cloud IP %s", cloudip_id)
		err := client.UnMapCloudIP(cloudip_id)
		if err != nil {
			return fmt.Errorf("Error unmapping Cloud IP %s: %s", cloudip_id, err)
		}
		_, err = waitForUnmappedCloudIp(client, cloudip_id)
		if err != nil {
			return err
		}
	} else {
		log.Printf("[DEBUG] Cloud IP %s is already unmapped", cloudip_id)
	}
	return nil
}

func waitForCloudip(
	client *brightbox.Client,
	cloudip_id string,
	pending string,
	target string,
) (*brightbox.CloudIP, error) {
	stateConf := resource.StateChangeConf{
		Pending:    []string{pending},
		Target:     []string{target},
		Refresh:    cloudipStateRefresh(client, cloudip_id),
		Timeout:    5 * time.Minute,
		MinTimeout: 3 * time.Second,
	}

	active_cloudip, err := stateConf.WaitForState()
	if err != nil {
		return nil, err
	}

	return active_cloudip.(*brightbox.CloudIP), err
}

func waitForMappedCloudIp(
	client *brightbox.Client,
	cloudip_id string,
) (*brightbox.CloudIP, error) {
	return waitForCloudip(client, cloudip_id, unmapped, mapped)
}

func waitForUnmappedCloudIp(
	client *brightbox.Client,
	cloudip_id string,
) (*brightbox.CloudIP, error) {
	return waitForCloudip(client, cloudip_id, mapped, unmapped)
}

func cloudipStateRefresh(client *brightbox.Client, cloudip_id string) resource.StateRefreshFunc {
	return func() (interface{}, string, error) {
		cloudip, err := client.CloudIP(cloudip_id)
		if err != nil {
			log.Printf("Error on Cloud IP State Refresh: %s", err)
			return nil, "", err
		}
		return cloudip, cloudip.Status, nil
	}
}

func setCloudipAttributes(
	d *schema.ResourceData,
	cloudip *brightbox.CloudIP,
) error {
	d.Set("name", cloudip.Name)
	d.Set("public_ip", cloudip.PublicIP)
	d.Set("status", cloudip.Status)
	d.Set("locked", cloudip.Locked)
	d.Set("reverse_dns", cloudip.ReverseDns)
	d.Set("fqdn", cloudip.Fqdn)
	d.Partial(false)
	return nil
}

func removeCloudIP(client *brightbox.Client, id string) error {
	log.Printf("[DEBUG] Unmapping Cloud IP %s", id)
	err := unmapCloudIP(client, id)
	if err != nil {
		return err
	}
	log.Printf("[INFO] Deleting Cloud IP %s", id)
	err = client.DestroyCloudIP(id)
	if err != nil {
		return fmt.Errorf("Error deleting Cloud IP (%s): %s", id, err)
	}
	return nil
}

func addUpdateableCloudipOptions(
	d *schema.ResourceData,
	opts *brightbox.CloudIPOptions,
) error {
	assign_string(d, &opts.Name, "name")
	assign_string(d, &opts.ReverseDns, "reverse_dns")
	return nil
}
<|endoftext|>


<commit_before>package fabric

// Basic imports
import (
	"context"
	"net"
	"sync"
	"testing"
	"time"

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

// TransportTCPTestSuite -
type TransportTCPTestSuite struct {
	suite.Suite
}

func (suite *TransportTCPTestSuite) SetupTest() {

}

func (suite *TransportTCPTestSuite) TestCanDial() {
	tcp := NewTransportTCP("127.0.0.1", 0)

	addrsValid := map[string]bool{
		"http:something.com:80/ping": false,
		"tcp:some-dns.com:90/ping":   true,
		"tcp:1.1.1.1:100/ping":       true,
		"/tcp:1.1.1.1:100/ping":      false,
	}

	for addr, can := range addrsValid {
		res, err := tcp.CanDial(NewAddress(addr))
		suite.Assert().Equal(can, res, "Addr %s should return %b", addr, can)
		suite.Assert().Nil(err, "Addr %s should not return error", addr)
	}

	addrsInvalid := map[string]bool{
		"tcp:some-dns.com/ping":         false,
		"tcp/some-dns.com/ping":         false,
		"tcp::/some-dns.com/ping":       false,
		"tcp:some-dns.com:9999990/ping": false,
		"tcp:some-dns.com:0/ping":       false,
		"tcp:some-dns.com:/ping":        false,
	}

	for addr, can := range addrsInvalid {
		res, err := tcp.CanDial(NewAddress(addr))
		suite.Assert().Equal(can, res, "Addr %s should return %b", addr, can)
		suite.Assert().NotNil(err, "Addr %s should not return error", addr)
	}
}

func (suite *TransportTCPTestSuite) TestListenSuccess() {
	wg := &sync.WaitGroup{}
	wg.Add(1)

	handled := 0

	handler := func(context.Context, net.Conn) error {
		handled++
		wg.Done()
		return nil
	}

	ctx := context.Background()
	tcps := NewTransportTCP("0.0.0.0", 0)
	err := tcps.Listen(ctx, handler)
	suite.Assert().Nil(err)

	addrs := tcps.Addresses()
	suite.Assert().Len(addrs, 1)

	tcpc := NewTransportTCP("0.0.0.0", 0)
	conn, err := tcpc.DialContext(ctx, NewAddress(addrs[0]))

	done := make(chan struct{})
	go func() {
		defer close(done)
		wg.Wait()
	}()

	select {
	case <-done:
	case <-time.After(time.Second * 2):
	}

	suite.Assert().Nil(err)
	suite.Assert().NotNil(conn)
	suite.Assert().Equal(1, handled)
}

func (suite *TransportTCPTestSuite) TestListenMultipleSuccess() {
	wg := &sync.WaitGroup{}
	wg.Add(4)

	handled := 0

	handler := func(context.Context, net.Conn) error {
		handled++
		wg.Done()
		return nil
	}

	ctx := context.Background()
	tcps := NewTransportTCP("0.0.0.0", 0)
	err := tcps.Listen(ctx, handler)
	suite.Assert().Nil(err)

	addrs := tcps.Addresses()
	suite.Assert().Len(addrs, 1)

	tcpc := NewTransportTCP("0.0.0.0", 0)
	conn1, err1 := tcpc.DialContext(ctx, NewAddress(addrs[0]))
	conn2, err2 := tcpc.DialContext(ctx, NewAddress(addrs[0]))
	conn3, err3 := tcpc.DialContext(ctx, NewAddress(addrs[0]))
	conn4, err4 := tcpc.DialContext(ctx, NewAddress(addrs[0]))

	done := make(chan struct{})
	go func() {
		defer close(done)
		wg.Wait()
	}()

	select {
	case <-done:
	case <-time.After(time.Second * 2):
	}

	suite.Assert().Nil(err1)
	suite.Assert().NotNil(conn1)
	suite.Assert().Nil(err2)
	suite.Assert().NotNil(conn2)
	suite.Assert().Nil(err3)
	suite.Assert().NotNil(conn3)
	suite.Assert().Nil(err4)
	suite.Assert().NotNil(conn4)
	suite.Assert().Equal(4, handled)
}

func TestTransportTCPTestSuite(t *testing.T) {
	suite.Run(t, new(TransportTCPTestSuite))
}
<commit_msg>Update test for transport tcp<commit_after>package fabric

// Basic imports
import (
	"context"
	"net"
	"sync"
	"testing"
	"time"

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

// TransportTCPTestSuite -
type TransportTCPTestSuite struct {
	suite.Suite
}

func (suite *TransportTCPTestSuite) SetupTest() {

}

func (suite *TransportTCPTestSuite) TestCanDial() {
	tcp := NewTransportTCP("127.0.0.1", 0)

	addrsValid := map[string]bool{
		"http:something.com:80/ping": false,
		"tcp:some-dns.com:90/ping":   true,
		"tcp:1.1.1.1:100/ping":       true,
		"/tcp:1.1.1.1:100/ping":      false,
	}

	for addr, can := range addrsValid {
		res, err := tcp.CanDial(NewAddress(addr))
		suite.Assert().Equal(can, res, "Addr %s should return %b", addr, can)
		suite.Assert().Nil(err, "Addr %s should not return error", addr)
	}

	addrsInvalid := map[string]bool{
		"tcp:some-dns.com/ping":         false,
		"tcp/some-dns.com/ping":         false,
		"tcp::/some-dns.com/ping":       false,
		"tcp:some-dns.com:9999990/ping": false,
		"tcp:some-dns.com:0/ping":       false,
		"tcp:some-dns.com:/ping":        false,
	}

	for addr, can := range addrsInvalid {
		res, err := tcp.CanDial(NewAddress(addr))
		suite.Assert().Equal(can, res, "Addr %s should return %b", addr, can)
		suite.Assert().NotNil(err, "Addr %s should not return error", addr)
	}
}

func (suite *TransportTCPTestSuite) TestListenSuccess() {
	wg := &sync.WaitGroup{}
	wg.Add(1)

	handled := 0

	handler := func(context.Context, net.Conn) error {
		handled++
		wg.Done()
		return nil
	}

	ctx := context.Background()
	tcps := NewTransportTCP("0.0.0.0", 0)
	err := tcps.Listen(ctx, handler)
	suite.Assert().Nil(err)

	addrs := tcps.Addresses()
	suite.Assert().NotEmpty(addrs)

	tcpc := NewTransportTCP("0.0.0.0", 0)
	conn, err := tcpc.DialContext(ctx, NewAddress(addrs[0]))

	done := make(chan struct{})
	go func() {
		defer close(done)
		wg.Wait()
	}()

	select {
	case <-done:
	case <-time.After(time.Second * 2):
	}

	suite.Assert().Nil(err)
	suite.Assert().NotNil(conn)
	suite.Assert().Equal(1, handled)
}

func (suite *TransportTCPTestSuite) TestListenMultipleSuccess() {
	wg := &sync.WaitGroup{}
	wg.Add(4)

	handled := 0

	handler := func(context.Context, net.Conn) error {
		handled++
		wg.Done()
		return nil
	}

	ctx := context.Background()
	tcps := NewTransportTCP("0.0.0.0", 0)
	err := tcps.Listen(ctx, handler)
	suite.Assert().Nil(err)

	addrs := tcps.Addresses()
	suite.Assert().NotEmpty(addrs)

	tcpc := NewTransportTCP("0.0.0.0", 0)
	conn1, err1 := tcpc.DialContext(ctx, NewAddress(addrs[0]))
	conn2, err2 := tcpc.DialContext(ctx, NewAddress(addrs[0]))
	conn3, err3 := tcpc.DialContext(ctx, NewAddress(addrs[0]))
	conn4, err4 := tcpc.DialContext(ctx, NewAddress(addrs[0]))

	done := make(chan struct{})
	go func() {
		defer close(done)
		wg.Wait()
	}()

	select {
	case <-done:
	case <-time.After(time.Second * 2):
	}

	suite.Assert().Nil(err1)
	suite.Assert().NotNil(conn1)
	suite.Assert().Nil(err2)
	suite.Assert().NotNil(conn2)
	suite.Assert().Nil(err3)
	suite.Assert().NotNil(conn3)
	suite.Assert().Nil(err4)
	suite.Assert().NotNil(conn4)
	suite.Assert().Equal(4, handled)
}

func TestTransportTCPTestSuite(t *testing.T) {
	suite.Run(t, new(TransportTCPTestSuite))
}
<|endoftext|>


<commit_before>package main

import (
	"koding/artifact"
	"koding/kites/common"
	"koding/kites/terraformer"

	"github.com/koding/kite"
	kiteconfig "github.com/koding/kite/config"
	"github.com/koding/metrics"
	"github.com/koding/multiconfig"
)

var (
	Name    = "terraformer"
	Version = "0.0.1"
)

func main() {
	conf := &terraformer.Config{}

	// Load the config, it's reads environment variables or from flags
	multiconfig.New().MustLoad(conf)

	k := newKite(conf)

	if conf.Debug {
		k.Log.Info("Debug mode enabled")
	}

	registerURL := k.RegisterURL(true)

	if err := k.RegisterForever(registerURL); err != nil {
		k.Log.Fatal(err.Error())
	}

	k.Run()
}

func newKite(conf *terraformer.Config) *kite.Kite {
	k := kite.New(Name, Version)
	k.Config = kiteconfig.MustGet()
	k.Config.Port = conf.Port

	if conf.Region != "" {
		k.Config.Region = conf.Region
	}

	if conf.Environment != "" {
		k.Config.Environment = conf.Environment
	}

	stats, err := metrics.NewDogStatsD("terraformer")
	if err != nil {
		panic(err)
	}

	t := terraformer.New()
	t.Metrics = stats
	t.Log = common.NewLogger(Name, conf.Debug)

	// track every kind of call
	k.PreHandleFunc(createTracker(stats))

	// Terraformer handling methods
	k.HandleFunc("apply", t.Apply)
	k.HandleFunc("destroy", t.Destroy)
	k.HandleFunc("plan", t.Plan)

	k.HandleHTTPFunc("/healthCheck", artifact.HealthCheckHandler(Name))
	k.HandleHTTPFunc("/version", artifact.VersionHandler())

	return k
}

func createTracker(metrics *metrics.DogStatsD) kite.HandlerFunc {
	return func(r *kite.Request) (interface{}, error) {
		metrics.Count(
			"functionCallCount", // metric name
			1,                   // count
			[]string{"funcName:" + r.Method}, // tags for metric call
			1.0, // rate
		)

		return true, nil
	}
}
<commit_msg>Terraformer: use worker name for metrics<commit_after>package main

import (
	"koding/artifact"
	"koding/kites/common"
	"koding/kites/terraformer"

	"github.com/koding/kite"
	kiteconfig "github.com/koding/kite/config"
	"github.com/koding/metrics"
	"github.com/koding/multiconfig"
)

var (
	Name    = "terraformer"
	Version = "0.0.1"
)

func main() {
	conf := &terraformer.Config{}

	// Load the config, it's reads environment variables or from flags
	multiconfig.New().MustLoad(conf)

	k := newKite(conf)

	if conf.Debug {
		k.Log.Info("Debug mode enabled")
	}

	registerURL := k.RegisterURL(true)

	if err := k.RegisterForever(registerURL); err != nil {
		k.Log.Fatal(err.Error())
	}

	k.Run()
}

func newKite(conf *terraformer.Config) *kite.Kite {
	k := kite.New(Name, Version)
	k.Config = kiteconfig.MustGet()
	k.Config.Port = conf.Port

	if conf.Region != "" {
		k.Config.Region = conf.Region
	}

	if conf.Environment != "" {
		k.Config.Environment = conf.Environment
	}

	stats, err := metrics.NewDogStatsD(Name)
	if err != nil {
		panic(err)
	}

	t := terraformer.New()
	t.Metrics = stats
	t.Log = common.NewLogger(Name, conf.Debug)

	// track every kind of call
	k.PreHandleFunc(createTracker(stats))

	// Terraformer handling methods
	k.HandleFunc("apply", t.Apply)
	k.HandleFunc("destroy", t.Destroy)
	k.HandleFunc("plan", t.Plan)

	k.HandleHTTPFunc("/healthCheck", artifact.HealthCheckHandler(Name))
	k.HandleHTTPFunc("/version", artifact.VersionHandler())

	return k
}

func createTracker(metrics *metrics.DogStatsD) kite.HandlerFunc {
	return func(r *kite.Request) (interface{}, error) {
		metrics.Count(
			"functionCallCount", // metric name
			1,                   // count
			[]string{"funcName:" + r.Method}, // tags for metric call
			1.0, // rate
		)

		return true, nil
	}
}
<|endoftext|>


<commit_before>//
// Copyright (c) 2014, Anupam Kapoor. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:

// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.

// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: anupam.kapoor@gmail.com (Anupam Kapoor)
//
// this file implements the shortest path from source to destination
// vertices in symbol graphs
//
package main

import (
	"bufio"
	"flag"
	"fmt"
	"github.com/anupamk/common-utilz/graph/symbol_graph"
	"github.com/anupamk/common-utilz/graph/traversal"
	"io"
	"log"
	"os"
	"strings"
)

//
// program input control
//
var (
	data_file     string // data-file
	separator     string // field-separator
	source        string // source-vertex
	verbose_debug bool   // just-what-it-sez
)

// setup various command line parameters
func init() {
	// application parameterz
	flag.StringVar(&data_file, "input-file", "", "symbol-graph data file name")
	flag.StringVar(&separator, "separator", "", "field separator in the input")
	flag.StringVar(&source, "source", "", "source vertex")

	// debugging stuff
	flag.BoolVar(&verbose_debug, "debug", true, "generate verbose debugging")

}

// rudimentary checks and parameter cleanups
func sanitize_and_validate_cmdline_params() {
	if data_file = strings.TrimSpace(data_file); len(data_file) == 0 {
		fmt.Fprintf(os.Stderr, "usage-error: bad data-file '%s'\n", data_file)
		flag.Usage()

		os.Exit(255)
	}

	// don't mess with the separator
	if len(separator) == 0 {
		fmt.Fprintf(os.Stderr, "usage-error: bad seperator '%s'\n", separator)
		flag.Usage()

		os.Exit(254)
	}

	if source = strings.TrimSpace(source); len(source) == 0 {
		fmt.Fprintf(os.Stderr, "usage-error: bad source '%s'\n", source)
		flag.Usage()

		os.Exit(253)
	}
}

func main() {
	flag.Parse()
	sanitize_and_validate_cmdline_params()

	if verbose_debug {
		log.Printf("-- degree-of-seperation parameter dump: input-file: '%s', separator: '%s', source-vertex: '%s' --\n",
			data_file, separator, source)
	}

	// parse the file-name and create a symbol graph
	sg, err := symbol_graph.LoadFromFile(data_file, separator)
	if err != nil {
		log.Fatal(err)
	}

	if verbose_debug {
		sg_g := sg.G()
		log.Printf("-- symbol-graph created. vertices: '%d', edges: '%d' --\n", sg_g.V(), sg_g.E())
	}

	if !sg.Contains(source) {
		fmt.Fprintf(os.Stderr, "fatal-error: '%s' not found in data-base\n", source)
		flag.Usage()

		os.Exit(252)
	}

	//
	// ok, so by now, we have a valid graph, and a valid source,
	// let's answer some questions...
	//

	// determine all paths from source -> other vertices on the
	// graph
	all_paths, err := traversal.SingleSourceShortestPaths(sg.G(), sg.Index(source))
	if err != nil {
		fmt.Fprintf(os.Stderr, "fatal-error: invalid source '%s'\n", source)
		os.Exit(128)
	}

	// query-rsp loop
	for stdin_reader := bufio.NewReader(os.Stdin); ; {
		fmt.Fprintf(os.Stdout, "degree-of-separation --> ")

		// read and sanitize input
		dest_name, err := stdin_reader.ReadString('\n')
		if err != nil || err == io.EOF {
			break
		}

		if dest_name = strings.TrimSpace(dest_name); len(dest_name) == 0 {
			continue
		}

		if verbose_debug {
			log.Printf("-- user-input: '%s' --\n", dest_name)
		}

		// got something useful, let's see do we know it ?
		if !sg.Contains(dest_name) {
			log.Printf("error: '%s' doesn't exist\n", err)
			continue
		}

		// is there a path to destination ?
		dst_vertex := sg.Index(dest_name)

		if !all_paths.PathExists(dst_vertex) {
			log.Printf("no path to: '%s'\n", dest_name)
			continue
		}

		// yes there is a path, enumerate it...
		src_dst_path := all_paths.PathTo(dst_vertex)

		fmt.Fprintf(os.Stdout, "%s\n", source)
		for _, v := range src_dst_path[1:] {
			vertex_name, _ := sg.Name(v)
			fmt.Fprintf(os.Stdout, "    %s\n", vertex_name)
		}
	}
}
<commit_msg>display path-length during traversal, and some minor corrections<commit_after>//
// Copyright (c) 2014, Anupam Kapoor. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:

// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.

// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: anupam.kapoor@gmail.com (Anupam Kapoor)
//
// this file implements the shortest path from source to destination
// vertices in symbol graphs
//
package main

import (
	"bufio"
	"flag"
	"fmt"
	"github.com/anupamk/common-utilz/graph/symbol_graph"
	"github.com/anupamk/common-utilz/graph/traversal"
	"io"
	"log"
	"os"
	"strings"
)

//
// program input control
//
var (
	data_file     string // data-file
	separator     string // field-separator
	source        string // source-vertex
	verbose_debug bool   // just-what-it-sez
)

// setup various command line parameters
func init() {
	// application parameterz
	flag.StringVar(&data_file, "input-file", "", "symbol-graph data file name")
	flag.StringVar(&separator, "separator", "", "field separator in the input")
	flag.StringVar(&source, "source", "", "source vertex")

	// debugging stuff
	flag.BoolVar(&verbose_debug, "debug", true, "generate verbose debugging")

}

// rudimentary checks and parameter cleanups
func sanitize_and_validate_cmdline_params() {
	if data_file = strings.TrimSpace(data_file); len(data_file) == 0 {
		fmt.Fprintf(os.Stderr, "usage-error: bad data-file '%s'\n", data_file)
		flag.Usage()

		os.Exit(255)
	}

	// don't mess with the separator
	if len(separator) == 0 {
		fmt.Fprintf(os.Stderr, "usage-error: bad seperator '%s'\n", separator)
		flag.Usage()

		os.Exit(254)
	}

	if source = strings.TrimSpace(source); len(source) == 0 {
		fmt.Fprintf(os.Stderr, "usage-error: bad source '%s'\n", source)
		flag.Usage()

		os.Exit(253)
	}
}

func main() {
	flag.Parse()
	sanitize_and_validate_cmdline_params()

	if verbose_debug {
		log.Printf("-- degree-of-seperation parameter dump: input-file: '%s', separator: '%s', source-vertex: '%s' --\n",
			data_file, separator, source)
	}

	// parse the file-name and create a symbol graph
	sg, err := symbol_graph.LoadFromFile(data_file, separator)
	if err != nil {
		log.Fatal(err)
	}

	if verbose_debug {
		sg_g := sg.G()
		log.Printf("-- symbol-graph created. vertices: '%d', edges: '%d' --\n", sg_g.V(), sg_g.E())
	}

	if !sg.Contains(source) {
		fmt.Fprintf(os.Stderr, "fatal-error: '%s' not found in data-base\n", source)
		flag.Usage()

		os.Exit(252)
	}

	//
	// ok, so by now, we have a valid graph, and a valid source,
	// let's answer some questions...
	//

	// determine all paths from source -> other vertices on the
	// graph
	all_paths, err := traversal.SingleSourceShortestPaths(sg.G(), sg.Index(source))
	if err != nil {
		fmt.Fprintf(os.Stderr, "fatal-error: invalid source '%s'\n", source)
		os.Exit(128)
	}

	// query-rsp loop
	for stdin_reader := bufio.NewReader(os.Stdin); ; {
		fmt.Fprintf(os.Stdout, "degree-of-separation --> ")

		// read and sanitize input
		dest_name, err := stdin_reader.ReadString('\n')
		if err != nil || err == io.EOF {
			break
		}

		if dest_name = strings.TrimSpace(dest_name); len(dest_name) == 0 {
			continue
		}

		if verbose_debug {
			log.Printf("-- user-input: '%s' --\n", dest_name)
		}

		// got something useful, let's see do we know it ?
		if !sg.Contains(dest_name) {
			log.Printf("error: '%s' doesn't exist\n", dest_name)
			continue
		}

		// is there a path to destination ?
		dst_vertex := sg.Index(dest_name)

		if !all_paths.PathExists(dst_vertex) {
			log.Printf("no path to: '%s'\n", dest_name)
			continue
		}

		// yes there is a path, enumerate it...
		src_dst_path := all_paths.PathTo(dst_vertex)

		fmt.Fprintf(os.Stdout, "source: %s, path-length: %d\npath:\n", source, len(src_dst_path)-1)
		for _, v := range src_dst_path[1:] {
			vertex_name, _ := sg.Name(v)
			fmt.Fprintf(os.Stdout, "    %s\n", vertex_name)
		}
	}
}
<|endoftext|>


<commit_before>package classic

import (
	"context"
	"fmt"
	"strings"

	"github.com/hashicorp/go-oracle-terraform/compute"
	"github.com/hashicorp/packer/common/uuid"
	"github.com/hashicorp/packer/helper/multistep"
	"github.com/hashicorp/packer/packer"
)

type stepSecurity struct{}

func (s *stepSecurity) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
	ui := state.Get("ui").(packer.Ui)
	config := state.Get("config").(*Config)

	commType := ""
	if config.Comm.Type == "ssh" {
		commType = "SSH"
	} else if config.Comm.Type == "winrm" {
		commType = "WINRM"
	}

	ui.Say(fmt.Sprintf("Configuring security lists and rules to enable %s access...", commType))

	client := state.Get("client").(*compute.ComputeClient)
	runUUID := uuid.TimeOrderedUUID()

	namePrefix := fmt.Sprintf("/Compute-%s/%s/", config.IdentityDomain, config.Username)
	secListName := fmt.Sprintf("Packer_%s_Allow_%s_%s", commType, config.ImageName, runUUID)
	secListClient := client.SecurityLists()
	secListInput := compute.CreateSecurityListInput{
		Description: fmt.Sprintf("Packer-generated security list to give packer %s access", commType),
		Name:        namePrefix + secListName,
	}
	_, err := secListClient.CreateSecurityList(&secListInput)
	if err != nil {
		if !strings.Contains(err.Error(), "already exists") {
			err = fmt.Errorf("Error creating security List to"+
				" allow Packer to connect to Oracle instance via %s: %s", commType, err)
			ui.Error(err.Error())
			state.Put("error", err)
			return multistep.ActionHalt
		}
	}
	// DOCS NOTE: user must have Compute_Operations role
	// Create security rule that allows Packer to connect via SSH or winRM
	var application string
	if commType == "SSH" {
		application = "/oracle/public/ssh"
	} else if commType == "WINRM" {
		// Check to see whether a winRM security protocol is already defined;
		// don't need to do this for SSH because it is built into the Oracle API.
		protocolClient := client.SecurityProtocols()
		winrmProtocol := fmt.Sprintf("WINRM_%s", runUUID)
		input := compute.CreateSecurityProtocolInput{
			Name:        winrmProtocol,
			Description: "packer-generated protocol to allow winRM communicator",
			DstPortSet:  []string{"5985", "5986", "443"}, // TODO make configurable
			IPProtocol:  "tcp",
		}
		_, err = protocolClient.CreateSecurityProtocol(&input)
		if err != nil {
			err = fmt.Errorf("Error creating security protocol to"+
				" allow Packer to connect to Oracle instance via %s: %s", commType, err)
			ui.Error(err.Error())
			state.Put("error", err)
			return multistep.ActionHalt
		}
		state.Put("winrm_protocol", winrmProtocol)

		// Check to see whether a winRM security application is already defined
		applicationClient := client.SecurityApplications()
		application = fmt.Sprintf("packer_winRM_%s", runUUID)
		applicationInput := compute.CreateSecurityApplicationInput{
			Description: "Allows Packer to connect to instance via winRM",
			DPort:       "5985-5986",
			Name:        application,
			Protocol:    "TCP",
		}
		_, err = applicationClient.CreateSecurityApplication(&applicationInput)
		if err != nil {
			err = fmt.Errorf("Error creating security application to"+
				" allow Packer to connect to Oracle instance via %s: %s", commType, err)
			ui.Error(err.Error())
			state.Put("error", err)
			return multistep.ActionHalt
		}
		state.Put("winrm_application", application)
	}
	secRulesClient := client.SecRules()
	secRuleName := fmt.Sprintf("Packer-allow-%s-Rule_%s_%s", commType,
		config.ImageName, runUUID)
	secRulesInput := compute.CreateSecRuleInput{
		Action:          "PERMIT",
		Application:     application,
		Description:     "Packer-generated security rule to allow ssh/winrm",
		DestinationList: "seclist:" + namePrefix + secListName,
		Name:            namePrefix + secRuleName,
		SourceList:      config.SSHSourceList,
	}

	_, err = secRulesClient.CreateSecRule(&secRulesInput)
	if err != nil {
		err = fmt.Errorf("Error creating security rule to"+
			" allow Packer to connect to Oracle instance: %s", err)
		ui.Error(err.Error())
		state.Put("error", err)
		return multistep.ActionHalt
	}
	state.Put("security_rule_name", secRuleName)
	state.Put("security_list", secListName)
	return multistep.ActionContinue
}

func (s *stepSecurity) Cleanup(state multistep.StateBag) {
	client := state.Get("client").(*compute.ComputeClient)
	ui := state.Get("ui").(packer.Ui)
	config := state.Get("config").(*Config)

	ui.Say("Deleting temporary rules and lists...")

	namePrefix := fmt.Sprintf("/Compute-%s/%s/", config.IdentityDomain, config.Username)
	// delete security rules that Packer generated
	secRuleName := state.Get("security_rule_name").(string)
	secRulesClient := client.SecRules()
	ruleInput := compute.DeleteSecRuleInput{Name: namePrefix + secRuleName}
	err := secRulesClient.DeleteSecRule(&ruleInput)
	if err != nil {
		ui.Say(fmt.Sprintf("Error deleting the packer-generated security rule %s; "+
			"please delete manually. (error: %s)", secRuleName, err.Error()))
	}

	// delete security list that Packer generated
	secListName := state.Get("security_list").(string)
	secListClient := client.SecurityLists()
	input := compute.DeleteSecurityListInput{Name: namePrefix + secListName}
	err = secListClient.DeleteSecurityList(&input)
	if err != nil {
		ui.Say(fmt.Sprintf("Error deleting the packer-generated security list %s; "+
			"please delete manually. (error : %s)", secListName, err.Error()))
	}

	// Some extra cleanup if we used the winRM communicator
	if config.Comm.Type == "winrm" {
		// Delete the packer-generated protocol
		protocol := state.Get("winrm_protocol").(string)
		protocolClient := client.SecurityProtocols()
		deleteProtocolInput := compute.DeleteSecurityProtocolInput{
			Name: namePrefix + protocol,
		}
		err = protocolClient.DeleteSecurityProtocol(&deleteProtocolInput)
		if err != nil {
			ui.Say(fmt.Sprintf("Error deleting the packer-generated winrm security protocol %s; "+
				"please delete manually. (error : %s)", protocol, err.Error()))
		}

		// Delete the packer-generated application
		application := state.Get("winrm_application").(string)
		applicationClient := client.SecurityApplications()
		deleteApplicationInput := compute.DeleteSecurityApplicationInput{
			Name: namePrefix + application,
		}
		err = applicationClient.DeleteSecurityApplication(&deleteApplicationInput)
		if err != nil {
			ui.Say(fmt.Sprintf("Error deleting the packer-generated winrm security application %s; "+
				"please delete manually. (error : %s)", application, err.Error()))
		}
	}

}
<commit_msg>remove redundant security_protocol code from the winrm implementation of the oracle-classic provisioner<commit_after>package classic

import (
	"context"
	"fmt"
	"strings"

	"github.com/hashicorp/go-oracle-terraform/compute"
	"github.com/hashicorp/packer/common/uuid"
	"github.com/hashicorp/packer/helper/multistep"
	"github.com/hashicorp/packer/packer"
)

type stepSecurity struct{}

func (s *stepSecurity) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
	ui := state.Get("ui").(packer.Ui)
	config := state.Get("config").(*Config)

	commType := ""
	if config.Comm.Type == "ssh" {
		commType = "SSH"
	} else if config.Comm.Type == "winrm" {
		commType = "WINRM"
	}

	ui.Say(fmt.Sprintf("Configuring security lists and rules to enable %s access...", commType))

	client := state.Get("client").(*compute.ComputeClient)
	runUUID := uuid.TimeOrderedUUID()

	namePrefix := fmt.Sprintf("/Compute-%s/%s/", config.IdentityDomain, config.Username)
	secListName := fmt.Sprintf("Packer_%s_Allow_%s_%s", commType, config.ImageName, runUUID)
	secListClient := client.SecurityLists()
	secListInput := compute.CreateSecurityListInput{
		Description: fmt.Sprintf("Packer-generated security list to give packer %s access", commType),
		Name:        namePrefix + secListName,
	}
	_, err := secListClient.CreateSecurityList(&secListInput)
	if err != nil {
		if !strings.Contains(err.Error(), "already exists") {
			err = fmt.Errorf("Error creating security List to"+
				" allow Packer to connect to Oracle instance via %s: %s", commType, err)
			ui.Error(err.Error())
			state.Put("error", err)
			return multistep.ActionHalt
		}
	}
	// DOCS NOTE: user must have Compute_Operations role
	// Create security rule that allows Packer to connect via SSH or winRM
	var application string
	if commType == "SSH" {
		application = "/oracle/public/ssh"
	} else if commType == "WINRM" {
		// Check to see whether a winRM security application is already defined
		applicationClient := client.SecurityApplications()
		application = fmt.Sprintf("packer_winRM_%s", runUUID)
		applicationInput := compute.CreateSecurityApplicationInput{
			Description: "Allows Packer to connect to instance via winRM",
			DPort:       "5985-5986",
			Name:        application,
			Protocol:    "TCP",
		}
		_, err = applicationClient.CreateSecurityApplication(&applicationInput)
		if err != nil {
			err = fmt.Errorf("Error creating security application to"+
				" allow Packer to connect to Oracle instance via %s: %s", commType, err)
			ui.Error(err.Error())
			state.Put("error", err)
			return multistep.ActionHalt
		}
		state.Put("winrm_application", application)
	}
	secRulesClient := client.SecRules()
	secRuleName := fmt.Sprintf("Packer-allow-%s-Rule_%s_%s", commType,
		config.ImageName, runUUID)
	secRulesInput := compute.CreateSecRuleInput{
		Action:          "PERMIT",
		Application:     application,
		Description:     "Packer-generated security rule to allow ssh/winrm",
		DestinationList: "seclist:" + namePrefix + secListName,
		Name:            namePrefix + secRuleName,
		SourceList:      config.SSHSourceList,
	}

	_, err = secRulesClient.CreateSecRule(&secRulesInput)
	if err != nil {
		err = fmt.Errorf("Error creating security rule to"+
			" allow Packer to connect to Oracle instance: %s", err)
		ui.Error(err.Error())
		state.Put("error", err)
		return multistep.ActionHalt
	}
	state.Put("security_rule_name", secRuleName)
	state.Put("security_list", secListName)
	return multistep.ActionContinue
}

func (s *stepSecurity) Cleanup(state multistep.StateBag) {
	client := state.Get("client").(*compute.ComputeClient)
	ui := state.Get("ui").(packer.Ui)
	config := state.Get("config").(*Config)

	ui.Say("Deleting temporary rules and lists...")

	namePrefix := fmt.Sprintf("/Compute-%s/%s/", config.IdentityDomain, config.Username)
	// delete security rules that Packer generated
	secRuleName := state.Get("security_rule_name").(string)
	secRulesClient := client.SecRules()
	ruleInput := compute.DeleteSecRuleInput{Name: namePrefix + secRuleName}
	err := secRulesClient.DeleteSecRule(&ruleInput)
	if err != nil {
		ui.Say(fmt.Sprintf("Error deleting the packer-generated security rule %s; "+
			"please delete manually. (error: %s)", secRuleName, err.Error()))
	}

	// delete security list that Packer generated
	secListName := state.Get("security_list").(string)
	secListClient := client.SecurityLists()
	input := compute.DeleteSecurityListInput{Name: namePrefix + secListName}
	err = secListClient.DeleteSecurityList(&input)
	if err != nil {
		ui.Say(fmt.Sprintf("Error deleting the packer-generated security list %s; "+
			"please delete manually. (error : %s)", secListName, err.Error()))
	}

	// Some extra cleanup if we used the winRM communicator
	if config.Comm.Type == "winrm" {
		// Delete the packer-generated application
		application := state.Get("winrm_application").(string)
		applicationClient := client.SecurityApplications()
		deleteApplicationInput := compute.DeleteSecurityApplicationInput{
			Name: namePrefix + application,
		}
		err = applicationClient.DeleteSecurityApplication(&deleteApplicationInput)
		if err != nil {
			ui.Say(fmt.Sprintf("Error deleting the packer-generated winrm security application %s; "+
				"please delete manually. (error : %s)", application, err.Error()))
		}
	}

}
<|endoftext|>