<commit_before>// ----------------------------------------------------------------------------
//
//     ***     AUTO GENERATED CODE    ***    AUTO GENERATED CODE     ***
//
// ----------------------------------------------------------------------------
//
//     This file is automatically generated by Magic Modules and manual
//     changes will be clobbered when the file is regenerated.
//
//     Please read more about how to change this file in
//     .github/CONTRIBUTING.md.
//
// ----------------------------------------------------------------------------

package google

import (
	"fmt"
	"reflect"
)

func GetComputeRegionAutoscalerCaiObject(d TerraformResourceData, config *Config) (Asset, error) {
	name, err := assetName(d, config, "//compute.googleapis.com/projects/{{project}}/regions/{{region}}/autoscalers/{{name}}")
	if err != nil {
		return Asset{}, err
	}
	if obj, err := GetComputeRegionAutoscalerApiObject(d, config); err == nil {
		return Asset{
			Name: name,
			Type: "compute.googleapis.com/RegionAutoscaler",
			Resource: &AssetResource{
				Version:              "v1",
				DiscoveryDocumentURI: "https://www.googleapis.com/discovery/v1/apis/compute/v1/rest",
				DiscoveryName:        "RegionAutoscaler",
				Data:                 obj,
			},
		}, nil
	} else {
		return Asset{}, err
	}
}

func GetComputeRegionAutoscalerApiObject(d TerraformResourceData, config *Config) (map[string]interface{}, error) {
	obj := make(map[string]interface{})
	nameProp, err := expandComputeRegionAutoscalerName(d.Get("name"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("name"); !isEmptyValue(reflect.ValueOf(nameProp)) && (ok || !reflect.DeepEqual(v, nameProp)) {
		obj["name"] = nameProp
	}
	descriptionProp, err := expandComputeRegionAutoscalerDescription(d.Get("description"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("description"); !isEmptyValue(reflect.ValueOf(descriptionProp)) && (ok || !reflect.DeepEqual(v, descriptionProp)) {
		obj["description"] = descriptionProp
	}
	autoscalingPolicyProp, err := expandComputeRegionAutoscalerAutoscalingPolicy(d.Get("autoscaling_policy"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("autoscaling_policy"); !isEmptyValue(reflect.ValueOf(autoscalingPolicyProp)) && (ok || !reflect.DeepEqual(v, autoscalingPolicyProp)) {
		obj["autoscalingPolicy"] = autoscalingPolicyProp
	}
	targetProp, err := expandComputeRegionAutoscalerTarget(d.Get("target"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("target"); !isEmptyValue(reflect.ValueOf(targetProp)) && (ok || !reflect.DeepEqual(v, targetProp)) {
		obj["target"] = targetProp
	}
	regionProp, err := expandComputeRegionAutoscalerRegion(d.Get("region"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("region"); !isEmptyValue(reflect.ValueOf(regionProp)) && (ok || !reflect.DeepEqual(v, regionProp)) {
		obj["region"] = regionProp
	}

	return obj, nil
}

func expandComputeRegionAutoscalerName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeRegionAutoscalerDescription(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeRegionAutoscalerAutoscalingPolicy(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	l := v.([]interface{})
	if len(l) == 0 || l[0] == nil {
		return nil, nil
	}
	raw := l[0]
	original := raw.(map[string]interface{})
	transformed := make(map[string]interface{})

	transformedMinReplicas, err := expandComputeRegionAutoscalerAutoscalingPolicyMinReplicas(original["min_replicas"], d, config)
	if err != nil {
		return nil, err
	} else {
		transformed["minNumReplicas"] = transformedMinReplicas
	}

	transformedMaxReplicas, err := expandComputeRegionAutoscalerAutoscalingPolicyMaxReplicas(original["max_replicas"], d, config)
	if err != nil {
		return nil, err
	} else if val := reflect.ValueOf(transformedMaxReplicas); val.IsValid() && !isEmptyValue(val) {
		transformed["maxNumReplicas"] = transformedMaxReplicas
	}

	transformedCooldownPeriod, err := expandComputeRegionAutoscalerAutoscalingPolicyCooldownPeriod(original["cooldown_period"], d, config)
	if err != nil {
		return nil, err
	} else if val := reflect.ValueOf(transformedCooldownPeriod); val.IsValid() && !isEmptyValue(val) {
		transformed["coolDownPeriodSec"] = transformedCooldownPeriod
	}

	transformedCpuUtilization, err := expandComputeRegionAutoscalerAutoscalingPolicyCpuUtilization(original["cpu_utilization"], d, config)
	if err != nil {
		return nil, err
	} else if val := reflect.ValueOf(transformedCpuUtilization); val.IsValid() && !isEmptyValue(val) {
		transformed["cpuUtilization"] = transformedCpuUtilization
	}

	transformedMetric, err := expandComputeRegionAutoscalerAutoscalingPolicyMetric(original["metric"], d, config)
	if err != nil {
		return nil, err
	} else if val := reflect.ValueOf(transformedMetric); val.IsValid() && !isEmptyValue(val) {
		transformed["customMetricUtilizations"] = transformedMetric
	}

	transformedLoadBalancingUtilization, err := expandComputeRegionAutoscalerAutoscalingPolicyLoadBalancingUtilization(original["load_balancing_utilization"], d, config)
	if err != nil {
		return nil, err
	} else if val := reflect.ValueOf(transformedLoadBalancingUtilization); val.IsValid() && !isEmptyValue(val) {
		transformed["loadBalancingUtilization"] = transformedLoadBalancingUtilization
	}

	return transformed, nil
}

func expandComputeRegionAutoscalerAutoscalingPolicyMinReplicas(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeRegionAutoscalerAutoscalingPolicyMaxReplicas(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeRegionAutoscalerAutoscalingPolicyCooldownPeriod(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeRegionAutoscalerAutoscalingPolicyCpuUtilization(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	l := v.([]interface{})
	if len(l) == 0 || l[0] == nil {
		return nil, nil
	}
	raw := l[0]
	original := raw.(map[string]interface{})
	transformed := make(map[string]interface{})

	transformedTarget, err := expandComputeRegionAutoscalerAutoscalingPolicyCpuUtilizationTarget(original["target"], d, config)
	if err != nil {
		return nil, err
	} else if val := reflect.ValueOf(transformedTarget); val.IsValid() && !isEmptyValue(val) {
		transformed["utilizationTarget"] = transformedTarget
	}

	return transformed, nil
}

func expandComputeRegionAutoscalerAutoscalingPolicyCpuUtilizationTarget(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeRegionAutoscalerAutoscalingPolicyMetric(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	l := v.([]interface{})
	req := make([]interface{}, 0, len(l))
	for _, raw := range l {
		if raw == nil {
			continue
		}
		original := raw.(map[string]interface{})
		transformed := make(map[string]interface{})

		transformedName, err := expandComputeRegionAutoscalerAutoscalingPolicyMetricName(original["name"], d, config)
		if err != nil {
			return nil, err
		} else if val := reflect.ValueOf(transformedName); val.IsValid() && !isEmptyValue(val) {
			transformed["metric"] = transformedName
		}

		transformedTarget, err := expandComputeRegionAutoscalerAutoscalingPolicyMetricTarget(original["target"], d, config)
		if err != nil {
			return nil, err
		} else if val := reflect.ValueOf(transformedTarget); val.IsValid() && !isEmptyValue(val) {
			transformed["utilizationTarget"] = transformedTarget
		}

		transformedType, err := expandComputeRegionAutoscalerAutoscalingPolicyMetricType(original["type"], d, config)
		if err != nil {
			return nil, err
		} else if val := reflect.ValueOf(transformedType); val.IsValid() && !isEmptyValue(val) {
			transformed["utilizationTargetType"] = transformedType
		}

		req = append(req, transformed)
	}
	return req, nil
}

func expandComputeRegionAutoscalerAutoscalingPolicyMetricName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeRegionAutoscalerAutoscalingPolicyMetricTarget(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeRegionAutoscalerAutoscalingPolicyMetricType(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeRegionAutoscalerAutoscalingPolicyLoadBalancingUtilization(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	l := v.([]interface{})
	if len(l) == 0 || l[0] == nil {
		return nil, nil
	}
	raw := l[0]
	original := raw.(map[string]interface{})
	transformed := make(map[string]interface{})

	transformedTarget, err := expandComputeRegionAutoscalerAutoscalingPolicyLoadBalancingUtilizationTarget(original["target"], d, config)
	if err != nil {
		return nil, err
	} else if val := reflect.ValueOf(transformedTarget); val.IsValid() && !isEmptyValue(val) {
		transformed["utilizationTarget"] = transformedTarget
	}

	return transformed, nil
}

func expandComputeRegionAutoscalerAutoscalingPolicyLoadBalancingUtilizationTarget(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeRegionAutoscalerTarget(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeRegionAutoscalerRegion(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	f, err := parseGlobalFieldValue("regions", v.(string), "project", d, config, true)
	if err != nil {
		return nil, fmt.Errorf("Invalid value for region: %s", err)
	}
	return f.RelativeLink(), nil
}
<commit_msg>Add mode and scaleDownControls for Compute Region AutoScaler (#3701) (#474)<commit_after>// ----------------------------------------------------------------------------
//
//     ***     AUTO GENERATED CODE    ***    AUTO GENERATED CODE     ***
//
// ----------------------------------------------------------------------------
//
//     This file is automatically generated by Magic Modules and manual
//     changes will be clobbered when the file is regenerated.
//
//     Please read more about how to change this file in
//     .github/CONTRIBUTING.md.
//
// ----------------------------------------------------------------------------

package google

import (
	"fmt"
	"reflect"
)

func GetComputeRegionAutoscalerCaiObject(d TerraformResourceData, config *Config) (Asset, error) {
	name, err := assetName(d, config, "//compute.googleapis.com/projects/{{project}}/regions/{{region}}/autoscalers/{{name}}")
	if err != nil {
		return Asset{}, err
	}
	if obj, err := GetComputeRegionAutoscalerApiObject(d, config); err == nil {
		return Asset{
			Name: name,
			Type: "compute.googleapis.com/RegionAutoscaler",
			Resource: &AssetResource{
				Version:              "v1",
				DiscoveryDocumentURI: "https://www.googleapis.com/discovery/v1/apis/compute/v1/rest",
				DiscoveryName:        "RegionAutoscaler",
				Data:                 obj,
			},
		}, nil
	} else {
		return Asset{}, err
	}
}

func GetComputeRegionAutoscalerApiObject(d TerraformResourceData, config *Config) (map[string]interface{}, error) {
	obj := make(map[string]interface{})
	nameProp, err := expandComputeRegionAutoscalerName(d.Get("name"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("name"); !isEmptyValue(reflect.ValueOf(nameProp)) && (ok || !reflect.DeepEqual(v, nameProp)) {
		obj["name"] = nameProp
	}
	descriptionProp, err := expandComputeRegionAutoscalerDescription(d.Get("description"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("description"); !isEmptyValue(reflect.ValueOf(descriptionProp)) && (ok || !reflect.DeepEqual(v, descriptionProp)) {
		obj["description"] = descriptionProp
	}
	autoscalingPolicyProp, err := expandComputeRegionAutoscalerAutoscalingPolicy(d.Get("autoscaling_policy"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("autoscaling_policy"); !isEmptyValue(reflect.ValueOf(autoscalingPolicyProp)) && (ok || !reflect.DeepEqual(v, autoscalingPolicyProp)) {
		obj["autoscalingPolicy"] = autoscalingPolicyProp
	}
	targetProp, err := expandComputeRegionAutoscalerTarget(d.Get("target"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("target"); !isEmptyValue(reflect.ValueOf(targetProp)) && (ok || !reflect.DeepEqual(v, targetProp)) {
		obj["target"] = targetProp
	}
	regionProp, err := expandComputeRegionAutoscalerRegion(d.Get("region"), d, config)
	if err != nil {
		return nil, err
	} else if v, ok := d.GetOkExists("region"); !isEmptyValue(reflect.ValueOf(regionProp)) && (ok || !reflect.DeepEqual(v, regionProp)) {
		obj["region"] = regionProp
	}

	return obj, nil
}

func expandComputeRegionAutoscalerName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeRegionAutoscalerDescription(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeRegionAutoscalerAutoscalingPolicy(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	l := v.([]interface{})
	if len(l) == 0 || l[0] == nil {
		return nil, nil
	}
	raw := l[0]
	original := raw.(map[string]interface{})
	transformed := make(map[string]interface{})

	transformedMinReplicas, err := expandComputeRegionAutoscalerAutoscalingPolicyMinReplicas(original["min_replicas"], d, config)
	if err != nil {
		return nil, err
	} else {
		transformed["minNumReplicas"] = transformedMinReplicas
	}

	transformedMaxReplicas, err := expandComputeRegionAutoscalerAutoscalingPolicyMaxReplicas(original["max_replicas"], d, config)
	if err != nil {
		return nil, err
	} else if val := reflect.ValueOf(transformedMaxReplicas); val.IsValid() && !isEmptyValue(val) {
		transformed["maxNumReplicas"] = transformedMaxReplicas
	}

	transformedCooldownPeriod, err := expandComputeRegionAutoscalerAutoscalingPolicyCooldownPeriod(original["cooldown_period"], d, config)
	if err != nil {
		return nil, err
	} else if val := reflect.ValueOf(transformedCooldownPeriod); val.IsValid() && !isEmptyValue(val) {
		transformed["coolDownPeriodSec"] = transformedCooldownPeriod
	}

	transformedMode, err := expandComputeRegionAutoscalerAutoscalingPolicyMode(original["mode"], d, config)
	if err != nil {
		return nil, err
	} else if val := reflect.ValueOf(transformedMode); val.IsValid() && !isEmptyValue(val) {
		transformed["mode"] = transformedMode
	}

	transformedCpuUtilization, err := expandComputeRegionAutoscalerAutoscalingPolicyCpuUtilization(original["cpu_utilization"], d, config)
	if err != nil {
		return nil, err
	} else if val := reflect.ValueOf(transformedCpuUtilization); val.IsValid() && !isEmptyValue(val) {
		transformed["cpuUtilization"] = transformedCpuUtilization
	}

	transformedMetric, err := expandComputeRegionAutoscalerAutoscalingPolicyMetric(original["metric"], d, config)
	if err != nil {
		return nil, err
	} else if val := reflect.ValueOf(transformedMetric); val.IsValid() && !isEmptyValue(val) {
		transformed["customMetricUtilizations"] = transformedMetric
	}

	transformedLoadBalancingUtilization, err := expandComputeRegionAutoscalerAutoscalingPolicyLoadBalancingUtilization(original["load_balancing_utilization"], d, config)
	if err != nil {
		return nil, err
	} else if val := reflect.ValueOf(transformedLoadBalancingUtilization); val.IsValid() && !isEmptyValue(val) {
		transformed["loadBalancingUtilization"] = transformedLoadBalancingUtilization
	}

	return transformed, nil
}

func expandComputeRegionAutoscalerAutoscalingPolicyMinReplicas(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeRegionAutoscalerAutoscalingPolicyMaxReplicas(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeRegionAutoscalerAutoscalingPolicyCooldownPeriod(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeRegionAutoscalerAutoscalingPolicyMode(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeRegionAutoscalerAutoscalingPolicyCpuUtilization(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	l := v.([]interface{})
	if len(l) == 0 || l[0] == nil {
		return nil, nil
	}
	raw := l[0]
	original := raw.(map[string]interface{})
	transformed := make(map[string]interface{})

	transformedTarget, err := expandComputeRegionAutoscalerAutoscalingPolicyCpuUtilizationTarget(original["target"], d, config)
	if err != nil {
		return nil, err
	} else if val := reflect.ValueOf(transformedTarget); val.IsValid() && !isEmptyValue(val) {
		transformed["utilizationTarget"] = transformedTarget
	}

	return transformed, nil
}

func expandComputeRegionAutoscalerAutoscalingPolicyCpuUtilizationTarget(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeRegionAutoscalerAutoscalingPolicyMetric(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	l := v.([]interface{})
	req := make([]interface{}, 0, len(l))
	for _, raw := range l {
		if raw == nil {
			continue
		}
		original := raw.(map[string]interface{})
		transformed := make(map[string]interface{})

		transformedName, err := expandComputeRegionAutoscalerAutoscalingPolicyMetricName(original["name"], d, config)
		if err != nil {
			return nil, err
		} else if val := reflect.ValueOf(transformedName); val.IsValid() && !isEmptyValue(val) {
			transformed["metric"] = transformedName
		}

		transformedTarget, err := expandComputeRegionAutoscalerAutoscalingPolicyMetricTarget(original["target"], d, config)
		if err != nil {
			return nil, err
		} else if val := reflect.ValueOf(transformedTarget); val.IsValid() && !isEmptyValue(val) {
			transformed["utilizationTarget"] = transformedTarget
		}

		transformedType, err := expandComputeRegionAutoscalerAutoscalingPolicyMetricType(original["type"], d, config)
		if err != nil {
			return nil, err
		} else if val := reflect.ValueOf(transformedType); val.IsValid() && !isEmptyValue(val) {
			transformed["utilizationTargetType"] = transformedType
		}

		req = append(req, transformed)
	}
	return req, nil
}

func expandComputeRegionAutoscalerAutoscalingPolicyMetricName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeRegionAutoscalerAutoscalingPolicyMetricTarget(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeRegionAutoscalerAutoscalingPolicyMetricType(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeRegionAutoscalerAutoscalingPolicyLoadBalancingUtilization(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	l := v.([]interface{})
	if len(l) == 0 || l[0] == nil {
		return nil, nil
	}
	raw := l[0]
	original := raw.(map[string]interface{})
	transformed := make(map[string]interface{})

	transformedTarget, err := expandComputeRegionAutoscalerAutoscalingPolicyLoadBalancingUtilizationTarget(original["target"], d, config)
	if err != nil {
		return nil, err
	} else if val := reflect.ValueOf(transformedTarget); val.IsValid() && !isEmptyValue(val) {
		transformed["utilizationTarget"] = transformedTarget
	}

	return transformed, nil
}

func expandComputeRegionAutoscalerAutoscalingPolicyLoadBalancingUtilizationTarget(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeRegionAutoscalerTarget(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	return v, nil
}

func expandComputeRegionAutoscalerRegion(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
	f, err := parseGlobalFieldValue("regions", v.(string), "project", d, config, true)
	if err != nil {
		return nil, fmt.Errorf("Invalid value for region: %s", err)
	}
	return f.RelativeLink(), nil
}
<|endoftext|>


<commit_before>/*
Copyright 2015 Google Inc. All Rights Reserved.

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

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

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

package main

import (
  "errors"
  "flag"
  "fmt"
  "net/http"
  "log"
  "os"
  "sync"
  "time"

  context "golang.org/x/net/context"
  emulators "google/emulators"
  grpc "google.golang.org/grpc"
)

var (
  active  = flag.Bool("active", false, "Whether this emulator actively registers with the broker")
  port       = flag.Int("port", 0, "The server port")
  specId = flag.String("spec_id", "samples.emulator", "The id this emulator registers as")
  wait = flag.Bool("wait", false, "Whether to wait for a request to '/setServing' before serving")
)

type statusServer struct {
  serving bool
  mux *http.ServeMux
  mu sync.Mutex
  servingCond *sync.Cond
}

func newStatusServer(serving bool) *statusServer {
  s := statusServer{serving: serving, mux: http.NewServeMux()}
  s.servingCond = sync.NewCond(&s.mu)
  s.mux.HandleFunc("/status", func (w http.ResponseWriter, r *http.Request) {
    s.mu.Lock()
    if s.serving {
      w.Write([]byte("ok\n"))
    } else {
      w.Write([]byte("bad\n"))
    }
    s.mu.Unlock()
  })
  s.mux.HandleFunc("/setServing", func(w http.ResponseWriter, r *http.Request) {
    s.mu.Lock()
    s.serving = true
    s.servingCond.Broadcast()
    s.mu.Unlock()
  })
  return &s
}

func (s* statusServer) waitUntilServing() {
  s.servingCond.L.Lock()
  for !s.serving {
    s.servingCond.Wait()
  }
  s.servingCond.L.Unlock()
}

func registerWithBroker(brokerAddress string, myAddress string) error {
  conn, err := grpc.Dial(brokerAddress, grpc.WithTimeout(1*time.Second))
  if err != nil {
    return errors.New(fmt.Sprintf("failed to dial broker: %v", err))
  }
  defer conn.Close()

  ctx, _ := context.WithTimeout(context.Background(), 1*time.Second)
  spec := emulators.EmulatorSpec{Id: *specId, ResolvedTarget: myAddress}
  broker := emulators.NewBrokerClient(conn)
  _, err = broker.UpdateEmulatorSpec(ctx, &spec)
  if err != nil {
    return err
  }
  return nil
}

func main() {
  flag.Parse()
  if *port == 0 {
    log.Fatalf("--port not specified")
  }

  // Start serving on port.
  myAddress := fmt.Sprintf("localhost:%d", *port)
  statusServer := newStatusServer(!*wait)
  s := &http.Server{
    Addr: myAddress,
    Handler: statusServer.mux,
  }
  log.Printf("starting status server...")
  done := make(chan bool, 1)
  go func() {
    s.ListenAndServe()
    done <- true
  }()
  statusServer.waitUntilServing()
  log.Printf("serving on port %d", *port)

  if *active {
    brokerAddress := os.Getenv("TESTENV_BROKER_ADDRESS")
    if brokerAddress == "" {
      log.Fatalf("TESTENV_BROKER_ADDRESS not specified")
    }
    err := registerWithBroker(brokerAddress, myAddress)
    if err != nil {
      log.Fatalf("failed to register with broker: %v", err)
    }
    log.Printf("registered with broker at %s", brokerAddress)
  }

  <- done
}

<commit_msg>gofmt emulator sample, and small fixes<commit_after>/*
Copyright 2015 Google Inc. All Rights Reserved.

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

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

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

package main

import (
	"errors"
	"flag"
	"fmt"
	"log"
	"net/http"
	"os"
	"sync"
	"time"

	context "golang.org/x/net/context"
	grpc "google.golang.org/grpc"
	emulators "google/emulators"
)

var (
	register = flag.Bool("register", false, "Whether this emulator registers with the broker")
	port     = flag.Int("port", 0, "The server port")
	specId   = flag.String("spec_id", "samples.emulator", "The id this emulator registers as")
	wait     = flag.Bool("wait", false, "Whether to wait for a request to '/setServing' before serving")
)

type statusServer struct {
	ok     bool
	mux    *http.ServeMux
	mu     sync.Mutex
	okCond *sync.Cond
}

func newStatusServer(ok bool) *statusServer {
	s := statusServer{ok: ok, mux: http.NewServeMux()}
	s.okCond = sync.NewCond(&s.mu)
	s.mux.HandleFunc("/status", func(w http.ResponseWriter, r *http.Request) {
		s.mu.Lock()
		if s.ok {
			w.Write([]byte("ok\n"))
		} else {
			w.Write([]byte("bad\n"))
		}
		s.mu.Unlock()
	})
	s.mux.HandleFunc("/setServing", func(w http.ResponseWriter, r *http.Request) {
		s.mu.Lock()
		s.ok = true
		s.okCond.Broadcast()
		s.mu.Unlock()
	})
	return &s
}

func (s *statusServer) waitUntilOk() {
	s.okCond.L.Lock()
	for !s.ok {
		s.okCond.Wait()
	}
	s.okCond.L.Unlock()
}

func registerWithBroker(brokerAddress string, myAddress string) error {
	conn, err := grpc.Dial(brokerAddress, grpc.WithTimeout(1*time.Second))
	if err != nil {
		return errors.New(fmt.Sprintf("failed to dial broker: %v", err))
	}
	defer conn.Close()

	ctx, _ := context.WithTimeout(context.Background(), 1*time.Second)
	spec := emulators.EmulatorSpec{Id: *specId, ResolvedTarget: myAddress}
	broker := emulators.NewBrokerClient(conn)
	_, err = broker.UpdateEmulatorSpec(ctx, &spec)
	if err != nil {
		return err
	}
	return nil
}

// Starts an HTTP server whose status is read via '/status'.
func main() {
	flag.Parse()
	if *port == 0 {
		log.Fatalf("--port not specified")
	}

	// Start serving on port.
	myAddress := fmt.Sprintf("localhost:%d", *port)
	statusServer := newStatusServer(!*wait)
	s := &http.Server{
		Addr:    myAddress,
		Handler: statusServer.mux,
	}
	log.Printf("serving on port %d", *port)
	done := make(chan bool, 1)
	go func() {
		s.ListenAndServe()
		done <- true
	}()
	statusServer.waitUntilOk()
	log.Printf("serving status is ok")

	if *register {
		// Register with the broker.
		brokerAddress := os.Getenv("TESTENV_BROKER_ADDRESS")
		if brokerAddress == "" {
			log.Fatalf("TESTENV_BROKER_ADDRESS not specified")
		}
		err := registerWithBroker(brokerAddress, myAddress)
		if err != nil {
			log.Fatalf("failed to register with broker: %v", err)
		}
		log.Printf("registered with broker at %s", brokerAddress)
	}

	<-done
}
<|endoftext|>


<commit_before>package buffer

import (
	"bytes"
	"encoding/gob"
	"fmt"
	"io"
	"os"
	"path/filepath"

	"github.com/djherbis/buffer/wrapio"
)

// File is used as the backing resource for a the NewFile BufferAt.
type File interface {
	Name() string
	Stat() (fi os.FileInfo, err error)
	io.ReaderAt
	io.WriterAt
	Close() error
}

type fileBuffer struct {
	file File
	*wrapio.Wrapper
}

// NewFile returns a new BufferAt backed by "file" with max-size N.
func NewFile(N int64, file File) BufferAt {
	return &fileBuffer{
		file:    file,
		Wrapper: wrapio.NewWrapper(file, 0, 0, N),
	}
}

func init() {
	gob.Register(&fileBuffer{})
}

func (buf *fileBuffer) MarshalBinary() ([]byte, error) {
	fullpath, err := filepath.Abs(filepath.Dir(buf.file.Name()))
	if err != nil {
		return nil, err
	}
	base := filepath.Base(buf.file.Name())
	buf.file.Close()

	buffer := bytes.NewBuffer(nil)
	fmt.Fprintln(buffer, filepath.Join(fullpath, base))
	fmt.Fprintln(buffer, buf.Wrapper.N, buf.Wrapper.L, buf.Wrapper.O)
	return buffer.Bytes(), nil
}

func (buf *fileBuffer) UnmarshalBinary(data []byte) error {
	buffer := bytes.NewBuffer(data)
	var filename string
	var N, L, O int64
	_, err := fmt.Fscanln(buffer, &filename)

	file, err := os.Open(filename)
	if err != nil {
		return err
	}
	buf.file = file

	_, err = fmt.Fscanln(buffer, &N, &L, &O)
	buf.Wrapper = wrapio.NewWrapper(file, L, O, N)
	return nil
}
<commit_msg>use err ret by fileBuffer.UnmarshalBinary<commit_after>package buffer

import (
	"bytes"
	"encoding/gob"
	"fmt"
	"io"
	"os"
	"path/filepath"

	"github.com/djherbis/buffer/wrapio"
)

// File is used as the backing resource for a the NewFile BufferAt.
type File interface {
	Name() string
	Stat() (fi os.FileInfo, err error)
	io.ReaderAt
	io.WriterAt
	Close() error
}

type fileBuffer struct {
	file File
	*wrapio.Wrapper
}

// NewFile returns a new BufferAt backed by "file" with max-size N.
func NewFile(N int64, file File) BufferAt {
	return &fileBuffer{
		file:    file,
		Wrapper: wrapio.NewWrapper(file, 0, 0, N),
	}
}

func init() {
	gob.Register(&fileBuffer{})
}

func (buf *fileBuffer) MarshalBinary() ([]byte, error) {
	fullpath, err := filepath.Abs(filepath.Dir(buf.file.Name()))
	if err != nil {
		return nil, err
	}
	base := filepath.Base(buf.file.Name())
	buf.file.Close()

	buffer := bytes.NewBuffer(nil)
	fmt.Fprintln(buffer, filepath.Join(fullpath, base))
	fmt.Fprintln(buffer, buf.Wrapper.N, buf.Wrapper.L, buf.Wrapper.O)
	return buffer.Bytes(), nil
}

func (buf *fileBuffer) UnmarshalBinary(data []byte) error {
	buffer := bytes.NewBuffer(data)
	var filename string
	var N, L, O int64
	_, err := fmt.Fscanln(buffer, &filename)

	file, err := os.Open(filename)
	if err != nil {
		return err
	}
	buf.file = file

	_, err = fmt.Fscanln(buffer, &N, &L, &O)
	buf.Wrapper = wrapio.NewWrapper(file, L, O, N)
	return err
}
<|endoftext|>


<commit_before>package scipipe

import (
	"os"
	"time"
)

type FileTarget struct {
	path string
}

func NewFileTarget(path string) *FileTarget {
	ft := new(FileTarget)
	ft.path = path
	return ft
}

func (ft *FileTarget) GetPath() string {
	return ft.path
}

func (ft *FileTarget) GetTempPath() string {
	return ft.path + ".tmp"
}

func (ft *FileTarget) Atomize() {
	time.Sleep(1 * time.Second) // TODO: Remove in production. Just for demo purposes!
	err := os.Rename(ft.GetTempPath(), ft.path)
	Check(err)
}
<commit_msg>Implement Exists() method on FileTarget<commit_after>package scipipe

import (
	"os"
	"time"
)

type FileTarget struct {
	path string
}

func NewFileTarget(path string) *FileTarget {
	ft := new(FileTarget)
	ft.path = path
	return ft
}

func (ft *FileTarget) GetPath() string {
	return ft.path
}

func (ft *FileTarget) GetTempPath() string {
	return ft.path + ".tmp"
}

func (ft *FileTarget) Atomize() {
	time.Sleep(1 * time.Second) // TODO: Remove in production. Just for demo purposes!
	err := os.Rename(ft.GetTempPath(), ft.path)
	Check(err)
}

func (ft *FileTarget) Exists() bool {
	if _, err := os.Stat(ft.GetPath()); err == nil {
		return true
	}
	return false
}
<|endoftext|>


<commit_before>package app

type Peer struct {
	Ip string `json:"ip"`
	Port int `json:"port"`
}

func (peer *Peer) getUrl() string{
	return "http://" + peer.Ip + ":" + string(peer.Port)
}<commit_msg>Fixed uri setup<commit_after>package app

import "strconv"
type Peer struct {
	Ip string `json:"ip"`
	Port int `json:"port"`
}

func (peer *Peer) getUrl() string{
	return "http://" + peer.Ip + ":" + strconv.Itoa(peer.Port)
}<|endoftext|>


<commit_before>package server

import (
	"net/http"

	"github.com/gin-gonic/gin"
)

// Version of IronFunctions
var Version = "0.1.15"

func handleVersion(c *gin.Context) {
	c.JSON(http.StatusOK, gin.H{"version": Version})
}
<commit_msg>functions: 0.1.16 release [skip ci]<commit_after>package server

import (
	"net/http"

	"github.com/gin-gonic/gin"
)

// Version of IronFunctions
var Version = "0.1.16"

func handleVersion(c *gin.Context) {
	c.JSON(http.StatusOK, gin.H{"version": Version})
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Chef Software Inc. and/or applicable contributors
//
// 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 v1beta1

import (
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

const (
	HabitatResourcePlural = "habitats"
	HabitatShortName      = "hab"

	// HabitatLabel labels the resources that belong to Habitat.
	// Example: 'habitat: true'
	HabitatLabel = "habitat"
	// HabitatNameLabel contains the user defined Habitat Service name.
	// Example: 'habitat-name: db'
	HabitatNameLabel = "habitat-name"

	TopologyLabel = "topology"
)

// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

type Habitat struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata"`
	Spec              HabitatSpec   `json:"spec"`
	Status            HabitatStatus `json:"status,omitempty"`
	// CustomVersion is a field that works around the lack of support for running
	// multiple versions of a CRD.  It encodes the actual version of the type, so
	// that controllers can decide whether to discard an object if the version
	// doesn't match.
	// When absent, it defaults to v1beta1.
	// +optional
	CustomVersion *string `json:"customVersion,omitempty"`
}

type HabitatSpec struct {
	// Count is the amount of Services to start in this Habitat.
	Count int `json:"count"`
	// Image is the Docker image of the Habitat Service.
	Image   string  `json:"image"`
	Service Service `json:"service"`
	// Env is a list of environment variables.
	// The EnvVar type is documented at https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#envvar-v1-core.
	// Optional.
	Env []corev1.EnvVar `json:"env,omitempty"`
	// V1beta2 are fields for the v1beta2 type.
	// +optional
	V1beta2 *V1beta2 `json:"v1beta2"`
}

// PersistentStorage contains the details of the persistent storage that the
// cluster should provision.
type PersistentStorage struct {
	// Size is the volume's size.
	// It uses the same format as Kubernetes' size fields, e.g. 10Gi
	Size string `json:"size"`
	// MountPath is the path at which the PersistentVolume will be mounted.
	MountPath string `json:"mountPath"`
	// StorageClassName is the name of the StorageClass that the StatefulSet will request.
	StorageClassName string `json:"storageClassName"`
}

// V1beta2 are fields for the v1beta2 type.
type V1beta2 struct {
	// Count is the amount of Services to start in this Habitat.
	Count int `json:"count"`
	// Image is the Docker image of the Habitat Service.
	Image   string  `json:"image"`
	Service Service `json:"service"`
	// Env is a list of environment variables.
	// The EnvVar type is documented at https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#envvar-v1-core.
	// Optional.
	Env []corev1.EnvVar `json:"env,omitempty"`
	// +optional
	PersistentStorage *PersistentStorage `json:"persistentStorage,omitempty"`
}

type HabitatStatus struct {
	State   HabitatState `json:"state,omitempty"`
	Message string       `json:"message,omitempty"`
}

type HabitatState string

type Service struct {
	// Group is the value of the --group flag for the hab client.
	// Optional. Defaults to `default`.
	Group string `json:"group"`
	// Topology is the value of the --topology flag for the hab client.
	Topology `json:"topology"`
	// ConfigSecretName is the name of a Secret containing a Habitat service's config in TOML format.
	// It will be mounted inside the pod as a file, and it will be used by Habitat to configure the service.
	// Optional.
	ConfigSecretName string `json:"configSecretName,omitempty"`
	// The name of the secret that contains the ring key.
	// Optional.
	RingSecretName string `json:"ringSecretName,omitempty"`
	// Bind is when one service connects to another forming a producer/consumer relationship.
	// Optional.
	Bind []Bind `json:"bind,omitempty"`
	// Name is the name of the Habitat service that this Habitat object represents.
	// This field is used to mount the user.toml file in the correct directory under /hab/user/ in the Pod.
	Name string `json:"name"`
}

type Bind struct {
	// Name is the name of the bind specified in the Habitat configuration files.
	Name string `json:"name"`
	// Service is the name of the service this bind refers to.
	Service string `json:"service"`
	// Group is the group of the service this bind refers to.
	Group string `json:"group"`
}

type Topology string

func (t Topology) String() string {
	return string(t)
}

const (
	HabitatStateCreated   HabitatState = "Created"
	HabitatStateProcessed HabitatState = "Processed"

	TopologyStandalone Topology = "standalone"
	TopologyLeader     Topology = "leader"

	HabitatKind = "Habitat"
)

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

type HabitatList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata"`
	Items           []Habitat `json:"items"`
}
<commit_msg>Use +optional comment tag for optional fields<commit_after>// Copyright (c) 2017 Chef Software Inc. and/or applicable contributors
//
// 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 v1beta1

import (
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

const (
	HabitatResourcePlural = "habitats"
	HabitatShortName      = "hab"

	// HabitatLabel labels the resources that belong to Habitat.
	// Example: 'habitat: true'
	HabitatLabel = "habitat"
	// HabitatNameLabel contains the user defined Habitat Service name.
	// Example: 'habitat-name: db'
	HabitatNameLabel = "habitat-name"

	TopologyLabel = "topology"
)

// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

type Habitat struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata"`
	Spec              HabitatSpec   `json:"spec"`
	Status            HabitatStatus `json:"status,omitempty"`
	// CustomVersion is a field that works around the lack of support for running
	// multiple versions of a CRD.  It encodes the actual version of the type, so
	// that controllers can decide whether to discard an object if the version
	// doesn't match.
	// When absent, it defaults to v1beta1.
	// +optional
	CustomVersion *string `json:"customVersion,omitempty"`
}

type HabitatSpec struct {
	// Count is the amount of Services to start in this Habitat.
	Count int `json:"count"`
	// Image is the Docker image of the Habitat Service.
	Image   string  `json:"image"`
	Service Service `json:"service"`
	// Env is a list of environment variables.
	// The EnvVar type is documented at https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#envvar-v1-core.
	// +optional
	Env []corev1.EnvVar `json:"env,omitempty"`
	// V1beta2 are fields for the v1beta2 type.
	// +optional
	V1beta2 *V1beta2 `json:"v1beta2"`
}

// PersistentStorage contains the details of the persistent storage that the
// cluster should provision.
type PersistentStorage struct {
	// Size is the volume's size.
	// It uses the same format as Kubernetes' size fields, e.g. 10Gi
	Size string `json:"size"`
	// MountPath is the path at which the PersistentVolume will be mounted.
	MountPath string `json:"mountPath"`
	// StorageClassName is the name of the StorageClass that the StatefulSet will request.
	StorageClassName string `json:"storageClassName"`
}

// V1beta2 are fields for the v1beta2 type.
type V1beta2 struct {
	// Count is the amount of Services to start in this Habitat.
	Count int `json:"count"`
	// Image is the Docker image of the Habitat Service.
	Image   string  `json:"image"`
	Service Service `json:"service"`
	// Env is a list of environment variables.
	// The EnvVar type is documented at https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#envvar-v1-core.
	// Optional.
	Env []corev1.EnvVar `json:"env,omitempty"`
	// +optional
	PersistentStorage *PersistentStorage `json:"persistentStorage,omitempty"`
}

type HabitatStatus struct {
	State   HabitatState `json:"state,omitempty"`
	Message string       `json:"message,omitempty"`
}

type HabitatState string

type Service struct {
	// Group is the value of the --group flag for the hab client.
	// Defaults to `default`.
	// +optional
	Group string `json:"group"`
	// Topology is the value of the --topology flag for the hab client.
	Topology `json:"topology"`
	// ConfigSecretName is the name of a Secret containing a Habitat service's config in TOML format.
	// It will be mounted inside the pod as a file, and it will be used by Habitat to configure the service.
	// +optional
	ConfigSecretName string `json:"configSecretName,omitempty"`
	// The name of the secret that contains the ring key.
	// +optional
	RingSecretName string `json:"ringSecretName,omitempty"`
	// Bind is when one service connects to another forming a producer/consumer relationship.
	// +optional
	Bind []Bind `json:"bind,omitempty"`
	// Name is the name of the Habitat service that this Habitat object represents.
	// This field is used to mount the user.toml file in the correct directory under /hab/user/ in the Pod.
	Name string `json:"name"`
}

type Bind struct {
	// Name is the name of the bind specified in the Habitat configuration files.
	Name string `json:"name"`
	// Service is the name of the service this bind refers to.
	Service string `json:"service"`
	// Group is the group of the service this bind refers to.
	Group string `json:"group"`
}

type Topology string

func (t Topology) String() string {
	return string(t)
}

const (
	HabitatStateCreated   HabitatState = "Created"
	HabitatStateProcessed HabitatState = "Processed"

	TopologyStandalone Topology = "standalone"
	TopologyLeader     Topology = "leader"

	HabitatKind = "Habitat"
)

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

type HabitatList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata"`
	Items           []Habitat `json:"items"`
}
<|endoftext|>


<commit_before>package v1

import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

type NodePoolConfig struct {
	Upgrade bool `json:"upgrade"`
	Repair  bool `json:"repair"`
}

type NodePool struct {
	Name   string         `json:"name"`
	Size   int            `json:"size"`
	Flavor string         `json:"flavor"`
	Image  string         `json:"image"`
	Config NodePoolConfig `json:"config"`
}

type OpenstackInfo struct {
	AuthURL    string `json:"authURL"`
	ProjectID  string `json:"projectID"`
	RouterID   string `json:"routerID"`
	NetworkID  string `json:"networkID"`
	LBSubnetID string `json:"lbSubnetID"`
	Domain     string `json:"domain"`
	Region     string `json:"region"`
	Username   string `json:"username"`
	Password   string `json:"password"`
}

type KubernikusInfo struct {
	Server         string `json:"server"`
	ServerURL      string `json:"serverURL"`
	BootstrapToken string `json:"bootstrapToken"`
}

type KlusterSpec struct {
	Name           string         `json:"name"`
	OpenstackInfo  OpenstackInfo  `json:"openstackInfo,omitempty"`
	KubernikusInfo KubernikusInfo `json:"kubernikusInfo,omitempty"`
	NodePools      []NodePool     `json:"nodePools,omitempty"`
}

type KlusterState string

const (
	KlusterPending     KlusterState = "Pending"
	KlusterCreating    KlusterState = "Creating"
	KlusterReady       KlusterState = "Ready"
	KlusterTerminating KlusterState = "Terminating"
	KlusterTerminated  KlusterState = "Terminated"
	KlusterError       KlusterState = "Error"
)

type KlusterStatus struct {
	State   KlusterState `json:"state,omitempty"`
	Message string       `json:"message,omitempty"`
}

// +genclient

type Kluster struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata"`
	Spec              KlusterSpec   `json:"spec"`
	Status            KlusterStatus `json:"status,omitempty"`
}

type KlusterList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata"`
	Items           []Kluster `json:"items"`
}

func (spec KlusterSpec) Validate() error {
	//Add some validation
	return nil
}

func (spec Kluster) Account() string {
	return spec.ObjectMeta.Labels["account"]
}
<commit_msg>populates wormholeURL<commit_after>package v1

import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

type NodePoolConfig struct {
	Upgrade bool `json:"upgrade"`
	Repair  bool `json:"repair"`
}

type NodePool struct {
	Name   string         `json:"name"`
	Size   int            `json:"size"`
	Flavor string         `json:"flavor"`
	Image  string         `json:"image"`
	Config NodePoolConfig `json:"config"`
}

type OpenstackInfo struct {
	AuthURL    string `json:"authURL"`
	ProjectID  string `json:"projectID"`
	RouterID   string `json:"routerID"`
	NetworkID  string `json:"networkID"`
	LBSubnetID string `json:"lbSubnetID"`
	Domain     string `json:"domain"`
	Region     string `json:"region"`
	Username   string `json:"username"`
	Password   string `json:"password"`
}

type KubernikusInfo struct {
	ServerURL      string `json:"serverURL"`
	WormholeURL    string `json:"wormholeURL"`
	BootstrapToken string `json:"bootstrapToken"`
}

type KlusterSpec struct {
	Name           string         `json:"name"`
	OpenstackInfo  OpenstackInfo  `json:"openstackInfo,omitempty"`
	KubernikusInfo KubernikusInfo `json:"kubernikusInfo,omitempty"`
	NodePools      []NodePool     `json:"nodePools,omitempty"`
}

type KlusterState string

const (
	KlusterPending     KlusterState = "Pending"
	KlusterCreating    KlusterState = "Creating"
	KlusterReady       KlusterState = "Ready"
	KlusterTerminating KlusterState = "Terminating"
	KlusterTerminated  KlusterState = "Terminated"
	KlusterError       KlusterState = "Error"
)

type KlusterStatus struct {
	State   KlusterState `json:"state,omitempty"`
	Message string       `json:"message,omitempty"`
}

// +genclient

type Kluster struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata"`
	Spec              KlusterSpec   `json:"spec"`
	Status            KlusterStatus `json:"status,omitempty"`
}

type KlusterList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata"`
	Items           []Kluster `json:"items"`
}

func (spec KlusterSpec) Validate() error {
	//Add some validation
	return nil
}

func (spec Kluster) Account() string {
	return spec.ObjectMeta.Labels["account"]
}
<|endoftext|>


<commit_before>package coverage

import (
	"fmt"
	"io/ioutil"
	"os"
	"regexp"
	"strconv"
	"testing"

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

var totalRgx = regexp.MustCompile(`total:\s+\(statements\)\s+([^"]*)%`)

const CodeCoverageThreshold = 55.1

func TestCoverage(t *testing.T) {
	if os.Getenv("CHECK_COVERAGE") != "true" {
		t.Skip("Skipping coverage check")
	}

	coverageOutput, err := ioutil.ReadFile("coverage.txt")

	if err != nil {
		assert.Fail(t, "unable to parse coverage test")
		return
	}

	// parse coverage output for total
	coverageAmt := totalRgx.FindStringSubmatch(string(coverageOutput))
	if len(coverageAmt) < 2 {
		assert.Fail(t, "no coverage total found")
		return
	}

	iCoverage, err := strconv.ParseFloat(coverageAmt[1], 64)
	if err != nil {
		assert.Fail(t, "unable to parse coverage amount")
		return
	}

	fmt.Println("coverage: ", iCoverage)
	if iCoverage > CodeCoverageThreshold {
		t.Fatalf("Please update CodeCoverageThreshold in coverage/coverage_test.go with lastest value: %v", iCoverage)
	} else if iCoverage < CodeCoverageThreshold {
		t.Fatalf("Your code coverage is %v. Please add more unit tests to reach code coverage: %v", iCoverage, CodeCoverageThreshold)
	}
	assert.Equal(t, iCoverage, CodeCoverageThreshold)
}
<commit_msg>fix codecoverage error<commit_after>package coverage

import (
	"fmt"
	"io/ioutil"
	"math"
	"os"
	"regexp"
	"strconv"
	"testing"

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

var totalRgx = regexp.MustCompile(`total:\s+\(statements\)\s+([^"]*)%`)

const CodeCoverageThreshold = 55.6

func TestCoverage(t *testing.T) {
	if os.Getenv("CHECK_COVERAGE") != "true" {
		t.Skip("Skipping coverage check")
	}

	coverageOutput, err := ioutil.ReadFile("coverage.txt")

	if err != nil {
		assert.Fail(t, "unable to parse coverage test")
		return
	}

	// parse coverage output for total
	coverageAmt := totalRgx.FindStringSubmatch(string(coverageOutput))
	if len(coverageAmt) < 2 {
		assert.Fail(t, "no coverage total found")
		return
	}

	iCoverage, err := strconv.ParseFloat(coverageAmt[1], 64)
	if err != nil {
		assert.Fail(t, "unable to parse coverage amount")
		return
	}

	fmt.Println("coverage: ", iCoverage)
	diff := math.Abs(iCoverage - CodeCoverageThreshold)
	if diff < 1.0 {
		fmt.Println("Skip this check because of round error in golang tool")
		t.SkipNow()
	}
	if iCoverage > CodeCoverageThreshold {
		t.Fatalf("Please update CodeCoverageThreshold in coverage/coverage_test.go with lastest value: %v", iCoverage)
	} else if iCoverage < CodeCoverageThreshold {
		t.Fatalf("Your code coverage is %v. Please add more unit tests to reach code coverage: %v", iCoverage, CodeCoverageThreshold)
	}
	assert.Equal(t, iCoverage, CodeCoverageThreshold)
}
<|endoftext|>


<commit_before>/*
Copyright 2019 The Knative 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.
*/

package apis

import (
	"reflect"
	"sort"
	"time"

	"fmt"

	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// Conditions is the interface for a Resource that implements the getter and
// setter for accessing a Condition collection.
// +k8s:deepcopy-gen=true
type ConditionsAccessor interface {
	GetConditions() Conditions
	SetConditions(Conditions)
}

// ConditionSet is an abstract collection of the possible ConditionType values
// that a particular resource might expose.  It also holds the "happy condition"
// for that resource, which we define to be one of Ready or Succeeded depending
// on whether it is a Living or Batch process respectively.
// +k8s:deepcopy-gen=false
type ConditionSet struct {
	happy      ConditionType
	dependents []ConditionType
}

// ConditionManager allows a resource to operate on its Conditions using higher
// order operations.
type ConditionManager interface {
	// IsHappy looks at the happy condition and returns true if that condition is
	// set to true.
	IsHappy() bool

	// GetCondition finds and returns the Condition that matches the ConditionType
	// previously set on Conditions.
	GetCondition(t ConditionType) *Condition

	// SetCondition sets or updates the Condition on Conditions for Condition.Type.
	// If there is an update, Conditions are stored back sorted.
	SetCondition(new Condition)

	// ClearCondition removes the non terminal condition that matches the ConditionType
	ClearCondition(t ConditionType) error

	// MarkTrue sets the status of t to true, and then marks the happy condition to
	// true if all dependents are true.
	MarkTrue(t ConditionType)

	// MarkUnknown sets the status of t to Unknown and also sets the happy condition
	// to Unknown if no other dependent condition is in an error state.
	MarkUnknown(t ConditionType, reason, messageFormat string, messageA ...interface{})

	// MarkFalse sets the status of t and the happy condition to False.
	MarkFalse(t ConditionType, reason, messageFormat string, messageA ...interface{})

	// InitializeConditions updates all Conditions in the ConditionSet to Unknown
	// if not set.
	InitializeConditions()
}

// NewLivingConditionSet returns a ConditionSet to hold the conditions for the
// living resource. ConditionReady is used as the happy condition.
// The set of condition types provided are those of the terminal subconditions.
func NewLivingConditionSet(d ...ConditionType) ConditionSet {
	return newConditionSet(ConditionReady, d...)
}

// NewBatchConditionSet returns a ConditionSet to hold the conditions for the
// batch resource. ConditionSucceeded is used as the happy condition.
// The set of condition types provided are those of the terminal subconditions.
func NewBatchConditionSet(d ...ConditionType) ConditionSet {
	return newConditionSet(ConditionSucceeded, d...)
}

// newConditionSet returns a ConditionSet to hold the conditions that are
// important for the caller. The first ConditionType is the overarching status
// for that will be used to signal the resources' status is Ready or Succeeded.
func newConditionSet(happy ConditionType, dependents ...ConditionType) ConditionSet {
	var deps []ConditionType
	for _, d := range dependents {
		// Skip duplicates
		if d == happy || contains(deps, d) {
			continue
		}
		deps = append(deps, d)
	}
	return ConditionSet{
		happy:      happy,
		dependents: deps,
	}
}

func contains(ct []ConditionType, t ConditionType) bool {
	for _, c := range ct {
		if c == t {
			return true
		}
	}
	return false
}

// Check that conditionsImpl implements ConditionManager.
var _ ConditionManager = (*conditionsImpl)(nil)

// conditionsImpl implements the helper methods for evaluating Conditions.
// +k8s:deepcopy-gen=false
type conditionsImpl struct {
	ConditionSet
	accessor ConditionsAccessor
}

// Manage creates a ConditionManager from a accessor object using the original
// ConditionSet as a reference. Status must be or point to a struct.
func (r ConditionSet) Manage(status ConditionsAccessor) ConditionManager {
	return conditionsImpl{
		accessor:     status,
		ConditionSet: r,
	}
}

// IsHappy looks at the happy condition and returns true if that condition is
// set to true.
func (r conditionsImpl) IsHappy() bool {
	if c := r.GetCondition(r.happy); c == nil || !c.IsTrue() {
		return false
	}
	return true
}

// GetCondition finds and returns the Condition that matches the ConditionType
// previously set on Conditions.
func (r conditionsImpl) GetCondition(t ConditionType) *Condition {
	if r.accessor == nil {
		return nil
	}

	for _, c := range r.accessor.GetConditions() {
		if c.Type == t {
			return &c
		}
	}
	return nil
}

// SetCondition sets or updates the Condition on Conditions for Condition.Type.
// If there is an update, Conditions are stored back sorted.
func (r conditionsImpl) SetCondition(new Condition) {
	if r.accessor == nil {
		return
	}
	t := new.Type
	var conditions Conditions
	for _, c := range r.accessor.GetConditions() {
		if c.Type != t {
			conditions = append(conditions, c)
		} else {
			// If we'd only update the LastTransitionTime, then return.
			new.LastTransitionTime = c.LastTransitionTime
			if reflect.DeepEqual(&new, &c) {
				return
			}
		}
	}
	new.LastTransitionTime = VolatileTime{Inner: metav1.NewTime(time.Now())}
	conditions = append(conditions, new)
	// Sorted for convenience of the consumer, i.e. kubectl.
	sort.Slice(conditions, func(i, j int) bool { return conditions[i].Type < conditions[j].Type })
	r.accessor.SetConditions(conditions)
}

func (r conditionsImpl) isTerminal(t ConditionType) bool {
	for _, cond := range r.dependents {
		if cond == t {
			return true
		}
	}
	return t == r.happy
}

func (r conditionsImpl) severity(t ConditionType) ConditionSeverity {
	if r.isTerminal(t) {
		return ConditionSeverityError
	}
	return ConditionSeverityInfo
}

// RemoveCondition removes the non terminal condition that matches the ConditionType
// Not implemented for terminal conditions
func (r conditionsImpl) ClearCondition(t ConditionType) error {
	var conditions Conditions

	if r.accessor == nil {
		return nil
	}
	// Terminal conditions are not handled as they can't be nil
	if r.isTerminal(t) {
		return fmt.Errorf("Clearing terminal conditions not implemented")
	}
	cond := r.GetCondition(t)
	if cond == nil {
		return nil
	}
	for _, c := range r.accessor.GetConditions() {
		if c.Type != t {
			conditions = append(conditions, c)
		}
	}

	// Sorted for convenience of the consumer, i.e. kubectl.
	sort.Slice(conditions, func(i, j int) bool { return conditions[i].Type < conditions[j].Type })
	r.accessor.SetConditions(conditions)

	return nil
}

// MarkTrue sets the status of t to true, and then marks the happy condition to
// true if all other dependents are also true.
func (r conditionsImpl) MarkTrue(t ConditionType) {
	// set the specified condition
	r.SetCondition(Condition{
		Type:     t,
		Status:   corev1.ConditionTrue,
		Severity: r.severity(t),
	})

	// check the dependents.
	for _, cond := range r.dependents {
		c := r.GetCondition(cond)
		// Failed or Unknown conditions trump true conditions
		if !c.IsTrue() {
			return
		}
	}

	// set the happy condition
	r.SetCondition(Condition{
		Type:     r.happy,
		Status:   corev1.ConditionTrue,
		Severity: r.severity(r.happy),
	})
}

// MarkUnknown sets the status of t to Unknown and also sets the happy condition
// to Unknown if no other dependent condition is in an error state.
func (r conditionsImpl) MarkUnknown(t ConditionType, reason, messageFormat string, messageA ...interface{}) {
	// set the specified condition
	r.SetCondition(Condition{
		Type:     t,
		Status:   corev1.ConditionUnknown,
		Reason:   reason,
		Message:  fmt.Sprintf(messageFormat, messageA...),
		Severity: r.severity(t),
	})

	// check the dependents.
	isDependent := false
	for _, cond := range r.dependents {
		c := r.GetCondition(cond)
		// Failed conditions trump Unknown conditions
		if c.IsFalse() {
			// Double check that the happy condition is also false.
			happy := r.GetCondition(r.happy)
			if !happy.IsFalse() {
				r.MarkFalse(r.happy, reason, messageFormat, messageA...)
			}
			return
		}
		if cond == t {
			isDependent = true
		}
	}

	if isDependent {
		// set the happy condition, if it is one of our dependent subconditions.
		r.SetCondition(Condition{
			Type:     r.happy,
			Status:   corev1.ConditionUnknown,
			Reason:   reason,
			Message:  fmt.Sprintf(messageFormat, messageA...),
			Severity: r.severity(r.happy),
		})
	}
}

// MarkFalse sets the status of t and the happy condition to False.
func (r conditionsImpl) MarkFalse(t ConditionType, reason, messageFormat string, messageA ...interface{}) {
	types := []ConditionType{t}
	for _, cond := range r.dependents {
		if cond == t {
			types = append(types, r.happy)
		}
	}

	for _, t := range types {
		r.SetCondition(Condition{
			Type:     t,
			Status:   corev1.ConditionFalse,
			Reason:   reason,
			Message:  fmt.Sprintf(messageFormat, messageA...),
			Severity: r.severity(t),
		})
	}
}

// InitializeConditions updates all Conditions in the ConditionSet to Unknown
// if not set.
func (r conditionsImpl) InitializeConditions() {
	happy := r.GetCondition(r.happy)
	if happy == nil {
		happy = &Condition{
			Type:     r.happy,
			Status:   corev1.ConditionUnknown,
			Severity: ConditionSeverityError,
		}
		r.SetCondition(*happy)
	}
	// If the happy state is true, it implies that all of the terminal
	// subconditions must be true, so initialize any unset conditions to
	// true if our happy condition is true, otherwise unknown.
	status := corev1.ConditionUnknown
	if happy.Status == corev1.ConditionTrue {
		status = corev1.ConditionTrue
	}
	for _, t := range r.dependents {
		r.initializeTerminalCondition(t, status)
	}
}

// initializeTerminalCondition initializes a Condition to the given status if unset.
func (r conditionsImpl) initializeTerminalCondition(t ConditionType, status corev1.ConditionStatus) *Condition {
	if c := r.GetCondition(t); c != nil {
		return c
	}
	c := Condition{
		Type:     t,
		Status:   status,
		Severity: ConditionSeverityError,
	}
	r.SetCondition(c)
	return &c
}
<commit_msg>apis: fix typo in ConditionSet.Manage comment (#551)<commit_after>/*
Copyright 2019 The Knative 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.
*/

package apis

import (
	"reflect"
	"sort"
	"time"

	"fmt"

	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// Conditions is the interface for a Resource that implements the getter and
// setter for accessing a Condition collection.
// +k8s:deepcopy-gen=true
type ConditionsAccessor interface {
	GetConditions() Conditions
	SetConditions(Conditions)
}

// ConditionSet is an abstract collection of the possible ConditionType values
// that a particular resource might expose.  It also holds the "happy condition"
// for that resource, which we define to be one of Ready or Succeeded depending
// on whether it is a Living or Batch process respectively.
// +k8s:deepcopy-gen=false
type ConditionSet struct {
	happy      ConditionType
	dependents []ConditionType
}

// ConditionManager allows a resource to operate on its Conditions using higher
// order operations.
type ConditionManager interface {
	// IsHappy looks at the happy condition and returns true if that condition is
	// set to true.
	IsHappy() bool

	// GetCondition finds and returns the Condition that matches the ConditionType
	// previously set on Conditions.
	GetCondition(t ConditionType) *Condition

	// SetCondition sets or updates the Condition on Conditions for Condition.Type.
	// If there is an update, Conditions are stored back sorted.
	SetCondition(new Condition)

	// ClearCondition removes the non terminal condition that matches the ConditionType
	ClearCondition(t ConditionType) error

	// MarkTrue sets the status of t to true, and then marks the happy condition to
	// true if all dependents are true.
	MarkTrue(t ConditionType)

	// MarkUnknown sets the status of t to Unknown and also sets the happy condition
	// to Unknown if no other dependent condition is in an error state.
	MarkUnknown(t ConditionType, reason, messageFormat string, messageA ...interface{})

	// MarkFalse sets the status of t and the happy condition to False.
	MarkFalse(t ConditionType, reason, messageFormat string, messageA ...interface{})

	// InitializeConditions updates all Conditions in the ConditionSet to Unknown
	// if not set.
	InitializeConditions()
}

// NewLivingConditionSet returns a ConditionSet to hold the conditions for the
// living resource. ConditionReady is used as the happy condition.
// The set of condition types provided are those of the terminal subconditions.
func NewLivingConditionSet(d ...ConditionType) ConditionSet {
	return newConditionSet(ConditionReady, d...)
}

// NewBatchConditionSet returns a ConditionSet to hold the conditions for the
// batch resource. ConditionSucceeded is used as the happy condition.
// The set of condition types provided are those of the terminal subconditions.
func NewBatchConditionSet(d ...ConditionType) ConditionSet {
	return newConditionSet(ConditionSucceeded, d...)
}

// newConditionSet returns a ConditionSet to hold the conditions that are
// important for the caller. The first ConditionType is the overarching status
// for that will be used to signal the resources' status is Ready or Succeeded.
func newConditionSet(happy ConditionType, dependents ...ConditionType) ConditionSet {
	var deps []ConditionType
	for _, d := range dependents {
		// Skip duplicates
		if d == happy || contains(deps, d) {
			continue
		}
		deps = append(deps, d)
	}
	return ConditionSet{
		happy:      happy,
		dependents: deps,
	}
}

func contains(ct []ConditionType, t ConditionType) bool {
	for _, c := range ct {
		if c == t {
			return true
		}
	}
	return false
}

// Check that conditionsImpl implements ConditionManager.
var _ ConditionManager = (*conditionsImpl)(nil)

// conditionsImpl implements the helper methods for evaluating Conditions.
// +k8s:deepcopy-gen=false
type conditionsImpl struct {
	ConditionSet
	accessor ConditionsAccessor
}

// Manage creates a ConditionManager from an accessor object using the original
// ConditionSet as a reference. Status must be a pointer to a struct.
func (r ConditionSet) Manage(status ConditionsAccessor) ConditionManager {
	return conditionsImpl{
		accessor:     status,
		ConditionSet: r,
	}
}

// IsHappy looks at the happy condition and returns true if that condition is
// set to true.
func (r conditionsImpl) IsHappy() bool {
	if c := r.GetCondition(r.happy); c == nil || !c.IsTrue() {
		return false
	}
	return true
}

// GetCondition finds and returns the Condition that matches the ConditionType
// previously set on Conditions.
func (r conditionsImpl) GetCondition(t ConditionType) *Condition {
	if r.accessor == nil {
		return nil
	}

	for _, c := range r.accessor.GetConditions() {
		if c.Type == t {
			return &c
		}
	}
	return nil
}

// SetCondition sets or updates the Condition on Conditions for Condition.Type.
// If there is an update, Conditions are stored back sorted.
func (r conditionsImpl) SetCondition(new Condition) {
	if r.accessor == nil {
		return
	}
	t := new.Type
	var conditions Conditions
	for _, c := range r.accessor.GetConditions() {
		if c.Type != t {
			conditions = append(conditions, c)
		} else {
			// If we'd only update the LastTransitionTime, then return.
			new.LastTransitionTime = c.LastTransitionTime
			if reflect.DeepEqual(&new, &c) {
				return
			}
		}
	}
	new.LastTransitionTime = VolatileTime{Inner: metav1.NewTime(time.Now())}
	conditions = append(conditions, new)
	// Sorted for convenience of the consumer, i.e. kubectl.
	sort.Slice(conditions, func(i, j int) bool { return conditions[i].Type < conditions[j].Type })
	r.accessor.SetConditions(conditions)
}

func (r conditionsImpl) isTerminal(t ConditionType) bool {
	for _, cond := range r.dependents {
		if cond == t {
			return true
		}
	}
	return t == r.happy
}

func (r conditionsImpl) severity(t ConditionType) ConditionSeverity {
	if r.isTerminal(t) {
		return ConditionSeverityError
	}
	return ConditionSeverityInfo
}

// RemoveCondition removes the non terminal condition that matches the ConditionType
// Not implemented for terminal conditions
func (r conditionsImpl) ClearCondition(t ConditionType) error {
	var conditions Conditions

	if r.accessor == nil {
		return nil
	}
	// Terminal conditions are not handled as they can't be nil
	if r.isTerminal(t) {
		return fmt.Errorf("Clearing terminal conditions not implemented")
	}
	cond := r.GetCondition(t)
	if cond == nil {
		return nil
	}
	for _, c := range r.accessor.GetConditions() {
		if c.Type != t {
			conditions = append(conditions, c)
		}
	}

	// Sorted for convenience of the consumer, i.e. kubectl.
	sort.Slice(conditions, func(i, j int) bool { return conditions[i].Type < conditions[j].Type })
	r.accessor.SetConditions(conditions)

	return nil
}

// MarkTrue sets the status of t to true, and then marks the happy condition to
// true if all other dependents are also true.
func (r conditionsImpl) MarkTrue(t ConditionType) {
	// set the specified condition
	r.SetCondition(Condition{
		Type:     t,
		Status:   corev1.ConditionTrue,
		Severity: r.severity(t),
	})

	// check the dependents.
	for _, cond := range r.dependents {
		c := r.GetCondition(cond)
		// Failed or Unknown conditions trump true conditions
		if !c.IsTrue() {
			return
		}
	}

	// set the happy condition
	r.SetCondition(Condition{
		Type:     r.happy,
		Status:   corev1.ConditionTrue,
		Severity: r.severity(r.happy),
	})
}

// MarkUnknown sets the status of t to Unknown and also sets the happy condition
// to Unknown if no other dependent condition is in an error state.
func (r conditionsImpl) MarkUnknown(t ConditionType, reason, messageFormat string, messageA ...interface{}) {
	// set the specified condition
	r.SetCondition(Condition{
		Type:     t,
		Status:   corev1.ConditionUnknown,
		Reason:   reason,
		Message:  fmt.Sprintf(messageFormat, messageA...),
		Severity: r.severity(t),
	})

	// check the dependents.
	isDependent := false
	for _, cond := range r.dependents {
		c := r.GetCondition(cond)
		// Failed conditions trump Unknown conditions
		if c.IsFalse() {
			// Double check that the happy condition is also false.
			happy := r.GetCondition(r.happy)
			if !happy.IsFalse() {
				r.MarkFalse(r.happy, reason, messageFormat, messageA...)
			}
			return
		}
		if cond == t {
			isDependent = true
		}
	}

	if isDependent {
		// set the happy condition, if it is one of our dependent subconditions.
		r.SetCondition(Condition{
			Type:     r.happy,
			Status:   corev1.ConditionUnknown,
			Reason:   reason,
			Message:  fmt.Sprintf(messageFormat, messageA...),
			Severity: r.severity(r.happy),
		})
	}
}

// MarkFalse sets the status of t and the happy condition to False.
func (r conditionsImpl) MarkFalse(t ConditionType, reason, messageFormat string, messageA ...interface{}) {
	types := []ConditionType{t}
	for _, cond := range r.dependents {
		if cond == t {
			types = append(types, r.happy)
		}
	}

	for _, t := range types {
		r.SetCondition(Condition{
			Type:     t,
			Status:   corev1.ConditionFalse,
			Reason:   reason,
			Message:  fmt.Sprintf(messageFormat, messageA...),
			Severity: r.severity(t),
		})
	}
}

// InitializeConditions updates all Conditions in the ConditionSet to Unknown
// if not set.
func (r conditionsImpl) InitializeConditions() {
	happy := r.GetCondition(r.happy)
	if happy == nil {
		happy = &Condition{
			Type:     r.happy,
			Status:   corev1.ConditionUnknown,
			Severity: ConditionSeverityError,
		}
		r.SetCondition(*happy)
	}
	// If the happy state is true, it implies that all of the terminal
	// subconditions must be true, so initialize any unset conditions to
	// true if our happy condition is true, otherwise unknown.
	status := corev1.ConditionUnknown
	if happy.Status == corev1.ConditionTrue {
		status = corev1.ConditionTrue
	}
	for _, t := range r.dependents {
		r.initializeTerminalCondition(t, status)
	}
}

// initializeTerminalCondition initializes a Condition to the given status if unset.
func (r conditionsImpl) initializeTerminalCondition(t ConditionType, status corev1.ConditionStatus) *Condition {
	if c := r.GetCondition(t); c != nil {
		return c
	}
	c := Condition{
		Type:     t,
		Status:   status,
		Severity: ConditionSeverityError,
	}
	r.SetCondition(c)
	return &c
}
<|endoftext|>


<commit_before>// Copyright 2016 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

// TODO(ericsnow) Remove this file once we add a registration mechanism.

package apiserver

import (
	"net/http"

	"github.com/juju/errors"
	"github.com/juju/names"

	internalserver "github.com/juju/juju/resource/api/private/server"
	"github.com/juju/juju/resource/api/server"
	"github.com/juju/juju/resource/resourceadapters"
	"github.com/juju/juju/state"
)

type resourcesHandlerDeps struct {
	httpCtxt httpContext
}

// ConnectForUser connects to state for an API user.
func (deps resourcesHandlerDeps) ConnectForUser(req *http.Request) (*state.State, state.Entity, error) {
	return deps.httpCtxt.stateForRequestAuthenticatedUser(req)
}

// ConnectForUnitAgent connects to state for a unit agent.
func (deps resourcesHandlerDeps) ConnectForUnitAgent(req *http.Request) (*state.State, *state.Unit, error) {
	st, ent, err := deps.httpCtxt.stateForRequestAuthenticatedAgent(req)
	if err != nil {
		return nil, nil, errors.Trace(err)
	}

	unit, ok := ent.(*state.Unit)
	if !ok {
		logger.Criticalf("unexpected type: %T", ent)
		return nil, nil, errors.Errorf("unexpected type: %T", ent)
	}
	return st, unit, nil
}

// TODO(ericsnow) Move these functions to resourceadapters?

func newResourceHandler(httpCtxt httpContext) http.Handler {
	deps := resourcesHandlerDeps{httpCtxt}
	return server.NewLegacyHTTPHandler(
		func(req *http.Request) (server.DataStore, names.Tag, error) {
			st, entity, err := deps.ConnectForUser(req)
			if err != nil {
				return nil, nil, errors.Trace(err)
			}
			resources, err := st.Resources()
			if err != nil {
				return nil, nil, errors.Trace(err)
			}
			return resources, entity.Tag(), nil
		},
	)
}

func newUnitResourceHandler(httpCtxt httpContext) http.Handler {
	extractor := resourceadapters.APIHTTPRequestExtractor{
		Connector: &resourcesHandlerDeps{httpCtxt},
	}
	deps := internalserver.NewLegacyHTTPHandlerDeps(extractor)
	return internalserver.NewLegacyHTTPHandler(deps)
}
<commit_msg>Downgrade a logger call.<commit_after>// Copyright 2016 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

// TODO(ericsnow) Remove this file once we add a registration mechanism.

package apiserver

import (
	"net/http"

	"github.com/juju/errors"
	"github.com/juju/names"

	internalserver "github.com/juju/juju/resource/api/private/server"
	"github.com/juju/juju/resource/api/server"
	"github.com/juju/juju/resource/resourceadapters"
	"github.com/juju/juju/state"
)

type resourcesHandlerDeps struct {
	httpCtxt httpContext
}

// ConnectForUser connects to state for an API user.
func (deps resourcesHandlerDeps) ConnectForUser(req *http.Request) (*state.State, state.Entity, error) {
	return deps.httpCtxt.stateForRequestAuthenticatedUser(req)
}

// ConnectForUnitAgent connects to state for a unit agent.
func (deps resourcesHandlerDeps) ConnectForUnitAgent(req *http.Request) (*state.State, *state.Unit, error) {
	st, ent, err := deps.httpCtxt.stateForRequestAuthenticatedAgent(req)
	if err != nil {
		return nil, nil, errors.Trace(err)
	}

	unit, ok := ent.(*state.Unit)
	if !ok {
		logger.Errorf("unexpected type: %T", ent)
		return nil, nil, errors.Errorf("unexpected type: %T", ent)
	}
	return st, unit, nil
}

// TODO(ericsnow) Move these functions to resourceadapters?

func newResourceHandler(httpCtxt httpContext) http.Handler {
	deps := resourcesHandlerDeps{httpCtxt}
	return server.NewLegacyHTTPHandler(
		func(req *http.Request) (server.DataStore, names.Tag, error) {
			st, entity, err := deps.ConnectForUser(req)
			if err != nil {
				return nil, nil, errors.Trace(err)
			}
			resources, err := st.Resources()
			if err != nil {
				return nil, nil, errors.Trace(err)
			}
			return resources, entity.Tag(), nil
		},
	)
}

func newUnitResourceHandler(httpCtxt httpContext) http.Handler {
	extractor := resourceadapters.APIHTTPRequestExtractor{
		Connector: &resourcesHandlerDeps{httpCtxt},
	}
	deps := internalserver.NewLegacyHTTPHandlerDeps(extractor)
	return internalserver.NewLegacyHTTPHandler(deps)
}
<|endoftext|>


<commit_before>package gerrittest

import (
	"encoding/json"
	"io/ioutil"

	"github.com/opalmer/dockertest"
	"github.com/spf13/cobra"
)

// ServiceSpec is used to serialize information about an instance
// of Gerrit.
type ServiceSpec struct {
	Admin     *User            `json:"admin"`
	Container string           `json:"container"`
	SSH       *dockertest.Port `json:"ssh"`
	HTTP      *dockertest.Port `json:"http"`
}

// ReadServiceSpec reads and returns a *ServiceSpec from a file.
func ReadServiceSpec(path string) (*ServiceSpec, error) {
	var spec ServiceSpec
	data, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, err
	}
	if err := json.Unmarshal(data, &spec); err != nil {
		return nil, err
	}
	return &spec, nil
}

// ReadServiceSpecFromArg is identical to ReadServiceSpec except we're
// reading the --json argument from a command.
func ReadServiceSpecFromArg(cmd *cobra.Command) (*ServiceSpec, error) {
	path, err := cmd.Flags().GetString("json")
	if err != nil {
		return nil, err
	}
	return ReadServiceSpec(path)
}
<commit_msg>adding SSHCommand/URL fields<commit_after>package gerrittest

import (
	"encoding/json"
	"io/ioutil"

	"github.com/opalmer/dockertest"
	"github.com/spf13/cobra"
)

// ServiceSpec is used to serialize information about an instance
// of Gerrit.
type ServiceSpec struct {
	Admin      *User            `json:"admin"`
	Container  string           `json:"container"`
	SSH        *dockertest.Port `json:"ssh"`
	HTTP       *dockertest.Port `json:"http"`
	URL        string           `json:"url"`
	SSHCommand string           `json:"ssh_command"`
}

// ReadServiceSpec reads and returns a *ServiceSpec from a file.
func ReadServiceSpec(path string) (*ServiceSpec, error) {
	var spec ServiceSpec
	data, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, err
	}
	if err := json.Unmarshal(data, &spec); err != nil {
		return nil, err
	}
	return &spec, nil
}

// ReadServiceSpecFromArg is identical to ReadServiceSpec except we're
// reading the --json argument from a command.
func ReadServiceSpecFromArg(cmd *cobra.Command) (*ServiceSpec, error) {
	path, err := cmd.Flags().GetString("json")
	if err != nil {
		return nil, err
	}
	return ReadServiceSpec(path)
}
<|endoftext|>


<commit_before>// Package ipnets ipmlements a slice of net.IPNet values with the ability
// to parse comma-delimited IPv4 and IPv6 hosts and networks in CIDR format
// using flag package and then check if individual net.IP match any of
// networks in the slice
package ipnets

import (
	"net"
	"strings"
)

// IPNet is a slice of net.IPNet
type IPNets []net.IPNet

// String returns a string with comma-delimited CIDR representations of
// networks stored in IPNets
// Together with Set implements flag.Value interface so it's possible to parse command-line parameters directly into *IPnets
func (nets *IPNets) String() string {
	s := make([]string, len(*nets))
	for i, net := range *nets {
		s[i] = net.String()
	}
	return strings.Join(s, ", ")
}

// Set parses supplied comma-delimited list of IPv4 or IPv6 IPs and CIDR networks into IPNets.
// Together with String implements flag.Value interface so it's possible to parse command-line parameters directly into *IPnets
func (nets *IPNets) Set(param string) error {
	var ipnet *net.IPNet
	var err error
	for _, s := range strings.Split(param, ",") {
		s = strings.TrimSpace(s)
		// no "/" symbol in the address, not CIDR
		if !strings.Contains(s, "/") {
			if strings.Contains(s, ".") {
				s = s + "/32"
			} else if strings.Contains(s, ":") {
				s = s + "/128"
			}
		}
		if _, ipnet, err = net.ParseCIDR(s); err != nil {
			return err
		}
		*nets = append(*nets, *ipnet)
	}
	return nil
}

// Contains returns true if ip matches any of networks stored in IPNets
func (nets IPNets) Contains(ip net.IP) bool {
	for _, n := range nets {
		if n.Contains(ip) {
			return true
		}
	}
	return false
}
<commit_msg>Typo in a comment<commit_after>// Package ipnets ipmlements a slice of net.IPNet values with the ability
// to parse comma-delimited IPv4 and IPv6 hosts and networks in CIDR format
// using flag package and then check if individual net.IP match any of
// networks in the slice
package ipnets

import (
	"net"
	"strings"
)

// IPNets is a slice of net.IPNet
type IPNets []net.IPNet

// String returns a string with comma-delimited CIDR representations of
// networks stored in IPNets
// Together with Set implements flag.Value interface so it's possible to parse command-line parameters directly into *IPnets
func (nets *IPNets) String() string {
	s := make([]string, len(*nets))
	for i, net := range *nets {
		s[i] = net.String()
	}
	return strings.Join(s, ", ")
}

// Set parses supplied comma-delimited list of IPv4 or IPv6 IPs and CIDR networks into IPNets.
// Together with String implements flag.Value interface so it's possible to parse command-line parameters directly into *IPnets
func (nets *IPNets) Set(param string) error {
	var ipnet *net.IPNet
	var err error
	for _, s := range strings.Split(param, ",") {
		s = strings.TrimSpace(s)
		// no "/" symbol in the address, not CIDR
		if !strings.Contains(s, "/") {
			if strings.Contains(s, ".") {
				s = s + "/32"
			} else if strings.Contains(s, ":") {
				s = s + "/128"
			}
		}
		if _, ipnet, err = net.ParseCIDR(s); err != nil {
			return err
		}
		*nets = append(*nets, *ipnet)
	}
	return nil
}

// Contains returns true if ip matches any of networks stored in IPNets
func (nets IPNets) Contains(ip net.IP) bool {
	for _, n := range nets {
		if n.Contains(ip) {
			return true
		}
	}
	return false
}
<|endoftext|>


<commit_before>package cli_test

import (
	"fmt"
	"github.com/codegangsta/cli"
	"os"
	"testing"
)

func ExampleApp() {
	// set args for examples sake
	os.Args = []string{"greet", "--name", "Jeremy"}

	app := cli.NewApp()
	app.Name = "greet"
	app.Flags = []cli.Flag{
		cli.StringFlag{Name: "name", Value: "bob", Usage: "a name to say"},
	}
	app.Action = func(c *cli.Context) {
		fmt.Printf("Hello %v\n", c.String("name"))
	}
	app.Run(os.Args)
	// Output:
	// Hello Jeremy
}

func TestApp_Run(t *testing.T) {
	s := ""

	app := cli.NewApp()
	app.Action = func(c *cli.Context) {
		s = s + c.Args().First()
	}

	err := app.Run([]string{"command", "foo"})
	expect(t, err, nil)
	err = app.Run([]string{"command", "bar"})
	expect(t, err, nil)
	expect(t, s, "foobar")
}

var commandAppTests = []struct {
	name     string
	expected bool
}{
	{"foobar", true},
	{"batbaz", true},
	{"b", true},
	{"f", true},
	{"bat", false},
	{"nothing", false},
}

func TestApp_Command(t *testing.T) {
	app := cli.NewApp()
	fooCommand := cli.Command{Name: "foobar", ShortName: "f"}
	batCommand := cli.Command{Name: "batbaz", ShortName: "b"}
	app.Commands = []cli.Command{
		fooCommand,
		batCommand,
	}

	for _, test := range commandAppTests {
		expect(t, app.Command(test.name) != nil, test.expected)
	}
}

func TestApp_CommandWithArgBeforeFlags(t *testing.T) {
	var parsedOption, firstArg string

	app := cli.NewApp()
	command := cli.Command{
		Name: "cmd",
		Flags: []cli.Flag{
			cli.StringFlag{Name: "option", Value: "", Usage: "some option"},
		},
		Action: func(c *cli.Context) {
			parsedOption = c.String("option")
			firstArg = c.Args().First()
		},
	}
	app.Commands = []cli.Command{command}

	app.Run([]string{"", "cmd", "my-arg", "--option", "my-option"})

	expect(t, parsedOption, "my-option")
	expect(t, firstArg, "my-arg")
}

func TestApp_Float64Flag(t *testing.T) {
	var meters float64

	app := cli.NewApp()
	app.Flags = []cli.Flag{
		cli.Float64Flag{Name: "height", Value: 1.5, Usage: "Set the height, in meters"},
	}
	app.Action = func(c *cli.Context) {
		meters = c.Float64("height")
	}

	app.Run([]string{"", "--height", "1.93"})
	expect(t, meters, 1.93)
}

func TestApp_ParseSliceFlags(t *testing.T) {
	var parsedOption, firstArg string
	var parsedIntSlice []int
	var parsedStringSlice []string

	app := cli.NewApp()
	command := cli.Command{
		Name: "cmd",
		Flags: []cli.Flag{
			cli.IntSliceFlag{Name: "p", Value: &cli.IntSlice{}, Usage: "set one or more ip addr"},
			cli.StringSliceFlag{Name: "ip", Value: &cli.StringSlice{}, Usage: "set one or more ports to open"},
		},
		Action: func(c *cli.Context) {
			parsedIntSlice = c.IntSlice("p")
			parsedStringSlice = c.StringSlice("ip")
			parsedOption = c.String("option")
			firstArg = c.Args().First()
		},
	}
	app.Commands = []cli.Command{command}

	app.Run([]string{"", "cmd", "my-arg", "-p", "22", "-p", "80", "-ip", "8.8.8.8", "-ip", "8.8.4.4"})

	IntsEquals := func(a, b []int) bool {
		if len(a) != len(b) {
			return false
		}
		for i, v := range a {
			if v != b[i] {
				return false
			}
		}
		return true
	}

	StrsEquals := func(a, b []string) bool {
		if len(a) != len(b) {
			return false
		}
		for i, v := range a {
			if v != b[i] {
				return false
			}
		}
		return true
	}
	var expectedIntSlice = []int{22, 80}
	var expectedStringSlice = []string{"8.8.8.8", "8.8.4.4"}

	if !IntsEquals(parsedIntSlice, expectedIntSlice) {
		t.Errorf("%s does not match %s", parsedIntSlice, expectedIntSlice)
	}

	if !StrsEquals(parsedStringSlice, expectedStringSlice) {
		t.Errorf("%s does not match %s", parsedStringSlice, expectedStringSlice)
	}
}

func TestApp_BeforeFunc(t *testing.T) {
	beforeRun, subcommandRun := false, false
	beforeError := fmt.Errorf("fail")
	var err error

	app := cli.NewApp()

	app.Before = func(c *cli.Context) error {
		beforeRun = true
		s := c.String("opt")
		if s == "fail" {
			return beforeError
		}

		return nil
	}

	app.Commands = []cli.Command{
		cli.Command{
			Name: "sub",
			Action: func(c *cli.Context) {
				subcommandRun = true
			},
		},
	}

	app.Flags = []cli.Flag{
		cli.StringFlag{Name: "opt"},
	}

	// run with the Before() func succeeding
	err = app.Run([]string{"command", "--opt", "succeed", "sub"})

	if err != nil {
		t.Fatalf("Run error: %s", err)
	}

	if beforeRun == false {
		t.Errorf("Before() not executed when expected")
	}

	if subcommandRun == false {
		t.Errorf("Subcommand not executed when expected")
	}

	// reset
	beforeRun, subcommandRun = false, false

	// run with the Before() func failing
	err = app.Run([]string{"command", "--opt", "fail", "sub"})

	// should be the same error produced by the Before func
	if err != beforeError {
		t.Errorf("Run error expected, but not received")
	}

	if beforeRun == false {
		t.Errorf("Before() not executed when expected")
	}

	if subcommandRun == true {
		t.Errorf("Subcommand executed when NOT expected")
	}

}

func TestAppHelpPrinter(t *testing.T) {
	oldPrinter := cli.HelpPrinter
	defer func() {
		cli.HelpPrinter = oldPrinter
	}()

	var wasCalled = false
	cli.HelpPrinter = func(template string, data interface{}) {
		wasCalled = true
	}

	app := cli.NewApp()
	app.Run([]string{"-h"})

	if wasCalled == false {
		t.Errorf("Help printer expected to be called, but was not")
	}
}
<commit_msg>add tests for description output<commit_after>package cli_test

import (
	"fmt"
	"github.com/codegangsta/cli"
	"os"
	"testing"
)

func ExampleApp() {
	// set args for examples sake
	os.Args = []string{"greet", "--name", "Jeremy"}

	app := cli.NewApp()
	app.Name = "greet"
	app.Flags = []cli.Flag{
		cli.StringFlag{Name: "name", Value: "bob", Usage: "a name to say"},
	}
	app.Action = func(c *cli.Context) {
		fmt.Printf("Hello %v\n", c.String("name"))
	}
	app.Run(os.Args)
	// Output:
	// Hello Jeremy
}

func ExampleAppHelp() {
	// set args for examples sake
	os.Args = []string{"greet", "h", "describeit"}

	app := cli.NewApp()
	app.Name = "greet"
	app.Flags = []cli.Flag{
		cli.StringFlag{Name: "name", Value: "bob", Usage: "a name to say"},
	}
	app.Commands = []cli.Command{
    {
			Name: "describeit",
			ShortName: "d",
			Usage: "use it to see a description",
			Description: "This is how we describe describeit the function",
			Action: func(c *cli.Context) {
        fmt.Printf("i like to describe things")
      },
		},
	}
	app.Run(os.Args)
	// Output:
  // NAME:
  //    describeit - use it to see a description
	//
  // USAGE:
  //    command describeit [command options] [arguments...]
	//
  // DESCRIPTION:
  //    This is how we describe describeit the function
  //
  // OPTIONS:
}

func TestApp_Run(t *testing.T) {
	s := ""

	app := cli.NewApp()
	app.Action = func(c *cli.Context) {
		s = s + c.Args().First()
	}

	err := app.Run([]string{"command", "foo"})
	expect(t, err, nil)
	err = app.Run([]string{"command", "bar"})
	expect(t, err, nil)
	expect(t, s, "foobar")
}

var commandAppTests = []struct {
	name     string
	expected bool
}{
	{"foobar", true},
	{"batbaz", true},
	{"b", true},
	{"f", true},
	{"bat", false},
	{"nothing", false},
}

func TestApp_Command(t *testing.T) {
	app := cli.NewApp()
	fooCommand := cli.Command{Name: "foobar", ShortName: "f", Description: "Foobar is nuts",}
	batCommand := cli.Command{Name: "batbaz", ShortName: "b"}
	app.Commands = []cli.Command{
		fooCommand,
		batCommand,
	}

	for _, test := range commandAppTests {
		expect(t, app.Command(test.name) != nil, test.expected)
	}
}

func TestApp_CommandWithArgBeforeFlags(t *testing.T) {
	var parsedOption, firstArg string

	app := cli.NewApp()
	command := cli.Command{
		Name: "cmd",
		Flags: []cli.Flag{
			cli.StringFlag{Name: "option", Value: "", Usage: "some option"},
		},
		Action: func(c *cli.Context) {
			parsedOption = c.String("option")
			firstArg = c.Args().First()
		},
	}
	app.Commands = []cli.Command{command}

	app.Run([]string{"", "cmd", "my-arg", "--option", "my-option"})

	expect(t, parsedOption, "my-option")
	expect(t, firstArg, "my-arg")
}

func TestApp_Float64Flag(t *testing.T) {
	var meters float64

	app := cli.NewApp()
	app.Flags = []cli.Flag{
		cli.Float64Flag{Name: "height", Value: 1.5, Usage: "Set the height, in meters"},
	}
	app.Action = func(c *cli.Context) {
		meters = c.Float64("height")
	}

	app.Run([]string{"", "--height", "1.93"})
	expect(t, meters, 1.93)
}

func TestApp_ParseSliceFlags(t *testing.T) {
	var parsedOption, firstArg string
	var parsedIntSlice []int
	var parsedStringSlice []string

	app := cli.NewApp()
	command := cli.Command{
		Name: "cmd",
		Flags: []cli.Flag{
			cli.IntSliceFlag{Name: "p", Value: &cli.IntSlice{}, Usage: "set one or more ip addr"},
			cli.StringSliceFlag{Name: "ip", Value: &cli.StringSlice{}, Usage: "set one or more ports to open"},
		},
		Action: func(c *cli.Context) {
			parsedIntSlice = c.IntSlice("p")
			parsedStringSlice = c.StringSlice("ip")
			parsedOption = c.String("option")
			firstArg = c.Args().First()
		},
	}

	app.Commands = []cli.Command{command}

	app.Run([]string{"", "cmd", "my-arg", "-p", "22", "-p", "80", "-ip", "8.8.8.8", "-ip", "8.8.4.4"})

	IntsEquals := func(a, b []int) bool {
		if len(a) != len(b) {
			return false
		}
		for i, v := range a {
			if v != b[i] {
				return false
			}
		}
		return true
	}

	StrsEquals := func(a, b []string) bool {
		if len(a) != len(b) {
			return false
		}
		for i, v := range a {
			if v != b[i] {
				return false
			}
		}
		return true
	}
	var expectedIntSlice = []int{22, 80}
	var expectedStringSlice = []string{"8.8.8.8", "8.8.4.4"}

	if !IntsEquals(parsedIntSlice, expectedIntSlice) {
		t.Errorf("%s does not match %s", parsedIntSlice, expectedIntSlice)
	}

	if !StrsEquals(parsedStringSlice, expectedStringSlice) {
		t.Errorf("%s does not match %s", parsedStringSlice, expectedStringSlice)
	}
}

func TestApp_BeforeFunc(t *testing.T) {
	beforeRun, subcommandRun := false, false
	beforeError := fmt.Errorf("fail")
	var err error

	app := cli.NewApp()

	app.Before = func(c *cli.Context) error {
		beforeRun = true
		s := c.String("opt")
		if s == "fail" {
			return beforeError
		}

		return nil
	}

	app.Commands = []cli.Command{
		cli.Command{
			Name: "sub",
			Action: func(c *cli.Context) {
				subcommandRun = true
			},
		},
	}

	app.Flags = []cli.Flag{
		cli.StringFlag{Name: "opt"},
	}

	// run with the Before() func succeeding
	err = app.Run([]string{"command", "--opt", "succeed", "sub"})

	if err != nil {
		t.Fatalf("Run error: %s", err)
	}

	if beforeRun == false {
		t.Errorf("Before() not executed when expected")
	}

	if subcommandRun == false {
		t.Errorf("Subcommand not executed when expected")
	}

	// reset
	beforeRun, subcommandRun = false, false

	// run with the Before() func failing
	err = app.Run([]string{"command", "--opt", "fail", "sub"})

	// should be the same error produced by the Before func
	if err != beforeError {
		t.Errorf("Run error expected, but not received")
	}

	if beforeRun == false {
		t.Errorf("Before() not executed when expected")
	}

	if subcommandRun == true {
		t.Errorf("Subcommand executed when NOT expected")
	}

}

func TestAppHelpPrinter(t *testing.T) {
	oldPrinter := cli.HelpPrinter
	defer func() {
		cli.HelpPrinter = oldPrinter
	}()

	var wasCalled = false
	cli.HelpPrinter = func(template string, data interface{}) {
		wasCalled = true
	}

	app := cli.NewApp()
	app.Run([]string{"-h"})

	if wasCalled == false {
		t.Errorf("Help printer expected to be called, but was not")
	}
}
<|endoftext|>