<commit_before>// +build !ignore_autogenerated

/*
Copyright 2019 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

// Code generated by deepcopy-gen. DO NOT EDIT.

package v1alpha1

import (
	v1 "k8s.io/api/core/v1"
	runtime "k8s.io/apimachinery/pkg/runtime"
)

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AWSUnsealConfig) DeepCopyInto(out *AWSUnsealConfig) {
	*out = *in
	return
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AWSUnsealConfig.
func (in *AWSUnsealConfig) DeepCopy() *AWSUnsealConfig {
	if in == nil {
		return nil
	}
	out := new(AWSUnsealConfig)
	in.DeepCopyInto(out)
	return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AlibabaUnsealConfig) DeepCopyInto(out *AlibabaUnsealConfig) {
	*out = *in
	return
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AlibabaUnsealConfig.
func (in *AlibabaUnsealConfig) DeepCopy() *AlibabaUnsealConfig {
	if in == nil {
		return nil
	}
	out := new(AlibabaUnsealConfig)
	in.DeepCopyInto(out)
	return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AzureUnsealConfig) DeepCopyInto(out *AzureUnsealConfig) {
	*out = *in
	return
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AzureUnsealConfig.
func (in *AzureUnsealConfig) DeepCopy() *AzureUnsealConfig {
	if in == nil {
		return nil
	}
	out := new(AzureUnsealConfig)
	in.DeepCopyInto(out)
	return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CredentialsConfig) DeepCopyInto(out *CredentialsConfig) {
	*out = *in
	return
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CredentialsConfig.
func (in *CredentialsConfig) DeepCopy() *CredentialsConfig {
	if in == nil {
		return nil
	}
	out := new(CredentialsConfig)
	in.DeepCopyInto(out)
	return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *GoogleUnsealConfig) DeepCopyInto(out *GoogleUnsealConfig) {
	*out = *in
	return
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GoogleUnsealConfig.
func (in *GoogleUnsealConfig) DeepCopy() *GoogleUnsealConfig {
	if in == nil {
		return nil
	}
	out := new(GoogleUnsealConfig)
	in.DeepCopyInto(out)
	return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *KubernetesUnsealConfig) DeepCopyInto(out *KubernetesUnsealConfig) {
	*out = *in
	return
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubernetesUnsealConfig.
func (in *KubernetesUnsealConfig) DeepCopy() *KubernetesUnsealConfig {
	if in == nil {
		return nil
	}
	out := new(KubernetesUnsealConfig)
	in.DeepCopyInto(out)
	return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *UnsealConfig) DeepCopyInto(out *UnsealConfig) {
	*out = *in
	if in.Kubernetes != nil {
		in, out := &in.Kubernetes, &out.Kubernetes
		*out = new(KubernetesUnsealConfig)
		**out = **in
	}
	if in.Google != nil {
		in, out := &in.Google, &out.Google
		*out = new(GoogleUnsealConfig)
		**out = **in
	}
	if in.Alibaba != nil {
		in, out := &in.Alibaba, &out.Alibaba
		*out = new(AlibabaUnsealConfig)
		**out = **in
	}
	if in.Azure != nil {
		in, out := &in.Azure, &out.Azure
		*out = new(AzureUnsealConfig)
		**out = **in
	}
	if in.AWS != nil {
		in, out := &in.AWS, &out.AWS
		*out = new(AWSUnsealConfig)
		**out = **in
	}
	return
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UnsealConfig.
func (in *UnsealConfig) DeepCopy() *UnsealConfig {
	if in == nil {
		return nil
	}
	out := new(UnsealConfig)
	in.DeepCopyInto(out)
	return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Vault) DeepCopyInto(out *Vault) {
	*out = *in
	out.TypeMeta = in.TypeMeta
	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
	in.Spec.DeepCopyInto(&out.Spec)
	in.Status.DeepCopyInto(&out.Status)
	return
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Vault.
func (in *Vault) DeepCopy() *Vault {
	if in == nil {
		return nil
	}
	out := new(Vault)
	in.DeepCopyInto(out)
	return out
}

// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *Vault) DeepCopyObject() runtime.Object {
	if c := in.DeepCopy(); c != nil {
		return c
	}
	return nil
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *VaultList) DeepCopyInto(out *VaultList) {
	*out = *in
	out.TypeMeta = in.TypeMeta
	out.ListMeta = in.ListMeta
	if in.Items != nil {
		in, out := &in.Items, &out.Items
		*out = make([]Vault, len(*in))
		for i := range *in {
			(*in)[i].DeepCopyInto(&(*out)[i])
		}
	}
	return
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VaultList.
func (in *VaultList) DeepCopy() *VaultList {
	if in == nil {
		return nil
	}
	out := new(VaultList)
	in.DeepCopyInto(out)
	return out
}

// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *VaultList) DeepCopyObject() runtime.Object {
	if c := in.DeepCopy(); c != nil {
		return c
	}
	return nil
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *VaultSpec) DeepCopyInto(out *VaultSpec) {
	*out = *in
	if in.Annotations != nil {
		in, out := &in.Annotations, &out.Annotations
		*out = make(map[string]string, len(*in))
		for key, val := range *in {
			(*out)[key] = val
		}
	}
	if in.Config != nil {
		in, out := &in.Config, &out.Config
		*out = make(map[string]interface{}, len(*in))
		for key, val := range *in {
			if val == nil {
				(*out)[key] = nil
			} else {
				(*out)[key] = val
			}
		}
	}
	if in.ExternalConfig != nil {
		in, out := &in.ExternalConfig, &out.ExternalConfig
		*out = make(map[string]interface{}, len(*in))
		for key, val := range *in {
			if val == nil {
				(*out)[key] = nil
			} else {
				(*out)[key] = val
			}
		}
	}
	in.UnsealConfig.DeepCopyInto(&out.UnsealConfig)
	out.CredentialsConfig = in.CredentialsConfig
	if in.EnvsConfig != nil {
		in, out := &in.EnvsConfig, &out.EnvsConfig
		*out = make([]v1.EnvVar, len(*in))
		for i := range *in {
			(*in)[i].DeepCopyInto(&(*out)[i])
		}
	}
	in.SecurityContext.DeepCopyInto(&out.SecurityContext)
	if in.SupportUpgrade != nil {
		in, out := &in.SupportUpgrade, &out.SupportUpgrade
		*out = new(bool)
		**out = **in
	}
	if in.EtcdAnnotations != nil {
		in, out := &in.EtcdAnnotations, &out.EtcdAnnotations
		*out = make(map[string]string, len(*in))
		for key, val := range *in {
			(*out)[key] = val
		}
	}
	in.NodeAffinity.DeepCopyInto(&out.NodeAffinity)
	if in.Volumes != nil {
		in, out := &in.Volumes, &out.Volumes
		*out = make([]v1.Volume, len(*in))
		for i := range *in {
			(*in)[i].DeepCopyInto(&(*out)[i])
		}
	}
	if in.VolumeMounts != nil {
		in, out := &in.VolumeMounts, &out.VolumeMounts
		*out = make([]v1.VolumeMount, len(*in))
		for i := range *in {
			(*in)[i].DeepCopyInto(&(*out)[i])
		}
	}
	if in.VaultEnvsConfig != nil {
		in, out := &in.VaultEnvsConfig, &out.VaultEnvsConfig
		*out = make([]v1.EnvVar, len(*in))
		for i := range *in {
			(*in)[i].DeepCopyInto(&(*out)[i])
		}
	}
	in.VaultResource.DeepCopyInto(&out.VaultResource)
	in.BankVaultsResource.DeepCopyInto(&out.BankVaultsResource)
	return
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VaultSpec.
func (in *VaultSpec) DeepCopy() *VaultSpec {
	if in == nil {
		return nil
	}
	out := new(VaultSpec)
	in.DeepCopyInto(out)
	return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *VaultStatus) DeepCopyInto(out *VaultStatus) {
	*out = *in
	if in.Nodes != nil {
		in, out := &in.Nodes, &out.Nodes
		*out = make([]string, len(*in))
		copy(*out, *in)
	}
	return
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VaultStatus.
func (in *VaultStatus) DeepCopy() *VaultStatus {
	if in == nil {
		return nil
	}
	out := new(VaultStatus)
	in.DeepCopyInto(out)
	return out
}
<commit_msg>After `operator-sdk generate k8s` with manual modify<commit_after>// +build !ignore_autogenerated

/*
Copyright 2019 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

// Code generated by deepcopy-gen. DO NOT EDIT.

package v1alpha1

import (
	v1 "k8s.io/api/core/v1"
	runtime "k8s.io/apimachinery/pkg/runtime"
)

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AWSUnsealConfig) DeepCopyInto(out *AWSUnsealConfig) {
	*out = *in
	return
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AWSUnsealConfig.
func (in *AWSUnsealConfig) DeepCopy() *AWSUnsealConfig {
	if in == nil {
		return nil
	}
	out := new(AWSUnsealConfig)
	in.DeepCopyInto(out)
	return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AlibabaUnsealConfig) DeepCopyInto(out *AlibabaUnsealConfig) {
	*out = *in
	return
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AlibabaUnsealConfig.
func (in *AlibabaUnsealConfig) DeepCopy() *AlibabaUnsealConfig {
	if in == nil {
		return nil
	}
	out := new(AlibabaUnsealConfig)
	in.DeepCopyInto(out)
	return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AzureUnsealConfig) DeepCopyInto(out *AzureUnsealConfig) {
	*out = *in
	return
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AzureUnsealConfig.
func (in *AzureUnsealConfig) DeepCopy() *AzureUnsealConfig {
	if in == nil {
		return nil
	}
	out := new(AzureUnsealConfig)
	in.DeepCopyInto(out)
	return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CredentialsConfig) DeepCopyInto(out *CredentialsConfig) {
	*out = *in
	return
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CredentialsConfig.
func (in *CredentialsConfig) DeepCopy() *CredentialsConfig {
	if in == nil {
		return nil
	}
	out := new(CredentialsConfig)
	in.DeepCopyInto(out)
	return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *GoogleUnsealConfig) DeepCopyInto(out *GoogleUnsealConfig) {
	*out = *in
	return
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GoogleUnsealConfig.
func (in *GoogleUnsealConfig) DeepCopy() *GoogleUnsealConfig {
	if in == nil {
		return nil
	}
	out := new(GoogleUnsealConfig)
	in.DeepCopyInto(out)
	return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *KubernetesUnsealConfig) DeepCopyInto(out *KubernetesUnsealConfig) {
	*out = *in
	return
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubernetesUnsealConfig.
func (in *KubernetesUnsealConfig) DeepCopy() *KubernetesUnsealConfig {
	if in == nil {
		return nil
	}
	out := new(KubernetesUnsealConfig)
	in.DeepCopyInto(out)
	return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Resources) DeepCopyInto(out *Resources) {
	*out = *in
	if in.Vault != nil {
		in, out := &in.Vault, &out.Vault
		*out = new(v1.ResourceRequirements)
		(*in).DeepCopyInto(*out)
	}
	if in.BankVaults != nil {
		in, out := &in.BankVaults, &out.BankVaults
		*out = new(v1.ResourceRequirements)
		(*in).DeepCopyInto(*out)
	}
	if in.PrometheusExporter != nil {
		in, out := &in.PrometheusExporter, &out.PrometheusExporter
		*out = new(v1.ResourceRequirements)
		(*in).DeepCopyInto(*out)
	}
	return
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Resources.
func (in *Resources) DeepCopy() *Resources {
	if in == nil {
		return nil
	}
	out := new(Resources)
	in.DeepCopyInto(out)
	return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *UnsealConfig) DeepCopyInto(out *UnsealConfig) {
	*out = *in
	if in.Kubernetes != nil {
		in, out := &in.Kubernetes, &out.Kubernetes
		*out = new(KubernetesUnsealConfig)
		**out = **in
	}
	if in.Google != nil {
		in, out := &in.Google, &out.Google
		*out = new(GoogleUnsealConfig)
		**out = **in
	}
	if in.Alibaba != nil {
		in, out := &in.Alibaba, &out.Alibaba
		*out = new(AlibabaUnsealConfig)
		**out = **in
	}
	if in.Azure != nil {
		in, out := &in.Azure, &out.Azure
		*out = new(AzureUnsealConfig)
		**out = **in
	}
	if in.AWS != nil {
		in, out := &in.AWS, &out.AWS
		*out = new(AWSUnsealConfig)
		**out = **in
	}
	return
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UnsealConfig.
func (in *UnsealConfig) DeepCopy() *UnsealConfig {
	if in == nil {
		return nil
	}
	out := new(UnsealConfig)
	in.DeepCopyInto(out)
	return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Vault) DeepCopyInto(out *Vault) {
	*out = *in
	out.TypeMeta = in.TypeMeta
	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
	in.Spec.DeepCopyInto(&out.Spec)
	in.Status.DeepCopyInto(&out.Status)
	return
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Vault.
func (in *Vault) DeepCopy() *Vault {
	if in == nil {
		return nil
	}
	out := new(Vault)
	in.DeepCopyInto(out)
	return out
}

// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *Vault) DeepCopyObject() runtime.Object {
	if c := in.DeepCopy(); c != nil {
		return c
	}
	return nil
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *VaultList) DeepCopyInto(out *VaultList) {
	*out = *in
	out.TypeMeta = in.TypeMeta
	out.ListMeta = in.ListMeta
	if in.Items != nil {
		in, out := &in.Items, &out.Items
		*out = make([]Vault, len(*in))
		for i := range *in {
			(*in)[i].DeepCopyInto(&(*out)[i])
		}
	}
	return
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VaultList.
func (in *VaultList) DeepCopy() *VaultList {
	if in == nil {
		return nil
	}
	out := new(VaultList)
	in.DeepCopyInto(out)
	return out
}

// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *VaultList) DeepCopyObject() runtime.Object {
	if c := in.DeepCopy(); c != nil {
		return c
	}
	return nil
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *VaultSpec) DeepCopyInto(out *VaultSpec) {
	*out = *in
	if in.Annotations != nil {
		in, out := &in.Annotations, &out.Annotations
		*out = make(map[string]string, len(*in))
		for key, val := range *in {
			(*out)[key] = val
		}
	}
	if in.Config != nil {
		in, out := &in.Config, &out.Config
		*out = make(map[string]interface{}, len(*in))
		for key, val := range *in {
			if val == nil {
				(*out)[key] = nil
			} else {
				(*out)[key] = val
			}
		}
	}
	if in.ExternalConfig != nil {
		in, out := &in.ExternalConfig, &out.ExternalConfig
		*out = make(map[string]interface{}, len(*in))
		for key, val := range *in {
			if val == nil {
				(*out)[key] = nil
			} else {
				(*out)[key] = val
			}
		}
	}
	in.UnsealConfig.DeepCopyInto(&out.UnsealConfig)
	out.CredentialsConfig = in.CredentialsConfig
	if in.EnvsConfig != nil {
		in, out := &in.EnvsConfig, &out.EnvsConfig
		*out = make([]v1.EnvVar, len(*in))
		for i := range *in {
			(*in)[i].DeepCopyInto(&(*out)[i])
		}
	}
	in.SecurityContext.DeepCopyInto(&out.SecurityContext)
	if in.SupportUpgrade != nil {
		in, out := &in.SupportUpgrade, &out.SupportUpgrade
		*out = new(bool)
		**out = **in
	}
	if in.EtcdAnnotations != nil {
		in, out := &in.EtcdAnnotations, &out.EtcdAnnotations
		*out = make(map[string]string, len(*in))
		for key, val := range *in {
			(*out)[key] = val
		}
	}
	in.NodeAffinity.DeepCopyInto(&out.NodeAffinity)
	if in.Volumes != nil {
		in, out := &in.Volumes, &out.Volumes
		*out = make([]v1.Volume, len(*in))
		for i := range *in {
			(*in)[i].DeepCopyInto(&(*out)[i])
		}
	}
	if in.VolumeMounts != nil {
		in, out := &in.VolumeMounts, &out.VolumeMounts
		*out = make([]v1.VolumeMount, len(*in))
		for i := range *in {
			(*in)[i].DeepCopyInto(&(*out)[i])
		}
	}
	if in.VaultEnvsConfig != nil {
		in, out := &in.VaultEnvsConfig, &out.VaultEnvsConfig
		*out = make([]v1.EnvVar, len(*in))
		for i := range *in {
			(*in)[i].DeepCopyInto(&(*out)[i])
		}
	}
	if in.Resources != nil {
		in, out := &in.Resources, &out.Resources
		*out = new(Resources)
		(*in).DeepCopyInto(*out)
	}
	return
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VaultSpec.
func (in *VaultSpec) DeepCopy() *VaultSpec {
	if in == nil {
		return nil
	}
	out := new(VaultSpec)
	in.DeepCopyInto(out)
	return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *VaultStatus) DeepCopyInto(out *VaultStatus) {
	*out = *in
	if in.Nodes != nil {
		in, out := &in.Nodes, &out.Nodes
		*out = make([]string, len(*in))
		copy(*out, *in)
	}
	return
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VaultStatus.
func (in *VaultStatus) DeepCopy() *VaultStatus {
	if in == nil {
		return nil
	}
	out := new(VaultStatus)
	in.DeepCopyInto(out)
	return out
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"os"
	"path/filepath"

	"golang.org/x/tools/go/loader"

	depbleed "github.com/depbleed/go/go-depbleed"
	"github.com/spf13/cobra"
)

var rootCmd = cobra.Command{
	Use:   "depbleed [path]",
	Short: "A Go package for dependency bleeding",
	RunE: func(cmd *cobra.Command, args []string) error {
		if len(args) > 1 {
			return errors.New("too many arguments")
		}

		path := "."

		if len(args) == 1 {
			path = args[0]
		}

		absPath, err := filepath.Abs(path)

		if err != nil {
			return fmt.Errorf("could not understand path \"%s\": %s", path, err)
		}

		gopath := os.Getenv("GOPATH")

		cmd.SilenceUsage = true

		// TODO: The current code does not handle the `./...` wildcard form but
		// it should. Which means we must also handle a list of package paths,
		// not just a single one.
		var packagePaths []string

		packagePath, err := depbleed.GetPackagePath(gopath, absPath)

		if err != nil {
			return fmt.Errorf("could not get package path: %s", err)
		}

		packagePaths = append(packagePaths, packagePath)

		for _, packagePath := range packagePaths {
			var config loader.Config
			config.Import(packagePath)
			program, err := config.Load()

			if err != nil {
				return err
			}

			info := program.Package(packagePath)

			// TODO: Remove this. For debugging purposes only.
			for name, def := range info.Defs {
				if def != nil {
					fmt.Printf("%s: %s\n", name, def.String())
				} else {
					fmt.Println("name", name)
				}
			}
		}

		return nil
	},
}

func main() {
	if err := rootCmd.Execute(); err != nil {
		os.Exit(1)
	}
}
<commit_msg>add leakage test to the main<commit_after>package main

import (
	"errors"
	"fmt"
	"os"
	"path/filepath"

	"golang.org/x/tools/go/loader"

	depbleed "github.com/depbleed/go/go-depbleed"
	"github.com/spf13/cobra"
)

var rootCmd = cobra.Command{
	Use:   "depbleed [path]",
	Short: "A Go package for dependency bleeding",
	RunE: func(cmd *cobra.Command, args []string) error {
		if len(args) > 1 {
			return errors.New("too many arguments")
		}

		path := "."

		if len(args) == 1 {
			path = args[0]
		}

		absPath, err := filepath.Abs(path)

		if err != nil {
			return fmt.Errorf("could not understand path \"%s\": %s", path, err)
		}

		gopath := os.Getenv("GOPATH")

		cmd.SilenceUsage = true

		// TODO: The current code does not handle the `./...` wildcard form but
		// it should. Which means we must also handle a list of package paths,
		// not just a single one.
		var packagePaths []string

		packagePath, err := depbleed.GetPackagePath(gopath, absPath)

		if err != nil {
			return fmt.Errorf("could not get package path: %s", err)
		}

		packagePaths = append(packagePaths, packagePath)

		for _, packagePath := range packagePaths {
			// TODO: Remove this. For debugging purposes only.
			fmt.Println("Exploring", packagePath)

			var config loader.Config
			config.Import(packagePath)
			program, err := config.Load()

			if err != nil {
				return err
			}

			info := program.Package(packagePath)

			// TODO: Remove this. For debugging purposes only.
			for name, def := range info.Defs {

				if def != nil && depbleed.IsLeaking(packagePath, def.Type().String()) {
					//This should print the file and line number too
					fmt.Printf("%s: %s is leaking \n", name, def.String())
				}
			}
		}

		return nil
	},
}

func main() {
	if err := rootCmd.Execute(); err != nil {
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>// Copyright 2009 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Adapted from encoding/xml/read_test.go.

// Package atom defines XML data structures for an Atom feed.
package atom

import (
	"encoding/xml"
	"time"
)

type Feed struct {
	XMLName xml.Name `xml:"http://www.w3.org/2005/Atom feed"`
	Title   string   `xml:"title"`
	ID      string   `xml:"id"`
	Link    []Link   `xml:"link"`
	Updated TimeStr  `xml:"updated"`
	Author  *Person  `xml:"author"`
	Entry   []*Entry `xml:"entry"`
}

type Entry struct {
	Title     string  `xml:"title"`
	ID        string  `xml:"id"`
	Link      []Link  `xml:"link"`
	Published TimeStr `xml:"published"`
	Updated   TimeStr `xml:"updated"`
	Author    *Person `xml:"author"`
	Summary   *Text   `xml:"summary"`
	Content   *Text   `xml:"content"`
}

type Link struct {
	Rel  string `xml:"rel,attr"`
	Href string `xml:"href,attr"`
}

type Person struct {
	Name     string `xml:"name"`
	URI      string `xml:"uri,omitempty"`
	Email    string `xml:"email,omitempty"`
	InnerXML string `xml:",innerxml"`
}

type Text struct {
	Type string `xml:"type,attr"`
	Body string `xml:",chardata"`
}

type TimeStr string

func Time(t time.Time) TimeStr {
	return TimeStr(t.Format("2006-01-02T15:04:05-07:00"))
}
<commit_msg>[x/blog] go.blog/pkg/atom: remove package<commit_after><|endoftext|>


<commit_before>// Copyright 2015 ThoughtWorks, Inc.

// This file is part of Gauge.

// Gauge is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Gauge is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Gauge.  If not, see <http://www.gnu.org/licenses/>.

package execution

import (
	"errors"
	"fmt"
	"github.com/getgauge/gauge/config"
	"github.com/getgauge/gauge/env"
	"github.com/getgauge/gauge/execution/result"
	"github.com/getgauge/gauge/filter"
	"github.com/getgauge/gauge/gauge_messages"
	"github.com/getgauge/gauge/logger"
	"github.com/getgauge/gauge/manifest"
	"github.com/getgauge/gauge/parser"
	"github.com/getgauge/gauge/plugin"
	"github.com/getgauge/gauge/runner"
	"path/filepath"
	"strconv"
	"strings"
	"sync"
	"time"
)

var Strategy string

const EAGER string = "eager"
const LAZY string = "lazy"

type parallelSpecExecution struct {
	wg                       sync.WaitGroup
	manifest                 *manifest.Manifest
	specifications           []*parser.Specification
	pluginHandler            *plugin.PluginHandler
	currentExecutionInfo     *gauge_messages.ExecutionInfo
	runner                   *runner.TestRunner
	aggregateResult          *result.SuiteResult
	numberOfExecutionStreams int
	logger                   *logger.GaugeLogger
	errMaps                  *validationErrMaps
}

type streamExecError struct {
	specsSkipped []string
	message      string
}

func (s streamExecError) Error() string {
	var specNames string
	for _, spec := range s.specsSkipped {
		specNames += fmt.Sprintf("%s\n", spec)
	}
	return fmt.Sprintf("The following specifications could not be executed:\n%sReason : %s.", specNames, s.message)
}

func (s streamExecError) numberOfSpecsSkipped() int {
	return len(s.specsSkipped)
}

type parallelInfo struct {
	inParallel      bool
	numberOfStreams int
}

func (self *parallelInfo) isValid() bool {
	if self.numberOfStreams < 1 {
		logger.Log.Error("Invalid input(%s) to --n flag.", strconv.Itoa(self.numberOfStreams))
		return false
	}
	currentStrategy := strings.ToLower(Strategy)
	if currentStrategy != LAZY && currentStrategy != EAGER {
		logger.Log.Error("Invalid input(%s) to --strategy flag.", Strategy)
		return false
	}
	return true
}

func isLazy() bool {
	if strings.ToLower(Strategy) == LAZY {
		return true
	}
	return false
}

func (e *parallelSpecExecution) getNumberOfStreams() int {
	streams := e.numberOfExecutionStreams
	if streams > len(e.specifications) {
		streams = len(e.specifications)
	}
	return streams
}

func (e *parallelSpecExecution) start() *result.SuiteResult {
	suiteResults := make([]*result.SuiteResult, 0)
	streams := e.getNumberOfStreams()
	e.logger.Info("Executing in %s parallel streams.", strconv.Itoa(streams))

	startTime := time.Now()
	if isLazy() {
		suiteResults = e.lazyExecution(streams)
	} else {
		suiteResults = e.eagerExecution(streams)
	}

	e.aggregateResult = e.aggregateResults(suiteResults)
	e.aggregateResult.Timestamp = startTime.Format(config.LayoutForTimeStamp)
	e.aggregateResult.ProjectName = filepath.Base(config.ProjectRoot)
	e.aggregateResult.Environment = env.CurrentEnv
	e.aggregateResult.Tags = ExecuteTags
	e.aggregateResult.ExecutionTime = int64(time.Since(startTime) / 1e6)
	return e.aggregateResult
}

func (e *parallelSpecExecution) eagerExecution(distributions int) []*result.SuiteResult {
	specCollections := filter.DistributeSpecs(e.specifications, distributions)
	suiteResultChannel := make(chan *result.SuiteResult, len(specCollections))
	for i, specCollection := range specCollections {
		go e.startSpecsExecution(specCollection, suiteResultChannel, nil, logger.NewParallelLogger(i+1))
	}
	suiteResults := make([]*result.SuiteResult, 0)
	for _, _ = range specCollections {
		suiteResults = append(suiteResults, <-suiteResultChannel)
	}
	return suiteResults
}

func (e *parallelSpecExecution) startSpecsExecution(specCollection *filter.SpecCollection, suiteResults chan *result.SuiteResult, testRunner *runner.TestRunner, log *logger.GaugeLogger) {
	var err error
	testRunner, err = runner.StartRunnerAndMakeConnection(e.manifest, log, make(chan bool))
	if err != nil {
		e.logger.Error("Failed: " + err.Error())
		e.logger.Debug("Skipping %s specifications", strconv.Itoa(len(specCollection.Specs)))
		suiteResults <- &result.SuiteResult{UnhandledErrors: []error{streamExecError{specsSkipped: specCollection.SpecNames(), message: fmt.Sprintf("Failed to start runner. %s", err.Error())}}}
		return
	}
	e.startSpecsExecutionWithRunner(specCollection, suiteResults, testRunner, log)
}

func (e *parallelSpecExecution) lazyExecution(totalStreams int) []*result.SuiteResult {
	allSpecs := &specList{}
	for _, spec := range e.specifications {
		allSpecs.specs = append(allSpecs.specs, spec)
	}
	suiteResultChannel := make(chan *result.SuiteResult, len(e.specifications))
	e.wg.Add(totalStreams)
	for i := 0; i < totalStreams; i++ {
		go e.startStream(allSpecs, logger.NewParallelLogger(i+1), suiteResultChannel)
	}
	e.wg.Wait()
	suiteResults := make([]*result.SuiteResult, 0)
	for i := 0; i < totalStreams; i++ {
		suiteResults = append(suiteResults, <-suiteResultChannel)
	}
	close(suiteResultChannel)
	return suiteResults
}

func (e *parallelSpecExecution) startStream(specs *specList, log *logger.GaugeLogger, suiteResultChannel chan *result.SuiteResult) {
	testRunner, err := runner.StartRunnerAndMakeConnection(e.manifest, log, make(chan bool))
	if err != nil {
		log.Error("Failed to start runner. Reason: %s", err.Error())
		suiteResultChannel <- &result.SuiteResult{UnhandledErrors: []error{errors.New(fmt.Sprintf("Failed to start runner. %s", err.Error()))}}
		e.wg.Done()
		return
	}
	simpleExecution := newSimpleExecution(&executionInfo{e.manifest, make([]*parser.Specification, 0), testRunner, e.pluginHandler, nil, log, e.errMaps})
	e.aggregateResult = simpleExecution.executeStream(specs)
	suiteResultChannel <- e.aggregateResult
	e.wg.Done()
}

func (e *parallelSpecExecution) startSpecsExecutionWithRunner(specCollection *filter.SpecCollection, suiteResults chan *result.SuiteResult, runner *runner.TestRunner, logger *logger.GaugeLogger) {
	execution := newExecution(&executionInfo{e.manifest, specCollection.Specs, runner, e.pluginHandler, &parallelInfo{inParallel: false}, logger, e.errMaps})
	result := execution.start()
	runner.Kill()
	suiteResults <- result
}

func (e *parallelSpecExecution) finish() {
	message := &gauge_messages.Message{MessageType: gauge_messages.Message_SuiteExecutionResult.Enum(),
		SuiteExecutionResult: &gauge_messages.SuiteExecutionResult{SuiteResult: parser.ConvertToProtoSuiteResult(e.aggregateResult)}}
	e.pluginHandler.NotifyPlugins(message)
	e.pluginHandler.GracefullyKillPlugins()
}

func (e *parallelSpecExecution) aggregateResults(suiteResults []*result.SuiteResult) *result.SuiteResult {
	aggregateResult := &result.SuiteResult{IsFailed: false, SpecResults: make([]*result.SpecResult, 0)}
	for _, result := range suiteResults {
		aggregateResult.ExecutionTime += result.ExecutionTime
		aggregateResult.SpecsFailedCount += result.SpecsFailedCount
		aggregateResult.SpecResults = append(aggregateResult.SpecResults, result.SpecResults...)
		if result.IsFailed {
			aggregateResult.IsFailed = true
		}
		if result.PreSuite != nil {
			aggregateResult.PreSuite = result.PreSuite
		}
		if result.PostSuite != nil {
			aggregateResult.PostSuite = result.PostSuite
		}
		if result.UnhandledErrors != nil {
			aggregateResult.UnhandledErrors = append(aggregateResult.UnhandledErrors, result.UnhandledErrors...)
		}
	}
	return aggregateResult
}

type specList struct {
	mutex sync.Mutex
	specs []*parser.Specification
}

func (s *specList) isEmpty() bool {
	s.mutex.Lock()
	if len(s.specs) == 0 {
		s.mutex.Unlock()
		return true
	}
	s.mutex.Unlock()
	return false
}

func (s *specList) getSpec() *parser.Specification {
	s.mutex.Lock()
	var spec *parser.Specification
	spec = s.specs[:1][0]
	s.specs = s.specs[1:]
	s.mutex.Unlock()
	return spec
}
<commit_msg>adding minor refactoring in parallelExecution.go<commit_after>// Copyright 2015 ThoughtWorks, Inc.

// This file is part of Gauge.

// Gauge is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Gauge is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Gauge.  If not, see <http://www.gnu.org/licenses/>.

package execution

import (
	"errors"
	"fmt"
	"github.com/getgauge/gauge/config"
	"github.com/getgauge/gauge/env"
	"github.com/getgauge/gauge/execution/result"
	"github.com/getgauge/gauge/filter"
	"github.com/getgauge/gauge/gauge_messages"
	"github.com/getgauge/gauge/logger"
	"github.com/getgauge/gauge/manifest"
	"github.com/getgauge/gauge/parser"
	"github.com/getgauge/gauge/plugin"
	"github.com/getgauge/gauge/runner"
	"path/filepath"
	"strconv"
	"strings"
	"sync"
	"time"
)

var Strategy string

const EAGER string = "eager"
const LAZY string = "lazy"

type parallelSpecExecution struct {
	wg                       sync.WaitGroup
	manifest                 *manifest.Manifest
	specifications           []*parser.Specification
	pluginHandler            *plugin.PluginHandler
	currentExecutionInfo     *gauge_messages.ExecutionInfo
	runner                   *runner.TestRunner
	aggregateResult          *result.SuiteResult
	numberOfExecutionStreams int
	logger                   *logger.GaugeLogger
	errMaps                  *validationErrMaps
}

type streamExecError struct {
	specsSkipped []string
	message      string
}

func (s streamExecError) Error() string {
	var specNames string
	for _, spec := range s.specsSkipped {
		specNames += fmt.Sprintf("%s\n", spec)
	}
	return fmt.Sprintf("The following specifications could not be executed:\n%sReason : %s.", specNames, s.message)
}

func (s streamExecError) numberOfSpecsSkipped() int {
	return len(s.specsSkipped)
}

type parallelInfo struct {
	inParallel      bool
	numberOfStreams int
}

func (self *parallelInfo) isValid() bool {
	if self.numberOfStreams < 1 {
		logger.Log.Error("Invalid input(%s) to --n flag.", strconv.Itoa(self.numberOfStreams))
		return false
	}
	currentStrategy := strings.ToLower(Strategy)
	if currentStrategy != LAZY && currentStrategy != EAGER {
		logger.Log.Error("Invalid input(%s) to --strategy flag.", Strategy)
		return false
	}
	return true
}

func isLazy() bool {
	return strings.ToLower(Strategy) == LAZY
}

func (e *parallelSpecExecution) getNumberOfStreams() int {
	nStreams := e.numberOfExecutionStreams
	if nStreams > len(e.specifications) {
		nStreams = len(e.specifications)
	}
	return nStreams
}

func (e *parallelSpecExecution) start() *result.SuiteResult {
	suiteResults := make([]*result.SuiteResult, 0)
	nStreams := e.getNumberOfStreams()
	e.logger.Info("Executing in %s parallel streams.", strconv.Itoa(nStreams))

	startTime := time.Now()
	if isLazy() {
		suiteResults = e.lazyExecution(nStreams)
	} else {
		suiteResults = e.eagerExecution(nStreams)
	}

	e.aggregateResult = e.aggregateResults(suiteResults)
	e.aggregateResult.Timestamp = startTime.Format(config.LayoutForTimeStamp)
	e.aggregateResult.ProjectName = filepath.Base(config.ProjectRoot)
	e.aggregateResult.Environment = env.CurrentEnv
	e.aggregateResult.Tags = ExecuteTags
	e.aggregateResult.ExecutionTime = int64(time.Since(startTime) / 1e6)
	return e.aggregateResult
}

func (e *parallelSpecExecution) eagerExecution(distributions int) []*result.SuiteResult {
	specCollections := filter.DistributeSpecs(e.specifications, distributions)
	suiteResultChannel := make(chan *result.SuiteResult, len(specCollections))
	for i, specCollection := range specCollections {
		go e.startSpecsExecution(specCollection, suiteResultChannel, nil, logger.NewParallelLogger(i+1))
	}
	suiteResults := make([]*result.SuiteResult, 0)
	for _, _ = range specCollections {
		suiteResults = append(suiteResults, <-suiteResultChannel)
	}
	return suiteResults
}

func (e *parallelSpecExecution) startSpecsExecution(specCollection *filter.SpecCollection, suiteResults chan *result.SuiteResult, testRunner *runner.TestRunner, log *logger.GaugeLogger) {
	var err error
	testRunner, err = runner.StartRunnerAndMakeConnection(e.manifest, log, make(chan bool))
	if err != nil {
		e.logger.Error("Failed: " + err.Error())
		e.logger.Debug("Skipping %s specifications", strconv.Itoa(len(specCollection.Specs)))
		suiteResults <- &result.SuiteResult{UnhandledErrors: []error{streamExecError{specsSkipped: specCollection.SpecNames(), message: fmt.Sprintf("Failed to start runner. %s", err.Error())}}}
		return
	}
	e.startSpecsExecutionWithRunner(specCollection, suiteResults, testRunner, log)
}

func (e *parallelSpecExecution) lazyExecution(totalStreams int) []*result.SuiteResult {
	allSpecs := &specList{}
	for _, spec := range e.specifications {
		allSpecs.specs = append(allSpecs.specs, spec)
	}
	suiteResultChannel := make(chan *result.SuiteResult, len(e.specifications))
	e.wg.Add(totalStreams)
	for i := 0; i < totalStreams; i++ {
		go e.startStream(allSpecs, logger.NewParallelLogger(i+1), suiteResultChannel)
	}
	e.wg.Wait()
	suiteResults := make([]*result.SuiteResult, 0)
	for i := 0; i < totalStreams; i++ {
		suiteResults = append(suiteResults, <-suiteResultChannel)
	}
	close(suiteResultChannel)
	return suiteResults
}

func (e *parallelSpecExecution) startStream(specs *specList, log *logger.GaugeLogger, suiteResultChannel chan *result.SuiteResult) {
	defer e.wg.Done()
	testRunner, err := runner.StartRunnerAndMakeConnection(e.manifest, log, make(chan bool))
	if err != nil {
		log.Error("Failed to start runner. Reason: %s", err.Error())
		suiteResultChannel <- &result.SuiteResult{UnhandledErrors: []error{errors.New(fmt.Sprintf("Failed to start runner. %s", err.Error()))}}
		return
	}
	simpleExecution := newSimpleExecution(&executionInfo{e.manifest, make([]*parser.Specification, 0), testRunner, e.pluginHandler, nil, log, e.errMaps})
	e.aggregateResult = simpleExecution.executeStream(specs)
	suiteResultChannel <- e.aggregateResult
}

func (e *parallelSpecExecution) startSpecsExecutionWithRunner(specCollection *filter.SpecCollection, suiteResults chan *result.SuiteResult, runner *runner.TestRunner, logger *logger.GaugeLogger) {
	execution := newExecution(&executionInfo{e.manifest, specCollection.Specs, runner, e.pluginHandler, &parallelInfo{inParallel: false}, logger, e.errMaps})
	result := execution.start()
	runner.Kill()
	suiteResults <- result
}

func (e *parallelSpecExecution) finish() {
	message := &gauge_messages.Message{MessageType: gauge_messages.Message_SuiteExecutionResult.Enum(),
		SuiteExecutionResult: &gauge_messages.SuiteExecutionResult{SuiteResult: parser.ConvertToProtoSuiteResult(e.aggregateResult)}}
	e.pluginHandler.NotifyPlugins(message)
	e.pluginHandler.GracefullyKillPlugins()
}

func (e *parallelSpecExecution) aggregateResults(suiteResults []*result.SuiteResult) *result.SuiteResult {
	aggregateResult := &result.SuiteResult{IsFailed: false, SpecResults: make([]*result.SpecResult, 0)}
	for _, result := range suiteResults {
		aggregateResult.ExecutionTime += result.ExecutionTime
		aggregateResult.SpecsFailedCount += result.SpecsFailedCount
		aggregateResult.SpecResults = append(aggregateResult.SpecResults, result.SpecResults...)
		if result.IsFailed {
			aggregateResult.IsFailed = true
		}
		if result.PreSuite != nil {
			aggregateResult.PreSuite = result.PreSuite
		}
		if result.PostSuite != nil {
			aggregateResult.PostSuite = result.PostSuite
		}
		if result.UnhandledErrors != nil {
			aggregateResult.UnhandledErrors = append(aggregateResult.UnhandledErrors, result.UnhandledErrors...)
		}
	}
	return aggregateResult
}

type specList struct {
	mutex sync.Mutex
	specs []*parser.Specification
}

func (s *specList) isEmpty() bool {
	s.mutex.Lock()
	if len(s.specs) == 0 {
		s.mutex.Unlock()
		return true
	}
	s.mutex.Unlock()
	return false
}

func (s *specList) getSpec() *parser.Specification {
	s.mutex.Lock()
	var spec *parser.Specification
	spec = s.specs[:1][0]
	s.specs = s.specs[1:]
	s.mutex.Unlock()
	return spec
}
<|endoftext|>


<commit_before>package terraform

import (
	"fmt"
	"log"
	"reflect"

	"github.com/hashicorp/hcl/v2"
	"github.com/hashicorp/terraform/addrs"
	"github.com/hashicorp/terraform/configs"
	"github.com/hashicorp/terraform/tfdiags"
	"github.com/zclconf/go-cty/cty"
	"github.com/zclconf/go-cty/cty/convert"
)

// EvalSetModuleCallArguments is an EvalNode implementation that sets values
// for arguments of a child module call, for later retrieval during
// expression evaluation.
type EvalSetModuleCallArguments struct {
	Module addrs.ModuleCallInstance
	Values map[string]cty.Value
}

// TODO: test
func (n *EvalSetModuleCallArguments) Eval(ctx EvalContext) (interface{}, error) {
	ctx.SetModuleCallArguments(n.Module, n.Values)
	return nil, nil
}

// EvalModuleCallArgument is an EvalNode implementation that produces the value
// for a particular variable as will be used by a child module instance.
//
// The result is written into the map given in Values, with its key
// set to the local name of the variable, disregarding the module instance
// address. Any existing values in that map are deleted first. This weird
// interface is a result of trying to be convenient for use with
// EvalContext.SetModuleCallArguments, which expects a map to merge in with
// any existing arguments.
type EvalModuleCallArgument struct {
	Addr           addrs.InputVariable
	Config         *configs.Variable
	Expr           hcl.Expression
	ModuleInstance addrs.ModuleInstance

	// If this flag is set, any diagnostics are discarded and this operation
	// will always succeed, though may produce an unknown value in the
	// event of an error.
	IgnoreDiagnostics bool

	Values map[string]cty.Value
}

func (n *EvalModuleCallArgument) Eval(ctx EvalContext) (interface{}, error) {
	// Clear out the existing mapping
	for k := range n.Values {
		delete(n.Values, k)
	}

	wantType := n.Config.Type
	name := n.Addr.Name
	expr := n.Expr

	if expr == nil {
		// Should never happen, but we'll bail out early here rather than
		// crash in case it does. We set no value at all in this case,
		// making a subsequent call to EvalContext.SetModuleCallArguments
		// a no-op.
		log.Printf("[ERROR] attempt to evaluate %s with nil expression", n.Addr.String())
		return nil, nil
	}

	// Get the repetition data for this module instance,
	// so we can create the appropriate scope for evaluating our expression
	moduleInstanceRepetitionData := ctx.InstanceExpander().GetModuleInstanceRepetitionData(n.ModuleInstance)
	scope := ctx.EvaluationScope(nil, moduleInstanceRepetitionData)
	val, diags := scope.EvalExpr(expr, cty.DynamicPseudoType)

	// We intentionally passed DynamicPseudoType to EvaluateExpr above because
	// now we can do our own local type conversion and produce an error message
	// with better context if it fails.
	var convErr error
	val, convErr = convert.Convert(val, wantType)
	if convErr != nil {
		diags = diags.Append(&hcl.Diagnostic{
			Severity: hcl.DiagError,
			Summary:  "Invalid value for module argument",
			Detail: fmt.Sprintf(
				"The given value is not suitable for child module variable %q defined at %s: %s.",
				name, n.Config.DeclRange.String(), convErr,
			),
			Subject: expr.Range().Ptr(),
		})
		// We'll return a placeholder unknown value to avoid producing
		// redundant downstream errors.
		val = cty.UnknownVal(wantType)
	}

	n.Values[name] = val
	if n.IgnoreDiagnostics {
		return nil, nil
	}
	return nil, diags.ErrWithWarnings()
}

// evalVariableValidations is an EvalNode implementation that ensures that
// all of the configured custom validations for a variable are passing.
//
// This must be used only after any side-effects that make the value of the
// variable available for use in expression evaluation, such as
// EvalModuleCallArgument for variables in descendent modules.
type evalVariableValidations struct {
	Addr   addrs.AbsInputVariableInstance
	Config *configs.Variable

	// Expr is the expression that provided the value for the variable, if any.
	// This will be nil for root module variables, because their values come
	// from outside the configuration.
	Expr hcl.Expression

	// If this flag is set, this node becomes a no-op.
	// This is here for consistency with EvalModuleCallArgument so that it
	// can be populated with the same value, where needed.
	IgnoreDiagnostics bool
}

func (n *evalVariableValidations) Eval(ctx EvalContext) (interface{}, error) {
	if n.Config == nil || n.IgnoreDiagnostics || len(n.Config.Validations) == 0 {
		log.Printf("[TRACE] evalVariableValidations: not active for %s, so skipping", n.Addr)
		return nil, nil
	}

	var diags tfdiags.Diagnostics

	// Variable nodes evaluate in the parent module to where they were declared
	// because the value expression (n.Expr, if set) comes from the calling
	// "module" block in the parent module.
	//
	// Validation expressions are statically validated (during configuration
	// loading) to refer only to the variable being validated, so we can
	// bypass our usual evaluation machinery here and just produce a minimal
	// evaluation context containing just the required value, and thus avoid
	// the problem that ctx's evaluation functions refer to the wrong module.
	val := ctx.GetVariableValue(n.Addr)
	hclCtx := &hcl.EvalContext{
		Variables: map[string]cty.Value{
			"var": cty.ObjectVal(map[string]cty.Value{
				n.Config.Name: val,
			}),
		},
		Functions: ctx.EvaluationScope(nil, EvalDataForNoInstanceKey).Functions(),
	}

	for _, validation := range n.Config.Validations {
		const errInvalidCondition = "Invalid variable validation result"
		const errInvalidValue = "Invalid value for variable"

		result, moreDiags := validation.Condition.Value(hclCtx)
		diags = diags.Append(moreDiags)
		if moreDiags.HasErrors() {
			log.Printf("[TRACE] evalVariableValidations: %s rule %s condition expression failed: %s", n.Addr, validation.DeclRange, diags.Err().Error())
		}
		if !result.IsKnown() {
			log.Printf("[TRACE] evalVariableValidations: %s rule %s condition value is unknown, so skipping validation for now", n.Addr, validation.DeclRange)
			continue // We'll wait until we've learned more, then.
		}
		if result.IsNull() {
			diags = diags.Append(&hcl.Diagnostic{
				Severity:    hcl.DiagError,
				Summary:     errInvalidCondition,
				Detail:      "Validation condition expression must return either true or false, not null.",
				Subject:     validation.Condition.Range().Ptr(),
				Expression:  validation.Condition,
				EvalContext: hclCtx,
			})
			continue
		}
		var err error
		result, err = convert.Convert(result, cty.Bool)
		if err != nil {
			diags = diags.Append(&hcl.Diagnostic{
				Severity:    hcl.DiagError,
				Summary:     errInvalidCondition,
				Detail:      fmt.Sprintf("Invalid validation condition result value: %s.", tfdiags.FormatError(err)),
				Subject:     validation.Condition.Range().Ptr(),
				Expression:  validation.Condition,
				EvalContext: hclCtx,
			})
			continue
		}

		if result.False() {
			if n.Expr != nil {
				diags = diags.Append(&hcl.Diagnostic{
					Severity: hcl.DiagError,
					Summary:  errInvalidValue,
					Detail:   fmt.Sprintf("%s\n\nThis was checked by the validation rule at %s.", validation.ErrorMessage, validation.DeclRange.String()),
					Subject:  n.Expr.Range().Ptr(),
				})
			} else {
				// Since we don't have a source expression for a root module
				// variable, we'll just report the error from the perspective
				// of the variable declaration itself.
				diags = diags.Append(&hcl.Diagnostic{
					Severity: hcl.DiagError,
					Summary:  errInvalidValue,
					Detail:   fmt.Sprintf("%s\n\nThis was checked by the validation rule at %s.", validation.ErrorMessage, validation.DeclRange.String()),
					Subject:  n.Config.DeclRange.Ptr(),
				})
			}
		}
	}

	return nil, diags.ErrWithWarnings()
}

// hclTypeName returns the name of the type that would represent this value in
// a config file, or falls back to the Go type name if there's no corresponding
// HCL type. This is used for formatted output, not for comparing types.
func hclTypeName(i interface{}) string {
	switch k := reflect.Indirect(reflect.ValueOf(i)).Kind(); k {
	case reflect.Bool:
		return "boolean"
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
		reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32,
		reflect.Uint64, reflect.Uintptr, reflect.Float32, reflect.Float64:
		return "number"
	case reflect.Array, reflect.Slice:
		return "list"
	case reflect.Map:
		return "map"
	case reflect.String:
		return "string"
	default:
		// fall back to the Go type if there's no match
		return k.String()
	}
}
<commit_msg>Update comment to reflect new code<commit_after>package terraform

import (
	"fmt"
	"log"
	"reflect"

	"github.com/hashicorp/hcl/v2"
	"github.com/hashicorp/terraform/addrs"
	"github.com/hashicorp/terraform/configs"
	"github.com/hashicorp/terraform/tfdiags"
	"github.com/zclconf/go-cty/cty"
	"github.com/zclconf/go-cty/cty/convert"
)

// EvalSetModuleCallArguments is an EvalNode implementation that sets values
// for arguments of a child module call, for later retrieval during
// expression evaluation.
type EvalSetModuleCallArguments struct {
	Module addrs.ModuleCallInstance
	Values map[string]cty.Value
}

// TODO: test
func (n *EvalSetModuleCallArguments) Eval(ctx EvalContext) (interface{}, error) {
	ctx.SetModuleCallArguments(n.Module, n.Values)
	return nil, nil
}

// EvalModuleCallArgument is an EvalNode implementation that produces the value
// for a particular variable as will be used by a child module instance.
//
// The result is written into the map given in Values, with its key
// set to the local name of the variable, disregarding the module instance
// address. Any existing values in that map are deleted first. This weird
// interface is a result of trying to be convenient for use with
// EvalContext.SetModuleCallArguments, which expects a map to merge in with
// any existing arguments.
type EvalModuleCallArgument struct {
	Addr           addrs.InputVariable
	Config         *configs.Variable
	Expr           hcl.Expression
	ModuleInstance addrs.ModuleInstance

	// If this flag is set, any diagnostics are discarded and this operation
	// will always succeed, though may produce an unknown value in the
	// event of an error.
	IgnoreDiagnostics bool

	Values map[string]cty.Value
}

func (n *EvalModuleCallArgument) Eval(ctx EvalContext) (interface{}, error) {
	// Clear out the existing mapping
	for k := range n.Values {
		delete(n.Values, k)
	}

	wantType := n.Config.Type
	name := n.Addr.Name
	expr := n.Expr

	if expr == nil {
		// Should never happen, but we'll bail out early here rather than
		// crash in case it does. We set no value at all in this case,
		// making a subsequent call to EvalContext.SetModuleCallArguments
		// a no-op.
		log.Printf("[ERROR] attempt to evaluate %s with nil expression", n.Addr.String())
		return nil, nil
	}

	// Get the repetition data for this module instance,
	// so we can create the appropriate scope for evaluating our expression
	moduleInstanceRepetitionData := ctx.InstanceExpander().GetModuleInstanceRepetitionData(n.ModuleInstance)
	scope := ctx.EvaluationScope(nil, moduleInstanceRepetitionData)
	val, diags := scope.EvalExpr(expr, cty.DynamicPseudoType)

	// We intentionally passed DynamicPseudoType to EvalExpr above because
	// now we can do our own local type conversion and produce an error message
	// with better context if it fails.
	var convErr error
	val, convErr = convert.Convert(val, wantType)
	if convErr != nil {
		diags = diags.Append(&hcl.Diagnostic{
			Severity: hcl.DiagError,
			Summary:  "Invalid value for module argument",
			Detail: fmt.Sprintf(
				"The given value is not suitable for child module variable %q defined at %s: %s.",
				name, n.Config.DeclRange.String(), convErr,
			),
			Subject: expr.Range().Ptr(),
		})
		// We'll return a placeholder unknown value to avoid producing
		// redundant downstream errors.
		val = cty.UnknownVal(wantType)
	}

	n.Values[name] = val
	if n.IgnoreDiagnostics {
		return nil, nil
	}
	return nil, diags.ErrWithWarnings()
}

// evalVariableValidations is an EvalNode implementation that ensures that
// all of the configured custom validations for a variable are passing.
//
// This must be used only after any side-effects that make the value of the
// variable available for use in expression evaluation, such as
// EvalModuleCallArgument for variables in descendent modules.
type evalVariableValidations struct {
	Addr   addrs.AbsInputVariableInstance
	Config *configs.Variable

	// Expr is the expression that provided the value for the variable, if any.
	// This will be nil for root module variables, because their values come
	// from outside the configuration.
	Expr hcl.Expression

	// If this flag is set, this node becomes a no-op.
	// This is here for consistency with EvalModuleCallArgument so that it
	// can be populated with the same value, where needed.
	IgnoreDiagnostics bool
}

func (n *evalVariableValidations) Eval(ctx EvalContext) (interface{}, error) {
	if n.Config == nil || n.IgnoreDiagnostics || len(n.Config.Validations) == 0 {
		log.Printf("[TRACE] evalVariableValidations: not active for %s, so skipping", n.Addr)
		return nil, nil
	}

	var diags tfdiags.Diagnostics

	// Variable nodes evaluate in the parent module to where they were declared
	// because the value expression (n.Expr, if set) comes from the calling
	// "module" block in the parent module.
	//
	// Validation expressions are statically validated (during configuration
	// loading) to refer only to the variable being validated, so we can
	// bypass our usual evaluation machinery here and just produce a minimal
	// evaluation context containing just the required value, and thus avoid
	// the problem that ctx's evaluation functions refer to the wrong module.
	val := ctx.GetVariableValue(n.Addr)
	hclCtx := &hcl.EvalContext{
		Variables: map[string]cty.Value{
			"var": cty.ObjectVal(map[string]cty.Value{
				n.Config.Name: val,
			}),
		},
		Functions: ctx.EvaluationScope(nil, EvalDataForNoInstanceKey).Functions(),
	}

	for _, validation := range n.Config.Validations {
		const errInvalidCondition = "Invalid variable validation result"
		const errInvalidValue = "Invalid value for variable"

		result, moreDiags := validation.Condition.Value(hclCtx)
		diags = diags.Append(moreDiags)
		if moreDiags.HasErrors() {
			log.Printf("[TRACE] evalVariableValidations: %s rule %s condition expression failed: %s", n.Addr, validation.DeclRange, diags.Err().Error())
		}
		if !result.IsKnown() {
			log.Printf("[TRACE] evalVariableValidations: %s rule %s condition value is unknown, so skipping validation for now", n.Addr, validation.DeclRange)
			continue // We'll wait until we've learned more, then.
		}
		if result.IsNull() {
			diags = diags.Append(&hcl.Diagnostic{
				Severity:    hcl.DiagError,
				Summary:     errInvalidCondition,
				Detail:      "Validation condition expression must return either true or false, not null.",
				Subject:     validation.Condition.Range().Ptr(),
				Expression:  validation.Condition,
				EvalContext: hclCtx,
			})
			continue
		}
		var err error
		result, err = convert.Convert(result, cty.Bool)
		if err != nil {
			diags = diags.Append(&hcl.Diagnostic{
				Severity:    hcl.DiagError,
				Summary:     errInvalidCondition,
				Detail:      fmt.Sprintf("Invalid validation condition result value: %s.", tfdiags.FormatError(err)),
				Subject:     validation.Condition.Range().Ptr(),
				Expression:  validation.Condition,
				EvalContext: hclCtx,
			})
			continue
		}

		if result.False() {
			if n.Expr != nil {
				diags = diags.Append(&hcl.Diagnostic{
					Severity: hcl.DiagError,
					Summary:  errInvalidValue,
					Detail:   fmt.Sprintf("%s\n\nThis was checked by the validation rule at %s.", validation.ErrorMessage, validation.DeclRange.String()),
					Subject:  n.Expr.Range().Ptr(),
				})
			} else {
				// Since we don't have a source expression for a root module
				// variable, we'll just report the error from the perspective
				// of the variable declaration itself.
				diags = diags.Append(&hcl.Diagnostic{
					Severity: hcl.DiagError,
					Summary:  errInvalidValue,
					Detail:   fmt.Sprintf("%s\n\nThis was checked by the validation rule at %s.", validation.ErrorMessage, validation.DeclRange.String()),
					Subject:  n.Config.DeclRange.Ptr(),
				})
			}
		}
	}

	return nil, diags.ErrWithWarnings()
}

// hclTypeName returns the name of the type that would represent this value in
// a config file, or falls back to the Go type name if there's no corresponding
// HCL type. This is used for formatted output, not for comparing types.
func hclTypeName(i interface{}) string {
	switch k := reflect.Indirect(reflect.ValueOf(i)).Kind(); k {
	case reflect.Bool:
		return "boolean"
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
		reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32,
		reflect.Uint64, reflect.Uintptr, reflect.Float32, reflect.Float64:
		return "number"
	case reflect.Array, reflect.Slice:
		return "list"
	case reflect.Map:
		return "map"
	case reflect.String:
		return "string"
	default:
		// fall back to the Go type if there's no match
		return k.String()
	}
}
<|endoftext|>


<commit_before>package terraform

import (
	"fmt"
	"log"
	"reflect"
	"strings"

	"github.com/hashicorp/terraform/config"
	"github.com/hashicorp/terraform/config/module"
	"github.com/hashicorp/terraform/helper/hilmapstructure"
)

// EvalTypeCheckVariable is an EvalNode which ensures that the variable
// values which are assigned as inputs to a module (including the root)
// match the types which are either declared for the variables explicitly
// or inferred from the default values.
//
// In order to achieve this three things are required:
//     - a map of the proposed variable values
//     - the configuration tree of the module in which the variable is
//       declared
//     - the path to the module (so we know which part of the tree to
//       compare the values against).
type EvalTypeCheckVariable struct {
	Variables  map[string]interface{}
	ModulePath []string
	ModuleTree *module.Tree
}

func (n *EvalTypeCheckVariable) Eval(ctx EvalContext) (interface{}, error) {
	currentTree := n.ModuleTree
	for _, pathComponent := range n.ModulePath[1:] {
		currentTree = currentTree.Children()[pathComponent]
	}
	targetConfig := currentTree.Config()

	prototypes := make(map[string]config.VariableType)
	for _, variable := range targetConfig.Variables {
		prototypes[variable.Name] = variable.Type()
	}

	// Only display a module in an error message if we are not in the root module
	modulePathDescription := fmt.Sprintf(" in module %s", strings.Join(n.ModulePath[1:], "."))
	if len(n.ModulePath) == 1 {
		modulePathDescription = ""
	}

	for name, declaredType := range prototypes {
		proposedValue, ok := n.Variables[name]
		if !ok {
			// This means the default value should be used as no overriding value
			// has been set. Therefore we should continue as no check is necessary.
			continue
		}

		if proposedValue == config.UnknownVariableValue {
			continue
		}

		switch declaredType {
		case config.VariableTypeString:
			switch proposedValue.(type) {
			case string:
				continue
			default:
				return nil, fmt.Errorf("variable %s%s should be type %s, got %s",
					name, modulePathDescription, declaredType.Printable(), hclTypeName(proposedValue))
			}
		case config.VariableTypeMap:
			switch proposedValue.(type) {
			case map[string]interface{}:
				continue
			default:
				return nil, fmt.Errorf("variable %s%s should be type %s, got %s",
					name, modulePathDescription, declaredType.Printable(), hclTypeName(proposedValue))
			}
		case config.VariableTypeList:
			switch proposedValue.(type) {
			case []interface{}:
				continue
			default:
				return nil, fmt.Errorf("variable %s%s should be type %s, got %s",
					name, modulePathDescription, declaredType.Printable(), hclTypeName(proposedValue))
			}
		default:
			return nil, fmt.Errorf("variable %s%s should be type %s, got type string",
				name, modulePathDescription, declaredType.Printable())
		}
	}

	return nil, nil
}

// EvalSetVariables is an EvalNode implementation that sets the variables
// explicitly for interpolation later.
type EvalSetVariables struct {
	Module    *string
	Variables map[string]interface{}
}

// TODO: test
func (n *EvalSetVariables) Eval(ctx EvalContext) (interface{}, error) {
	ctx.SetVariables(*n.Module, n.Variables)
	return nil, nil
}

// EvalVariableBlock is an EvalNode implementation that evaluates the
// given configuration, and uses the final values as a way to set the
// mapping.
type EvalVariableBlock struct {
	Config         **ResourceConfig
	VariableValues map[string]interface{}
}

// TODO: test
func (n *EvalVariableBlock) Eval(ctx EvalContext) (interface{}, error) {
	// Clear out the existing mapping
	for k, _ := range n.VariableValues {
		delete(n.VariableValues, k)
	}

	// Get our configuration
	rc := *n.Config
	for k, v := range rc.Config {
		var vString string
		if err := hilmapstructure.WeakDecode(v, &vString); err == nil {
			n.VariableValues[k] = vString
			continue
		}

		var vMap map[string]interface{}
		if err := hilmapstructure.WeakDecode(v, &vMap); err == nil {
			n.VariableValues[k] = vMap
			continue
		}

		var vSlice []interface{}
		if err := hilmapstructure.WeakDecode(v, &vSlice); err == nil {
			n.VariableValues[k] = vSlice
			continue
		}

		return nil, fmt.Errorf("Variable value for %s is not a string, list or map type", k)
	}
	for k, _ := range rc.Raw {
		if _, ok := n.VariableValues[k]; !ok {
			n.VariableValues[k] = config.UnknownVariableValue
		}
	}

	return nil, nil
}

// EvalCoerceMapVariable is an EvalNode implementation that recognizes a
// specific ambiguous HCL parsing situation and resolves it. In HCL parsing, a
// bare map literal is indistinguishable from a list of maps w/ one element.
//
// We take all the same inputs as EvalTypeCheckVariable above, since we need
// both the target type and the proposed value in order to properly coerce.
type EvalCoerceMapVariable struct {
	Variables  map[string]interface{}
	ModulePath []string
	ModuleTree *module.Tree
}

// Eval implements the EvalNode interface. See EvalCoerceMapVariable for
// details.
func (n *EvalCoerceMapVariable) Eval(ctx EvalContext) (interface{}, error) {
	currentTree := n.ModuleTree
	for _, pathComponent := range n.ModulePath[1:] {
		currentTree = currentTree.Children()[pathComponent]
	}
	targetConfig := currentTree.Config()

	prototypes := make(map[string]config.VariableType)
	for _, variable := range targetConfig.Variables {
		prototypes[variable.Name] = variable.Type()
	}

	for name, declaredType := range prototypes {
		if declaredType != config.VariableTypeMap {
			continue
		}

		proposedValue, ok := n.Variables[name]
		if !ok {
			continue
		}

		if list, ok := proposedValue.([]interface{}); ok && len(list) == 1 {
			if m, ok := list[0].(map[string]interface{}); ok {
				log.Printf("[DEBUG] EvalCoerceMapVariable: "+
					"Coercing single element list into map: %#v", m)
				n.Variables[name] = m
			}
		}
	}

	return nil, nil
}

// hclTypeName returns the name of the type that would represent this value in
// a config file, or falls back to the Go type name if there's no corresponding
// HCL type. This is used for formatted output, not for comparing types.
func hclTypeName(i interface{}) string {
	switch k := reflect.Indirect(reflect.ValueOf(i)).Kind(); k {
	case reflect.Bool:
		return "boolean"
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
		reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32,
		reflect.Uint64, reflect.Uintptr, reflect.Float32, reflect.Float64:
		return "number"
	case reflect.Array, reflect.Slice:
		return "list"
	case reflect.Map:
		return "map"
	case reflect.String:
		return "string"
	default:
		// fall back to the Go type if there's no match
		return k.String()
	}
}
<commit_msg>core: Set all unknown keys to UnknownVariableValue<commit_after>package terraform

import (
	"fmt"
	"log"
	"reflect"
	"strconv"
	"strings"

	"github.com/hashicorp/terraform/config"
	"github.com/hashicorp/terraform/config/module"
	"github.com/hashicorp/terraform/helper/hilmapstructure"
)

// EvalTypeCheckVariable is an EvalNode which ensures that the variable
// values which are assigned as inputs to a module (including the root)
// match the types which are either declared for the variables explicitly
// or inferred from the default values.
//
// In order to achieve this three things are required:
//     - a map of the proposed variable values
//     - the configuration tree of the module in which the variable is
//       declared
//     - the path to the module (so we know which part of the tree to
//       compare the values against).
type EvalTypeCheckVariable struct {
	Variables  map[string]interface{}
	ModulePath []string
	ModuleTree *module.Tree
}

func (n *EvalTypeCheckVariable) Eval(ctx EvalContext) (interface{}, error) {
	currentTree := n.ModuleTree
	for _, pathComponent := range n.ModulePath[1:] {
		currentTree = currentTree.Children()[pathComponent]
	}
	targetConfig := currentTree.Config()

	prototypes := make(map[string]config.VariableType)
	for _, variable := range targetConfig.Variables {
		prototypes[variable.Name] = variable.Type()
	}

	// Only display a module in an error message if we are not in the root module
	modulePathDescription := fmt.Sprintf(" in module %s", strings.Join(n.ModulePath[1:], "."))
	if len(n.ModulePath) == 1 {
		modulePathDescription = ""
	}

	for name, declaredType := range prototypes {
		proposedValue, ok := n.Variables[name]
		if !ok {
			// This means the default value should be used as no overriding value
			// has been set. Therefore we should continue as no check is necessary.
			continue
		}

		if proposedValue == config.UnknownVariableValue {
			continue
		}

		switch declaredType {
		case config.VariableTypeString:
			switch proposedValue.(type) {
			case string:
				continue
			default:
				return nil, fmt.Errorf("variable %s%s should be type %s, got %s",
					name, modulePathDescription, declaredType.Printable(), hclTypeName(proposedValue))
			}
		case config.VariableTypeMap:
			switch proposedValue.(type) {
			case map[string]interface{}:
				continue
			default:
				return nil, fmt.Errorf("variable %s%s should be type %s, got %s",
					name, modulePathDescription, declaredType.Printable(), hclTypeName(proposedValue))
			}
		case config.VariableTypeList:
			switch proposedValue.(type) {
			case []interface{}:
				continue
			default:
				return nil, fmt.Errorf("variable %s%s should be type %s, got %s",
					name, modulePathDescription, declaredType.Printable(), hclTypeName(proposedValue))
			}
		default:
			return nil, fmt.Errorf("variable %s%s should be type %s, got type string",
				name, modulePathDescription, declaredType.Printable())
		}
	}

	return nil, nil
}

// EvalSetVariables is an EvalNode implementation that sets the variables
// explicitly for interpolation later.
type EvalSetVariables struct {
	Module    *string
	Variables map[string]interface{}
}

// TODO: test
func (n *EvalSetVariables) Eval(ctx EvalContext) (interface{}, error) {
	ctx.SetVariables(*n.Module, n.Variables)
	return nil, nil
}

// EvalVariableBlock is an EvalNode implementation that evaluates the
// given configuration, and uses the final values as a way to set the
// mapping.
type EvalVariableBlock struct {
	Config         **ResourceConfig
	VariableValues map[string]interface{}
}

// TODO: test
func (n *EvalVariableBlock) Eval(ctx EvalContext) (interface{}, error) {
	// Clear out the existing mapping
	for k, _ := range n.VariableValues {
		delete(n.VariableValues, k)
	}

	// Get our configuration
	rc := *n.Config
	for k, v := range rc.Config {
		var vString string
		if err := hilmapstructure.WeakDecode(v, &vString); err == nil {
			n.VariableValues[k] = vString
			continue
		}

		var vMap map[string]interface{}
		if err := hilmapstructure.WeakDecode(v, &vMap); err == nil {
			n.VariableValues[k] = vMap
			continue
		}

		var vSlice []interface{}
		if err := hilmapstructure.WeakDecode(v, &vSlice); err == nil {
			n.VariableValues[k] = vSlice
			continue
		}

		return nil, fmt.Errorf("Variable value for %s is not a string, list or map type", k)
	}

	for _, path := range rc.ComputedKeys {
		log.Printf("[DEBUG] Setting Unknown Variable Value for computed key: %s", path)
		err := n.setUnknownVariableValueForPath(path)
		if err != nil {
			return nil, err
		}
	}

	return nil, nil
}

func (n *EvalVariableBlock) setUnknownVariableValueForPath(path string) error {
	pathComponents := strings.Split(path, ".")

	if len(pathComponents) < 1 {
		return fmt.Errorf("No path comoponents in %s", path)
	}

	if len(pathComponents) == 1 {
		// Special case the "top level" since we know the type
		if _, ok := n.VariableValues[pathComponents[0]]; !ok {
			n.VariableValues[pathComponents[0]] = config.UnknownVariableValue
		}
		return nil
	}

	// Otherwise find the correct point in the tree and then set to unknown
	var current interface{} = n.VariableValues[pathComponents[0]]
	for i := 1; i < len(pathComponents); i++ {
		switch current.(type) {
		case []interface{}, []map[string]interface{}:
			tCurrent := current.([]interface{})
			index, err := strconv.Atoi(pathComponents[i])
			if err != nil {
				return fmt.Errorf("Cannot convert %s to slice index in path %s",
					pathComponents[i], path)
			}
			current = tCurrent[index]
		case map[string]interface{}:
			tCurrent := current.(map[string]interface{})
			if val, hasVal := tCurrent[pathComponents[i]]; hasVal {
				current = val
				continue
			}

			tCurrent[pathComponents[i]] = config.UnknownVariableValue
			break
		}
	}

	return nil
}

// EvalCoerceMapVariable is an EvalNode implementation that recognizes a
// specific ambiguous HCL parsing situation and resolves it. In HCL parsing, a
// bare map literal is indistinguishable from a list of maps w/ one element.
//
// We take all the same inputs as EvalTypeCheckVariable above, since we need
// both the target type and the proposed value in order to properly coerce.
type EvalCoerceMapVariable struct {
	Variables  map[string]interface{}
	ModulePath []string
	ModuleTree *module.Tree
}

// Eval implements the EvalNode interface. See EvalCoerceMapVariable for
// details.
func (n *EvalCoerceMapVariable) Eval(ctx EvalContext) (interface{}, error) {
	currentTree := n.ModuleTree
	for _, pathComponent := range n.ModulePath[1:] {
		currentTree = currentTree.Children()[pathComponent]
	}
	targetConfig := currentTree.Config()

	prototypes := make(map[string]config.VariableType)
	for _, variable := range targetConfig.Variables {
		prototypes[variable.Name] = variable.Type()
	}

	for name, declaredType := range prototypes {
		if declaredType != config.VariableTypeMap {
			continue
		}

		proposedValue, ok := n.Variables[name]
		if !ok {
			continue
		}

		if list, ok := proposedValue.([]interface{}); ok && len(list) == 1 {
			if m, ok := list[0].(map[string]interface{}); ok {
				log.Printf("[DEBUG] EvalCoerceMapVariable: "+
					"Coercing single element list into map: %#v", m)
				n.Variables[name] = m
			}
		}
	}

	return nil, nil
}

// hclTypeName returns the name of the type that would represent this value in
// a config file, or falls back to the Go type name if there's no corresponding
// HCL type. This is used for formatted output, not for comparing types.
func hclTypeName(i interface{}) string {
	switch k := reflect.Indirect(reflect.ValueOf(i)).Kind(); k {
	case reflect.Bool:
		return "boolean"
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
		reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32,
		reflect.Uint64, reflect.Uintptr, reflect.Float32, reflect.Float64:
		return "number"
	case reflect.Array, reflect.Slice:
		return "list"
	case reflect.Map:
		return "map"
	case reflect.String:
		return "string"
	default:
		// fall back to the Go type if there's no match
		return k.String()
	}
}
<|endoftext|>


<commit_before>package expr

import (
	"math"
	"strconv"
	"testing"

	"github.com/grafana/metrictank/api/models"
	"github.com/grafana/metrictank/schema"
	"github.com/grafana/metrictank/test"
)

func TestOffsetToZeroNoInput(t *testing.T) {
	testOffsetToZero("no_input", []models.Series{}, []models.Series{}, t)
}

func TestOffsetToZeroSingle(t *testing.T) {
	const offset = 10
	in := []schema.Point{
		{Val: 0 + offset, Ts: 10},
		{Val: 0 + offset, Ts: 20},
		{Val: 5.5 + offset, Ts: 30},
		{Val: math.NaN(), Ts: 40},
		{Val: math.NaN(), Ts: 50},
		{Val: 1234567890 + offset, Ts: 60},
	}
	out := []schema.Point{
		{Val: 0, Ts: 10},
		{Val: 0, Ts: 20},
		{Val: 5.5, Ts: 30},
		{Val: math.NaN(), Ts: 40},
		{Val: math.NaN(), Ts: 50},
		{Val: 1234567890, Ts: 60},
	}

	testOffsetToZero(
		"single",
		[]models.Series{
			getSeriesNamed("a", in),
		},
		[]models.Series{
			getSeriesNamed("offsetToZero(a)", out),
		},
		t,
	)
}

func TestOffsetToZeroMultiple(t *testing.T) {
	const offset = 10
	in := []schema.Point{
		{Val: 0 + offset, Ts: 10},
		{Val: 0 + offset, Ts: 20},
		{Val: 5.5 + offset, Ts: 30},
		{Val: math.NaN(), Ts: 40},
		{Val: math.NaN(), Ts: 50},
		{Val: 1234567890 + offset, Ts: 60},
	}
	out := []schema.Point{
		{Val: 0, Ts: 10},
		{Val: 0, Ts: 20},
		{Val: 5.5, Ts: 30},
		{Val: math.NaN(), Ts: 40},
		{Val: math.NaN(), Ts: 50},
		{Val: 1234567890, Ts: 60},
	}

	testOffsetToZero(
		"single",
		[]models.Series{
			getSeriesNamed("a", in),
			getSeriesNamed("a2", in),
		},
		[]models.Series{
			getSeriesNamed("offsetToZero(a)", out),
			getSeriesNamed("offsetToZero(a2)", out),
		},
		t,
	)
}

func testOffsetToZero(name string, in []models.Series, out []models.Series, t *testing.T) {
	f := NewOffsetToZero()
	f.(*FuncOffsetToZero).in = NewMock(in)

	inputCopy := models.SeriesCopy(in) // to later verify that it is unchanged

	dataMap := initDataMap(in)

	got, err := f.Exec(dataMap)
	if err := equalOutput(out, got, nil, err); err != nil {
		t.Fatalf("Case %s: %s", name, err)
	}

	t.Run("DidNotModifyInput", func(t *testing.T) {
		if err := equalOutput(inputCopy, in, nil, nil); err != nil {
			t.Fatalf("Case %s: Input was modified, err = %s", name, err)
		}
	})

	t.Run("DoesNotDoubleReturnPoints", func(t *testing.T) {
		if err := dataMap.CheckForOverlappingPoints(); err != nil {
			t.Fatalf("Case %s: Point slices in datamap overlap, err = %s", name, err)
		}
	})

	t.Run("OutputIsCanonical", func(t *testing.T) {
		for i, s := range got {
			if !s.IsCanonical() {
				t.Fatalf("Case %s: output series %d is not canonical: %v", name, i, s)
			}
		}
	})
}

func BenchmarkOffsetToZero10k_1NoNulls(b *testing.B) {
	benchmarkOffsetToZero(b, 1, test.RandFloats10k, test.RandFloats10k)
}
func BenchmarkOffsetToZero10k_10NoNulls(b *testing.B) {
	benchmarkOffsetToZero(b, 10, test.RandFloats10k, test.RandFloats10k)
}
func BenchmarkOffsetToZero10k_100NoNulls(b *testing.B) {
	benchmarkOffsetToZero(b, 100, test.RandFloats10k, test.RandFloats10k)
}
func BenchmarkOffsetToZero10k_1000NoNulls(b *testing.B) {
	benchmarkOffsetToZero(b, 1000, test.RandFloats10k, test.RandFloats10k)
}

func BenchmarkOffsetToZero10k_1SomeSeriesHalfNulls(b *testing.B) {
	benchmarkOffsetToZero(b, 1, test.RandFloats10k, test.RandFloatsWithNulls10k)
}
func BenchmarkOffsetToZero10k_10SomeSeriesHalfNulls(b *testing.B) {
	benchmarkOffsetToZero(b, 10, test.RandFloats10k, test.RandFloatsWithNulls10k)
}
func BenchmarkOffsetToZero10k_100SomeSeriesHalfNulls(b *testing.B) {
	benchmarkOffsetToZero(b, 100, test.RandFloats10k, test.RandFloatsWithNulls10k)
}
func BenchmarkOffsetToZero10k_1000SomeSeriesHalfNulls(b *testing.B) {
	benchmarkOffsetToZero(b, 1000, test.RandFloats10k, test.RandFloatsWithNulls10k)
}

func BenchmarkOffsetToZero10k_1AllSeriesHalfNulls(b *testing.B) {
	benchmarkOffsetToZero(b, 1, test.RandFloatsWithNulls10k, test.RandFloatsWithNulls10k)
}
func BenchmarkOffsetToZero10k_10AllSeriesHalfNulls(b *testing.B) {
	benchmarkOffsetToZero(b, 10, test.RandFloatsWithNulls10k, test.RandFloatsWithNulls10k)
}
func BenchmarkOffsetToZero10k_100AllSeriesHalfNulls(b *testing.B) {
	benchmarkOffsetToZero(b, 100, test.RandFloatsWithNulls10k, test.RandFloatsWithNulls10k)
}
func BenchmarkOffsetToZero10k_1000AllSeriesHalfNulls(b *testing.B) {
	benchmarkOffsetToZero(b, 1000, test.RandFloatsWithNulls10k, test.RandFloatsWithNulls10k)
}

func benchmarkOffsetToZero(b *testing.B, numSeries int, fn0, fn1 func() []schema.Point) {
	var input []models.Series
	for i := 0; i < numSeries; i++ {
		series := models.Series{
			QueryPatt: strconv.Itoa(i),
		}
		if i%2 == 0 {
			series.Datapoints = fn0()
		} else {
			series.Datapoints = fn1()
		}
		input = append(input, series)
	}
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		f := NewOffsetToZero()
		f.(*FuncOffsetToZero).in = NewMock(input)
		got, err := f.Exec(make(map[Req][]models.Series))
		if err != nil {
			b.Fatalf("%s", err)
		}
		results = got
	}
}
<commit_msg>Rewrite tests into a table tests<commit_after>package expr

import (
	"math"
	"strconv"
	"testing"

	"github.com/grafana/metrictank/api/models"
	"github.com/grafana/metrictank/schema"
	"github.com/grafana/metrictank/test"
)

func TestOffsetToZero(t *testing.T) {
	const (
		positiveOffset = 10
		negativeOffset = -10
	)
	for _, tc := range []struct {
		name   string
		input  []models.Series
		output []models.Series
	}{
		{
			name:   "no input",
			input:  []models.Series{},
			output: []models.Series{},
		},
		{
			name: "single positive offset",
			input: []models.Series{
				getSeriesNamed("a", []schema.Point{
					{Val: 0 + positiveOffset, Ts: 10},
					{Val: 0 + positiveOffset, Ts: 20},
					{Val: 5.5 + positiveOffset, Ts: 30},
					{Val: math.NaN(), Ts: 40},
					{Val: math.Inf(1), Ts: 50},
					{Val: 1234567890 + positiveOffset, Ts: 60},
				}),
			},
			output: []models.Series{
				getSeriesNamed("offsetToZero(a)", []schema.Point{
					{Val: 0, Ts: 10},
					{Val: 0, Ts: 20},
					{Val: 5.5, Ts: 30},
					{Val: math.NaN(), Ts: 40},
					{Val: math.Inf(1), Ts: 50},
					{Val: 1234567890, Ts: 60},
				}),
			},
		},
		{
			name: "single negative offset",
			input: []models.Series{
				getSeriesNamed("a", []schema.Point{
					{Val: 0 + negativeOffset, Ts: 10},
					{Val: 0 + negativeOffset, Ts: 20},
					{Val: 5.5 + negativeOffset, Ts: 30},
					{Val: math.NaN(), Ts: 40},
					{Val: math.Inf(1), Ts: 50},
					{Val: 1234567890 + negativeOffset, Ts: 60},
				}),
			},
			output: []models.Series{
				getSeriesNamed("offsetToZero(a)", []schema.Point{
					{Val: 0, Ts: 10},
					{Val: 0, Ts: 20},
					{Val: 5.5, Ts: 30},
					{Val: math.NaN(), Ts: 40},
					{Val: math.Inf(1), Ts: 50},
					{Val: 1234567890, Ts: 60},
				}),
			},
		},
		{
			name: "negative infinity",
			input: []models.Series{
				getSeriesNamed("a", []schema.Point{
					{Val: 0, Ts: 10},
					{Val: 0, Ts: 20},
					{Val: 5.5, Ts: 30},
					{Val: math.Inf(-1), Ts: 40},
					{Val: math.Inf(1), Ts: 50},
					{Val: 1234567890, Ts: 60},
				}),
			},
			output: []models.Series{
				getSeriesNamed("offsetToZero(a)", []schema.Point{
					{Val: math.Inf(1), Ts: 10},
					{Val: math.Inf(1), Ts: 20},
					{Val: math.Inf(1), Ts: 30},
					{Val: math.NaN(), Ts: 40},
					{Val: math.Inf(1), Ts: 50},
					{Val: math.Inf(1), Ts: 60},
				}),
			},
		},
		{
			name: "multiple",
			input: []models.Series{
				getSeriesNamed("a", []schema.Point{
					{Val: 0 + positiveOffset, Ts: 10},
					{Val: 0 + positiveOffset, Ts: 20},
					{Val: 5.5 + positiveOffset, Ts: 30},
					{Val: math.NaN(), Ts: 40},
					{Val: math.NaN(), Ts: 50},
					{Val: 1234567890 + positiveOffset, Ts: 60},
				}),
				getSeriesNamed("b", []schema.Point{
					{Val: 0 + positiveOffset, Ts: 10},
					{Val: 0 + positiveOffset, Ts: 20},
					{Val: 5.5 + positiveOffset, Ts: 30},
					{Val: math.NaN(), Ts: 40},
					{Val: math.NaN(), Ts: 50},
					{Val: 1234567890 + positiveOffset, Ts: 60},
				}),
			},
			output: []models.Series{
				getSeriesNamed("offsetToZero(a)", []schema.Point{
					{Val: 0, Ts: 10},
					{Val: 0, Ts: 20},
					{Val: 5.5, Ts: 30},
					{Val: math.NaN(), Ts: 40},
					{Val: math.NaN(), Ts: 50},
					{Val: 1234567890, Ts: 60},
				}),
				getSeriesNamed("offsetToZero(b)", []schema.Point{
					{Val: 0, Ts: 10},
					{Val: 0, Ts: 20},
					{Val: 5.5, Ts: 30},
					{Val: math.NaN(), Ts: 40},
					{Val: math.NaN(), Ts: 50},
					{Val: 1234567890, Ts: 60},
				}),
			},
		},
	} {
		t.Run(tc.name, func(t *testing.T) {
			f := NewOffsetToZero()
			f.(*FuncOffsetToZero).in = NewMock(tc.input)

			inputCopy := models.SeriesCopy(tc.input) // to later verify that it is unchanged

			dataMap := initDataMap(tc.input)

			got, err := f.Exec(dataMap)
			if err := equalOutput(tc.output, got, nil, err); err != nil {
				t.Fatalf("Case %s: %s", tc.name, err)
			}

			t.Run("DidNotModifyInput", func(t *testing.T) {
				if err := equalOutput(inputCopy, tc.input, nil, nil); err != nil {
					t.Fatalf("Case %s: Input was modified, err = %s", tc.name, err)
				}
			})

			t.Run("DoesNotDoubleReturnPoints", func(t *testing.T) {
				if err := dataMap.CheckForOverlappingPoints(); err != nil {
					t.Fatalf("Case %s: Point slices in datamap overlap, err = %s", tc.name, err)
				}
			})

			t.Run("OutputIsCanonical", func(t *testing.T) {
				for i, s := range got {
					if !s.IsCanonical() {
						t.Fatalf("Case %s: output series %d is not canonical: %v", tc.name, i, s)
					}
				}
			})

		})
	}
}

func BenchmarkOffsetToZero10k_1NoNulls(b *testing.B) {
	benchmarkOffsetToZero(b, 1, test.RandFloats10k, test.RandFloats10k)
}
func BenchmarkOffsetToZero10k_10NoNulls(b *testing.B) {
	benchmarkOffsetToZero(b, 10, test.RandFloats10k, test.RandFloats10k)
}
func BenchmarkOffsetToZero10k_100NoNulls(b *testing.B) {
	benchmarkOffsetToZero(b, 100, test.RandFloats10k, test.RandFloats10k)
}
func BenchmarkOffsetToZero10k_1000NoNulls(b *testing.B) {
	benchmarkOffsetToZero(b, 1000, test.RandFloats10k, test.RandFloats10k)
}

func BenchmarkOffsetToZero10k_1SomeSeriesHalfNulls(b *testing.B) {
	benchmarkOffsetToZero(b, 1, test.RandFloats10k, test.RandFloatsWithNulls10k)
}
func BenchmarkOffsetToZero10k_10SomeSeriesHalfNulls(b *testing.B) {
	benchmarkOffsetToZero(b, 10, test.RandFloats10k, test.RandFloatsWithNulls10k)
}
func BenchmarkOffsetToZero10k_100SomeSeriesHalfNulls(b *testing.B) {
	benchmarkOffsetToZero(b, 100, test.RandFloats10k, test.RandFloatsWithNulls10k)
}
func BenchmarkOffsetToZero10k_1000SomeSeriesHalfNulls(b *testing.B) {
	benchmarkOffsetToZero(b, 1000, test.RandFloats10k, test.RandFloatsWithNulls10k)
}

func BenchmarkOffsetToZero10k_1AllSeriesHalfNulls(b *testing.B) {
	benchmarkOffsetToZero(b, 1, test.RandFloatsWithNulls10k, test.RandFloatsWithNulls10k)
}
func BenchmarkOffsetToZero10k_10AllSeriesHalfNulls(b *testing.B) {
	benchmarkOffsetToZero(b, 10, test.RandFloatsWithNulls10k, test.RandFloatsWithNulls10k)
}
func BenchmarkOffsetToZero10k_100AllSeriesHalfNulls(b *testing.B) {
	benchmarkOffsetToZero(b, 100, test.RandFloatsWithNulls10k, test.RandFloatsWithNulls10k)
}
func BenchmarkOffsetToZero10k_1000AllSeriesHalfNulls(b *testing.B) {
	benchmarkOffsetToZero(b, 1000, test.RandFloatsWithNulls10k, test.RandFloatsWithNulls10k)
}

func benchmarkOffsetToZero(b *testing.B, numSeries int, fn0, fn1 func() []schema.Point) {
	var input []models.Series
	for i := 0; i < numSeries; i++ {
		series := models.Series{
			QueryPatt: strconv.Itoa(i),
		}
		if i%2 == 0 {
			series.Datapoints = fn0()
		} else {
			series.Datapoints = fn1()
		}
		input = append(input, series)
	}
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		f := NewOffsetToZero()
		f.(*FuncOffsetToZero).in = NewMock(input)
		got, err := f.Exec(make(map[Req][]models.Series))
		if err != nil {
			b.Fatalf("%s", err)
		}
		results = got
	}
}
<|endoftext|>


<commit_before>package runner

import (
	"fmt"
	"net"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"syscall"
	"time"

	"github.com/cloudfoundry-incubator/garden/client"
	"github.com/cloudfoundry-incubator/garden/client/connection"
	"github.com/onsi/ginkgo"
	"github.com/pivotal-golang/lager"
	"github.com/tedsuo/ifrit"
	"github.com/tedsuo/ifrit/ginkgomon"
)

type Runner struct {
	Command *exec.Cmd

	network string
	addr    string

	bin  string
	argv []string

	binPath    string
	rootFSPath string

	tmpdir    string
	graphPath string

	debugAddr string
}

func New(network, addr string, bin, binPath, rootFSPath, graphPath string, argv ...string) *Runner {
	if graphPath == "" {
		graphPath = os.TempDir()
	}

	return &Runner{
		network: network,
		addr:    addr,

		bin:  bin,
		argv: argv,

		binPath:    binPath,
		rootFSPath: rootFSPath,
		graphPath:  filepath.Join(graphPath, fmt.Sprintf("test-warden-%d", ginkgo.GinkgoParallelNode())),
		tmpdir: filepath.Join(
			os.TempDir(),
			fmt.Sprintf("test-warden-%d", ginkgo.GinkgoParallelNode()),
		),
		debugAddr: fmt.Sprintf("0.0.0.0:%d", 15000+ginkgo.GinkgoParallelNode()),
	}
}

func (r *Runner) DebugAddr() string {
	return r.debugAddr
}

func (r *Runner) Run(signals <-chan os.Signal, ready chan<- struct{}) error {
	logger := lager.NewLogger("warden-runner")
	logger.RegisterSink(lager.NewWriterSink(ginkgo.GinkgoWriter, lager.DEBUG))

	err := os.MkdirAll(r.tmpdir, 0755)
	if err != nil {
		return err
	}

	depotPath := filepath.Join(r.tmpdir, "containers")
	overlaysPath := filepath.Join(r.tmpdir, "overlays")
	snapshotsPath := filepath.Join(r.tmpdir, "snapshots")

	if err := os.MkdirAll(depotPath, 0755); err != nil {
		return err
	}

	if err := os.MkdirAll(snapshotsPath, 0755); err != nil {
		return err
	}

	wardenArgs := append(
		r.argv,
		"--listenNetwork", r.network,
		"--listenAddr", r.addr,
		"--bin", r.binPath,
		"--rootfs", r.rootFSPath,
		"--depot", depotPath,
		"--debugAddr", r.debugAddr,
		"--overlays", overlaysPath,
		"--snapshots", snapshotsPath,
		"--graph", r.graphPath,
		"--logLevel", "debug",
		"--disableQuotas",
		"--networkPool", fmt.Sprintf("10.250.%d.0/24", ginkgo.GinkgoParallelNode()),
		"--portPoolStart", strconv.Itoa(51000+(1000*ginkgo.GinkgoParallelNode())),
		"--portPoolSize", "1000",
		"--uidPoolStart", strconv.Itoa(10000*ginkgo.GinkgoParallelNode()),
		"--tag", strconv.Itoa(ginkgo.GinkgoParallelNode()),
	)

	var signal os.Signal

	r.Command = exec.Command(r.bin, wardenArgs...)

	process := ifrit.Envoke(&ginkgomon.Runner{
		Name:              "garden-linux",
		Command:           r.Command,
		AnsiColorCode:     "31m",
		StartCheck:        "garden-linux.started",
		StartCheckTimeout: 10 * time.Second,
		Cleanup: func() {
			if signal == syscall.SIGKILL {
				logger.Info("removing-tmp-dirs")
				if err := os.RemoveAll(r.tmpdir); err != nil {
					logger.Error("cleanup-tempdirs-failed", err, lager.Data{"tmpdir": r.tmpdir})
				} else {
					logger.Info("tmp-dirs-removed")
				}
			}
		},
	})

	close(ready)

	var waitErr error

dance:
	for {
		select {
		case signal = <-signals:
			if signal == syscall.SIGKILL {
				logger.Info("received-sigkill")
				if err := r.destroyContainers(); err != nil {
					logger.Error("destroy-containers-failed", err)
					return err
				}
				logger.Info("destroyed-containers")
			}

			process.Signal(syscall.SIGTERM)
		case waitErr = <-process.Wait():
			break dance
		}
	}

	logger.Info("process-exited")

	return waitErr
}

func (r *Runner) TryDial() error {
	conn, dialErr := net.DialTimeout(r.network, r.addr, 100*time.Millisecond)

	if dialErr == nil {
		conn.Close()
		return nil
	}

	return dialErr
}

func (r *Runner) NewClient() client.Client {
	return client.New(connection.New(r.network, r.addr))
}

func (r *Runner) destroyContainers() error {
	client := r.NewClient()

	containers, err := client.Containers(nil)
	if err != nil {
		return err
	}

	for _, container := range containers {
		err := client.Destroy(container.Handle())
		if err != nil {
			return err
		}
	}

	return nil
}
<commit_msg>[eliminate-warden#78779164]: Removed "warden" name from `runner.go`.<commit_after>package runner

import (
	"fmt"
	"net"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"syscall"
	"time"

	"github.com/cloudfoundry-incubator/garden/client"
	"github.com/cloudfoundry-incubator/garden/client/connection"
	"github.com/onsi/ginkgo"
	"github.com/pivotal-golang/lager"
	"github.com/tedsuo/ifrit"
	"github.com/tedsuo/ifrit/ginkgomon"
)

type Runner struct {
	Command *exec.Cmd

	network string
	addr    string

	bin  string
	argv []string

	binPath    string
	rootFSPath string

	tmpdir    string
	graphPath string

	debugAddr string
}

func New(network, addr string, bin, binPath, rootFSPath, graphPath string, argv ...string) *Runner {
	if graphPath == "" {
		graphPath = os.TempDir()
	}

	return &Runner{
		network: network,
		addr:    addr,

		bin:  bin,
		argv: argv,

		binPath:    binPath,
		rootFSPath: rootFSPath,
		graphPath:  filepath.Join(graphPath, fmt.Sprintf("test-garden-%d", ginkgo.GinkgoParallelNode())),
		tmpdir: filepath.Join(
			os.TempDir(),
			fmt.Sprintf("test-garden-%d", ginkgo.GinkgoParallelNode()),
		),
		debugAddr: fmt.Sprintf("0.0.0.0:%d", 15000+ginkgo.GinkgoParallelNode()),
	}
}

func (r *Runner) DebugAddr() string {
	return r.debugAddr
}

func (r *Runner) Run(signals <-chan os.Signal, ready chan<- struct{}) error {
	logger := lager.NewLogger("garden-runner")
	logger.RegisterSink(lager.NewWriterSink(ginkgo.GinkgoWriter, lager.DEBUG))

	err := os.MkdirAll(r.tmpdir, 0755)
	if err != nil {
		return err
	}

	depotPath := filepath.Join(r.tmpdir, "containers")
	overlaysPath := filepath.Join(r.tmpdir, "overlays")
	snapshotsPath := filepath.Join(r.tmpdir, "snapshots")

	if err := os.MkdirAll(depotPath, 0755); err != nil {
		return err
	}

	if err := os.MkdirAll(snapshotsPath, 0755); err != nil {
		return err
	}

	gardenArgs := append(
		r.argv,
		"--listenNetwork", r.network,
		"--listenAddr", r.addr,
		"--bin", r.binPath,
		"--rootfs", r.rootFSPath,
		"--depot", depotPath,
		"--debugAddr", r.debugAddr,
		"--overlays", overlaysPath,
		"--snapshots", snapshotsPath,
		"--graph", r.graphPath,
		"--logLevel", "debug",
		"--disableQuotas",
		"--networkPool", fmt.Sprintf("10.250.%d.0/24", ginkgo.GinkgoParallelNode()),
		"--portPoolStart", strconv.Itoa(51000+(1000*ginkgo.GinkgoParallelNode())),
		"--portPoolSize", "1000",
		"--uidPoolStart", strconv.Itoa(10000*ginkgo.GinkgoParallelNode()),
		"--tag", strconv.Itoa(ginkgo.GinkgoParallelNode()),
	)

	var signal os.Signal

	r.Command = exec.Command(r.bin, gardenArgs...)

	process := ifrit.Envoke(&ginkgomon.Runner{
		Name:              "garden-linux",
		Command:           r.Command,
		AnsiColorCode:     "31m",
		StartCheck:        "garden-linux.started",
		StartCheckTimeout: 10 * time.Second,
		Cleanup: func() {
			if signal == syscall.SIGKILL {
				logger.Info("removing-tmp-dirs")
				if err := os.RemoveAll(r.tmpdir); err != nil {
					logger.Error("cleanup-tempdirs-failed", err, lager.Data{"tmpdir": r.tmpdir})
				} else {
					logger.Info("tmp-dirs-removed")
				}
			}
		},
	})

	close(ready)

	var waitErr error

dance:
	for {
		select {
		case signal = <-signals:
			if signal == syscall.SIGKILL {
				logger.Info("received-sigkill")
				if err := r.destroyContainers(); err != nil {
					logger.Error("destroy-containers-failed", err)
					return err
				}
				logger.Info("destroyed-containers")
			}

			process.Signal(syscall.SIGTERM)
		case waitErr = <-process.Wait():
			break dance
		}
	}

	logger.Info("process-exited")

	return waitErr
}

func (r *Runner) TryDial() error {
	conn, dialErr := net.DialTimeout(r.network, r.addr, 100*time.Millisecond)

	if dialErr == nil {
		conn.Close()
		return nil
	}

	return dialErr
}

func (r *Runner) NewClient() client.Client {
	return client.New(connection.New(r.network, r.addr))
}

func (r *Runner) destroyContainers() error {
	client := r.NewClient()

	containers, err := client.Containers(nil)
	if err != nil {
		return err
	}

	for _, container := range containers {
		err := client.Destroy(container.Handle())
		if err != nil {
			return err
		}
	}

	return nil
}
<|endoftext|>


<commit_before>// +build go1.9

// Copyright 2018 Microsoft Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cmd

import (
	"fmt"
	"os"

	"github.com/spf13/cobra"
)

// command line options common to all commands
var (
	clearOutputFlag bool
	verboseFlag     bool
	modulesFlag     bool
	profileName     string
	outputRootDir   string
	semLimit        int
)

// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
	Use:   "profileBuilder",
	Short: "Creates virtualized packages to simplify multi-API Version applications.",
	Long: `A profile is a virtualized set of packages, which attempts to hide the
complexity of choosing API Versions from customers who don't need the
flexiblity of separating the version of the Azure SDK for Go they're employing
from the version of Azure services they are targeting.

"profileBuilder" does the heavy-lifting of creating those virtualized packages.
Each of the sub-commands of profileBuilder applies a different strategy for
choosing which packages to include in the profile.
`,
}

// Execute adds all child commands to the root command and sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
	if err := rootCmd.Execute(); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}

func init() {
	rootCmd.PersistentFlags().BoolVarP(&clearOutputFlag, "clear-output", "c", false, "Removes any directories in the output-folder before writing a profile.")
	rootCmd.PersistentFlags().BoolVarP(&verboseFlag, "verbose", "v", false, "Use stderr to log verbose output.")
	rootCmd.PersistentFlags().BoolVarP(&modulesFlag, "modules", "m", false, "Executes commands in modules-aware mode.")
	rootCmd.PersistentFlags().StringVarP(&profileName, "name", "n", "", "The name that should be used to identify the profile.")
	rootCmd.PersistentFlags().StringVarP(&outputRootDir, "output-location", "o", "", "The folder in which to output the generated profile.")
	rootCmd.PersistentFlags().IntVar(&semLimit, "sem-limit", 8, "The maximum number of packages to concurrently build.")
	rootCmd.MarkPersistentFlagRequired("name")
	rootCmd.MarkPersistentFlagRequired("output-location")
}
<commit_msg>turn the concurrency off by default (#14258)<commit_after>// +build go1.9

// Copyright 2018 Microsoft Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cmd

import (
	"fmt"
	"os"

	"github.com/spf13/cobra"
)

// command line options common to all commands
var (
	clearOutputFlag bool
	verboseFlag     bool
	modulesFlag     bool
	profileName     string
	outputRootDir   string
	semLimit        int
)

// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
	Use:   "profileBuilder",
	Short: "Creates virtualized packages to simplify multi-API Version applications.",
	Long: `A profile is a virtualized set of packages, which attempts to hide the
complexity of choosing API Versions from customers who don't need the
flexiblity of separating the version of the Azure SDK for Go they're employing
from the version of Azure services they are targeting.

"profileBuilder" does the heavy-lifting of creating those virtualized packages.
Each of the sub-commands of profileBuilder applies a different strategy for
choosing which packages to include in the profile.
`,
}

// Execute adds all child commands to the root command and sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
	if err := rootCmd.Execute(); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}

func init() {
	rootCmd.PersistentFlags().BoolVarP(&clearOutputFlag, "clear-output", "c", false, "Removes any directories in the output-folder before writing a profile.")
	rootCmd.PersistentFlags().BoolVarP(&verboseFlag, "verbose", "v", false, "Use stderr to log verbose output.")
	rootCmd.PersistentFlags().BoolVarP(&modulesFlag, "modules", "m", false, "Executes commands in modules-aware mode.")
	rootCmd.PersistentFlags().StringVarP(&profileName, "name", "n", "", "The name that should be used to identify the profile.")
	rootCmd.PersistentFlags().StringVarP(&outputRootDir, "output-location", "o", "", "The folder in which to output the generated profile.")
	rootCmd.PersistentFlags().IntVar(&semLimit, "sem-limit", 1, "The maximum number of packages to concurrently build. The concurrency is off by default to avoid causing issues on some operation systems.")
	rootCmd.MarkPersistentFlagRequired("name")
	rootCmd.MarkPersistentFlagRequired("output-location")
}
<|endoftext|>