<commit_before>// (C) Copyright 2016 Hewlett Packard Enterprise Development LP
//
// 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 oneview

import (
	"github.com/HewlettPackard/oneview-golang/ov"
	"github.com/HewlettPackard/oneview-golang/utils"
	"github.com/hashicorp/terraform/helper/schema"
)

func resourceUplinkSet() *schema.Resource {
	return &schema.Resource{
		Create: resourceUplinkSetCreate,
		Read:   resourceUplinkSetRead,
		Update: resourceUplinkSetUpdate,
		Delete: resourceUplinkSetDelete,

		Schema: map[string]*schema.Schema{
			"name": {
				Type:     schema.TypeString,
				Required: true,
			},
			"logical_interconnect_uri": {
				Type:     schema.TypeString,
				Optional: true,
			},
			"network_uris": {
				Optional: true,
				Type:     schema.TypeSet,
				Elem: &schema.Schema{
					Type: schema.TypeString,
				},
				Set: schema.HashString,
			},
			"fc_network_uris": {
				Optional: true,
				Type:     schema.TypeSet,
				Elem: &schema.Schema{
					Type: schema.TypeString,
				},
				Set: schema.HashString,
			},
			"fcoe_network_uris": {
				Optional: true,
				Type:     schema.TypeSet,
				Elem: &schema.Schema{
					Type: schema.TypeString,
				},
				Set: schema.HashString,
			},
			"connection_mode": {
				Type:     schema.TypeString,
				Optional: true,
			},
			"network_type": {
				Type:     schema.TypeString,
				Optional: true,
			},
			"ethernet_network_type": {
				Type:     schema.TypeString,
				Optional: true,
			},
			"type": {
				Type:     schema.TypeString,
				Optional: true,
				Default:  "uplink-setV4",
			},
			"description": {
				Type:     schema.TypeString,
				Optional: true,
			},
			"uri": {
				Type:     schema.TypeString,
				Optional: true,
			},
			"status": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"category": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"state": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"eTag": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"created": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"modified": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"lcaptimer": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"manual_login_redistribution_state": {
				Type:     schema.TypeString,
				Optional: true,
			},
			"native_network_uri": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"reachability": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"fc_mode": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"port_config_infos": {
				Type:     schema.TypeSet,
				Optional: true,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"desired_speed": {
							Type:     schema.TypeString,
							Optional: true,
						},
						"port_uri": {
							Type:     schema.TypeString,
							Optional: true,
						},
						"bay_number": {
							Type:     schema.TypeString,
							Optional: true,
						},
						"enclosure_uri": {
							Type:     schema.TypeString,
							Optional: true,
						},
						"port_number": {
							Type:     schema.TypeString,
							Optional: true,
						},
						"remote_chassis_id": {
							Type:     schema.TypeString,
							Optional: true,
						},
						"remote_port_id": {
							Type:     schema.TypeString,
							Optional: true,
						},
					},
				},
			},
		},
	}
}

func resourceUplinkSetCreate(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)

	const Bay = "Bay"
	const Enclosure = "Enclosure"
	const Port = "Port"

	uplinkSet := ov.UplinkSet{
		Name: d.Get("name").(string),
		LogicalInterconnectURI: utils.NewNstring(d.Get("logical_interconnect_uri").(string)),
		ConnectionMode:         d.Get("connection_mode").(string),
		NetworkType:            d.Get("network_type").(string),
		EthernetNetworkType:    d.Get("ethernet_network_type").(string),
		Type:                   d.Get("type").(string),
		ManualLoginRedistributionState: d.Get("manual_login_redistribution_state").(string),
	}

	networkUriList := d.Get("network_uris").(*schema.Set).List()
	networkUris := make([]utils.Nstring, 0)

	for _, raw := range networkUriList {
		networkUris = append(networkUris, utils.NewNstring(raw.(string)))
	}
	uplinkSet.NetworkURIs = networkUris

	fcNetworkUriList := d.Get("fc_network_uris").(*schema.Set).List()
	fcNetworkUris := make([]utils.Nstring, 0)

	for _, raw := range fcNetworkUriList {
		fcNetworkUris = append(fcNetworkUris, utils.NewNstring(raw.(string)))
	}
	uplinkSet.FcNetworkURIs = fcNetworkUris

	fcoeNetworkUriList := d.Get("fcoe_network_uris").(*schema.Set).List()
	fcoeNetworkUris := make([]utils.Nstring, 0)

	for _, raw := range fcoeNetworkUriList {
		fcoeNetworkUris = append(fcoeNetworkUris, utils.NewNstring(raw.(string)))
	}
	uplinkSet.FcoeNetworkURIs = fcoeNetworkUris

	// Getting list of port config info
	portConfigInfosList := d.Get("port_config_infos").(*schema.Set).List()
	portConfigInfos := make([]ov.PortConfigInfos, 0)

	for _, raw := range portConfigInfosList {
		portConfigInfo := raw.(map[string]interface{})

		desiredSpeed := portConfigInfo["desired_speed"].(string)
		portUri := portConfigInfo["port_uri"].(string)

		enclosureLocation := ov.LocationEntries{
			Value: portConfigInfo["enclosure_uri"].(string),
			Type:  Enclosure,
		}
		locationEntries := make([]ov.LocationEntries, 0)
		locationEntries = append(locationEntries, enclosureLocation)

		bayLocation := ov.LocationEntries{
			Value: portConfigInfo["bay_number"].(string),
			Type:  Bay,
		}
		locationEntries = append(locationEntries, bayLocation)

		portLocation := ov.LocationEntries{
			Value: portConfigInfo["port_number"].(string),
			Type:  Port,
		}
		locationEntries = append(locationEntries, portLocation)

		location := ov.Location{
			LocationEntries: locationEntries,
		}

		expectedNeighbor := ov.ExpectedNeighbor{
			RemoteChassisId: portConfigInfo["remote_chassis_id"].(string),
			RemotePortId:    portConfigInfo["remote_port_id"].(string),
		}

		portConfigInfos = append(portConfigInfos, ov.PortConfigInfos{
			DesiredSpeed:     desiredSpeed,
			PortUri:          portUri,
			ExpectedNeighbor: &expectedNeighbor,
			Location:         location,
		})
	}

	uplinkSet.PortConfigInfos = portConfigInfos

	uplinkSetError := config.ovClient.CreateUplinkSet(uplinkSet)
	d.SetId(d.Get("name").(string))
	if uplinkSetError != nil {
		d.SetId("")
		return uplinkSetError
	}
	return resourceUplinkSetRead(d, meta)
}

func resourceUplinkSetRead(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)

	uplinkSet, err := config.ovClient.GetUplinkSetByName(d.Get("name").(string))
	if err != nil || uplinkSet.URI.IsNil() {
		d.SetId("")
		return nil
	}
	d.Set("name", uplinkSet.Name)
	d.Set("logical_interconnect_uri", uplinkSet.LogicalInterconnectURI)
	d.Set("network_uris", uplinkSet.NetworkURIs)
	d.Set("manual_login_redistribution_state", uplinkSet.ManualLoginRedistributionState)
	d.Set("description", uplinkSet.Description)
	d.Set("type", uplinkSet.Type)
	d.Set("uri", uplinkSet.URI.String())
	d.Set("fcoe_network_uris", uplinkSet.FcoeNetworkURIs)
	d.Set("status", uplinkSet.Status)
	d.Set("category", uplinkSet.Category)
	d.Set("state", uplinkSet.State)
	d.Set("fc_network_uris", uplinkSet.FcNetworkURIs)
	d.Set("created", uplinkSet.Created)
	d.Set("modified", uplinkSet.Modified)
	d.Set("eTag", uplinkSet.Etag)
	d.Set("reachability", uplinkSet.Reachability)
	d.Set("network_type", uplinkSet.NetworkType)
	d.Set("ethernet_network_type", uplinkSet.EthernetNetworkType)
	d.Set("port_config_infos", uplinkSet.PortConfigInfos)
	return nil
}

func resourceUplinkSetUpdate(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)

	const Bay = "Bay"
	const Enclosure = "Enclosure"
	const Port = "Port"

	uplinkSet := ov.UplinkSet{
		Name: d.Get("name").(string),
		LogicalInterconnectURI: utils.NewNstring(d.Get("logical_interconnect_uri").(string)),
		ConnectionMode:         d.Get("connection_mode").(string),
		NetworkType:            d.Get("network_type").(string),
		EthernetNetworkType:    d.Get("ethernet_network_type").(string),
		Type:                   d.Get("type").(string),
		URI:                    utils.NewNstring(d.Get("uri").(string)),
		ManualLoginRedistributionState: d.Get("manual_login_redistribution_state").(string),
	}

	networkUriList := d.Get("network_uris").(*schema.Set).List()
	networkUris := make([]utils.Nstring, 0)

	for _, raw := range networkUriList {
		networkUris = append(networkUris, utils.NewNstring(raw.(string)))
	}
	uplinkSet.NetworkURIs = networkUris

	fcNetworkUriList := d.Get("fc_network_uris").(*schema.Set).List()
	fcNetworkUris := make([]utils.Nstring, 0)

	for _, raw := range fcNetworkUriList {
		fcNetworkUris = append(fcNetworkUris, utils.NewNstring(raw.(string)))
	}
	uplinkSet.FcNetworkURIs = fcNetworkUris

	fcoeNetworkUriList := d.Get("fcoe_network_uris").(*schema.Set).List()
	fcoeNetworkUris := make([]utils.Nstring, 0)

	for _, raw := range fcoeNetworkUriList {
		fcoeNetworkUris = append(fcoeNetworkUris, utils.NewNstring(raw.(string)))
	}
	uplinkSet.FcoeNetworkURIs = fcoeNetworkUris

	// Getting list of port config info
	portConfigInfosList := d.Get("port_config_infos").(*schema.Set).List()
	portConfigInfos := make([]ov.PortConfigInfos, 0)

	for _, raw := range portConfigInfosList {
		portConfigInfo := raw.(map[string]interface{})

		desiredSpeed := portConfigInfo["desired_speed"].(string)
		portUri := portConfigInfo["port_uri"].(string)

		enclosureLocation := ov.LocationEntries{
			Value: portConfigInfo["enclosure_uri"].(string),
			Type:  Enclosure,
		}
		locationEntries := make([]ov.LocationEntries, 0)
		locationEntries = append(locationEntries, enclosureLocation)

		bayLocation := ov.LocationEntries{
			Value: portConfigInfo["bay_number"].(string),
			Type:  Bay,
		}
		locationEntries = append(locationEntries, bayLocation)

		portLocation := ov.LocationEntries{
			Value: portConfigInfo["port_number"].(string),
			Type:  Port,
		}
		locationEntries = append(locationEntries, portLocation)

		location := ov.Location{
			LocationEntries: locationEntries,
		}

		expectedNeighbor := ov.ExpectedNeighbor{
			RemoteChassisId: portConfigInfo["remote_chassis_id"].(string),
			RemotePortId:    portConfigInfo["remote_port_id"].(string),
		}

		portConfigInfos = append(portConfigInfos, ov.PortConfigInfos{
			DesiredSpeed:     desiredSpeed,
			PortUri:          portUri,
			ExpectedNeighbor: &expectedNeighbor,
			Location:         location,
		})
	}

	uplinkSet.PortConfigInfos = portConfigInfos

	err := config.ovClient.UpdateUplinkSet(uplinkSet)
	if err != nil {
		return err
	}
	d.SetId(d.Get("name").(string))

	return resourceUplinkSetRead(d, meta)
}

func resourceUplinkSetDelete(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)

	err := config.ovClient.DeleteUplinkSet(d.Get("name").(string))
	if err != nil {
		return err
	}
	return nil
}
<commit_msg>udating lib file as per review<commit_after>// (C) Copyright 2016 Hewlett Packard Enterprise Development LP
//
// 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 oneview

import (
	"github.com/HewlettPackard/oneview-golang/ov"
	"github.com/HewlettPackard/oneview-golang/utils"
	"github.com/hashicorp/terraform/helper/schema"
)

func resourceUplinkSet() *schema.Resource {
	return &schema.Resource{
		Create: resourceUplinkSetCreate,
		Read:   resourceUplinkSetRead,
		Update: resourceUplinkSetUpdate,
		Delete: resourceUplinkSetDelete,

		Schema: map[string]*schema.Schema{
			"name": {
				Type:     schema.TypeString,
				Required: true,
			},
			"logical_interconnect_uri": {
				Type:     schema.TypeString,
				Required: true,
			},
			"network_uris": {
				Required: true,
				Type:     schema.TypeSet,
				Elem: &schema.Schema{
					Type: schema.TypeString,
				},
				Set: schema.HashString,
			},
			"fc_network_uris": {
				Required: true,
				Type:     schema.TypeSet,
				Elem: &schema.Schema{
					Type: schema.TypeString,
				},
				Set: schema.HashString,
			},
			"fcoe_network_uris": {
				Required: true,
				Type:     schema.TypeSet,
				Elem: &schema.Schema{
					Type: schema.TypeString,
				},
				Set: schema.HashString,
			},
			"connection_mode": {
				Type:     schema.TypeString,
				Required: true,
			},
			"network_type": {
				Type:     schema.TypeString,
				Required: true,
			},
			"ethernet_network_type": {
				Type:     schema.TypeString,
				Required: true,
			},
			"type": {
				Type:     schema.TypeString,
				Required: true,
				Default:  "uplink-setV4",
			},
			"description": {
				Type:     schema.TypeString,
				Optional: true,
			},
			"uri": {
				Type:     schema.TypeString,
				Optional: true,
			},
			"eTag": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"lacptimer": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"manual_login_redistribution_state": {
				Type:     schema.TypeString,
				Required: true,
			},
			"native_network_uri": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"reachability": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"fc_mode": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"port_config_infos": {
				Type:     schema.TypeSet,
				Required: true,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"desired_speed": {
							Type:     schema.TypeString,
							Optional: true,
						},
						"port_uri": {
							Type:     schema.TypeString,
							Optional: true,
						},
						"bay_number": {
							Type:     schema.TypeString,
							Optional: true,
						},
						"enclosure_uri": {
							Type:     schema.TypeString,
							Optional: true,
						},
						"port_number": {
							Type:     schema.TypeString,
							Optional: true,
						},
						"remote_chassis_id": {
							Type:     schema.TypeString,
							Optional: true,
						},
						"remote_port_id": {
							Type:     schema.TypeString,
							Optional: true,
						},
					},
				},
			},
		},
	}
}

func resourceUplinkSetCreate(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)

	const Bay = "Bay"
	const Enclosure = "Enclosure"
	const Port = "Port"

	uplinkSet := ov.UplinkSet{
		Name: d.Get("name").(string),
		LogicalInterconnectURI: utils.NewNstring(d.Get("logical_interconnect_uri").(string)),
		ConnectionMode:         d.Get("connection_mode").(string),
		NetworkType:            d.Get("network_type").(string),
		EthernetNetworkType:    d.Get("ethernet_network_type").(string),
		Type:                   d.Get("type").(string),
		ManualLoginRedistributionState: d.Get("manual_login_redistribution_state").(string),
	}

	networkUriList := d.Get("network_uris").(*schema.Set).List()
	networkUris := make([]utils.Nstring, 0)

	for _, raw := range networkUriList {
		networkUris = append(networkUris, utils.NewNstring(raw.(string)))
	}
	uplinkSet.NetworkURIs = networkUris

	fcNetworkUriList := d.Get("fc_network_uris").(*schema.Set).List()
	fcNetworkUris := make([]utils.Nstring, 0)

	for _, raw := range fcNetworkUriList {
		fcNetworkUris = append(fcNetworkUris, utils.NewNstring(raw.(string)))
	}
	uplinkSet.FcNetworkURIs = fcNetworkUris

	fcoeNetworkUriList := d.Get("fcoe_network_uris").(*schema.Set).List()
	fcoeNetworkUris := make([]utils.Nstring, 0)

	for _, raw := range fcoeNetworkUriList {
		fcoeNetworkUris = append(fcoeNetworkUris, utils.NewNstring(raw.(string)))
	}
	uplinkSet.FcoeNetworkURIs = fcoeNetworkUris

	// Getting list of port config info
	portConfigInfosList := d.Get("port_config_infos").(*schema.Set).List()
	portConfigInfos := make([]ov.PortConfigInfos, 0)

	for _, raw := range portConfigInfosList {
		portConfigInfo := raw.(map[string]interface{})

		desiredSpeed := portConfigInfo["desired_speed"].(string)
		portUri := portConfigInfo["port_uri"].(string)

		enclosureLocation := ov.LocationEntries{
			Value: portConfigInfo["enclosure_uri"].(string),
			Type:  Enclosure,
		}
		locationEntries := make([]ov.LocationEntries, 0)
		locationEntries = append(locationEntries, enclosureLocation)

		bayLocation := ov.LocationEntries{
			Value: portConfigInfo["bay_number"].(string),
			Type:  Bay,
		}
		locationEntries = append(locationEntries, bayLocation)

		portLocation := ov.LocationEntries{
			Value: portConfigInfo["port_number"].(string),
			Type:  Port,
		}
		locationEntries = append(locationEntries, portLocation)

		location := ov.Location{
			LocationEntries: locationEntries,
		}

		expectedNeighbor := ov.ExpectedNeighbor{
			RemoteChassisId: portConfigInfo["remote_chassis_id"].(string),
			RemotePortId:    portConfigInfo["remote_port_id"].(string),
		}

		portConfigInfos = append(portConfigInfos, ov.PortConfigInfos{
			DesiredSpeed:     desiredSpeed,
			PortUri:          portUri,
			ExpectedNeighbor: &expectedNeighbor,
			Location:         location,
		})
	}

	uplinkSet.PortConfigInfos = portConfigInfos

	uplinkSetError := config.ovClient.CreateUplinkSet(uplinkSet)
	d.SetId(d.Get("name").(string))
	if uplinkSetError != nil {
		d.SetId("")
		return uplinkSetError
	}
	return resourceUplinkSetRead(d, meta)
}

func resourceUplinkSetRead(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)

	uplinkSet, err := config.ovClient.GetUplinkSetByName(d.Get("name").(string))
	if err != nil || uplinkSet.URI.IsNil() {
		d.SetId("")
		return nil
	}
	d.Set("name", uplinkSet.Name)
	d.Set("logical_interconnect_uri", uplinkSet.LogicalInterconnectURI)
	d.Set("network_uris", uplinkSet.NetworkURIs)
	d.Set("manual_login_redistribution_state", uplinkSet.ManualLoginRedistributionState)
	d.Set("description", uplinkSet.Description)
	d.Set("type", uplinkSet.Type)
	d.Set("uri", uplinkSet.URI.String())
	d.Set("fcoe_network_uris", uplinkSet.FcoeNetworkURIs)
	d.Set("status", uplinkSet.Status)
	d.Set("category", uplinkSet.Category)
	d.Set("state", uplinkSet.State)
	d.Set("fc_network_uris", uplinkSet.FcNetworkURIs)
	d.Set("created", uplinkSet.Created)
	d.Set("modified", uplinkSet.Modified)
	d.Set("eTag", uplinkSet.Etag)
	d.Set("reachability", uplinkSet.Reachability)
	d.Set("network_type", uplinkSet.NetworkType)
	d.Set("ethernet_network_type", uplinkSet.EthernetNetworkType)
	d.Set("port_config_infos", uplinkSet.PortConfigInfos)
	d.Set("connection_mode", uplinkSet.ConnectionMode)
	d.Set("lacptimer", uplinkSet.LacpTimer)
	d.Set("native_network_uri", uplinkSet.NativeNetworkUri)
	d.Set("fc_mode", uplinkSet.FcMode)

	return nil
}

func resourceUplinkSetUpdate(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)

	const Bay = "Bay"
	const Enclosure = "Enclosure"
	const Port = "Port"

	uplinkSet := ov.UplinkSet{
		Name: d.Get("name").(string),
		LogicalInterconnectURI: utils.NewNstring(d.Get("logical_interconnect_uri").(string)),
		ConnectionMode:         d.Get("connection_mode").(string),
		NetworkType:            d.Get("network_type").(string),
		EthernetNetworkType:    d.Get("ethernet_network_type").(string),
		Type:                   d.Get("type").(string),
		URI:                    utils.NewNstring(d.Get("uri").(string)),
		ManualLoginRedistributionState: d.Get("manual_login_redistribution_state").(string),
	}

	networkUriList := d.Get("network_uris").(*schema.Set).List()
	networkUris := make([]utils.Nstring, 0)

	for _, raw := range networkUriList {
		networkUris = append(networkUris, utils.NewNstring(raw.(string)))
	}
	uplinkSet.NetworkURIs = networkUris

	fcNetworkUriList := d.Get("fc_network_uris").(*schema.Set).List()
	fcNetworkUris := make([]utils.Nstring, 0)

	for _, raw := range fcNetworkUriList {
		fcNetworkUris = append(fcNetworkUris, utils.NewNstring(raw.(string)))
	}
	uplinkSet.FcNetworkURIs = fcNetworkUris

	fcoeNetworkUriList := d.Get("fcoe_network_uris").(*schema.Set).List()
	fcoeNetworkUris := make([]utils.Nstring, 0)

	for _, raw := range fcoeNetworkUriList {
		fcoeNetworkUris = append(fcoeNetworkUris, utils.NewNstring(raw.(string)))
	}
	uplinkSet.FcoeNetworkURIs = fcoeNetworkUris

	// Getting list of port config info
	portConfigInfosList := d.Get("port_config_infos").(*schema.Set).List()
	portConfigInfos := make([]ov.PortConfigInfos, 0)

	for _, raw := range portConfigInfosList {
		portConfigInfo := raw.(map[string]interface{})

		desiredSpeed := portConfigInfo["desired_speed"].(string)
		portUri := portConfigInfo["port_uri"].(string)

		enclosureLocation := ov.LocationEntries{
			Value: portConfigInfo["enclosure_uri"].(string),
			Type:  Enclosure,
		}
		locationEntries := make([]ov.LocationEntries, 0)
		locationEntries = append(locationEntries, enclosureLocation)

		bayLocation := ov.LocationEntries{
			Value: portConfigInfo["bay_number"].(string),
			Type:  Bay,
		}
		locationEntries = append(locationEntries, bayLocation)

		portLocation := ov.LocationEntries{
			Value: portConfigInfo["port_number"].(string),
			Type:  Port,
		}
		locationEntries = append(locationEntries, portLocation)

		location := ov.Location{
			LocationEntries: locationEntries,
		}

		expectedNeighbor := ov.ExpectedNeighbor{
			RemoteChassisId: portConfigInfo["remote_chassis_id"].(string),
			RemotePortId:    portConfigInfo["remote_port_id"].(string),
		}

		portConfigInfos = append(portConfigInfos, ov.PortConfigInfos{
			DesiredSpeed:     desiredSpeed,
			PortUri:          portUri,
			ExpectedNeighbor: &expectedNeighbor,
			Location:         location,
		})
	}

	uplinkSet.PortConfigInfos = portConfigInfos

	err := config.ovClient.UpdateUplinkSet(uplinkSet)
	if err != nil {
		return err
	}
	d.SetId(d.Get("name").(string))

	return resourceUplinkSetRead(d, meta)
}

func resourceUplinkSetDelete(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)

	err := config.ovClient.DeleteUplinkSet(d.Get("name").(string))
	if err != nil {
		return err
	}
	return nil
}
<|endoftext|>


<commit_before>// (C) Copyright 2016 Hewlett Packard Enterprise Development LP
//
// 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 oneview

import (
	"fmt"
	"github.com/HewlettPackard/oneview-golang/ov"
	"github.com/HewlettPackard/oneview-golang/utils"
	"github.com/hashicorp/terraform/helper/schema"
)

func resourceUplinkSet() *schema.Resource {
	return &schema.Resource{
		Create: resourceUplinkSetCreate,
		Read:   resourceUplinkSetRead,
		Update: resourceUplinkSetUpdate,
		Delete: resourceUplinkSetDelete,

		Schema: map[string]*schema.Schema{
			"name": {
				Type:     schema.TypeString,
				Required: true,
			},
			"logical_interconnect_uri": {
				Type:     schema.TypeString,
				Optional: true,
			},
			"network_uris": {
				Optional: true,
				Type:     schema.TypeSet,
				Elem: &schema.Schema{
					Type: schema.TypeString,
				},
				Set: schema.HashString,
			},
			"fc_network_uris": {
				Optional: true,
				Type:     schema.TypeSet,
				Elem: &schema.Schema{
					Type: schema.TypeString,
				},
				Set: schema.HashString,
			},
			"fcoe_network_uris": {
				Optional: true,
				Type:     schema.TypeSet,
				Elem: &schema.Schema{
					Type: schema.TypeString,
				},
				Set: schema.HashString,
			},
			"connection_mode": {
				Type:     schema.TypeString,
				Optional: true,
			},
			"network_type": {
				Type:     schema.TypeString,
				Required: true,
			},
			"ethernet_network_type": {
				Type:     schema.TypeString,
				Required: true,
			},
			"type": {
				Type:     schema.TypeString,
				Optional: true,
				Default:  "uplink-setV4",
			},
			"description": {
				Type:     schema.TypeString,
				Optional: true,
			},
			"uri": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"status": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"category": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"state": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"eTag": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"created": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"modified": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"lcaptimer": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"manual_login_redistribution_state": {
				Type:     schema.TypeString,
				Required: true,
			},
			"native_network_uri": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"reachability": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"fc_mode": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"expected_neighbour": {
				Type:     schema.TypeList,
				Optional: true,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"remote_chasis_id": {
							Type:     schema.TypeString,
							Optional: true,
						},
						"remote_port_id": {
							Type:     schema.TypeString,
							Optional: true,
						},
					},
				},
			},
			"port_config_infos": {
				Type:     schema.TypeSet,
				Optional: true,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"desired_speed": {
							Type:     schema.TypeString,
							Optional: true,
						},
						"location": {
							Type:     schema.TypeSet,
							Optional: true,
							Elem: &schema.Resource{
								Schema: map[string]*schema.Schema{
									"location_entries": {
										Type:     schema.TypeSet,
										Optional: true,
										Elem: &schema.Resource{
											Schema: map[string]*schema.Schema{
												"value": {
													Type:     schema.TypeString,
													Optional: true,
												},
												"type": {
													Type:     schema.TypeString,
													Optional: true,
												},
											},
										},
									},
								},
							},
						},
					},
				},
			},
		},
	}
}

func resourceUplinkSetCreate(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)

	uplinkSet := ov.UplinkSet{
		Name: d.Get("name").(string),
		LogicalInterconnectURI: utils.NewNstring(d.Get("logical_interconnect_uri").(string)),
		ConnectionMode:         d.Get("connection_mode").(string),
		NetworkType:            d.Get("network_type").(string),
		EthernetNetworkType:    d.Get("ethernet_network_type").(string),
		Type:                   d.Get("type").(string),
		ManualLoginRedistributionState: d.Get("manual_login_redistribution_state").(string),
	}

	if val, ok := d.GetOk("network_uris"); ok {
		rawNetworkUris := val.(*schema.Set).List()
		NetworkUris := make([]utils.Nstring, len(rawNetworkUris))
		for i, raw := range rawNetworkUris {
			NetworkUris[i] = utils.Nstring(raw.(string))
		}
		uplinkSet.NetworkURIs = NetworkUris
	}

	if val, ok := d.GetOk("fc_network_uris"); ok {
		rawFcNetworkUris := val.(*schema.Set).List()
		FcNetworkUris := make([]utils.Nstring, len(rawFcNetworkUris))
		for i, raw := range rawFcNetworkUris {
			FcNetworkUris[i] = utils.Nstring(raw.(string))
		}
		uplinkSet.FcNetworkURIs = FcNetworkUris
	}

	if val, ok := d.GetOk("fcoe_network_uris"); ok {
		rawFcoeNetworkUris := val.(*schema.Set).List()
		FcoeNetworkUris := make([]utils.Nstring, len(rawFcoeNetworkUris))
		for i, raw := range rawFcoeNetworkUris {
			FcoeNetworkUris[i] = utils.Nstring(raw.(string))
		}
		uplinkSet.FcoeNetworkURIs = FcoeNetworkUris
	}

	// Getting list of port config info
	portConfigInfosCount := d.Get("port_config_infos.#").(int)
	portConfigInfosAll := make([]ov.PortConfigInfos, 0)

	for i := 0; i < portConfigInfosCount; i++ {
		portConfigInfosPrefix := fmt.Sprintf("port_config_infos.%d", i)

		// Getting the list of Location Entries.
		locationPrefix := fmt.Sprintf(portConfigInfosPrefix + ".location.0")
		locationEntriesCount := d.Get(locationPrefix + ".location_entries.#").(int)
		locationEntriesAll := make([]ov.LocationEntries, 0)

		for j := 0; j < locationEntriesCount; j++ {
			locationEntriesPrefix := fmt.Sprintf(locationPrefix+".locationEntries.%d", j)
			locationEntries := ov.LocationEntries{
				Value: d.Get(locationEntriesPrefix + ".value").(string),
				Type:  d.Get(locationEntriesPrefix + ".type").(string),
			}
			locationEntriesAll = append(locationEntriesAll, locationEntries)
		}

		// Setting the Location attribute of port config info
		location := ov.Location{
			LocationEntries: locationEntriesAll,
		}
		portConfigInfos := ov.PortConfigInfos{}
		portConfigInfos.Location = location

		// Setting Desired Speed of port config info
		if val, ok := d.GetOk(portConfigInfosPrefix + ".desired_speed"); ok {
			portConfigInfos.DesiredSpeed = val.(string)
		}

		portConfigInfosAll = append(portConfigInfosAll, portConfigInfos)

	}
	uplinkSet.PortConfigInfos = portConfigInfosAll

	uplinkSetError := config.ovClient.CreateUplinkSet(uplinkSet)
	d.SetId(d.Get("name").(string))
	if uplinkSetError != nil {
		d.SetId("")
		return uplinkSetError
	}
	return resourceUplinkSetRead(d, meta)
}

func resourceUplinkSetRead(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)

	uplinkSet, err := config.ovClient.GetUplinkSetByName(d.Get("name").(string))
	if err != nil || uplinkSet.URI.IsNil() {
		d.SetId("")
		return nil
	}
	d.Set("name", uplinkSet.Name)
	d.Set("logical_interconnect_uri", uplinkSet.LogicalInterconnectURI)
	d.Set("network_uris", uplinkSet.NetworkURIs)
	d.Set("manual_login_redistribution_state", uplinkSet.ManualLoginRedistributionState)
	d.Set("description", uplinkSet.Description)
	d.Set("type", uplinkSet.Type)
	d.Set("uri", uplinkSet.URI.String())
	d.Set("fcoe_network_uris", uplinkSet.FcoeNetworkURIs)
	d.Set("status", uplinkSet.Status)
	d.Set("category", uplinkSet.Category)
	d.Set("state", uplinkSet.State)
	d.Set("fc_network_uris", uplinkSet.FcNetworkURIs)
	d.Set("created", uplinkSet.Created)
	d.Set("modified", uplinkSet.Modified)
	d.Set("eTag", uplinkSet.Etag)
	d.Set("reachability", uplinkSet.Reachability)
	d.Set("expected_neighbor", uplinkSet.ExpectedNeighbor)
	d.Set("network_type", uplinkSet.NetworkType)
	d.Set("ethernet_network_type", uplinkSet.EthernetNetworkType)
	d.Set("port_config_infos", uplinkSet.PortConfigInfos)
	return nil
}

func resourceUplinkSetUpdate(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)

	uplinkSet := ov.UplinkSet{
		Etag:        d.Get("eTag").(string),
		URI:         utils.NewNstring(d.Get("uri").(string)),
		Name:        d.Get("name").(string),
		Type:        d.Get("type").(string),
		Description: utils.NewNstring(d.Get("description").(string)),
	}

	err := config.ovClient.UpdateUplinkSet(uplinkSet)
	if err != nil {
		return err
	}
	d.SetId(d.Get("name").(string))

	return resourceUplinkSetRead(d, meta)
}

func resourceUplinkSetDelete(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)

	err := config.ovClient.DeleteUplinkSet(d.Get("name").(string))
	if err != nil {
		return err
	}
	return nil
}
<commit_msg>updating lib file<commit_after>// (C) Copyright 2016 Hewlett Packard Enterprise Development LP
//
// 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 oneview

import (
	"fmt"
	"github.com/HewlettPackard/oneview-golang/ov"
	"github.com/HewlettPackard/oneview-golang/utils"
	"github.com/hashicorp/terraform/helper/schema"
)

func resourceUplinkSet() *schema.Resource {
	return &schema.Resource{
		Create: resourceUplinkSetCreate,
		Read:   resourceUplinkSetRead,
		Update: resourceUplinkSetUpdate,
		Delete: resourceUplinkSetDelete,

		Schema: map[string]*schema.Schema{
			"name": {
				Type:     schema.TypeString,
				Required: true,
			},
			"logical_interconnect_uri": {
				Type:     schema.TypeString,
				Optional: true,
			},
			"network_uris": {
				Optional: true,
				Type:     schema.TypeSet,
				Elem: &schema.Schema{
					Type: schema.TypeString,
				},
				Set: schema.HashString,
			},
			"fc_network_uris": {
				Optional: true,
				Type:     schema.TypeSet,
				Elem: &schema.Schema{
					Type: schema.TypeString,
				},
				Set: schema.HashString,
			},
			"fcoe_network_uris": {
				Optional: true,
				Type:     schema.TypeSet,
				Elem: &schema.Schema{
					Type: schema.TypeString,
				},
				Set: schema.HashString,
			},
			"connection_mode": {
				Type:     schema.TypeString,
				Optional: true,
			},
			"network_type": {
				Type:     schema.TypeString,
				Required: true,
			},
			"ethernet_network_type": {
				Type:     schema.TypeString,
				Required: true,
			},
			"type": {
				Type:     schema.TypeString,
				Optional: true,
				Default:  "uplink-setV4",
			},
			"description": {
				Type:     schema.TypeString,
				Optional: true,
			},
			"uri": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"status": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"category": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"state": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"eTag": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"created": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"modified": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"lcaptimer": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"manual_login_redistribution_state": {
				Type:     schema.TypeString,
				Required: true,
			},
			"native_network_uri": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"reachability": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"fc_mode": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"expected_neighbour": {
				Type:     schema.TypeList,
				Optional: true,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"remote_chasis_id": {
							Type:     schema.TypeString,
							Optional: true,
						},
						"remote_port_id": {
							Type:     schema.TypeString,
							Optional: true,
						},
					},
				},
			},
			"port_config_infos": {
				Type:     schema.TypeSet,
				Optional: true,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"desired_speed": {
							Type:     schema.TypeString,
							Optional: true,
						},
						"location": {
							Type:     schema.TypeSet,
							Optional: true,
							Elem: &schema.Resource{
								Schema: map[string]*schema.Schema{
									"location_entries": {
										Type:     schema.TypeSet,
										Optional: true,
										Elem: &schema.Resource{
											Schema: map[string]*schema.Schema{
												"value": {
													Type:     schema.TypeString,
													Optional: true,
												},
												"type": {
													Type:     schema.TypeString,
													Optional: true,
												},
											},
										},
									},
								},
							},
						},
					},
				},
			},
		},
	}
}

func resourceUplinkSetCreate(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)

	uplinkSet := ov.UplinkSet{
		Name: d.Get("name").(string),
		LogicalInterconnectURI: utils.NewNstring(d.Get("logical_interconnect_uri").(string)),
		ConnectionMode:         d.Get("connection_mode").(string),
		NetworkType:            d.Get("network_type").(string),
		EthernetNetworkType:    d.Get("ethernet_network_type").(string),
		Type:                   d.Get("type").(string),
		ManualLoginRedistributionState: d.Get("manual_login_redistribution_state").(string),
	}

	if val, ok := d.GetOk("network_uris"); ok {
		rawNetworkUris := val.(*schema.Set).List()
		NetworkUris := make([]utils.Nstring, len(rawNetworkUris))
		for i, raw := range rawNetworkUris {
			NetworkUris[i] = utils.Nstring(raw.(string))
		}
		uplinkSet.NetworkURIs = NetworkUris
	}

	if val, ok := d.GetOk("fc_network_uris"); ok {
		rawFcNetworkUris := val.(*schema.Set).List()
		FcNetworkUris := make([]utils.Nstring, len(rawFcNetworkUris))
		for i, raw := range rawFcNetworkUris {
			FcNetworkUris[i] = utils.Nstring(raw.(string))
		}
		uplinkSet.FcNetworkURIs = FcNetworkUris
	}

	if val, ok := d.GetOk("fcoe_network_uris"); ok {
		rawFcoeNetworkUris := val.(*schema.Set).List()
		FcoeNetworkUris := make([]utils.Nstring, len(rawFcoeNetworkUris))
		for i, raw := range rawFcoeNetworkUris {
			FcoeNetworkUris[i] = utils.Nstring(raw.(string))
		}
		uplinkSet.FcoeNetworkURIs = FcoeNetworkUris
	}

	// Getting list of port config info
	portConfigInfosCount := d.Get("port_config_infos.#").(int)
	portConfigInfosAll := make([]ov.PortConfigInfos, 0)

	for i := 0; i < portConfigInfosCount; i++ {
		portConfigInfosPrefix := fmt.Sprintf("port_config_infos.%d", i)

		// Getting the list of Location Entries.
		locationPrefix := fmt.Sprintf(portConfigInfosPrefix + ".location.0")
		locationEntriesCount := d.Get(locationPrefix + ".location_entries.#").(int)
		locationEntriesAll := make([]ov.LocationEntries, 0)

		for j := 0; j < locationEntriesCount; j++ {
			locationEntriesPrefix := fmt.Sprintf(locationPrefix+".locationEntries.%d", j)
			locationEntries := ov.LocationEntries{
				Value: d.Get(locationEntriesPrefix + ".value").(string),
				Type:  d.Get(locationEntriesPrefix + ".type").(string),
			}
			locationEntriesAll = append(locationEntriesAll, locationEntries)
		}

		// Setting the Location attribute of port config info
		location := ov.Location{
			LocationEntries: locationEntriesAll,
		}

		portConfigInfos := ov.PortConfigInfos{
			Location:     location,
			DesiredSpeed: d.Get(portConfigInfosPrefix + ".desired_speed").(string),
		}

		portConfigInfosAll = append(portConfigInfosAll, portConfigInfos)

	}
	uplinkSet.PortConfigInfos = portConfigInfosAll

	uplinkSetError := config.ovClient.CreateUplinkSet(uplinkSet)
	d.SetId(d.Get("name").(string))
	if uplinkSetError != nil {
		d.SetId("")
		return uplinkSetError
	}
	return resourceUplinkSetRead(d, meta)
}

func resourceUplinkSetRead(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)

	uplinkSet, err := config.ovClient.GetUplinkSetByName(d.Get("name").(string))
	if err != nil || uplinkSet.URI.IsNil() {
		d.SetId("")
		return nil
	}
	d.Set("name", uplinkSet.Name)
	d.Set("logical_interconnect_uri", uplinkSet.LogicalInterconnectURI)
	d.Set("network_uris", uplinkSet.NetworkURIs)
	d.Set("manual_login_redistribution_state", uplinkSet.ManualLoginRedistributionState)
	d.Set("description", uplinkSet.Description)
	d.Set("type", uplinkSet.Type)
	d.Set("uri", uplinkSet.URI.String())
	d.Set("fcoe_network_uris", uplinkSet.FcoeNetworkURIs)
	d.Set("status", uplinkSet.Status)
	d.Set("category", uplinkSet.Category)
	d.Set("state", uplinkSet.State)
	d.Set("fc_network_uris", uplinkSet.FcNetworkURIs)
	d.Set("created", uplinkSet.Created)
	d.Set("modified", uplinkSet.Modified)
	d.Set("eTag", uplinkSet.Etag)
	d.Set("reachability", uplinkSet.Reachability)
	d.Set("expected_neighbor", uplinkSet.ExpectedNeighbor)
	d.Set("network_type", uplinkSet.NetworkType)
	d.Set("ethernet_network_type", uplinkSet.EthernetNetworkType)
	d.Set("port_config_infos", uplinkSet.PortConfigInfos)
	return nil
}

func resourceUplinkSetUpdate(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)

	uplinkSet := ov.UplinkSet{
		Etag:        d.Get("eTag").(string),
		URI:         utils.NewNstring(d.Get("uri").(string)),
		Name:        d.Get("name").(string),
		Type:        d.Get("type").(string),
		Description: utils.NewNstring(d.Get("description").(string)),
	}

	err := config.ovClient.UpdateUplinkSet(uplinkSet)
	if err != nil {
		return err
	}
	d.SetId(d.Get("name").(string))

	return resourceUplinkSetRead(d, meta)
}

func resourceUplinkSetDelete(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)

	err := config.ovClient.DeleteUplinkSet(d.Get("name").(string))
	if err != nil {
		return err
	}
	return nil
}
<|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 e2e

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"os/exec"
	"regexp"
	"strings"
	"sync"
	"testing"
	"time"
)

type runOpts struct {
	NoNamespace  bool
	AllowError   bool
	StderrWriter io.Writer
	StdoutWriter io.Writer
	StdinReader  io.Reader
	CancelCh     chan struct{}
	Redact       bool
}

const (
	KnDefaultTestImage string        = "gcr.io/knative-samples/helloworld-go"
	MaxRetries         int           = 10
	RetrySleepDuration time.Duration = 30 * time.Second
)

var m sync.Mutex

type e2eTest struct {
	env env
	kn  kn
}

func NewE2eTest(t *testing.T) *e2eTest {
	return &e2eTest{
		env: buildEnv(t),
	}
}

// Setup set up an enviroment for kn integration test returns the Teardown cleanup function
func (test *e2eTest) Setup(t *testing.T) {
	test.env.Namespace = fmt.Sprintf("%s%d", test.env.Namespace, getNamespaceCountAndIncrement())
	test.kn = kn{t, test.env.Namespace, Logger{}}
	test.CreateTestNamespace(t, test.env.Namespace)
}

func getNamespaceCountAndIncrement() int {
	m.Lock()
	defer m.Unlock()
	current := namespaceCount
	namespaceCount++
	return current
}

// Teardown clean up
func (test *e2eTest) Teardown(t *testing.T) {
	test.DeleteTestNamespace(t, test.env.Namespace)
}

// CreateTestNamespace creates and tests a namesspace creation invoking kubectl
func (test *e2eTest) CreateTestNamespace(t *testing.T, namespace string) {
	logger := Logger{}
	expectedOutputRegexp := fmt.Sprintf("namespace?.+%s.+created", namespace)
	out, err := createNamespace(t, namespace, MaxRetries, logger)
	if err != nil {
		logger.Fatalf("Could not create namespace, giving up")
	}

	// check that last output indeed show created namespace
	if !matchRegexp(t, expectedOutputRegexp, out) {
		t.Fatalf("Expected output incorrect, expecting to include:\n%s\n Instead found:\n%s\n", expectedOutputRegexp, out)
	}
}

// CreateTestNamespace deletes and tests a namesspace deletion invoking kubectl
func (test *e2eTest) DeleteTestNamespace(t *testing.T, namespace string) {
	kubectl := kubectl{t, Logger{}}
	out, err := kubectl.RunWithOpts([]string{"delete", "namespace", namespace}, runOpts{})
	if err != nil {
		t.Fatalf(fmt.Sprintf("Error executing 'kubectl delete namespace' command. Error: %s", err.Error()))
	}

	expectedOutputRegexp := fmt.Sprintf("namespace?.+%s.+deleted", namespace)
	if !matchRegexp(t, expectedOutputRegexp, out) {
		t.Fatalf("Expected output incorrect, expecting to include:\n%s\n Instead found:\n%s\n", expectedOutputRegexp, out)
	}
}

// WaitForNamespaceDeleted wait until namespace is deleted
func (test *e2eTest) WaitForNamespaceDeleted(t *testing.T, namespace string) {
	logger := Logger{}
	deleted := checkNamespaceDeleted(t, namespace, MaxRetries, logger)
	if !deleted {
		t.Fatalf(fmt.Sprintf("Error deleting namespace %s, timed out", namespace))
	}
}

// Private functions
func checkNamespaceDeleted(t *testing.T, namespace string, maxRetries int, logger Logger) bool {
	kubectlGetNamespace := func() (string, error) {
		kubectl := kubectl{t, logger}
		return kubectl.RunWithOpts([]string{"get", "namespace"}, runOpts{})
	}

	retries := 0
	for retries < MaxRetries {
		output, _ := kubectlGetNamespace()
		if !strings.Contains(output, namespace) {
			return true
		}

		retries++
		logger.Debugf("Namespace is terminating, waiting %ds, and trying again: %d of %d\n", int(RetrySleepDuration.Seconds()), retries, maxRetries)
		time.Sleep(RetrySleepDuration)
	}

	return true
}

func createNamespace(t *testing.T, namespace string, maxRetries int, logger Logger) (string, error) {
	kubectlCreateNamespace := func() (string, error) {
		kubectl := kubectl{t, logger}
		return kubectl.RunWithOpts([]string{"create", "namespace", namespace}, runOpts{AllowError: true})
	}

	var (
		retries int
		err     error
		out     string
	)

	for retries < maxRetries {
		out, err := kubectlCreateNamespace()
		if err == nil {
			return out, nil
		}
		retries++
		logger.Debugf("Could not create namespace, waiting %ds, and trying again: %d of %d\n", int(RetrySleepDuration.Seconds()), retries, maxRetries)
		time.Sleep(RetrySleepDuration)
	}

	return out, err
}

func runCLIWithOpts(cli string, args []string, opts runOpts, logger Logger) (string, error) {
	logger.Debugf("Running '%s'...\n", cmdCLIDesc(cli, args))

	var stderr bytes.Buffer
	var stdout bytes.Buffer

	cmd := exec.Command(cli, args...)
	cmd.Stderr = &stderr

	if opts.CancelCh != nil {
		go func() {
			select {
			case <-opts.CancelCh:
				cmd.Process.Signal(os.Interrupt)
			}
		}()
	}

	if opts.StdoutWriter != nil {
		cmd.Stdout = opts.StdoutWriter
	} else {
		cmd.Stdout = &stdout
	}

	cmd.Stdin = opts.StdinReader

	err := cmd.Run()
	if err != nil {
		err = fmt.Errorf("Execution error: stderr: '%s' error: '%s'", stderr.String(), err)

		if !opts.AllowError {
			logger.Fatalf("Failed to successfully execute '%s': %v", cmdCLIDesc(cli, args), err)
		}
	}

	return stdout.String(), err
}

func cmdCLIDesc(cli string, args []string) string {
	return fmt.Sprintf("%s %s", cli, strings.Join(args, " "))
}

func matchRegexp(t *testing.T, matchingRegexp, actual string) bool {
	matched, err := regexp.MatchString(matchingRegexp, actual)
	if err != nil {
		t.Fatalf(fmt.Sprintf("Failed to match regexp '%s'. Error: '%s'", matchingRegexp, err.Error()))
	}
	return matched
}
<commit_msg>fix(test): Give the namespace some time setup (#348)<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 e2e

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"os/exec"
	"regexp"
	"strings"
	"sync"
	"testing"
	"time"
)

type runOpts struct {
	NoNamespace  bool
	AllowError   bool
	StderrWriter io.Writer
	StdoutWriter io.Writer
	StdinReader  io.Reader
	CancelCh     chan struct{}
	Redact       bool
}

const (
	KnDefaultTestImage string        = "gcr.io/knative-samples/helloworld-go"
	MaxRetries         int           = 10
	RetrySleepDuration time.Duration = 30 * time.Second
)

var m sync.Mutex

type e2eTest struct {
	env env
	kn  kn
}

func NewE2eTest(t *testing.T) *e2eTest {
	return &e2eTest{
		env: buildEnv(t),
	}
}

// Setup set up an enviroment for kn integration test returns the Teardown cleanup function
func (test *e2eTest) Setup(t *testing.T) {
	test.env.Namespace = fmt.Sprintf("%s%d", test.env.Namespace, getNamespaceCountAndIncrement())
	test.kn = kn{t, test.env.Namespace, Logger{}}
	test.CreateTestNamespace(t, test.env.Namespace)
	time.Sleep(20 * time.Second)
}

func getNamespaceCountAndIncrement() int {
	m.Lock()
	defer m.Unlock()
	current := namespaceCount
	namespaceCount++
	return current
}

// Teardown clean up
func (test *e2eTest) Teardown(t *testing.T) {
	test.DeleteTestNamespace(t, test.env.Namespace)
}

// CreateTestNamespace creates and tests a namesspace creation invoking kubectl
func (test *e2eTest) CreateTestNamespace(t *testing.T, namespace string) {
	logger := Logger{}
	expectedOutputRegexp := fmt.Sprintf("namespace?.+%s.+created", namespace)
	out, err := createNamespace(t, namespace, MaxRetries, logger)
	if err != nil {
		logger.Fatalf("Could not create namespace, giving up")
	}

	// check that last output indeed show created namespace
	if !matchRegexp(t, expectedOutputRegexp, out) {
		t.Fatalf("Expected output incorrect, expecting to include:\n%s\n Instead found:\n%s\n", expectedOutputRegexp, out)
	}
}

// CreateTestNamespace deletes and tests a namesspace deletion invoking kubectl
func (test *e2eTest) DeleteTestNamespace(t *testing.T, namespace string) {
	kubectl := kubectl{t, Logger{}}
	out, err := kubectl.RunWithOpts([]string{"delete", "namespace", namespace}, runOpts{})
	if err != nil {
		t.Fatalf(fmt.Sprintf("Error executing 'kubectl delete namespace' command. Error: %s", err.Error()))
	}

	expectedOutputRegexp := fmt.Sprintf("namespace?.+%s.+deleted", namespace)
	if !matchRegexp(t, expectedOutputRegexp, out) {
		t.Fatalf("Expected output incorrect, expecting to include:\n%s\n Instead found:\n%s\n", expectedOutputRegexp, out)
	}
}

// WaitForNamespaceDeleted wait until namespace is deleted
func (test *e2eTest) WaitForNamespaceDeleted(t *testing.T, namespace string) {
	logger := Logger{}
	deleted := checkNamespaceDeleted(t, namespace, MaxRetries, logger)
	if !deleted {
		t.Fatalf(fmt.Sprintf("Error deleting namespace %s, timed out", namespace))
	}
}

// Private functions
func checkNamespaceDeleted(t *testing.T, namespace string, maxRetries int, logger Logger) bool {
	kubectlGetNamespace := func() (string, error) {
		kubectl := kubectl{t, logger}
		return kubectl.RunWithOpts([]string{"get", "namespace"}, runOpts{})
	}

	retries := 0
	for retries < MaxRetries {
		output, _ := kubectlGetNamespace()
		if !strings.Contains(output, namespace) {
			return true
		}

		retries++
		logger.Debugf("Namespace is terminating, waiting %ds, and trying again: %d of %d\n", int(RetrySleepDuration.Seconds()), retries, maxRetries)
		time.Sleep(RetrySleepDuration)
	}

	return true
}

func createNamespace(t *testing.T, namespace string, maxRetries int, logger Logger) (string, error) {
	kubectlCreateNamespace := func() (string, error) {
		kubectl := kubectl{t, logger}
		return kubectl.RunWithOpts([]string{"create", "namespace", namespace}, runOpts{AllowError: true})
	}

	var (
		retries int
		err     error
		out     string
	)

	for retries < maxRetries {
		out, err := kubectlCreateNamespace()
		if err == nil {
			return out, nil
		}
		retries++
		logger.Debugf("Could not create namespace, waiting %ds, and trying again: %d of %d\n", int(RetrySleepDuration.Seconds()), retries, maxRetries)
		time.Sleep(RetrySleepDuration)
	}

	return out, err
}

func runCLIWithOpts(cli string, args []string, opts runOpts, logger Logger) (string, error) {
	logger.Debugf("Running '%s'...\n", cmdCLIDesc(cli, args))

	var stderr bytes.Buffer
	var stdout bytes.Buffer

	cmd := exec.Command(cli, args...)
	cmd.Stderr = &stderr

	if opts.CancelCh != nil {
		go func() {
			select {
			case <-opts.CancelCh:
				cmd.Process.Signal(os.Interrupt)
			}
		}()
	}

	if opts.StdoutWriter != nil {
		cmd.Stdout = opts.StdoutWriter
	} else {
		cmd.Stdout = &stdout
	}

	cmd.Stdin = opts.StdinReader

	err := cmd.Run()
	if err != nil {
		err = fmt.Errorf("Execution error: stderr: '%s' error: '%s'", stderr.String(), err)

		if !opts.AllowError {
			logger.Fatalf("Failed to successfully execute '%s': %v", cmdCLIDesc(cli, args), err)
		}
	}

	return stdout.String(), err
}

func cmdCLIDesc(cli string, args []string) string {
	return fmt.Sprintf("%s %s", cli, strings.Join(args, " "))
}

func matchRegexp(t *testing.T, matchingRegexp, actual string) bool {
	matched, err := regexp.MatchString(matchingRegexp, actual)
	if err != nil {
		t.Fatalf(fmt.Sprintf("Failed to match regexp '%s'. Error: '%s'", matchingRegexp, err.Error()))
	}
	return matched
}
<|endoftext|>


<commit_before>package blockstore

import (
	"fmt"
	"sync"
	"testing"
	"time"

	"github.com/ipfs/go-ipfs/blocks"

	ds "gx/ipfs/QmNgqJarToRiq2GBaPJhkmW4B5BxS5B74E1rkGvv2JoaTp/go-datastore"
	dsq "gx/ipfs/QmNgqJarToRiq2GBaPJhkmW4B5BxS5B74E1rkGvv2JoaTp/go-datastore/query"
	syncds "gx/ipfs/QmNgqJarToRiq2GBaPJhkmW4B5BxS5B74E1rkGvv2JoaTp/go-datastore/sync"
	context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
)

func testBloomCached(bs GCBlockstore, ctx context.Context) (*bloomcache, error) {
	if ctx == nil {
		ctx = context.TODO()
	}
	opts := DefaultCacheOpts()
	opts.HasARCCacheSize = 0
	bbs, err := CachedBlockstore(bs, ctx, opts)
	if err == nil {
		return bbs.(*bloomcache), nil
	} else {
		return nil, err
	}
}

func TestReturnsErrorWhenSizeNegative(t *testing.T) {
	bs := NewBlockstore(syncds.MutexWrap(ds.NewMapDatastore()))
	_, err := bloomCached(bs, context.TODO(), -1, 1)
	if err == nil {
		t.Fail()
	}
}
func TestHasIsBloomCached(t *testing.T) {
	cd := &callbackDatastore{f: func() {}, ds: ds.NewMapDatastore()}
	bs := NewBlockstore(syncds.MutexWrap(cd))

	for i := 0; i < 1000; i++ {
		bs.Put(blocks.NewBlock([]byte(fmt.Sprintf("data: %d", i))))
	}
	ctx, _ := context.WithTimeout(context.Background(), 1*time.Second)
	cachedbs, err := testBloomCached(bs, ctx)
	if err != nil {
		t.Fatal(err)
	}

	select {
	case <-cachedbs.rebuildChan:
	case <-ctx.Done():
		t.Fatalf("Timeout wating for rebuild: %d", cachedbs.bloom.ElementsAdded())
	}

	cacheFails := 0
	cd.SetFunc(func() {
		cacheFails++
	})

	for i := 0; i < 1000; i++ {
		cachedbs.Has(blocks.NewBlock([]byte(fmt.Sprintf("data: %d", i+2000))).Key())
	}

	if float64(cacheFails)/float64(1000) > float64(0.05) {
		t.Fatal("Bloom filter has cache miss rate of more than 5%")
	}

	cacheFails = 0
	block := blocks.NewBlock([]byte("newBlock"))

	cachedbs.PutMany([]blocks.Block{block})
	if cacheFails != 2 {
		t.Fatalf("expected two datastore hits: %d", cacheFails)
	}
	cachedbs.Put(block)
	if cacheFails != 3 {
		t.Fatalf("expected datastore hit: %d", cacheFails)
	}

	if has, err := cachedbs.Has(block.Key()); !has || err != nil {
		t.Fatal("has gave wrong response")
	}

	bl, err := cachedbs.Get(block.Key())
	if bl.String() != block.String() {
		t.Fatal("block data doesn't match")
	}

	if err != nil {
		t.Fatal("there should't be an error")
	}
}

type callbackDatastore struct {
	sync.Mutex
	f  func()
	ds ds.Datastore
}

func (c *callbackDatastore) SetFunc(f func()) {
	c.Lock()
	defer c.Unlock()
	c.f = f
}

func (c *callbackDatastore) CallF() {
	c.Lock()
	defer c.Unlock()
	c.f()
}

func (c *callbackDatastore) Put(key ds.Key, value interface{}) (err error) {
	c.CallF()
	return c.ds.Put(key, value)
}

func (c *callbackDatastore) Get(key ds.Key) (value interface{}, err error) {
	c.CallF()
	return c.ds.Get(key)
}

func (c *callbackDatastore) Has(key ds.Key) (exists bool, err error) {
	c.CallF()
	return c.ds.Has(key)
}

func (c *callbackDatastore) Delete(key ds.Key) (err error) {
	c.CallF()
	return c.ds.Delete(key)
}

func (c *callbackDatastore) Query(q dsq.Query) (dsq.Results, error) {
	c.CallF()
	return c.ds.Query(q)
}

func (c *callbackDatastore) Batch() (ds.Batch, error) {
	return ds.NewBasicBatch(c), nil
}
<commit_msg>test: add test case for PutMany on bloom filter skipping add to bloom<commit_after>package blockstore

import (
	"fmt"
	"sync"
	"testing"
	"time"

	"github.com/ipfs/go-ipfs/blocks"

	ds "gx/ipfs/QmNgqJarToRiq2GBaPJhkmW4B5BxS5B74E1rkGvv2JoaTp/go-datastore"
	dsq "gx/ipfs/QmNgqJarToRiq2GBaPJhkmW4B5BxS5B74E1rkGvv2JoaTp/go-datastore/query"
	syncds "gx/ipfs/QmNgqJarToRiq2GBaPJhkmW4B5BxS5B74E1rkGvv2JoaTp/go-datastore/sync"
	context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
)

func testBloomCached(bs GCBlockstore, ctx context.Context) (*bloomcache, error) {
	if ctx == nil {
		ctx = context.TODO()
	}
	opts := DefaultCacheOpts()
	opts.HasARCCacheSize = 0
	bbs, err := CachedBlockstore(bs, ctx, opts)
	if err == nil {
		return bbs.(*bloomcache), nil
	} else {
		return nil, err
	}
}

func TestPutManyAddsToBloom(t *testing.T) {
	bs := NewBlockstore(syncds.MutexWrap(ds.NewMapDatastore()))

	ctx, _ := context.WithTimeout(context.Background(), 1*time.Second)
	cachedbs, err := testBloomCached(bs, ctx)

	select {
	case <-cachedbs.rebuildChan:
	case <-ctx.Done():
		t.Fatalf("Timeout wating for rebuild: %d", cachedbs.bloom.ElementsAdded())
	}

	block1 := blocks.NewBlock([]byte("foo"))
	block2 := blocks.NewBlock([]byte("bar"))

	cachedbs.PutMany([]blocks.Block{block1})
	has, err := cachedbs.Has(block1.Key())
	if err != nil {
		t.Fatal(err)
	}
	if has == false {
		t.Fatal("added block is reported missing")
	}

	has, err = cachedbs.Has(block2.Key())
	if err != nil {
		t.Fatal(err)
	}
	if has == true {
		t.Fatal("not added block is reported to be in blockstore")
	}
}

func TestReturnsErrorWhenSizeNegative(t *testing.T) {
	bs := NewBlockstore(syncds.MutexWrap(ds.NewMapDatastore()))
	_, err := bloomCached(bs, context.TODO(), -1, 1)
	if err == nil {
		t.Fail()
	}
}
func TestHasIsBloomCached(t *testing.T) {
	cd := &callbackDatastore{f: func() {}, ds: ds.NewMapDatastore()}
	bs := NewBlockstore(syncds.MutexWrap(cd))

	for i := 0; i < 1000; i++ {
		bs.Put(blocks.NewBlock([]byte(fmt.Sprintf("data: %d", i))))
	}
	ctx, _ := context.WithTimeout(context.Background(), 1*time.Second)
	cachedbs, err := testBloomCached(bs, ctx)
	if err != nil {
		t.Fatal(err)
	}

	select {
	case <-cachedbs.rebuildChan:
	case <-ctx.Done():
		t.Fatalf("Timeout wating for rebuild: %d", cachedbs.bloom.ElementsAdded())
	}

	cacheFails := 0
	cd.SetFunc(func() {
		cacheFails++
	})

	for i := 0; i < 1000; i++ {
		cachedbs.Has(blocks.NewBlock([]byte(fmt.Sprintf("data: %d", i+2000))).Key())
	}

	if float64(cacheFails)/float64(1000) > float64(0.05) {
		t.Fatal("Bloom filter has cache miss rate of more than 5%")
	}

	cacheFails = 0
	block := blocks.NewBlock([]byte("newBlock"))

	cachedbs.PutMany([]blocks.Block{block})
	if cacheFails != 2 {
		t.Fatalf("expected two datastore hits: %d", cacheFails)
	}
	cachedbs.Put(block)
	if cacheFails != 3 {
		t.Fatalf("expected datastore hit: %d", cacheFails)
	}

	if has, err := cachedbs.Has(block.Key()); !has || err != nil {
		t.Fatal("has gave wrong response")
	}

	bl, err := cachedbs.Get(block.Key())
	if bl.String() != block.String() {
		t.Fatal("block data doesn't match")
	}

	if err != nil {
		t.Fatal("there should't be an error")
	}
}

type callbackDatastore struct {
	sync.Mutex
	f  func()
	ds ds.Datastore
}

func (c *callbackDatastore) SetFunc(f func()) {
	c.Lock()
	defer c.Unlock()
	c.f = f
}

func (c *callbackDatastore) CallF() {
	c.Lock()
	defer c.Unlock()
	c.f()
}

func (c *callbackDatastore) Put(key ds.Key, value interface{}) (err error) {
	c.CallF()
	return c.ds.Put(key, value)
}

func (c *callbackDatastore) Get(key ds.Key) (value interface{}, err error) {
	c.CallF()
	return c.ds.Get(key)
}

func (c *callbackDatastore) Has(key ds.Key) (exists bool, err error) {
	c.CallF()
	return c.ds.Has(key)
}

func (c *callbackDatastore) Delete(key ds.Key) (err error) {
	c.CallF()
	return c.ds.Delete(key)
}

func (c *callbackDatastore) Query(q dsq.Query) (dsq.Results, error) {
	c.CallF()
	return c.ds.Query(q)
}

func (c *callbackDatastore) Batch() (ds.Batch, error) {
	return ds.NewBasicBatch(c), nil
}
<|endoftext|>


<commit_before>// Copyright 2012 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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 blob_test

import (
	"errors"
	"github.com/jacobsa/comeback/blob"
	"github.com/jacobsa/comeback/kv/mock"
	. "github.com/jacobsa/oglematchers"
	"github.com/jacobsa/oglemock"
	. "github.com/jacobsa/ogletest"
	"testing"
)

func TestKv(t *testing.T) { RunTests(t) }

////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////

type kvBasedStoreTest struct {
	kvBasedStore mock_kv.MockStore
	store        blob.Store
}

func (t *kvBasedStoreTest) SetUp(i *TestInfo) {
	t.kvBasedStore = mock_kv.NewMockStore(i.MockController, "kvBasedStore")
	t.store = blob.NewKvBasedBlobStore(t.kvBasedStore)
}

////////////////////////////////////////////////////////////////////////
// Store
////////////////////////////////////////////////////////////////////////

type KvBasedStore_StoreTest struct {
	kvBasedStoreTest

	data  []byte
	score blob.Score
	err   error
}

func init() { RegisterTestSuite(&KvBasedStore_StoreTest{}) }

func (t *KvBasedStore_StoreTest) callStore() {
	t.score, t.err = t.store.Store(t.data)
}

func (t *KvBasedStore_StoreTest) CallsContains() {
	t.data = []byte("hello")
	expectedKey := []byte("aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d")

	// Contains
	ExpectCall(t.kvBasedStore, "Contains")(DeepEquals(expectedKey)).
		WillOnce(oglemock.Return(false, errors.New("")))

	// Call
	t.callStore()
}

func (t *KvBasedStore_StoreTest) ContainsReturnsError() {
	// Contains
	ExpectCall(t.kvBasedStore, "Contains")(Any()).
		WillOnce(oglemock.Return(false, errors.New("taco")))

	// Call
	t.callStore()

	ExpectThat(t.err, Error(HasSubstr("Contains")))
	ExpectThat(t.err, Error(HasSubstr("taco")))
}

func (t *KvBasedStore_StoreTest) ContainsSaysYes() {
	t.data = []byte("hello")

	// Contains
	ExpectCall(t.kvBasedStore, "Contains")(Any()).
		WillOnce(oglemock.Return(true, nil))

	// Call
	t.callStore()

	AssertEq(nil, t.err)
	ExpectThat(t.score, DeepEquals(blob.ComputeScore(t.data)))
}

func (t *KvBasedStore_StoreTest) CallsSet() {
	t.data = []byte("hello")
	expectedKey := []byte("aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d")

	// Contains
	ExpectCall(t.kvBasedStore, "Contains")(Any()).
		WillOnce(oglemock.Return(false, nil))

	// Set
	ExpectCall(t.kvBasedStore, "Set")(DeepEquals(expectedKey), DeepEquals(t.data)).
		WillOnce(oglemock.Return(errors.New("")))

	// Call
	t.callStore()
}

func (t *KvBasedStore_StoreTest) SetReturnsError() {
	// Contains
	ExpectCall(t.kvBasedStore, "Contains")(Any()).
		WillOnce(oglemock.Return(false, nil))

	// Set
	ExpectCall(t.kvBasedStore, "Set")(Any(), Any()).
		WillOnce(oglemock.Return(errors.New("taco")))

	// Call
	t.callStore()

	ExpectThat(t.err, Error(HasSubstr("Set")))
	ExpectThat(t.err, Error(HasSubstr("taco")))
}

func (t *KvBasedStore_StoreTest) SetSaysOkay() {
	t.data = []byte("hello")

	// Contains
	ExpectCall(t.kvBasedStore, "Contains")(Any()).
		WillOnce(oglemock.Return(false, nil))

	// Set
	ExpectCall(t.kvBasedStore, "Set")(Any(), Any()).
		WillOnce(oglemock.Return(nil))

	// Call
	t.callStore()

	AssertEq(nil, t.err)
	ExpectThat(t.score, DeepEquals(blob.ComputeScore(t.data)))
}

////////////////////////////////////////////////////////////////////////
// Load
////////////////////////////////////////////////////////////////////////

type KvBasedStore_LoadTest struct {
	kvBasedStoreTest

	score blob.Score
	data  []byte
	err   error
}

func init() { RegisterTestSuite(&KvBasedStore_LoadTest{}) }

func (t *KvBasedStore_LoadTest) callStore() {
	t.data, t.err = t.store.Load(t.score)
}

func (t *KvBasedStore_LoadTest) CallsGet() {
	t.score = blob.ComputeScore([]byte("hello"))
	expectedKey := []byte("aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d")

	// Get
	ExpectCall(t.kvBasedStore, "Get")(DeepEquals(expectedKey)).
		WillOnce(oglemock.Return(nil, errors.New("")))

	// Call
	t.callStore()
}

func (t *KvBasedStore_LoadTest) GetReturnsError() {
	// Get
	ExpectCall(t.kvBasedStore, "Get")(Any()).
		WillOnce(oglemock.Return(nil, errors.New("taco")))

	// Call
	t.callStore()

	ExpectThat(t.err, Error(HasSubstr("Get")))
	ExpectThat(t.err, Error(HasSubstr("taco")))
}

func (t *KvBasedStore_LoadTest) GetSucceeds() {
	// Get
	returnedData := []byte{0xde, 0xad}
	ExpectCall(t.kvBasedStore, "Get")(Any()).
		WillOnce(oglemock.Return(returnedData, nil))

	// Call
	t.callStore()

	AssertEq(nil, t.err)
	ExpectThat(t.data, DeepEquals(returnedData))
}
<commit_msg>Updated tests for the new key format.<commit_after>// Copyright 2012 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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 blob_test

import (
	"errors"
	"github.com/jacobsa/comeback/blob"
	"github.com/jacobsa/comeback/kv/mock"
	. "github.com/jacobsa/oglematchers"
	"github.com/jacobsa/oglemock"
	. "github.com/jacobsa/ogletest"
	"testing"
)

func TestKv(t *testing.T) { RunTests(t) }

////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////

type kvBasedStoreTest struct {
	kvBasedStore mock_kv.MockStore
	store        blob.Store
}

func (t *kvBasedStoreTest) SetUp(i *TestInfo) {
	t.kvBasedStore = mock_kv.NewMockStore(i.MockController, "kvBasedStore")
	t.store = blob.NewKvBasedBlobStore(t.kvBasedStore)
}

////////////////////////////////////////////////////////////////////////
// Store
////////////////////////////////////////////////////////////////////////

type KvBasedStore_StoreTest struct {
	kvBasedStoreTest

	data  []byte
	score blob.Score
	err   error
}

func init() { RegisterTestSuite(&KvBasedStore_StoreTest{}) }

func (t *KvBasedStore_StoreTest) callStore() {
	t.score, t.err = t.store.Store(t.data)
}

func (t *KvBasedStore_StoreTest) CallsContains() {
	t.data = []byte("hello")
	expectedKey := []byte("blob:aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d")

	// Contains
	ExpectCall(t.kvBasedStore, "Contains")(DeepEquals(expectedKey)).
		WillOnce(oglemock.Return(false, errors.New("")))

	// Call
	t.callStore()
}

func (t *KvBasedStore_StoreTest) ContainsReturnsError() {
	// Contains
	ExpectCall(t.kvBasedStore, "Contains")(Any()).
		WillOnce(oglemock.Return(false, errors.New("taco")))

	// Call
	t.callStore()

	ExpectThat(t.err, Error(HasSubstr("Contains")))
	ExpectThat(t.err, Error(HasSubstr("taco")))
}

func (t *KvBasedStore_StoreTest) ContainsSaysYes() {
	t.data = []byte("hello")

	// Contains
	ExpectCall(t.kvBasedStore, "Contains")(Any()).
		WillOnce(oglemock.Return(true, nil))

	// Call
	t.callStore()

	AssertEq(nil, t.err)
	ExpectThat(t.score, DeepEquals(blob.ComputeScore(t.data)))
}

func (t *KvBasedStore_StoreTest) CallsSet() {
	t.data = []byte("hello")
	expectedKey := []byte("blob:aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d")

	// Contains
	ExpectCall(t.kvBasedStore, "Contains")(Any()).
		WillOnce(oglemock.Return(false, nil))

	// Set
	ExpectCall(t.kvBasedStore, "Set")(DeepEquals(expectedKey), DeepEquals(t.data)).
		WillOnce(oglemock.Return(errors.New("")))

	// Call
	t.callStore()
}

func (t *KvBasedStore_StoreTest) SetReturnsError() {
	// Contains
	ExpectCall(t.kvBasedStore, "Contains")(Any()).
		WillOnce(oglemock.Return(false, nil))

	// Set
	ExpectCall(t.kvBasedStore, "Set")(Any(), Any()).
		WillOnce(oglemock.Return(errors.New("taco")))

	// Call
	t.callStore()

	ExpectThat(t.err, Error(HasSubstr("Set")))
	ExpectThat(t.err, Error(HasSubstr("taco")))
}

func (t *KvBasedStore_StoreTest) SetSaysOkay() {
	t.data = []byte("hello")

	// Contains
	ExpectCall(t.kvBasedStore, "Contains")(Any()).
		WillOnce(oglemock.Return(false, nil))

	// Set
	ExpectCall(t.kvBasedStore, "Set")(Any(), Any()).
		WillOnce(oglemock.Return(nil))

	// Call
	t.callStore()

	AssertEq(nil, t.err)
	ExpectThat(t.score, DeepEquals(blob.ComputeScore(t.data)))
}

////////////////////////////////////////////////////////////////////////
// Load
////////////////////////////////////////////////////////////////////////

type KvBasedStore_LoadTest struct {
	kvBasedStoreTest

	score blob.Score
	data  []byte
	err   error
}

func init() { RegisterTestSuite(&KvBasedStore_LoadTest{}) }

func (t *KvBasedStore_LoadTest) callStore() {
	t.data, t.err = t.store.Load(t.score)
}

func (t *KvBasedStore_LoadTest) CallsGet() {
	t.score = blob.ComputeScore([]byte("hello"))
	expectedKey := []byte("blob:aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d")

	// Get
	ExpectCall(t.kvBasedStore, "Get")(DeepEquals(expectedKey)).
		WillOnce(oglemock.Return(nil, errors.New("")))

	// Call
	t.callStore()
}

func (t *KvBasedStore_LoadTest) GetReturnsError() {
	// Get
	ExpectCall(t.kvBasedStore, "Get")(Any()).
		WillOnce(oglemock.Return(nil, errors.New("taco")))

	// Call
	t.callStore()

	ExpectThat(t.err, Error(HasSubstr("Get")))
	ExpectThat(t.err, Error(HasSubstr("taco")))
}

func (t *KvBasedStore_LoadTest) GetSucceeds() {
	// Get
	returnedData := []byte{0xde, 0xad}
	ExpectCall(t.kvBasedStore, "Get")(Any()).
		WillOnce(oglemock.Return(returnedData, nil))

	// Call
	t.callStore()

	AssertEq(nil, t.err)
	ExpectThat(t.data, DeepEquals(returnedData))
}
<|endoftext|>


<commit_before>// Copyright 2019 Google LLC.
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
package main

import (
	"bufio"
	"bytes"
	"flag"
	"fmt"
	"log"
	"math/rand"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
	"time"
)

// Too many GPU processes and we'll start to overwhelm your GPU,
// even hanging your machine in the worst case.  Here's a reasonable default.
func defaultGpuLimit() int {
	limit := 8
	if n := runtime.NumCPU(); n < limit {
		return n
	}
	return limit
}

var script = flag.String("script", "", "A file with jobs to run, one per line. - for stdin.")
var random = flag.Bool("random", true, "Assign sources into job batches randomly?")
var quiet = flag.Bool("quiet", false, "Print only failures?")
var exact = flag.Bool("exact", false, "Match GM names only exactly.")
var cpuLimit = flag.Int("cpuLimit", runtime.NumCPU(),
	"Maximum number of concurrent processes for CPU-bound work.")
var gpuLimit = flag.Int("gpuLimit", defaultGpuLimit(),
	"Maximum number of concurrent processes for GPU-bound work.")

func init() {
	flag.StringVar(script, "s", *script, "Alias for --script.")
	flag.BoolVar(random, "r", *random, "Alias for --random.")
	flag.BoolVar(quiet, "q", *quiet, "Alias for --quiet.")
	flag.BoolVar(exact, "e", *exact, "Alias for --exact.")
	flag.IntVar(cpuLimit, "c", *cpuLimit, "Alias for --cpuLimit.")
	flag.IntVar(gpuLimit, "g", *gpuLimit, "Alias for --gpuLimit.")
}

func listAllGMs(fm string) (gms []string, err error) {
	// Query fm binary for list of all available GMs by running with no arguments.
	cmd := exec.Command(fm)
	stdout, err := cmd.Output()
	if err != nil {
		return
	}
	// GM names are listed line-by-line.
	scanner := bufio.NewScanner(bytes.NewReader(stdout))
	for scanner.Scan() {
		gms = append(gms, scanner.Text())
	}
	err = scanner.Err()
	return
}

func callFM(fm string, sources []string, flags []string) bool {
	start := time.Now()

	args := flags[:]
	args = append(args, "-s")
	args = append(args, sources...)

	cmd := exec.Command(fm, args...)
	output, err := cmd.CombinedOutput()

	if err != nil {
		log.Printf("\n%v #failed (%v):\n%s\n", strings.Join(cmd.Args, " "), err, output)
		return false
	} else if !*quiet {
		log.Printf("\n%v #done in %v:\n%s", strings.Join(cmd.Args, " "), time.Since(start), output)
	}
	return true
}

func sourcesAndFlags(args []string, gms []string) ([]string, []string, error) {
	sources := []string{}
	flags := []string{}
	for _, arg := range args {
		// I wish we could parse flags here too, but it's too late.
		if strings.HasPrefix(arg, "-") {
			msg := "Is '%s' an fm flag? If so please pass it using flag=value syntax."
			if flag.Lookup(arg[1:]) != nil {
				msg = "Please pass fm_bot flags like '%s' on the command line before the FM binary."
			}
			return nil, nil, fmt.Errorf(msg, arg)
		}

		// Everything after a # is a comment.
		if strings.HasPrefix(arg, "#") {
			break
		}

		// Treat "gm" or "gms" as a shortcut for all known GMs.
		if arg == "gm" || arg == "gms" {
			sources = append(sources, gms...)
			continue
		}

		// Is this an option to pass through to fm?
		if parts := strings.Split(arg, "="); len(parts) == 2 {
			f := "-"
			if len(parts[0]) > 1 {
				f += "-"
			}
			f += parts[0]

			flags = append(flags, f, parts[1])
			continue
		}

		// Is this argument naming a GM?
		matchedAnyGM := false
		for _, gm := range gms {
			if (*exact && gm == arg) || (!*exact && strings.Contains(gm, arg)) {
				sources = append(sources, gm)
				matchedAnyGM = true
			}
		}
		if matchedAnyGM {
			continue
		}

		// Anything left ought to be on the file system: a file, a directory, or a glob.
		// Not all shells expand globs, so we'll do it here just in case.
		matches, err := filepath.Glob(arg)
		if err != nil {
			return nil, nil, err
		}
		if len(matches) == 0 {
			return nil, nil, fmt.Errorf("Don't understand '%s'.", arg)
		}

		for _, match := range matches {
			err := filepath.Walk(match, func(path string, info os.FileInfo, err error) error {
				if !info.IsDir() {
					sources = append(sources, path)
				}
				return err
			})
			if err != nil {
				return nil, nil, err
			}
		}
	}
	return sources, flags, nil
}

type work struct {
	Sources []string
	Flags   []string
}

func main() {
	flag.Parse()

	if flag.NArg() < 1 {
		log.Fatal("Please pass an fm binary as the first argument.")
	}
	fm := flag.Args()[0]

	gms, err := listAllGMs(fm)
	if err != nil {
		log.Fatalln("Could not query", fm, "for GMs:", err)
	}

	// One job can comes right on the command line,
	// and any number can come one per line from -script.
	jobs := [][]string{flag.Args()[1:]}
	if *script != "" {
		file := os.Stdin
		if *script != "-" {
			file, err = os.Open(*script)
			if err != nil {
				log.Fatal(err)
			}
			defer file.Close()
		}

		scanner := bufio.NewScanner(file)
		for scanner.Scan() {
			jobs = append(jobs, strings.Fields(scanner.Text()))
		}
		if err = scanner.Err(); err != nil {
			log.Fatal(err)
		}
	}

	// The buffer size of main->worker channels isn't super important...
	// presumably we'll have many hungry goroutines snapping up work as quick
	// as they can, and if things get backed up, no real reason for main to do
	// anything but block.
	cpu := make(chan work, *cpuLimit)
	gpu := make(chan work, *gpuLimit)

	// The buffer size of this worker->main results channel is much more
	// sensitive.  Since it's a many->one funnel, it's easy for the workers to
	// produce lots of results that main can't keep up with.
	//
	// This needlessly throttles our progress, and we can even deadlock if
	// the buffer fills up before main has finished enqueueing all the work.
	//
	// So we set the buffer size here large enough to hold a result for every
	// item we might possibly enqueue.
	results := make(chan bool, (*cpuLimit+*gpuLimit)*len(jobs))

	for i := 0; i < *cpuLimit; i++ {
		go func() {
			for w := range cpu {
				results <- callFM(fm, w.Sources, w.Flags)
			}
		}()
	}
	for i := 0; i < *gpuLimit; i++ {
		go func() {
			for w := range gpu {
				results <- callFM(fm, w.Sources, w.Flags)
			}
		}()
	}

	sent := 0
	for _, job := range jobs {
		// Skip blank lines, empty command lines.
		if len(job) == 0 {
			continue
		}
		sources, flags, err := sourcesAndFlags(job, gms)
		if err != nil {
			log.Fatal(err)
		}

		// Determine if this is CPU-bound or GPU-bound work, conservatively assuming GPU.
		queue, limit := gpu, *gpuLimit
		backend := ""
		for i, flag := range flags {
			if flag == "-b" || flag == "--backend" {
				backend = flags[i+1]
			}
		}
		whitelisted := map[string]bool{
			"cpu": true,
			"skp": true,
			"pdf": true,
		}
		if whitelisted[backend] {
			queue, limit = cpu, *cpuLimit
		}

		if *random {
			rand.Shuffle(len(sources), func(i, j int) {
				sources[i], sources[j] = sources[j], sources[i]
			})
		}

		// Round up so there's at least one source per batch.
		// This math also helps guarantee that sent stays <= cap(results).
		sourcesPerBatch := (len(sources) + limit - 1) / limit

		for i := 0; i < len(sources); i += sourcesPerBatch {
			end := i + sourcesPerBatch
			if end > len(sources) {
				end = len(sources)
			}
			batch := sources[i:end]

			queue <- work{batch, flags}

			sent += 1
		}
	}
	close(cpu)
	close(gpu)

	if sent > cap(results) {
		log.Fatalf("Oops, we sent %d but cap(results) is only %d.  "+
			"This could lead to deadlock and is a bug.", sent, cap(results))
	}

	failures := 0
	for i := 0; i < sent; i++ {
		if !<-results {
			failures += 1
		}
	}
	if failures > 0 {
		log.Fatalln(failures, "invocations of", fm, "failed")
	}
}
<commit_msg>add retries to fm_bot<commit_after>// Copyright 2019 Google LLC.
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
package main

import (
	"bufio"
	"bytes"
	"flag"
	"fmt"
	"log"
	"math/rand"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
	"sync"
	"sync/atomic"
	"time"
)

// Too many GPU processes and we'll start to overwhelm your GPU,
// even hanging your machine in the worst case.  Here's a reasonable default.
func defaultGpuLimit() int {
	limit := 8
	if n := runtime.NumCPU(); n < limit {
		return n
	}
	return limit
}

var script = flag.String("script", "", "A file with jobs to run, one per line. - for stdin.")
var random = flag.Bool("random", true, "Assign sources into job batches randomly?")
var quiet = flag.Bool("quiet", false, "Print only failures?")
var exact = flag.Bool("exact", false, "Match GM names only exactly.")
var cpuLimit = flag.Int("cpuLimit", runtime.NumCPU(),
	"Maximum number of concurrent processes for CPU-bound work.")
var gpuLimit = flag.Int("gpuLimit", defaultGpuLimit(),
	"Maximum number of concurrent processes for GPU-bound work.")

func init() {
	flag.StringVar(script, "s", *script, "Alias for --script.")
	flag.BoolVar(random, "r", *random, "Alias for --random.")
	flag.BoolVar(quiet, "q", *quiet, "Alias for --quiet.")
	flag.BoolVar(exact, "e", *exact, "Alias for --exact.")
	flag.IntVar(cpuLimit, "c", *cpuLimit, "Alias for --cpuLimit.")
	flag.IntVar(gpuLimit, "g", *gpuLimit, "Alias for --gpuLimit.")
}

func listAllGMs(fm string) (gms []string, err error) {
	// Query fm binary for list of all available GMs by running with no arguments.
	cmd := exec.Command(fm)
	stdout, err := cmd.Output()
	if err != nil {
		return
	}
	// GM names are listed line-by-line.
	scanner := bufio.NewScanner(bytes.NewReader(stdout))
	for scanner.Scan() {
		gms = append(gms, scanner.Text())
	}
	err = scanner.Err()
	return
}

func callFM(fm string, sources []string, flags []string) bool {
	start := time.Now()

	args := flags[:]
	args = append(args, "-s")
	args = append(args, sources...)

	cmd := exec.Command(fm, args...)
	output, err := cmd.CombinedOutput()

	if err != nil {
		if !*quiet || len(sources) == 1 {
			log.Printf("\n%v #failed (%v):\n%s\n", strings.Join(cmd.Args, " "), err, output)
		}
		return false
	} else if !*quiet {
		log.Printf("\n%v #done in %v:\n%s", strings.Join(cmd.Args, " "), time.Since(start), output)
	}
	return true
}

func sourcesAndFlags(args []string, gms []string) ([]string, []string, error) {
	sources := []string{}
	flags := []string{}
	for _, arg := range args {
		// I wish we could parse flags here too, but it's too late.
		if strings.HasPrefix(arg, "-") {
			msg := "Is '%s' an fm flag? If so please pass it using flag=value syntax."
			if flag.Lookup(arg[1:]) != nil {
				msg = "Please pass fm_bot flags like '%s' on the command line before the FM binary."
			}
			return nil, nil, fmt.Errorf(msg, arg)
		}

		// Everything after a # is a comment.
		if strings.HasPrefix(arg, "#") {
			break
		}

		// Treat "gm" or "gms" as a shortcut for all known GMs.
		if arg == "gm" || arg == "gms" {
			sources = append(sources, gms...)
			continue
		}

		// Is this an option to pass through to fm?
		if parts := strings.Split(arg, "="); len(parts) == 2 {
			f := "-"
			if len(parts[0]) > 1 {
				f += "-"
			}
			f += parts[0]

			flags = append(flags, f, parts[1])
			continue
		}

		// Is this argument naming a GM?
		matchedAnyGM := false
		for _, gm := range gms {
			if (*exact && gm == arg) || (!*exact && strings.Contains(gm, arg)) {
				sources = append(sources, gm)
				matchedAnyGM = true
			}
		}
		if matchedAnyGM {
			continue
		}

		// Anything left ought to be on the file system: a file, a directory, or a glob.
		// Not all shells expand globs, so we'll do it here just in case.
		matches, err := filepath.Glob(arg)
		if err != nil {
			return nil, nil, err
		}
		if len(matches) == 0 {
			return nil, nil, fmt.Errorf("Don't understand '%s'.", arg)
		}

		for _, match := range matches {
			err := filepath.Walk(match, func(path string, info os.FileInfo, err error) error {
				if !info.IsDir() {
					sources = append(sources, path)
				}
				return err
			})
			if err != nil {
				return nil, nil, err
			}
		}
	}
	return sources, flags, nil
}

type work struct {
	Sources []string
	Flags   []string
}

func main() {
	flag.Parse()

	if flag.NArg() < 1 {
		log.Fatal("Please pass an fm binary as the first argument.")
	}
	fm := flag.Args()[0]

	gms, err := listAllGMs(fm)
	if err != nil {
		log.Fatalln("Could not query", fm, "for GMs:", err)
	}

	// One job can comes right on the command line,
	// and any number can come one per line from -script.
	jobs := [][]string{flag.Args()[1:]}
	if *script != "" {
		file := os.Stdin
		if *script != "-" {
			file, err = os.Open(*script)
			if err != nil {
				log.Fatal(err)
			}
			defer file.Close()
		}

		scanner := bufio.NewScanner(file)
		for scanner.Scan() {
			jobs = append(jobs, strings.Fields(scanner.Text()))
		}
		if err = scanner.Err(); err != nil {
			log.Fatal(err)
		}
	}

	wg := &sync.WaitGroup{}
	var failures int32 = 0

	worker := func(queue chan work) {
		for w := range queue {
			if !callFM(fm, w.Sources, w.Flags) {
				if len(w.Sources) == 1 {
					// If a source ran alone and failed, that's just a failure.
					atomic.AddInt32(&failures, 1)
				} else {
					// If a batch of sources ran and failed, split them up and try again.
					for _, source := range w.Sources {
						wg.Add(1)
						queue <- work{[]string{source}, w.Flags}
					}
				}
			}
			wg.Done()
		}
	}

	cpu := make(chan work, *cpuLimit)
	for i := 0; i < *cpuLimit; i++ {
		go worker(cpu)
	}

	gpu := make(chan work, *gpuLimit)
	for i := 0; i < *gpuLimit; i++ {
		go worker(gpu)
	}

	for _, job := range jobs {
		// Skip blank lines, empty command lines.
		if len(job) == 0 {
			continue
		}
		sources, flags, err := sourcesAndFlags(job, gms)
		if err != nil {
			log.Fatal(err)
		}

		// Determine if this is CPU-bound or GPU-bound work, conservatively assuming GPU.
		queue, limit := gpu, *gpuLimit
		backend := ""
		for i, flag := range flags {
			if flag == "-b" || flag == "--backend" {
				backend = flags[i+1]
			}
		}
		whitelisted := map[string]bool{
			"cpu": true,
			"skp": true,
			"pdf": true,
		}
		if whitelisted[backend] {
			queue, limit = cpu, *cpuLimit
		}

		if *random {
			rand.Shuffle(len(sources), func(i, j int) {
				sources[i], sources[j] = sources[j], sources[i]
			})
		}

		// Round up so there's at least one source per batch.
		sourcesPerBatch := (len(sources) + limit - 1) / limit

		for i := 0; i < len(sources); i += sourcesPerBatch {
			end := i + sourcesPerBatch
			if end > len(sources) {
				end = len(sources)
			}
			batch := sources[i:end]

			wg.Add(1)
			queue <- work{batch, flags}
		}
	}

	wg.Wait()

	if failures > 0 {
		log.Fatalln(failures, "failures after retries")
	}
}
<|endoftext|>


<commit_before>package clearbit

import (
	"net/http"
	"time"

	"github.com/dghubble/sling"
)

const (
	companyBase = "https://company.clearbit.com"
)

// Company contains all the company fields gathered from the Company json
// structure. https://dashboard.clearbit.com/docs#enrichment-api-company-api
type Company struct {
	ID            string   `json:"id"`
	Name          string   `json:"name"`
	LegalName     string   `json:"legalName"`
	Domain        string   `json:"domain"`
	DomainAliases []string `json:"domainAliases"`
	Site          struct {
		PhoneNumbers   []string `json:"phoneNumbers"`
		EmailAddresses []string `json:"emailAddresses"`
	} `json:"site"`
	Category struct {
		Sector        string `json:"sector"`
		IndustryGroup string `json:"industryGroup"`
		Industry      string `json:"industry"`
		SubIndustry   string `json:"subIndustry"`
		SicCode       string `json:"sicCode"`
		NaicsCode     string `json:"naicsCode"`
	} `json:"category"`
	Tags        []string `json:"tags"`
	Description string   `json:"description"`
	FoundedYear int      `json:"foundedYear"`
	Location    string   `json:"location"`
	TimeZone    string   `json:"timeZone"`
	UtcOffset   int      `json:"utcOffset"`
	Geo         struct {
		StreetNumber string  `json:"streetNumber"`
		StreetName   string  `json:"streetName"`
		SubPremise   string  `json:"subPremise"`
		City         string  `json:"city"`
		PostalCode   string  `json:"postalCode"`
		State        string  `json:"state"`
		StateCode    string  `json:"stateCode"`
		Country      string  `json:"country"`
		CountryCode  string  `json:"countryCode"`
		Lat          float64 `json:"lat"`
		Lng          float64 `json:"lng"`
	} `json:"geo"`
	Logo     string `json:"logo"`
	Facebook struct {
		Handle string `json:"handle"`
		Likes  int    `json:"likes"`
	} `json:"facebook"`
	LinkedIn struct {
		Handle string `json:"handle"`
	} `json:"linkedin"`
	Twitter struct {
		Handle    string `json:"handle"`
		ID        string `json:"id"`
		Bio       string `json:"bio"`
		Followers int    `json:"followers"`
		Following int    `json:"following"`
		Location  string `json:"location"`
		Site      string `json:"site"`
		Avatar    string `json:"avatar"`
	} `json:"twitter"`
	Crunchbase struct {
		Handle string `json:"handle"`
	} `json:"crunchbase"`
	EmailProvider bool   `json:"emailProvider"`
	Type          string `json:"type"`
	Ticker        string `json:"ticker"`
	Identifiers   struct {
		UsEIN string `json:"usEIN"`
	} `json:"identifiers"`
	Phone   string `json:"phone"`
	Metrics struct {
		AlexaUsRank            int    `json:"alexaUsRank"`
		AlexaGlobalRank        int    `json:"alexaGlobalRank"`
		Employees              int    `json:"employees"`
		EmployeesRange         string `json:"employeesRange"`
		MarketCap              string `json:"marketCap"`
		Raised                 int    `json:"raised"`
		AnnualRevenue          int    `json:"annualRevenue"`
		EstimatedAnnualRevenue string `json:"estimatedAnnualRevenue"`
		FiscalYearEnd          int    `json:"fiscalYearEnd"`
	} `json:"metrics"`
	IndexedAt time.Time `json:"indexedAt"`
	Tech      []string  `json:"tech"`
	Parent    struct {
		Domain string `json:"domain"`
	} `json:"parent"`
}

// CompanyFindParams wraps the parameters needed to interact with the Company
// API through the Find method
type CompanyFindParams struct {
	Domain string `url:"domain,omitempty"`
}

// CompanyService gives access to the Company API.
// https://dashboard.clearbit.com/docs#enrichment-api-company-api
type CompanyService struct {
	baseSling *sling.Sling
	sling     *sling.Sling
}

func newCompanyService(sling *sling.Sling) *CompanyService {
	return &CompanyService{
		baseSling: sling.New(),
		sling:     sling.Base(companyBase).Path("/v2/companies/"),
	}
}

//Find looks up a company based on its domain
func (s *CompanyService) Find(params CompanyFindParams) (*Company, *http.Response, error) {
	item := new(Company)
	ae := new(apiError)
	resp, err := s.sling.New().Get("find").QueryStruct(params).Receive(item, ae)
	return item, resp, relevantError(err, *ae)
}
<commit_msg>Revert company marketcap to an int (#19)<commit_after>package clearbit

import (
	"net/http"
	"time"

	"github.com/dghubble/sling"
)

const (
	companyBase = "https://company.clearbit.com"
)

// Company contains all the company fields gathered from the Company json
// structure. https://dashboard.clearbit.com/docs#enrichment-api-company-api
type Company struct {
	ID            string   `json:"id"`
	Name          string   `json:"name"`
	LegalName     string   `json:"legalName"`
	Domain        string   `json:"domain"`
	DomainAliases []string `json:"domainAliases"`
	Site          struct {
		PhoneNumbers   []string `json:"phoneNumbers"`
		EmailAddresses []string `json:"emailAddresses"`
	} `json:"site"`
	Category struct {
		Sector        string `json:"sector"`
		IndustryGroup string `json:"industryGroup"`
		Industry      string `json:"industry"`
		SubIndustry   string `json:"subIndustry"`
		SicCode       string `json:"sicCode"`
		NaicsCode     string `json:"naicsCode"`
	} `json:"category"`
	Tags        []string `json:"tags"`
	Description string   `json:"description"`
	FoundedYear int      `json:"foundedYear"`
	Location    string   `json:"location"`
	TimeZone    string   `json:"timeZone"`
	UtcOffset   int      `json:"utcOffset"`
	Geo         struct {
		StreetNumber string  `json:"streetNumber"`
		StreetName   string  `json:"streetName"`
		SubPremise   string  `json:"subPremise"`
		City         string  `json:"city"`
		PostalCode   string  `json:"postalCode"`
		State        string  `json:"state"`
		StateCode    string  `json:"stateCode"`
		Country      string  `json:"country"`
		CountryCode  string  `json:"countryCode"`
		Lat          float64 `json:"lat"`
		Lng          float64 `json:"lng"`
	} `json:"geo"`
	Logo     string `json:"logo"`
	Facebook struct {
		Handle string `json:"handle"`
		Likes  int    `json:"likes"`
	} `json:"facebook"`
	LinkedIn struct {
		Handle string `json:"handle"`
	} `json:"linkedin"`
	Twitter struct {
		Handle    string `json:"handle"`
		ID        string `json:"id"`
		Bio       string `json:"bio"`
		Followers int    `json:"followers"`
		Following int    `json:"following"`
		Location  string `json:"location"`
		Site      string `json:"site"`
		Avatar    string `json:"avatar"`
	} `json:"twitter"`
	Crunchbase struct {
		Handle string `json:"handle"`
	} `json:"crunchbase"`
	EmailProvider bool   `json:"emailProvider"`
	Type          string `json:"type"`
	Ticker        string `json:"ticker"`
	Identifiers   struct {
		UsEIN string `json:"usEIN"`
	} `json:"identifiers"`
	Phone   string `json:"phone"`
	Metrics struct {
		AlexaUsRank            int    `json:"alexaUsRank"`
		AlexaGlobalRank        int    `json:"alexaGlobalRank"`
		Employees              int    `json:"employees"`
		EmployeesRange         string `json:"employeesRange"`
		MarketCap              int    `json:"marketCap"`
		Raised                 int    `json:"raised"`
		AnnualRevenue          int    `json:"annualRevenue"`
		EstimatedAnnualRevenue string `json:"estimatedAnnualRevenue"`
		FiscalYearEnd          int    `json:"fiscalYearEnd"`
	} `json:"metrics"`
	IndexedAt time.Time `json:"indexedAt"`
	Tech      []string  `json:"tech"`
	Parent    struct {
		Domain string `json:"domain"`
	} `json:"parent"`
}

// CompanyFindParams wraps the parameters needed to interact with the Company
// API through the Find method
type CompanyFindParams struct {
	Domain string `url:"domain,omitempty"`
}

// CompanyService gives access to the Company API.
// https://dashboard.clearbit.com/docs#enrichment-api-company-api
type CompanyService struct {
	baseSling *sling.Sling
	sling     *sling.Sling
}

func newCompanyService(sling *sling.Sling) *CompanyService {
	return &CompanyService{
		baseSling: sling.New(),
		sling:     sling.Base(companyBase).Path("/v2/companies/"),
	}
}

//Find looks up a company based on its domain
func (s *CompanyService) Find(params CompanyFindParams) (*Company, *http.Response, error) {
	item := new(Company)
	ae := new(apiError)
	resp, err := s.sling.New().Get("find").QueryStruct(params).Receive(item, ae)
	return item, resp, relevantError(err, *ae)
}
<|endoftext|>