<commit_before>package main

// todo: add process error checking
// todo: add check for invalid command
// todo: clean up arg parsing!! (recursive?)
// todo: command history with arrow keys (not possible)

import (
	"bufio"
	"fmt"
	"os"
	"strings"
    "time"
)

// Maps strings (names) to lyprocesses.
var processes = make(map[string]*lyprocess)

// Counter of processes that are running to keep O(1) time.
// This is NOT the length of the processes map. Some processes may have exited,
// and thus are not running.
var nRunning = 0;

func main() {
	fmt.Println("Welcome to Ly! Type 'help' if you're lost.")

	reader := bufio.NewReader(os.Stdin)

    // Run the lyfile if the -l switch is provided
    if len(os.Args) > 1 && os.Args[1] == "-l" {
        runLyfile()
    }

	for {
        // Read and tokenize user input
        fmt.Print("ly > ")
		line, _ := reader.ReadString('\n')
        runInstruction(line)

        fmt.Println()
	}
}

func runInstruction(instr string) {
    words := strings.Fields(instr)

    // No command given
    if len(words) == 0 {
        return
    }

    switch words[0] {
        case "new":
            // Start a new process
            if len(words) < 3 {
                fmt.Println("Not enough arguments.")
                break
            }
            startProcess(words[1], words[2:]...)
        case "kill":
            // Kill an existing process
            if len(words) < 2 {
                fmt.Println("Not enough arguments.")
                break
            }
            killProcess(words[1])
        case "killall":
            fmt.Println("Attempting to kill all processes.")
            killAllProcesses()
        case "out":
            // Print the output of a process
            if len(words) < 2 {
                fmt.Println("Not enough arguments.")
                break
            }
            printOut(words[1])
        case "in":
            // Send some input to a process
            if len(words) < 3 {
                fmt.Println("Not enough arguments.")
                break
            }
            sendInput(words[1], words[2:]...)
        case "list":
            // List running processes
            list()
        case "lyfile":
            runLyfile()
        case "exit":
            // Kill all processes and exit
            exit()
        default:
            printUsage()
    }
}

func startProcess(name string, cmd ...string) {
    if processRunning(name) {
        fmt.Println("Process", name, "is already running.")
        return
    }

    cmdString := strings.Join(cmd, " ")
    fmt.Printf("Starting %s :: %s.\n", name, cmdString)
    processes[name] = newLyprocess(cmdString)

    go func() {
        processes[name].Running = true
        nRunning++
        processes[name].Run()
        processes[name].Running = false
        nRunning--
    }()
}

func killAllProcesses() {
    go func() {
        for k, _ := range(processes) {
            killProcess(k)
        }
    }()
}

func killProcess(name string) {
    if !processExists(name) {
        fmt.Println("Process", name, "does not exist.")
    } else if processes[name].Cmd.Process != nil {
        processes[name].Cmd.Process.Kill()
    }
}

func printOut(name string) {
    if !processExists(name) {
        fmt.Println("Process", name, "does not exist.")
    } else {
        processes[name].PrintLog()
    }
}

func sendInput(name string, in ...string) {
    if !processExists(name) {
        fmt.Println("Process", name, "does not exist.")
    } else {
        processes[name].WriteInput(strings.Join(in, " "))
    }
}

func list() {
    if len(processes) == 0 {
        fmt.Println("No processes")
    } else {
        fmt.Println(len(processes), "processes:")

        for k, v := range(processes) {
            // Don't print the PID if the process isn't started
            if v.Cmd.Process == nil {
                fmt.Printf("  %v(-)\n", k)
            } else {
                fmt.Printf("  %v(%v)", k, v.Cmd.Process.Pid)
                if !processRunning(k) {
                    fmt.Println(" -- Exited")
                } else {
                    fmt.Println()
                }
            }
        }
    }
}

func exit() {
    // Try to kill all processes for 3 seconds, then exit forcefully.
    killAllProcesses()

    // Try to exit for 3000 ms if no processes are running
    for t := 0; t < 3000; {
        if nRunning == 0 {
            fmt.Println("Goodbye!")
            os.Exit(0)
        }

        t += 300;
        time.Sleep(300 * time.Millisecond)
    }

    fmt.Println("Ly couldn't close all processes in time. These processes may still be running:")
    for k, v := range(processes) {
        if v.Running {
            fmt.Println("  " + k)
        }
    }
    fmt.Println("Goodbye!")
    os.Exit(1)
}

func printUsage() {
    helpStr := `Usage: <operation> [arguments]
Operations:
    lyfile                  Runs commands from 'Lyfile' or 'lyfile'.
    new <name> <command>    Spawns a new process called <name> by running <command>.
                            All processes are started in their own shell.
    kill <name>             Kills a running process by <name>
    killall                 Attempts to kill all running processes.
    out <name>              Outputs the most recent standard output/error for a process.
    list                    Lists running processes with their PID and status.
    exit                    Nicely quits all processes and exists.
    help                    Prints this help message.

Run ly with the -l switch to automatically run the lyfile.`

    fmt.Println(helpStr)
}
<commit_msg>Added some todos<commit_after>package main

// todo: add process error checking
// todo: add check for invalid command
// todo: clean up arg parsing!! (recursive?)
// todo: command history with arrow keys (not possible)
// todo: output unread lines after input (delay?)
// todo: output unread lines in list

import (
	"bufio"
	"fmt"
	"os"
	"strings"
    "time"
)

// Maps strings (names) to lyprocesses.
var processes = make(map[string]*lyprocess)

// Counter of processes that are running to keep O(1) time.
// This is NOT the length of the processes map. Some processes may have exited,
// and thus are not running.
var nRunning = 0;

func main() {
	fmt.Println("Welcome to Ly! Type 'help' if you're lost.")

	reader := bufio.NewReader(os.Stdin)

    // Run the lyfile if the -l switch is provided
    if len(os.Args) > 1 && os.Args[1] == "-l" {
        runLyfile()
    }

	for {
        // Read and tokenize user input
        fmt.Print("ly > ")
		line, _ := reader.ReadString('\n')
        runInstruction(line)

        fmt.Println()
	}
}

func runInstruction(instr string) {
    words := strings.Fields(instr)

    // No command given
    if len(words) == 0 {
        return
    }

    switch words[0] {
        case "new":
            // Start a new process
            if len(words) < 3 {
                fmt.Println("Not enough arguments.")
                break
            }
            startProcess(words[1], words[2:]...)
        case "kill":
            // Kill an existing process
            if len(words) < 2 {
                fmt.Println("Not enough arguments.")
                break
            }
            killProcess(words[1])
        case "killall":
            fmt.Println("Attempting to kill all processes.")
            killAllProcesses()
        case "out":
            // Print the output of a process
            if len(words) < 2 {
                fmt.Println("Not enough arguments.")
                break
            }
            printOut(words[1])
        case "in":
            // Send some input to a process
            if len(words) < 3 {
                fmt.Println("Not enough arguments.")
                break
            }
            sendInput(words[1], words[2:]...)
        case "list":
            // List running processes
            list()
        case "lyfile":
            runLyfile()
        case "exit":
            // Kill all processes and exit
            exit()
        default:
            printUsage()
    }
}

func startProcess(name string, cmd ...string) {
    if processRunning(name) {
        fmt.Println("Process", name, "is already running.")
        return
    }

    cmdString := strings.Join(cmd, " ")
    fmt.Printf("Starting %s :: %s.\n", name, cmdString)
    processes[name] = newLyprocess(cmdString)

    go func() {
        processes[name].Running = true
        nRunning++
        processes[name].Run()
        processes[name].Running = false
        nRunning--
    }()
}

func killAllProcesses() {
    go func() {
        for k, _ := range(processes) {
            killProcess(k)
        }
    }()
}

func killProcess(name string) {
    if !processExists(name) {
        fmt.Println("Process", name, "does not exist.")
    } else if processes[name].Cmd.Process != nil {
        processes[name].Cmd.Process.Kill()
    }
}

func printOut(name string) {
    if !processExists(name) {
        fmt.Println("Process", name, "does not exist.")
    } else {
        processes[name].PrintLog()
    }
}

func sendInput(name string, in ...string) {
    if !processExists(name) {
        fmt.Println("Process", name, "does not exist.")
    } else {
        processes[name].WriteInput(strings.Join(in, " "))
    }
}

func list() {
    if len(processes) == 0 {
        fmt.Println("No processes")
    } else {
        fmt.Println(len(processes), "processes:")

        for k, v := range(processes) {
            // Don't print the PID if the process isn't started
            if v.Cmd.Process == nil {
                fmt.Printf("  %v(-)\n", k)
            } else {
                fmt.Printf("  %v(%v)", k, v.Cmd.Process.Pid)
                if !processRunning(k) {
                    fmt.Println(" -- Exited")
                } else {
                    fmt.Println()
                }
            }
        }
    }
}

func exit() {
    // Try to kill all processes for 3 seconds, then exit forcefully.
    killAllProcesses()

    // Try to exit for 3000 ms if no processes are running
    for t := 0; t < 3000; {
        if nRunning == 0 {
            fmt.Println("Goodbye!")
            os.Exit(0)
        }

        t += 300;
        time.Sleep(300 * time.Millisecond)
    }

    fmt.Println("Ly couldn't close all processes in time. These processes may still be running:")
    for k, v := range(processes) {
        if v.Running {
            fmt.Println("  " + k)
        }
    }
    fmt.Println("Goodbye!")
    os.Exit(1)
}

func printUsage() {
    helpStr := `Usage: <operation> [arguments]
Operations:
    lyfile                  Runs commands from 'Lyfile' or 'lyfile'.
    new <name> <command>    Spawns a new process called <name> by running <command>.
                            All processes are started in their own shell.
    kill <name>             Kills a running process by <name>
    killall                 Attempts to kill all running processes.
    out <name>              Outputs the most recent standard output/error for a process.
    list                    Lists running processes with their PID and status.
    exit                    Nicely quits all processes and exists.
    help                    Prints this help message.

Run ly with the -l switch to automatically run the lyfile.`

    fmt.Println(helpStr)
}
<|endoftext|>


<commit_before>package solidserver

import (
	"encoding/json"
	"fmt"
	"github.com/hashicorp/terraform/helper/schema"
	"log"
	"net/url"
	"strconv"
)

func resourcevlan() *schema.Resource {
	return &schema.Resource{
		Create: resourcevlanCreate,
		Read:   resourcevlanRead,
		Update: resourcevlanUpdate,
		Delete: resourcevlanDelete,
		Exists: resourcevlanExists,
		Importer: &schema.ResourceImporter{
			State: resourcevlanImportState,
		},

		Schema: map[string]*schema.Schema{
			"vlan_domain": {
				Type:        schema.TypeString,
				Description: "The name of the vlan domain.",
				Required:    true,
				ForceNew:    true,
			},
			"request_id": {
				Type:        schema.TypeInt,
				Description: "The optionally requested vlan ID.",
				Optional:    true,
				ForceNew:    true,
				Default:     0,
			},
			"vlan_id": {
				Type:        schema.TypeInt,
				Description: "The vlan ID.",
				Computed:    true,
				ForceNew:    true,
			},
			"name": {
				Type:        schema.TypeString,
				Description: "The name of the vlan to create.",
				Required:    true,
				ForceNew:    false,
			},
			"class": {
				Type:        schema.TypeString,
				Description: "The class associated to the vlan.",
				Optional:    true,
				ForceNew:    false,
				Default:     "",
			},
			"class_parameters": {
				Type:        schema.TypeMap,
				Description: "The class parameters associated to vlan.",
				Optional:    true,
				ForceNew:    false,
				Default:     map[string]string{},
			},
		},
	}
}

func resourcevlanExists(d *schema.ResourceData, meta interface{}) (bool, error) {
	s := meta.(*SOLIDserver)

	// Building parameters
	parameters := url.Values{}
	parameters.Add("vlmvlan_id", d.Id())

	log.Printf("[DEBUG] Checking existence of vlan (oid): %s\n", d.Id())

	// Sending read request
	resp, body, err := s.Request("get", "rest/vlmvlan_info", &parameters)

	if err == nil {
		var buf [](map[string]interface{})
		json.Unmarshal([]byte(body), &buf)

		// Checking answer
		if (resp.StatusCode == 200 || resp.StatusCode == 201) && len(buf) > 0 {
			return true, nil
		}

		if len(buf) > 0 {
			if errMsg, errExist := buf[0]["errmsg"].(string); errExist {
				log.Printf("[DEBUG] SOLIDServer - Unable to find vlan (oid): %s (%s)\n", d.Id(), errMsg)
			}
		} else {
			log.Printf("[DEBUG] SOLIDServer - Unable to find vlan (oid): %s\n", d.Id())
		}

		// Unset local ID
		d.SetId("")
	}

	// Reporting a failure
	return false, err
}

func resourcevlanCreate(d *schema.ResourceData, meta interface{}) error {
	s := meta.(*SOLIDserver)

	var vlanIDs []string = nil

	// Determining if a VLAN ID was submitted in or if we should get one from the VLAN Manager
	if d.Get("request_id").(int) > 0 {
		vlanIDs = []string{d.Get("request_id").(string)}
	} else {
		var vlanErr error = nil

		vlanIDs, vlanErr = vlanidfindfree(d.Get("vlan_domain").(string), meta)

		if vlanErr != nil {
			// Reporting a failure
			return vlanErr
		}
	}

	for i := 0; i < len(vlanIDs); i++ {
		// Building parameters
		parameters := url.Values{}
		parameters.Add("add_flag", "new_only")
		parameters.Add("vlmdomain_name", d.Get("vlan_domain").(string))
		parameters.Add("vlmvlan_vlan_id", vlanIDs[i])
		parameters.Add("vlmvlan_name", d.Get("name").(string))

		if s.Version < 730 {
			log.Printf("[INFO] SOLIDServer - Ignoring class_parameters for vlan: %s as not supported by your SOLIDserver version\n", d.Get("name").(string))
		} else {
			parameters.Add("vlmvlan_class_name", d.Get("class").(string))
			parameters.Add("vlmvlan_class_parameters", urlfromclassparams(d.Get("class_parameters")).Encode())
		}

		// Sending creation request
		resp, body, err := s.Request("post", "rest/vlm_vlan_add", &parameters)

		if err == nil {
			var buf [](map[string]interface{})
			json.Unmarshal([]byte(body), &buf)

			// Checking the answer
			if (resp.StatusCode == 200 || resp.StatusCode == 201) && len(buf) > 0 {
				if oid, oidExist := buf[0]["ret_oid"].(string); oidExist {
					log.Printf("[DEBUG] SOLIDServer - Created vlan (oid): %s\n", oid)

					vnid, _ := strconv.Atoi(vlanIDs[i])
					d.Set("vlan_id", vnid)
					d.SetId(oid)

					return nil
				}
			} else {
				if len(buf) > 0 {
					if errMsg, errExist := buf[0]["errmsg"].(string); errExist {
						log.Printf("[DEBUG] SOLIDServer - Failed vlan registration for vlan: %s with vnid: %s (%s)\n", d.Get("name").(string), vlanIDs[i], errMsg)
					} else {
						log.Printf("[DEBUG] SOLIDServer - Failed vlan registration for vlan: %s with vnid: %s\n", d.Get("name").(string), vlanIDs[i])
					}
				} else {
					log.Printf("[DEBUG] SOLIDServer - Failed vlan registration for vlan: %s with vnid: %s\n", d.Get("name").(string), vlanIDs[i])
				}
			}
		} else {
			// Reporting a failure
			return err
		}
	}

	// Reporting a failure
	return fmt.Errorf("SOLIDServer - Unable to create vlan: %s, unable to find a suitable vnid\n", d.Get("name").(string))
}

func resourcevlanUpdate(d *schema.ResourceData, meta interface{}) error {
	s := meta.(*SOLIDserver)

	// Building parameters
	parameters := url.Values{}
	parameters.Add("vlmvlan_id", d.Id())
	parameters.Add("add_flag", "edit_only")
	parameters.Add("vlmvlan_name", d.Get("name").(string))

	if s.Version < 730 {
		log.Printf("[INFO] SOLIDServer - Ignoring class_parameters for vlan: %s as not supported by your SOLIDserver version\n", d.Get("name").(string))
	} else {
		parameters.Add("vlmvlan_class_name", d.Get("class").(string))
		parameters.Add("vlmvlan_class_parameters", urlfromclassparams(d.Get("class_parameters")).Encode())
	}

	// Sending the update request
	resp, body, err := s.Request("put", "rest/vlm_vlan_add", &parameters)

	if err == nil {
		var buf [](map[string]interface{})
		json.Unmarshal([]byte(body), &buf)

		// Checking the answer
		if (resp.StatusCode == 200 || resp.StatusCode == 201) && len(buf) > 0 {
			if oid, oidExist := buf[0]["ret_oid"].(string); oidExist {
				log.Printf("[DEBUG] SOLIDServer - Updated vlan (oid): %s\n", oid)
				d.SetId(oid)
				return nil
			}
		}

		// Reporting a failure
		if len(buf) > 0 {
			if errMsg, errExist := buf[0]["errmsg"].(string); errExist {
				return fmt.Errorf("SOLIDServer - Unable to update vlan: %s (%s)", d.Get("name").(string), errMsg)
			}
		}

		return fmt.Errorf("SOLIDServer - Unable to update vlan: %s\n", d.Get("name").(string))
	}

	// Reporting a failure
	return err
}

func resourcevlanDelete(d *schema.ResourceData, meta interface{}) error {
	s := meta.(*SOLIDserver)

	// Building parameters
	parameters := url.Values{}
	parameters.Add("vlmvlan_id", d.Id())

	// Sending the deletion request
	resp, body, err := s.Request("delete", "rest/vlm_vlan_delete", &parameters)

	if err == nil {
		var buf [](map[string]interface{})
		json.Unmarshal([]byte(body), &buf)

		// Checking the answer
		if resp.StatusCode != 200 && resp.StatusCode != 204 {
			// Reporting a failure
			if len(buf) > 0 {
				if errMsg, errExist := buf[0]["errmsg"].(string); errExist {
					return fmt.Errorf("SOLIDServer - Unable to delete vlan: %s (%s)", d.Get("name").(string), errMsg)
				}
			}

			return fmt.Errorf("SOLIDServer - Unable to delete vlan: %s", d.Get("name").(string))
		}

		// Log deletion
		log.Printf("[DEBUG] SOLIDServer - Deleted vlan (oid): %s\n", d.Id())

		// Unset local ID
		d.SetId("")

		// Reporting a success
		return nil
	}

	// Reporting a failure
	return err
}

func resourcevlanRead(d *schema.ResourceData, meta interface{}) error {
	s := meta.(*SOLIDserver)

	// Building parameters
	parameters := url.Values{}
	parameters.Add("vlmvlan_id", d.Id())

	// Sending the read request
	resp, body, err := s.Request("get", "rest/vlmvlan_info", &parameters)

	if err == nil {
		var buf [](map[string]interface{})
		json.Unmarshal([]byte(body), &buf)

		// Checking the answer
		if resp.StatusCode == 200 && len(buf) > 0 {
			vnid, _ := strconv.Atoi(buf[0]["vlmvlan_vlan_id"].(string))

			d.Set("name", buf[0]["vlmvlan_name"].(string))
			d.Set("vlan_id", vnid)

			if s.Version < 730 {
				log.Printf("[INFO] SOLIDServer - Ignoring class_parameters for vlan: %s as not supported by your SOLIDserver version\n", d.Get("name").(string))
			} else {
				d.Set("class", buf[0]["vlmvlan_class_name"].(string))

				// Updating local class_parameters
				currentClassParameters := d.Get("class_parameters").(map[string]interface{})
				retrievedClassParameters, _ := url.ParseQuery(buf[0]["vlmvlan_class_parameters"].(string))
				computedClassParameters := map[string]string{}

				for ck := range currentClassParameters {
					if rv, rvExist := retrievedClassParameters[ck]; rvExist {
						computedClassParameters[ck] = rv[0]
					} else {
						computedClassParameters[ck] = ""
					}
				}

				d.Set("class_parameters", computedClassParameters)
			}

			return nil
		}

		if len(buf) > 0 {
			if errMsg, errExist := buf[0]["errmsg"].(string); errExist {
				// Log the error
				log.Printf("[DEBUG] SOLIDServer - Unable to find vlan: %s (%s)\n", d.Get("name"), errMsg)
			}
		} else {
			// Log the error
			log.Printf("[DEBUG] SOLIDServer - Unable to find vlan (oid): %s\n", d.Id())
		}

		// Do not unset the local ID to avoid inconsistency

		// Reporting a failure
		return fmt.Errorf("SOLIDServer - Unable to find vlan: %s\n", d.Get("name").(string))
	}

	// Reporting a failure
	return err
}

func resourcevlanImportState(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
	s := meta.(*SOLIDserver)

	// Building parameters
	parameters := url.Values{}
	parameters.Add("vlmvlan_id", d.Id())

	// Sending the read request
	resp, body, err := s.Request("get", "rest/vlmvlan_info", &parameters)

	if err == nil {
		var buf [](map[string]interface{})
		json.Unmarshal([]byte(body), &buf)

		// Checking the answer
		if resp.StatusCode == 200 && len(buf) > 0 {
			vnid, _ := strconv.Atoi(buf[0]["vlmvlan_vlan_id"].(string))

			d.Set("name", buf[0]["vlmvlan_name"].(string))
			d.Set("vlan_id", vnid)

			if s.Version < 730 {
				log.Printf("[INFO] SOLIDServer - Ignoring class_parameters for vlan: %s as not supported by your SOLIDserver version\n", d.Get("name").(string))
			} else {
				d.Set("class", buf[0]["vlmvlan_class_name"].(string))

				// Updating local class_parameters
				currentClassParameters := d.Get("class_parameters").(map[string]interface{})
				retrievedClassParameters, _ := url.ParseQuery(buf[0]["vlmvlan_class_parameters"].(string))
				computedClassParameters := map[string]string{}

				for ck := range currentClassParameters {
					if rv, rvExist := retrievedClassParameters[ck]; rvExist {
						computedClassParameters[ck] = rv[0]
					} else {
						computedClassParameters[ck] = ""
					}
				}

				d.Set("class_parameters", computedClassParameters)
			}

			return []*schema.ResourceData{d}, nil
		}

		if len(buf) > 0 {
			if errMsg, errExist := buf[0]["errmsg"].(string); errExist {
				log.Printf("[DEBUG] SOLIDServer - Unable to import vlan(oid): %s (%s)\n", d.Id(), errMsg)
			}
		} else {
			log.Printf("[DEBUG] SOLIDServer - Unable to find and import vlan (oid): %s\n", d.Id())
		}

		// Reporting a failure
		return nil, fmt.Errorf("SOLIDServer - Unable to find and import vlan (oid): %s\n", d.Id())
	}

	// Reporting a failure
	return nil, err
}
<commit_msg>Fixing issue with requested vlan ID on vlan resource.<commit_after>package solidserver

import (
	"encoding/json"
	"fmt"
	"github.com/hashicorp/terraform/helper/schema"
	"log"
	"net/url"
	"strconv"
)

func resourcevlan() *schema.Resource {
	return &schema.Resource{
		Create: resourcevlanCreate,
		Read:   resourcevlanRead,
		Update: resourcevlanUpdate,
		Delete: resourcevlanDelete,
		Exists: resourcevlanExists,
		Importer: &schema.ResourceImporter{
			State: resourcevlanImportState,
		},

		Schema: map[string]*schema.Schema{
			"vlan_domain": {
				Type:        schema.TypeString,
				Description: "The name of the vlan domain.",
				Required:    true,
				ForceNew:    true,
			},
			"request_id": {
				Type:        schema.TypeInt,
				Description: "The optionally requested vlan ID.",
				Optional:    true,
				ForceNew:    true,
				Default:     0,
			},
			"vlan_id": {
				Type:        schema.TypeInt,
				Description: "The vlan ID.",
				Computed:    true,
				ForceNew:    true,
			},
			"name": {
				Type:        schema.TypeString,
				Description: "The name of the vlan to create.",
				Required:    true,
				ForceNew:    false,
			},
			"class": {
				Type:        schema.TypeString,
				Description: "The class associated to the vlan.",
				Optional:    true,
				ForceNew:    false,
				Default:     "",
			},
			"class_parameters": {
				Type:        schema.TypeMap,
				Description: "The class parameters associated to vlan.",
				Optional:    true,
				ForceNew:    false,
				Default:     map[string]string{},
			},
		},
	}
}

func resourcevlanExists(d *schema.ResourceData, meta interface{}) (bool, error) {
	s := meta.(*SOLIDserver)

	// Building parameters
	parameters := url.Values{}
	parameters.Add("vlmvlan_id", d.Id())

	log.Printf("[DEBUG] Checking existence of vlan (oid): %s\n", d.Id())

	// Sending read request
	resp, body, err := s.Request("get", "rest/vlmvlan_info", &parameters)

	if err == nil {
		var buf [](map[string]interface{})
		json.Unmarshal([]byte(body), &buf)

		// Checking answer
		if (resp.StatusCode == 200 || resp.StatusCode == 201) && len(buf) > 0 {
			return true, nil
		}

		if len(buf) > 0 {
			if errMsg, errExist := buf[0]["errmsg"].(string); errExist {
				log.Printf("[DEBUG] SOLIDServer - Unable to find vlan (oid): %s (%s)\n", d.Id(), errMsg)
			}
		} else {
			log.Printf("[DEBUG] SOLIDServer - Unable to find vlan (oid): %s\n", d.Id())
		}

		// Unset local ID
		d.SetId("")
	}

	// Reporting a failure
	return false, err
}

func resourcevlanCreate(d *schema.ResourceData, meta interface{}) error {
	s := meta.(*SOLIDserver)

	var vlanIDs []string = nil

	// Determining if a VLAN ID was submitted in or if we should get one from the VLAN Manager
	if d.Get("request_id").(int) > 0 {
		vlanIDs = []string{strconv.Itoa(d.Get("request_id").(int))}
	} else {
		var vlanErr error = nil

		vlanIDs, vlanErr = vlanidfindfree(d.Get("vlan_domain").(string), meta)

		if vlanErr != nil {
			// Reporting a failure
			return vlanErr
		}
	}

	for i := 0; i < len(vlanIDs); i++ {
		// Building parameters
		parameters := url.Values{}
		parameters.Add("add_flag", "new_only")
		parameters.Add("vlmdomain_name", d.Get("vlan_domain").(string))
		parameters.Add("vlmvlan_vlan_id", vlanIDs[i])
		parameters.Add("vlmvlan_name", d.Get("name").(string))

		if s.Version < 730 {
			log.Printf("[INFO] SOLIDServer - Ignoring class_parameters for vlan: %s as not supported by your SOLIDserver version\n", d.Get("name").(string))
		} else {
			parameters.Add("vlmvlan_class_name", d.Get("class").(string))
			parameters.Add("vlmvlan_class_parameters", urlfromclassparams(d.Get("class_parameters")).Encode())
		}

		// Sending creation request
		resp, body, err := s.Request("post", "rest/vlm_vlan_add", &parameters)

		if err == nil {
			var buf [](map[string]interface{})
			json.Unmarshal([]byte(body), &buf)

			// Checking the answer
			if (resp.StatusCode == 200 || resp.StatusCode == 201) && len(buf) > 0 {
				if oid, oidExist := buf[0]["ret_oid"].(string); oidExist {
					log.Printf("[DEBUG] SOLIDServer - Created vlan (oid): %s\n", oid)

					vnid, _ := strconv.Atoi(vlanIDs[i])
					d.Set("vlan_id", vnid)
					d.SetId(oid)

					return nil
				}
			} else {
				if len(buf) > 0 {
					if errMsg, errExist := buf[0]["errmsg"].(string); errExist {
						log.Printf("[DEBUG] SOLIDServer - Failed vlan registration for vlan: %s with vnid: %s (%s)\n", d.Get("name").(string), vlanIDs[i], errMsg)
					} else {
						log.Printf("[DEBUG] SOLIDServer - Failed vlan registration for vlan: %s with vnid: %s\n", d.Get("name").(string), vlanIDs[i])
					}
				} else {
					log.Printf("[DEBUG] SOLIDServer - Failed vlan registration for vlan: %s with vnid: %s\n", d.Get("name").(string), vlanIDs[i])
				}
			}
		} else {
			// Reporting a failure
			return err
		}
	}

	// Reporting a failure
	return fmt.Errorf("SOLIDServer - Unable to create vlan: %s, unable to find a suitable vnid\n", d.Get("name").(string))
}

func resourcevlanUpdate(d *schema.ResourceData, meta interface{}) error {
	s := meta.(*SOLIDserver)

	// Building parameters
	parameters := url.Values{}
	parameters.Add("vlmvlan_id", d.Id())
	parameters.Add("add_flag", "edit_only")
	parameters.Add("vlmvlan_name", d.Get("name").(string))

	if s.Version < 730 {
		log.Printf("[INFO] SOLIDServer - Ignoring class_parameters for vlan: %s as not supported by your SOLIDserver version\n", d.Get("name").(string))
	} else {
		parameters.Add("vlmvlan_class_name", d.Get("class").(string))
		parameters.Add("vlmvlan_class_parameters", urlfromclassparams(d.Get("class_parameters")).Encode())
	}

	// Sending the update request
	resp, body, err := s.Request("put", "rest/vlm_vlan_add", &parameters)

	if err == nil {
		var buf [](map[string]interface{})
		json.Unmarshal([]byte(body), &buf)

		// Checking the answer
		if (resp.StatusCode == 200 || resp.StatusCode == 201) && len(buf) > 0 {
			if oid, oidExist := buf[0]["ret_oid"].(string); oidExist {
				log.Printf("[DEBUG] SOLIDServer - Updated vlan (oid): %s\n", oid)
				d.SetId(oid)
				return nil
			}
		}

		// Reporting a failure
		if len(buf) > 0 {
			if errMsg, errExist := buf[0]["errmsg"].(string); errExist {
				return fmt.Errorf("SOLIDServer - Unable to update vlan: %s (%s)", d.Get("name").(string), errMsg)
			}
		}

		return fmt.Errorf("SOLIDServer - Unable to update vlan: %s\n", d.Get("name").(string))
	}

	// Reporting a failure
	return err
}

func resourcevlanDelete(d *schema.ResourceData, meta interface{}) error {
	s := meta.(*SOLIDserver)

	// Building parameters
	parameters := url.Values{}
	parameters.Add("vlmvlan_id", d.Id())

	// Sending the deletion request
	resp, body, err := s.Request("delete", "rest/vlm_vlan_delete", &parameters)

	if err == nil {
		var buf [](map[string]interface{})
		json.Unmarshal([]byte(body), &buf)

		// Checking the answer
		if resp.StatusCode != 200 && resp.StatusCode != 204 {
			// Reporting a failure
			if len(buf) > 0 {
				if errMsg, errExist := buf[0]["errmsg"].(string); errExist {
					return fmt.Errorf("SOLIDServer - Unable to delete vlan: %s (%s)", d.Get("name").(string), errMsg)
				}
			}

			return fmt.Errorf("SOLIDServer - Unable to delete vlan: %s", d.Get("name").(string))
		}

		// Log deletion
		log.Printf("[DEBUG] SOLIDServer - Deleted vlan (oid): %s\n", d.Id())

		// Unset local ID
		d.SetId("")

		// Reporting a success
		return nil
	}

	// Reporting a failure
	return err
}

func resourcevlanRead(d *schema.ResourceData, meta interface{}) error {
	s := meta.(*SOLIDserver)

	// Building parameters
	parameters := url.Values{}
	parameters.Add("vlmvlan_id", d.Id())

	// Sending the read request
	resp, body, err := s.Request("get", "rest/vlmvlan_info", &parameters)

	if err == nil {
		var buf [](map[string]interface{})
		json.Unmarshal([]byte(body), &buf)

		// Checking the answer
		if resp.StatusCode == 200 && len(buf) > 0 {
			vnid, _ := strconv.Atoi(buf[0]["vlmvlan_vlan_id"].(string))

			d.Set("name", buf[0]["vlmvlan_name"].(string))
			d.Set("vlan_id", vnid)

			if s.Version < 730 {
				log.Printf("[INFO] SOLIDServer - Ignoring class_parameters for vlan: %s as not supported by your SOLIDserver version\n", d.Get("name").(string))
			} else {
				d.Set("class", buf[0]["vlmvlan_class_name"].(string))

				// Updating local class_parameters
				currentClassParameters := d.Get("class_parameters").(map[string]interface{})
				retrievedClassParameters, _ := url.ParseQuery(buf[0]["vlmvlan_class_parameters"].(string))
				computedClassParameters := map[string]string{}

				for ck := range currentClassParameters {
					if rv, rvExist := retrievedClassParameters[ck]; rvExist {
						computedClassParameters[ck] = rv[0]
					} else {
						computedClassParameters[ck] = ""
					}
				}

				d.Set("class_parameters", computedClassParameters)
			}

			return nil
		}

		if len(buf) > 0 {
			if errMsg, errExist := buf[0]["errmsg"].(string); errExist {
				// Log the error
				log.Printf("[DEBUG] SOLIDServer - Unable to find vlan: %s (%s)\n", d.Get("name"), errMsg)
			}
		} else {
			// Log the error
			log.Printf("[DEBUG] SOLIDServer - Unable to find vlan (oid): %s\n", d.Id())
		}

		// Do not unset the local ID to avoid inconsistency

		// Reporting a failure
		return fmt.Errorf("SOLIDServer - Unable to find vlan: %s\n", d.Get("name").(string))
	}

	// Reporting a failure
	return err
}

func resourcevlanImportState(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
	s := meta.(*SOLIDserver)

	// Building parameters
	parameters := url.Values{}
	parameters.Add("vlmvlan_id", d.Id())

	// Sending the read request
	resp, body, err := s.Request("get", "rest/vlmvlan_info", &parameters)

	if err == nil {
		var buf [](map[string]interface{})
		json.Unmarshal([]byte(body), &buf)

		// Checking the answer
		if resp.StatusCode == 200 && len(buf) > 0 {
			vnid, _ := strconv.Atoi(buf[0]["vlmvlan_vlan_id"].(string))

			d.Set("name", buf[0]["vlmvlan_name"].(string))
			d.Set("vlan_id", vnid)

			if s.Version < 730 {
				log.Printf("[INFO] SOLIDServer - Ignoring class_parameters for vlan: %s as not supported by your SOLIDserver version\n", d.Get("name").(string))
			} else {
				d.Set("class", buf[0]["vlmvlan_class_name"].(string))

				// Updating local class_parameters
				currentClassParameters := d.Get("class_parameters").(map[string]interface{})
				retrievedClassParameters, _ := url.ParseQuery(buf[0]["vlmvlan_class_parameters"].(string))
				computedClassParameters := map[string]string{}

				for ck := range currentClassParameters {
					if rv, rvExist := retrievedClassParameters[ck]; rvExist {
						computedClassParameters[ck] = rv[0]
					} else {
						computedClassParameters[ck] = ""
					}
				}

				d.Set("class_parameters", computedClassParameters)
			}

			return []*schema.ResourceData{d}, nil
		}

		if len(buf) > 0 {
			if errMsg, errExist := buf[0]["errmsg"].(string); errExist {
				log.Printf("[DEBUG] SOLIDServer - Unable to import vlan(oid): %s (%s)\n", d.Id(), errMsg)
			}
		} else {
			log.Printf("[DEBUG] SOLIDServer - Unable to find and import vlan (oid): %s\n", d.Id())
		}

		// Reporting a failure
		return nil, fmt.Errorf("SOLIDServer - Unable to find and import vlan (oid): %s\n", d.Id())
	}

	// Reporting a failure
	return nil, err
}
<|endoftext|>


<commit_before>package pstoreds

import (
	"context"
	"io/ioutil"
	"os"
	"testing"
	"time"

	ds "github.com/ipfs/go-datastore"
	badger "github.com/ipfs/go-ds-badger"
	leveldb "github.com/ipfs/go-ds-leveldb"

	pstore "github.com/libp2p/go-libp2p-peerstore"
	pt "github.com/libp2p/go-libp2p-peerstore/test"
)

type datastoreFactory func(tb testing.TB) (ds.TxnDatastore, func())

var dstores = map[string]datastoreFactory{
	"Badger": badgerStore,
	// TODO: Enable once go-ds-leveldb supports TTL via a shim.
	// "Leveldb": leveldbStore,
}

func TestDsPeerstore(t *testing.T) {
	for name, dsFactory := range dstores {
		t.Run(name, func(t *testing.T) {
			pt.TestPeerstore(t, peerstoreFactory(t, dsFactory, DefaultOpts()))
		})
	}
}

func TestDsAddrBook(t *testing.T) {
	for name, dsFactory := range dstores {
		t.Run(name, func(t *testing.T) {
			t.Run("Cacheful", func(t *testing.T) {
				t.Parallel()

				opts := DefaultOpts()
				opts.TTLInterval = 100 * time.Microsecond
				opts.CacheSize = 1024

				pt.TestAddrBook(t, addressBookFactory(t, dsFactory, opts))
			})

			t.Run("Cacheless", func(t *testing.T) {
				t.Parallel()

				opts := DefaultOpts()
				opts.TTLInterval = 100 * time.Microsecond
				opts.CacheSize = 0

				pt.TestAddrBook(t, addressBookFactory(t, dsFactory, opts))
			})
		})
	}
}

func TestDsKeyBook(t *testing.T) {
	for name, dsFactory := range dstores {
		t.Run(name, func(t *testing.T) {
			pt.TestKeyBook(t, keyBookFactory(t, dsFactory, DefaultOpts()))
		})
	}
}

func BenchmarkDsPeerstore(b *testing.B) {
	caching := DefaultOpts()
	caching.CacheSize = 1024

	cacheless := DefaultOpts()
	cacheless.CacheSize = 0

	for name, dsFactory := range dstores {
		b.Run(name, func(b *testing.B) {
			pt.BenchmarkPeerstore(b, peerstoreFactory(b, dsFactory, caching), "Caching")
			pt.BenchmarkPeerstore(b, peerstoreFactory(b, dsFactory, cacheless), "Cacheless")
		})
	}
}

func badgerStore(tb testing.TB) (ds.TxnDatastore, func()) {
	dataPath, err := ioutil.TempDir(os.TempDir(), "badger")
	if err != nil {
		tb.Fatal(err)
	}
	store, err := badger.NewDatastore(dataPath, nil)
	if err != nil {
		tb.Fatal(err)
	}
	closer := func() {
		store.Close()
		os.RemoveAll(dataPath)
	}
	return store, closer
}

func leveldbStore(tb testing.TB) (ds.TxnDatastore, func()) {
	dataPath, err := ioutil.TempDir(os.TempDir(), "leveldb")
	if err != nil {
		tb.Fatal(err)
	}
	store, err := leveldb.NewDatastore(dataPath, nil)
	if err != nil {
		tb.Fatal(err)
	}
	closer := func() {
		store.Close()
		os.RemoveAll(dataPath)
	}
	return store, closer
}

func peerstoreFactory(tb testing.TB, storeFactory datastoreFactory, opts Options) pt.PeerstoreFactory {
	return func() (pstore.Peerstore, func()) {
		store, closeFunc := storeFactory(tb)

		ps, err := NewPeerstore(context.Background(), store, opts)
		if err != nil {
			tb.Fatal(err)
		}

		return ps, closeFunc
	}
}

func addressBookFactory(tb testing.TB, storeFactory datastoreFactory, opts Options) pt.AddrBookFactory {
	return func() (pstore.AddrBook, func()) {
		store, closeFunc := storeFactory(tb)

		ab, err := NewAddrBook(context.Background(), store, opts)
		if err != nil {
			tb.Fatal(err)
		}

		return ab, closeFunc
	}
}

func keyBookFactory(tb testing.TB, storeFactory datastoreFactory, opts Options) pt.KeyBookFactory {
	return func() (pstore.KeyBook, func()) {
		store, closeFunc := storeFactory(tb)

		kb, err := NewKeyBook(context.Background(), store, opts)
		if err != nil {
			tb.Fatal(err)
		}

		return kb, closeFunc
	}
}
<commit_msg>prevent timeout by un-nesting tb.Runs<commit_after>package pstoreds

import (
	"context"
	"io/ioutil"
	"os"
	"testing"
	"time"

	ds "github.com/ipfs/go-datastore"
	badger "github.com/ipfs/go-ds-badger"
	leveldb "github.com/ipfs/go-ds-leveldb"

	pstore "github.com/libp2p/go-libp2p-peerstore"
	pt "github.com/libp2p/go-libp2p-peerstore/test"
)

type datastoreFactory func(tb testing.TB) (ds.TxnDatastore, func())

var dstores = map[string]datastoreFactory{
	"Badger": badgerStore,
	// TODO: Enable once go-ds-leveldb supports TTL via a shim.
	// "Leveldb": leveldbStore,
}

func TestDsPeerstore(t *testing.T) {
	for name, dsFactory := range dstores {
		t.Run(name, func(t *testing.T) {
			pt.TestPeerstore(t, peerstoreFactory(t, dsFactory, DefaultOpts()))
		})
	}
}

func TestDsAddrBook(t *testing.T) {
	for name, dsFactory := range dstores {
		t.Run(name+" Cacheful", func(t *testing.T) {
			t.Parallel()

			opts := DefaultOpts()
			opts.TTLInterval = 100 * time.Microsecond
			opts.CacheSize = 1024

			pt.TestAddrBook(t, addressBookFactory(t, dsFactory, opts))
		})

		t.Run(name+" Cacheless", func(t *testing.T) {
			t.Parallel()

			opts := DefaultOpts()
			opts.TTLInterval = 100 * time.Microsecond
			opts.CacheSize = 0

			pt.TestAddrBook(t, addressBookFactory(t, dsFactory, opts))
		})
	}
}

func TestDsKeyBook(t *testing.T) {
	for name, dsFactory := range dstores {
		t.Run(name, func(t *testing.T) {
			pt.TestKeyBook(t, keyBookFactory(t, dsFactory, DefaultOpts()))
		})
	}
}

func BenchmarkDsPeerstore(b *testing.B) {
	caching := DefaultOpts()
	caching.CacheSize = 1024

	cacheless := DefaultOpts()
	cacheless.CacheSize = 0

	for name, dsFactory := range dstores {
		b.Run(name, func(b *testing.B) {
			pt.BenchmarkPeerstore(b, peerstoreFactory(b, dsFactory, caching), "Caching")
		})
		b.Run(name, func(b *testing.B) {
			pt.BenchmarkPeerstore(b, peerstoreFactory(b, dsFactory, cacheless), "Cacheless")
		})
	}
}

func badgerStore(tb testing.TB) (ds.TxnDatastore, func()) {
	dataPath, err := ioutil.TempDir(os.TempDir(), "badger")
	if err != nil {
		tb.Fatal(err)
	}
	store, err := badger.NewDatastore(dataPath, nil)
	if err != nil {
		tb.Fatal(err)
	}
	closer := func() {
		store.Close()
		os.RemoveAll(dataPath)
	}
	return store, closer
}

func leveldbStore(tb testing.TB) (ds.TxnDatastore, func()) {
	dataPath, err := ioutil.TempDir(os.TempDir(), "leveldb")
	if err != nil {
		tb.Fatal(err)
	}
	store, err := leveldb.NewDatastore(dataPath, nil)
	if err != nil {
		tb.Fatal(err)
	}
	closer := func() {
		store.Close()
		os.RemoveAll(dataPath)
	}
	return store, closer
}

func peerstoreFactory(tb testing.TB, storeFactory datastoreFactory, opts Options) pt.PeerstoreFactory {
	return func() (pstore.Peerstore, func()) {
		store, closeFunc := storeFactory(tb)

		ps, err := NewPeerstore(context.Background(), store, opts)
		if err != nil {
			tb.Fatal(err)
		}

		return ps, closeFunc
	}
}

func addressBookFactory(tb testing.TB, storeFactory datastoreFactory, opts Options) pt.AddrBookFactory {
	return func() (pstore.AddrBook, func()) {
		store, closeFunc := storeFactory(tb)

		ab, err := NewAddrBook(context.Background(), store, opts)
		if err != nil {
			tb.Fatal(err)
		}

		return ab, closeFunc
	}
}

func keyBookFactory(tb testing.TB, storeFactory datastoreFactory, opts Options) pt.KeyBookFactory {
	return func() (pstore.KeyBook, func()) {
		store, closeFunc := storeFactory(tb)

		kb, err := NewKeyBook(context.Background(), store, opts)
		if err != nil {
			tb.Fatal(err)
		}

		return kb, closeFunc
	}
}
<|endoftext|>


<commit_before>// Copyright 2017 Google Inc.
//
// 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 adapter

import (
	"fmt"

	me "github.com/hashicorp/go-multierror"
)

// A collection of configuration errors
//
// The usage pattern for this type is pretty simple:
//
// 	func (a *adapterState) ValidateConfig(cfg proto.Message) (ce *adapter.ConfigErrors) {
//      c := cfg.(*Config)
//      if c.Url == nil {
// 			ce = ce.Appendf("Url", "Must have a valid URL")
//		}
//		if c.RetryCount < 0 {
//          ce = ce.Appendf("RetryCount", "Expecting >= 0, got %d", cfg.RetryCount)
//		}
//		return
//  }
type ConfigErrors struct {
	// Multi is the accumulator of errors
	Multi *me.Error
}

// ConfigError represents an error encountered while validating a block of configuration state.
type ConfigError struct {
	Field      string
	Underlying error
}

// Appendf adds a ConfigError to a multierror. This function is intended
// to be used by adapter's ValidateConfig method to report errors
// in configuration. The field parameter indicates the name of the
// specific configuration field name that is problematic.
func (e *ConfigErrors) Appendf(field, format string, args ...interface{}) *ConfigErrors {
	if e == nil {
		e = &ConfigErrors{}
	}

	e.Multi = me.Append(e.Multi, ConfigError{field, fmt.Errorf(format, args...)})
	return e
}

// Append adds a ConfigError to a multierror. This function is intended
// to be used by adapter's ValidateConfig method to report errors
// in configuration. The field parameter indicates the name of the
// specific configuration field name that is problematic.
func (e *ConfigErrors) Append(field string, err error) *ConfigErrors {
	if e == nil {
		e = &ConfigErrors{}
	}

	e.Multi = me.Append(e.Multi, ConfigError{field, err})
	return e
}

// Error returns a string representation of the configuration error.
func (e ConfigError) Error() string {
	return fmt.Sprintf("%s: %s", e.Field, e.Underlying)
}

func (e *ConfigErrors) Error() string {
	return e.Multi.Error()
}
<commit_msg>Fix comment formatting. (#132)<commit_after>// Copyright 2017 Google Inc.
//
// 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 adapter

import (
	"fmt"

	me "github.com/hashicorp/go-multierror"
)

// A collection of configuration errors
//
// The usage pattern for this type is pretty simple:
//
//  	func (a *adapterState) ValidateConfig(cfg proto.Message) (ce *adapter.ConfigErrors) {
//  		c := cfg.(*Config)
//      	if c.Url == nil {
//  			ce = ce.Appendf("Url", "Must have a valid URL")
//  		}
//  		if c.RetryCount < 0 {
//  			ce = ce.Appendf("RetryCount", "Expecting >= 0, got %d", cfg.RetryCount)
//  		}
//  		return
//  	}
type ConfigErrors struct {
	// Multi is the accumulator of errors
	Multi *me.Error
}

// ConfigError represents an error encountered while validating a block of configuration state.
type ConfigError struct {
	Field      string
	Underlying error
}

// Appendf adds a ConfigError to a multierror. This function is intended
// to be used by adapter's ValidateConfig method to report errors
// in configuration. The field parameter indicates the name of the
// specific configuration field name that is problematic.
func (e *ConfigErrors) Appendf(field, format string, args ...interface{}) *ConfigErrors {
	if e == nil {
		e = &ConfigErrors{}
	}

	e.Multi = me.Append(e.Multi, ConfigError{field, fmt.Errorf(format, args...)})
	return e
}

// Append adds a ConfigError to a multierror. This function is intended
// to be used by adapter's ValidateConfig method to report errors
// in configuration. The field parameter indicates the name of the
// specific configuration field name that is problematic.
func (e *ConfigErrors) Append(field string, err error) *ConfigErrors {
	if e == nil {
		e = &ConfigErrors{}
	}

	e.Multi = me.Append(e.Multi, ConfigError{field, err})
	return e
}

// Error returns a string representation of the configuration error.
func (e ConfigError) Error() string {
	return fmt.Sprintf("%s: %s", e.Field, e.Underlying)
}

func (e *ConfigErrors) Error() string {
	return e.Multi.Error()
}
<|endoftext|>


<commit_before><commit_msg>template filters: rename humanize to humanize_time<commit_after><|endoftext|>


<commit_before>// Copyright 2020 Authors of Cilium
//
// 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 k8sTest

import (
	"context"
	"fmt"
	"net"
	"strings"

	"github.com/cilium/cilium/pkg/annotation"
	. "github.com/cilium/cilium/test/ginkgo-ext"
	"github.com/cilium/cilium/test/helpers"

	. "github.com/onsi/gomega"
)

var _ = Describe("K8sHubbleTest", func() {

	var (
		kubectl        *helpers.Kubectl
		ciliumFilename string

		hubblePodK8s1 string

		hubbleSelector  = "-l k8s-app=hubble-cli"
		hubbleNamespace = helpers.CiliumNamespace

		demoPath string

		app1Service    = "app1-service"
		app1Labels     = "id=app1,zgroup=testapp"
		apps           = []string{helpers.App1, helpers.App2, helpers.App3}
		prometheusPort = "9091"
	)

	addVisibilityAnnotation := func(ns, podLabels, direction, port, l4proto, l7proto string) {
		visibilityAnnotation := fmt.Sprintf("<%s/%s/%s/%s>", direction, port, l4proto, l7proto)
		By("Adding visibility annotation %s on pod with labels %s", visibilityAnnotation, podLabels)

		// Prints <node>=<ns>/<podname> for each pod the annotation was applied to
		res := kubectl.Exec(fmt.Sprintf("%s annotate pod -n %s -l %s %s=%q"+
			" -o 'jsonpath={.spec.nodeName}={.metadata.namespace}/{.metadata.name}{\"\\n\"}'",
			helpers.KubectlCmd,
			ns, app1Labels,
			annotation.ProxyVisibility, visibilityAnnotation))
		res.ExpectSuccess("adding proxy visibility annotation failed")

		// For each pod, check that the Cilium proxy-statistics contain the new annotation
		expectedProxyState := strings.ToLower(visibilityAnnotation)
		for node, podName := range res.KVOutput() {
			ciliumPod, err := kubectl.GetCiliumPodOnNode(helpers.CiliumNamespace, node)
			Expect(err).To(BeNil())

			// Extract annotation from endpoint model of pod. It does not have the l4proto, so we insert it manually.
			cmd := fmt.Sprintf("cilium endpoint get pod-name:%s"+
				" -o jsonpath='{range [*].status.policy.proxy-statistics[*]}<{.location}/{.port}/%s/{.protocol}>{\"\\n\"}{end}'",
				podName, strings.ToLower(l4proto))
			err = kubectl.CiliumExecUntilMatch(ciliumPod, cmd, expectedProxyState)
			Expect(err).To(BeNil(), "timed out waiting for endpoint to regenerate for visibility annotation")
		}
	}

	removeVisbilityAnnotation := func(ns, podLabels string) {
		By("Removing visibility annotation on pod with labels %s", app1Labels)
		res := kubectl.Exec(fmt.Sprintf("%s annotate pod -n %s -l %s %s-", helpers.KubectlCmd, ns, podLabels, annotation.ProxyVisibility))
		res.ExpectSuccess("removing proxy visibility annotation failed")
	}

	BeforeAll(func() {
		kubectl = helpers.CreateKubectl(helpers.K8s1VMName(), logger)
		ciliumFilename = helpers.TimestampFilename("cilium.yaml")

		demoPath = helpers.ManifestGet(kubectl.BasePath(), "demo.yaml")

		DeployCiliumOptionsAndDNS(kubectl, ciliumFilename, map[string]string{
			"global.hubble.cli.enabled":     "true",
			"global.hubble.metricsServer":   fmt.Sprintf(":%s", prometheusPort),
			"global.hubble.metrics.enabled": `"{dns:query;ignoreAAAA,drop,tcp,flow,port-distribution,icmp,http}"`,
		})

		err := kubectl.WaitforPods(hubbleNamespace, hubbleSelector, helpers.HelperTimeout)
		Expect(err).Should(BeNil(), "hubble-cli pods did not become ready")

		hubblePodK8s1, err = kubectl.GetHubbleClientPodOnNodeWithLabel(hubbleNamespace, helpers.K8s1)
		Expect(err).Should(BeNil(), "unable to find hubble-cli pod on %s", helpers.K8s1)
	})

	AfterFailed(func() {
		kubectl.CiliumReport(helpers.CiliumNamespace,
			"cilium endpoint list")
	})

	JustAfterEach(func() {
		kubectl.ValidateNoErrorsInLogs(CurrentGinkgoTestDescription().Duration)
	})

	AfterEach(func() {
		ExpectAllPodsTerminated(kubectl)
	})

	AfterAll(func() {
		kubectl.Delete(ciliumFilename)
		ExpectAllPodsTerminated(kubectl)
		kubectl.CloseSSHClient()
	})

	Context("Hubble Observe", func() {
		var (
			namespaceForTest string
			appPods          map[string]string
			app1ClusterIP    string
			app1Port         int
		)

		BeforeAll(func() {
			namespaceForTest = helpers.GenerateNamespaceForTest("")
			kubectl.NamespaceDelete(namespaceForTest)
			res := kubectl.NamespaceCreate(namespaceForTest)
			res.ExpectSuccess("could not create namespace")

			res = kubectl.Apply(helpers.ApplyOptions{FilePath: demoPath, Namespace: namespaceForTest})
			res.ExpectSuccess("could not create resource")

			err := kubectl.WaitforPods(namespaceForTest, "-l zgroup=testapp", helpers.HelperTimeout)
			Expect(err).Should(BeNil(), "test pods are not ready after timeout")

			appPods = helpers.GetAppPods(apps, namespaceForTest, kubectl, "id")
			app1ClusterIP, app1Port, err = kubectl.GetServiceHostPort(namespaceForTest, app1Service)
			Expect(err).To(BeNil(), "unable to find service in %q namespace", namespaceForTest)
		})

		AfterAll(func() {
			kubectl.Delete(demoPath)
			kubectl.NamespaceDelete(namespaceForTest)
		})

		It("Test L3/L4 Flow", func() {
			ctx, cancel := context.WithTimeout(context.Background(), helpers.MidCommandTimeout)
			defer cancel()
			follow := kubectl.HubbleObserveFollow(ctx, hubbleNamespace, hubblePodK8s1, fmt.Sprintf(
				"--last 1 --type trace --from-pod %s/%s --to-namespace %s --to-label %s --to-port %d",
				namespaceForTest, appPods[helpers.App2], namespaceForTest, app1Labels, app1Port))

			res := kubectl.ExecPodCmd(namespaceForTest, appPods[helpers.App2],
				helpers.CurlFail(fmt.Sprintf("http://%s/public", app1ClusterIP)))
			res.ExpectSuccess("%q cannot curl clusterIP %q", appPods[helpers.App2], app1ClusterIP)

			err := follow.WaitUntilMatchFilterLineTimeout(`{$.Type}`, "L3_L4", helpers.ShortCommandTimeout)
			Expect(err).To(BeNil(), fmt.Sprintf("hubble observe query timed out on %q", follow.OutputPrettyPrint()))

			// Basic check for L4 Prometheus metrics.
			_, nodeIP := kubectl.GetNodeInfo(helpers.K8s1)
			metricsUrl := fmt.Sprintf("%s/metrics", net.JoinHostPort(nodeIP, prometheusPort))
			res = kubectl.ExecPodCmd(hubbleNamespace, hubblePodK8s1, helpers.CurlFail(metricsUrl))
			res.ExpectSuccess("%s/%s cannot curl metrics %q", hubblePodK8s1, hubblePodK8s1, app1ClusterIP)
			res.ExpectContains(`hubble_flows_processed_total{subtype="to-endpoint",type="Trace",verdict="FORWARDED"}`)
		})

		It("Test L7 Flow", func() {
			addVisibilityAnnotation(namespaceForTest, app1Labels, "Ingress", "80", "TCP", "HTTP")
			defer removeVisbilityAnnotation(namespaceForTest, app1Labels)

			ctx, cancel := context.WithTimeout(context.Background(), helpers.MidCommandTimeout)
			defer cancel()
			follow := kubectl.HubbleObserveFollow(ctx, hubbleNamespace, hubblePodK8s1, fmt.Sprintf(
				"--last 1 --type l7 --from-pod %s/%s --to-namespace %s --to-label %s --protocol http",
				namespaceForTest, appPods[helpers.App2], namespaceForTest, app1Labels))

			res := kubectl.ExecPodCmd(namespaceForTest, appPods[helpers.App2],
				helpers.CurlFail(fmt.Sprintf("http://%s/public", app1ClusterIP)))
			res.ExpectSuccess("%q cannot curl clusterIP %q", appPods[helpers.App2], app1ClusterIP)

			err := follow.WaitUntilMatchFilterLineTimeout(`{$.Type}`, "L7", helpers.ShortCommandTimeout)
			Expect(err).To(BeNil(), fmt.Sprintf("hubble observe query timed out on %q", follow.OutputPrettyPrint()))

			// Basic check for L7 Prometheus metrics.
			_, nodeIP := kubectl.GetNodeInfo(helpers.K8s1)
			metricsUrl := fmt.Sprintf("%s/metrics", net.JoinHostPort(nodeIP, prometheusPort))
			res = kubectl.ExecPodCmd(hubbleNamespace, hubblePodK8s1, helpers.CurlFail(metricsUrl))
			res.ExpectSuccess("%s/%s cannot curl metrics %q", hubbleNamespace, hubblePodK8s1, app1ClusterIP)
			res.ExpectContains(`hubble_flows_processed_total{subtype="HTTP",type="L7",verdict="FORWARDED"}`)
		})
	})
})
<commit_msg>test: add basic tests for hubble-relay<commit_after>// Copyright 2020 Authors of Cilium
//
// 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 k8sTest

import (
	"context"
	"fmt"
	"net"
	"strconv"
	"strings"

	"github.com/asaskevich/govalidator"
	"github.com/cilium/cilium/pkg/annotation"
	. "github.com/cilium/cilium/test/ginkgo-ext"
	"github.com/cilium/cilium/test/helpers"

	. "github.com/onsi/gomega"
)

var _ = Describe("K8sHubbleTest", func() {

	var (
		kubectl        *helpers.Kubectl
		ciliumFilename string

		hubblePodK8s1 string

		hubbleNamespace    = helpers.CiliumNamespace
		hubbleRelayService = "hubble-relay"
		hubbleRelayAddress string

		demoPath string

		app1Service    = "app1-service"
		app1Labels     = "id=app1,zgroup=testapp"
		apps           = []string{helpers.App1, helpers.App2, helpers.App3}
		prometheusPort = "9091"
	)

	addVisibilityAnnotation := func(ns, podLabels, direction, port, l4proto, l7proto string) {
		visibilityAnnotation := fmt.Sprintf("<%s/%s/%s/%s>", direction, port, l4proto, l7proto)
		By("Adding visibility annotation %s on pod with labels %s", visibilityAnnotation, podLabels)

		// Prints <node>=<ns>/<podname> for each pod the annotation was applied to
		res := kubectl.Exec(fmt.Sprintf("%s annotate pod -n %s -l %s %s=%q"+
			" -o 'jsonpath={.spec.nodeName}={.metadata.namespace}/{.metadata.name}{\"\\n\"}'",
			helpers.KubectlCmd,
			ns, app1Labels,
			annotation.ProxyVisibility, visibilityAnnotation))
		res.ExpectSuccess("adding proxy visibility annotation failed")

		// For each pod, check that the Cilium proxy-statistics contain the new annotation
		expectedProxyState := strings.ToLower(visibilityAnnotation)
		for node, podName := range res.KVOutput() {
			ciliumPod, err := kubectl.GetCiliumPodOnNode(helpers.CiliumNamespace, node)
			Expect(err).To(BeNil())

			// Extract annotation from endpoint model of pod. It does not have the l4proto, so we insert it manually.
			cmd := fmt.Sprintf("cilium endpoint get pod-name:%s"+
				" -o jsonpath='{range [*].status.policy.proxy-statistics[*]}<{.location}/{.port}/%s/{.protocol}>{\"\\n\"}{end}'",
				podName, strings.ToLower(l4proto))
			err = kubectl.CiliumExecUntilMatch(ciliumPod, cmd, expectedProxyState)
			Expect(err).To(BeNil(), "timed out waiting for endpoint to regenerate for visibility annotation")
		}
	}

	removeVisbilityAnnotation := func(ns, podLabels string) {
		By("Removing visibility annotation on pod with labels %s", app1Labels)
		res := kubectl.Exec(fmt.Sprintf("%s annotate pod -n %s -l %s %s-", helpers.KubectlCmd, ns, podLabels, annotation.ProxyVisibility))
		res.ExpectSuccess("removing proxy visibility annotation failed")
	}

	BeforeAll(func() {
		kubectl = helpers.CreateKubectl(helpers.K8s1VMName(), logger)
		ciliumFilename = helpers.TimestampFilename("cilium.yaml")

		demoPath = helpers.ManifestGet(kubectl.BasePath(), "demo.yaml")

		DeployCiliumOptionsAndDNS(kubectl, ciliumFilename, map[string]string{
			"global.hubble.metricsServer":   fmt.Sprintf(":%s", prometheusPort),
			"global.hubble.metrics.enabled": `"{dns:query;ignoreAAAA,drop,tcp,flow,port-distribution,icmp,http}"`,
			"global.hubble.cli.enabled":     "true",
			"global.hubble.relay.enabled":   "true",
		})

		var err error
		ExpectHubbleCLIReady(kubectl, hubbleNamespace)
		hubblePodK8s1, err = kubectl.GetHubbleClientPodOnNodeWithLabel(hubbleNamespace, helpers.K8s1)
		Expect(err).Should(BeNil(), "unable to find hubble-cli pod on %s", helpers.K8s1)

		ExpectHubbleRelayReady(kubectl, hubbleNamespace)
		hubbleRelayIP, hubbleRelayPort, err := kubectl.GetServiceHostPort(hubbleNamespace, hubbleRelayService)
		Expect(err).Should(BeNil(), "Cannot get service %s", hubbleRelayService)
		Expect(govalidator.IsIP(hubbleRelayIP)).Should(BeTrue(), "hubbleRelayIP is not an IP")
		hubbleRelayAddress = net.JoinHostPort(hubbleRelayIP, strconv.Itoa(hubbleRelayPort))
	})

	AfterFailed(func() {
		kubectl.CiliumReport(helpers.CiliumNamespace,
			"cilium endpoint list")
	})

	JustAfterEach(func() {
		kubectl.ValidateNoErrorsInLogs(CurrentGinkgoTestDescription().Duration)
	})

	AfterEach(func() {
		ExpectAllPodsTerminated(kubectl)
	})

	AfterAll(func() {
		kubectl.Delete(ciliumFilename)
		ExpectAllPodsTerminated(kubectl)
		kubectl.CloseSSHClient()
	})

	Context("Hubble Observe", func() {
		var (
			namespaceForTest string
			appPods          map[string]string
			app1ClusterIP    string
			app1Port         int
		)

		BeforeAll(func() {
			namespaceForTest = helpers.GenerateNamespaceForTest("")
			kubectl.NamespaceDelete(namespaceForTest)
			res := kubectl.NamespaceCreate(namespaceForTest)
			res.ExpectSuccess("could not create namespace")

			res = kubectl.Apply(helpers.ApplyOptions{FilePath: demoPath, Namespace: namespaceForTest})
			res.ExpectSuccess("could not create resource")

			err := kubectl.WaitforPods(namespaceForTest, "-l zgroup=testapp", helpers.HelperTimeout)
			Expect(err).Should(BeNil(), "test pods are not ready after timeout")

			appPods = helpers.GetAppPods(apps, namespaceForTest, kubectl, "id")
			app1ClusterIP, app1Port, err = kubectl.GetServiceHostPort(namespaceForTest, app1Service)
			Expect(err).To(BeNil(), "unable to find service in %q namespace", namespaceForTest)
		})

		AfterAll(func() {
			kubectl.Delete(demoPath)
			kubectl.NamespaceDelete(namespaceForTest)
		})

		It("Test L3/L4 Flow", func() {
			ctx, cancel := context.WithTimeout(context.Background(), helpers.MidCommandTimeout)
			defer cancel()
			follow := kubectl.HubbleObserveFollow(ctx, hubbleNamespace, hubblePodK8s1, fmt.Sprintf(
				"--last 1 --type trace --from-pod %s/%s --to-namespace %s --to-label %s --to-port %d",
				namespaceForTest, appPods[helpers.App2], namespaceForTest, app1Labels, app1Port))

			res := kubectl.ExecPodCmd(namespaceForTest, appPods[helpers.App2],
				helpers.CurlFail(fmt.Sprintf("http://%s/public", app1ClusterIP)))
			res.ExpectSuccess("%q cannot curl clusterIP %q", appPods[helpers.App2], app1ClusterIP)

			err := follow.WaitUntilMatchFilterLineTimeout(`{$.Type}`, "L3_L4", helpers.ShortCommandTimeout)
			Expect(err).To(BeNil(), fmt.Sprintf("hubble observe query timed out on %q", follow.OutputPrettyPrint()))

			// Basic check for L4 Prometheus metrics.
			_, nodeIP := kubectl.GetNodeInfo(helpers.K8s1)
			metricsUrl := fmt.Sprintf("%s/metrics", net.JoinHostPort(nodeIP, prometheusPort))
			res = kubectl.ExecPodCmd(hubbleNamespace, hubblePodK8s1, helpers.CurlFail(metricsUrl))
			res.ExpectSuccess("%s/%s cannot curl metrics %q", hubblePodK8s1, hubblePodK8s1, app1ClusterIP)
			res.ExpectContains(`hubble_flows_processed_total{subtype="to-endpoint",type="Trace",verdict="FORWARDED"}`)
		})

		It("Test L3/L4 Flow with hubble-relay", func() {
			ctx, cancel := context.WithTimeout(context.Background(), helpers.MidCommandTimeout)
			defer cancel()
			follow := kubectl.HubbleObserveFollow(ctx, hubbleNamespace, hubblePodK8s1, fmt.Sprintf(
				"--server %s --last 1 --type trace --from-pod %s/%s --to-namespace %s --to-label %s --to-port %d",
				hubbleRelayAddress, namespaceForTest, appPods[helpers.App2], namespaceForTest, app1Labels, app1Port))

			res := kubectl.ExecPodCmd(namespaceForTest, appPods[helpers.App2],
				helpers.CurlFail(fmt.Sprintf("http://%s/public", app1ClusterIP)))
			res.ExpectSuccess("%q cannot curl clusterIP %q", appPods[helpers.App2], app1ClusterIP)

			err := follow.WaitUntilMatchFilterLineTimeout(`{$.Type}`, "L3_L4", helpers.ShortCommandTimeout)
			Expect(err).To(BeNil(), fmt.Sprintf("hubble observe query timed out on %q", follow.OutputPrettyPrint()))
		})

		It("Test L7 Flow", func() {
			addVisibilityAnnotation(namespaceForTest, app1Labels, "Ingress", "80", "TCP", "HTTP")
			defer removeVisbilityAnnotation(namespaceForTest, app1Labels)

			ctx, cancel := context.WithTimeout(context.Background(), helpers.MidCommandTimeout)
			defer cancel()
			follow := kubectl.HubbleObserveFollow(ctx, hubbleNamespace, hubblePodK8s1, fmt.Sprintf(
				"--last 1 --type l7 --from-pod %s/%s --to-namespace %s --to-label %s --protocol http",
				namespaceForTest, appPods[helpers.App2], namespaceForTest, app1Labels))

			res := kubectl.ExecPodCmd(namespaceForTest, appPods[helpers.App2],
				helpers.CurlFail(fmt.Sprintf("http://%s/public", app1ClusterIP)))
			res.ExpectSuccess("%q cannot curl clusterIP %q", appPods[helpers.App2], app1ClusterIP)

			err := follow.WaitUntilMatchFilterLineTimeout(`{$.Type}`, "L7", helpers.ShortCommandTimeout)
			Expect(err).To(BeNil(), fmt.Sprintf("hubble observe query timed out on %q", follow.OutputPrettyPrint()))

			// Basic check for L7 Prometheus metrics.
			_, nodeIP := kubectl.GetNodeInfo(helpers.K8s1)
			metricsUrl := fmt.Sprintf("%s/metrics", net.JoinHostPort(nodeIP, prometheusPort))
			res = kubectl.ExecPodCmd(hubbleNamespace, hubblePodK8s1, helpers.CurlFail(metricsUrl))
			res.ExpectSuccess("%s/%s cannot curl metrics %q", hubbleNamespace, hubblePodK8s1, app1ClusterIP)
			res.ExpectContains(`hubble_flows_processed_total{subtype="HTTP",type="L7",verdict="FORWARDED"}`)
		})

		It("Test L7 Flow with hubble-relay", func() {
			addVisibilityAnnotation(namespaceForTest, app1Labels, "Ingress", "80", "TCP", "HTTP")
			defer removeVisbilityAnnotation(namespaceForTest, app1Labels)

			ctx, cancel := context.WithTimeout(context.Background(), helpers.MidCommandTimeout)
			defer cancel()
			follow := kubectl.HubbleObserveFollow(ctx, hubbleNamespace, hubblePodK8s1, fmt.Sprintf(
				"--server %s --last 1 --type l7 --from-pod %s/%s --to-namespace %s --to-label %s --protocol http",
				hubbleRelayAddress, namespaceForTest, appPods[helpers.App2], namespaceForTest, app1Labels))

			res := kubectl.ExecPodCmd(namespaceForTest, appPods[helpers.App2],
				helpers.CurlFail(fmt.Sprintf("http://%s/public", app1ClusterIP)))
			res.ExpectSuccess("%q cannot curl clusterIP %q", appPods[helpers.App2], app1ClusterIP)

			err := follow.WaitUntilMatchFilterLineTimeout(`{$.Type}`, "L7", helpers.ShortCommandTimeout)
			Expect(err).To(BeNil(), fmt.Sprintf("hubble observe query timed out on %q", follow.OutputPrettyPrint()))
		})
	})
})
<|endoftext|>


<commit_before>/*
Copyright 2018 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.
*/

// spoof contains logic to make polling HTTP requests against an endpoint with optional host spoofing.

package spoof

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	"time"

	"github.com/knative/pkg/test/logging"
	zipkin "github.com/knative/pkg/test/zipkin"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/wait"
	"k8s.io/client-go/kubernetes"

	"go.opencensus.io/plugin/ochttp"
	"go.opencensus.io/plugin/ochttp/propagation/b3"
	"go.opencensus.io/trace"
)

const (
	requestInterval = 1 * time.Second
	requestTimeout  = 5 * time.Minute
	// TODO(tcnghia): These probably shouldn't be hard-coded here?
	ingressName      = "knative-ingressgateway"
	ingressNamespace = "istio-system"
)

// Response is a stripped down subset of http.Response. The is primarily useful
// for ResponseCheckers to inspect the response body without consuming it.
// Notably, Body is a byte slice instead of an io.ReadCloser.
type Response struct {
	Status     string
	StatusCode int
	Header     http.Header
	Body       []byte
}

// Interface defines the actions that can be performed by the spoofing client.
type Interface interface {
	Do(*http.Request) (*Response, error)
	Poll(*http.Request, ResponseChecker) (*Response, error)
}

// https://medium.com/stupid-gopher-tricks/ensuring-go-interface-satisfaction-at-compile-time-1ed158e8fa17
var _ Interface = (*SpoofingClient)(nil)

// ResponseChecker is used to determine when SpoofinClient.Poll is done polling.
// This allows you to predicate wait.PollImmediate on the request's http.Response.
//
// See the apimachinery wait package:
// https://github.com/kubernetes/apimachinery/blob/cf7ae2f57dabc02a3d215f15ca61ae1446f3be8f/pkg/util/wait/wait.go#L172
type ResponseChecker func(resp *Response) (done bool, err error)

// SpoofingClient is a minimal http client wrapper that spoofs the domain of requests
// for non-resolvable domains.
type SpoofingClient struct {
	Client          *http.Client
	RequestInterval time.Duration
	RequestTimeout  time.Duration

	endpoint string
	domain   string

	logger *logging.BaseLogger
}

// New returns a SpoofingClient that rewrites requests if the target domain is not `resolveable`.
// It does this by looking up the ingress at construction time, so reusing a client will not
// follow the ingress if it moves (or if there are multiple ingresses).
//
// If that's a problem, see test/request.go#WaitForEndpointState for oneshot spoofing.
func New(kubeClientset *kubernetes.Clientset, logger *logging.BaseLogger, domain string, resolvable bool) (*SpoofingClient, error) {
	sc := SpoofingClient{
		Client:          &http.Client{Transport: &ochttp.Transport{Propagation: &b3.HTTPFormat{}}}, // Using ochttp Transport required for zipkin-tracing
		RequestInterval: requestInterval,
		RequestTimeout:  requestTimeout,
		logger:          logger,
	}

	if !resolvable {
		// If the domain that the Route controller is configured to assign to Route.Status.Domain
		// (the domainSuffix) is not resolvable, we need to retrieve the IP of the endpoint and
		// spoof the Host in our requests.
		e, err := GetServiceEndpoint(kubeClientset)
		if err != nil {
			return nil, err
		}

		sc.endpoint = *e
		sc.domain = domain
	} else {
		// If the domain is resolvable, we can use it directly when we make requests.
		sc.endpoint = domain
	}

	return &sc, nil
}

// GetServiceEndpoint gets the endpoint IP or hostname to use for the service
func GetServiceEndpoint(kubeClientset *kubernetes.Clientset) (*string, error) {
	var endpoint string
	ingress, err := kubeClientset.CoreV1().Services(ingressNamespace).Get(ingressName, metav1.GetOptions{})
	if err != nil {
		return nil, err
	}
	ingresses := ingress.Status.LoadBalancer.Ingress
	if len(ingresses) != 1 {
		return nil, fmt.Errorf("Expected exactly one ingress load balancer, instead had %d: %s", len(ingresses), ingresses)
	}
	ingressToUse := ingresses[0]
	if ingressToUse.IP == "" {
		if ingressToUse.Hostname == "" {
			return nil, fmt.Errorf("Expected ingress loadbalancer IP or hostname for %s to be set, instead was empty", ingressName)
		}
		endpoint = ingressToUse.Hostname
	} else {
		endpoint = ingressToUse.IP
	}
	return &endpoint, nil
}

// Do dispatches to the underlying http.Client.Do, spoofing domains as needed
// and transforming the http.Response into a spoof.Response.
// Each response is augmented with "ZipkinTraceID" header that identifies the zipkin trace corresponding to the request.
func (sc *SpoofingClient) Do(req *http.Request) (*Response, error) {
	// Controls the Host header, for spoofing.
	if sc.domain != "" {
		req.Host = sc.domain
	}

	// Controls the actual resolution.
	if sc.endpoint != "" {
		req.URL.Host = sc.endpoint
	}

	// Starting span to capture zipkin trace.
	traceContext, span := trace.StartSpan(req.Context(), "SpoofingClient-Trace")
	defer span.End()

	resp, err := sc.Client.Do(req.WithContext(traceContext))
	if err != nil {
		return nil, err
	}

	defer resp.Body.Close()

	resp.Header.Add(zipkin.ZipkinTraceIDHeader, span.SpanContext().TraceID.String())
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	return &Response{
		Status:     resp.Status,
		StatusCode: resp.StatusCode,
		Header:     resp.Header,
		Body:       body,
	}, nil
}

// Poll executes an http request until it satisfies the inState condition or encounters an error.
func (sc *SpoofingClient) Poll(req *http.Request, inState ResponseChecker) (*Response, error) {
	var (
		resp *Response
		err  error
	)

	err = wait.PollImmediate(sc.RequestInterval, sc.RequestTimeout, func() (bool, error) {
		resp, err = sc.Do(req)
		if err != nil {
			if err, ok := err.(net.Error); ok && err.Timeout() {
				sc.logger.Infof("Retrying for TCP timeout %v", err)
				return false, nil
			}
			return true, err
		}

		return inState(resp)
	})

	return resp, err
}

// LogZipkinTrace provides support to log Zipkin Trace for param: traceID
func (sc *SpoofingClient) LogZipkinTrace(traceID string) error {
	if err := zipkin.CheckZipkinPortAvailability(); err == nil {
		return errors.New("port-forwarding for Zipkin is not-setup. Failing Zipkin Trace retrieval")
	}

	sc.logger.Infof("Logging Zipkin Trace: %s", traceID)

	zipkinTraceEndpoint := zipkin.ZipkinTraceEndpoint + traceID
	// Sleep to ensure all traces are correctly pushed on the backend.
	time.Sleep(5 * time.Second)
	resp, err := http.Get(zipkinTraceEndpoint)
	if err != nil {
		return fmt.Errorf("Error retrieving Zipkin trace: %v", err)
	}

	trace, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("Error reading Zipkin trace response: %v", err)
	}

	var prettyJSON bytes.Buffer
	error := json.Indent(&prettyJSON, trace, "", "\t")
	if error != nil {
		return fmt.Errorf("JSON Parser Error while trying for Pretty-Format: %v, Original Response: %s", error, string(trace))
	}
	sc.logger.Infof(prettyJSON.String())

	return nil
}
<commit_msg>update gateway (#170)<commit_after>/*
Copyright 2018 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.
*/

// spoof contains logic to make polling HTTP requests against an endpoint with optional host spoofing.

package spoof

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	"time"

	"github.com/knative/pkg/test/logging"
	zipkin "github.com/knative/pkg/test/zipkin"
	"k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/wait"
	"k8s.io/client-go/kubernetes"

	"go.opencensus.io/plugin/ochttp"
	"go.opencensus.io/plugin/ochttp/propagation/b3"
	"go.opencensus.io/trace"
)

const (
	requestInterval = 1 * time.Second
	requestTimeout  = 5 * time.Minute
	// TODO(tcnghia): These probably shouldn't be hard-coded here?
	ingressNamespace = "istio-system"
)

// Temporary work around the upgrade test issue for knative/serving#2434.
// TODO(lichuqiang): remove the backward compatibility for knative-ingressgateway
// once knative/serving#2434 is merged
var ingressNames = []string{"knative-ingressgateway", "istio-ingressgateway"}

// Response is a stripped down subset of http.Response. The is primarily useful
// for ResponseCheckers to inspect the response body without consuming it.
// Notably, Body is a byte slice instead of an io.ReadCloser.
type Response struct {
	Status     string
	StatusCode int
	Header     http.Header
	Body       []byte
}

// Interface defines the actions that can be performed by the spoofing client.
type Interface interface {
	Do(*http.Request) (*Response, error)
	Poll(*http.Request, ResponseChecker) (*Response, error)
}

// https://medium.com/stupid-gopher-tricks/ensuring-go-interface-satisfaction-at-compile-time-1ed158e8fa17
var _ Interface = (*SpoofingClient)(nil)

// ResponseChecker is used to determine when SpoofinClient.Poll is done polling.
// This allows you to predicate wait.PollImmediate on the request's http.Response.
//
// See the apimachinery wait package:
// https://github.com/kubernetes/apimachinery/blob/cf7ae2f57dabc02a3d215f15ca61ae1446f3be8f/pkg/util/wait/wait.go#L172
type ResponseChecker func(resp *Response) (done bool, err error)

// SpoofingClient is a minimal http client wrapper that spoofs the domain of requests
// for non-resolvable domains.
type SpoofingClient struct {
	Client          *http.Client
	RequestInterval time.Duration
	RequestTimeout  time.Duration

	endpoint string
	domain   string

	logger *logging.BaseLogger
}

// New returns a SpoofingClient that rewrites requests if the target domain is not `resolveable`.
// It does this by looking up the ingress at construction time, so reusing a client will not
// follow the ingress if it moves (or if there are multiple ingresses).
//
// If that's a problem, see test/request.go#WaitForEndpointState for oneshot spoofing.
func New(kubeClientset *kubernetes.Clientset, logger *logging.BaseLogger, domain string, resolvable bool) (*SpoofingClient, error) {
	sc := SpoofingClient{
		Client:          &http.Client{Transport: &ochttp.Transport{Propagation: &b3.HTTPFormat{}}}, // Using ochttp Transport required for zipkin-tracing
		RequestInterval: requestInterval,
		RequestTimeout:  requestTimeout,
		logger:          logger,
	}

	if !resolvable {
		// If the domain that the Route controller is configured to assign to Route.Status.Domain
		// (the domainSuffix) is not resolvable, we need to retrieve the IP of the endpoint and
		// spoof the Host in our requests.
		e, err := GetServiceEndpoint(kubeClientset)
		if err != nil {
			return nil, err
		}

		sc.endpoint = *e
		sc.domain = domain
	} else {
		// If the domain is resolvable, we can use it directly when we make requests.
		sc.endpoint = domain
	}

	return &sc, nil
}

// GetServiceEndpoint gets the endpoint IP or hostname to use for the service
func GetServiceEndpoint(kubeClientset *kubernetes.Clientset) (*string, error) {
	var endpoint string
	var ingress *v1.Service
	var err error
	for _, ingressName := range ingressNames {
		ingress, err = kubeClientset.CoreV1().Services(ingressNamespace).Get(ingressName, metav1.GetOptions{})
		if err == nil {
			break
		}
	}
	if err != nil {
		return nil, err
	}

	ingresses := ingress.Status.LoadBalancer.Ingress
	if len(ingresses) != 1 {
		return nil, fmt.Errorf("Expected exactly one ingress load balancer, instead had %d: %s", len(ingresses), ingresses)
	}
	ingressToUse := ingresses[0]
	if ingressToUse.IP == "" {
		if ingressToUse.Hostname == "" {
			return nil, fmt.Errorf("Expected ingress loadbalancer IP or hostname for %s to be set, instead was empty", ingress.Name)
		}
		endpoint = ingressToUse.Hostname
	} else {
		endpoint = ingressToUse.IP
	}
	return &endpoint, nil
}

// Do dispatches to the underlying http.Client.Do, spoofing domains as needed
// and transforming the http.Response into a spoof.Response.
// Each response is augmented with "ZipkinTraceID" header that identifies the zipkin trace corresponding to the request.
func (sc *SpoofingClient) Do(req *http.Request) (*Response, error) {
	// Controls the Host header, for spoofing.
	if sc.domain != "" {
		req.Host = sc.domain
	}

	// Controls the actual resolution.
	if sc.endpoint != "" {
		req.URL.Host = sc.endpoint
	}

	// Starting span to capture zipkin trace.
	traceContext, span := trace.StartSpan(req.Context(), "SpoofingClient-Trace")
	defer span.End()

	resp, err := sc.Client.Do(req.WithContext(traceContext))
	if err != nil {
		return nil, err
	}

	defer resp.Body.Close()

	resp.Header.Add(zipkin.ZipkinTraceIDHeader, span.SpanContext().TraceID.String())
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	return &Response{
		Status:     resp.Status,
		StatusCode: resp.StatusCode,
		Header:     resp.Header,
		Body:       body,
	}, nil
}

// Poll executes an http request until it satisfies the inState condition or encounters an error.
func (sc *SpoofingClient) Poll(req *http.Request, inState ResponseChecker) (*Response, error) {
	var (
		resp *Response
		err  error
	)

	err = wait.PollImmediate(sc.RequestInterval, sc.RequestTimeout, func() (bool, error) {
		resp, err = sc.Do(req)
		if err != nil {
			if err, ok := err.(net.Error); ok && err.Timeout() {
				sc.logger.Infof("Retrying for TCP timeout %v", err)
				return false, nil
			}
			return true, err
		}

		return inState(resp)
	})

	return resp, err
}

// LogZipkinTrace provides support to log Zipkin Trace for param: traceID
func (sc *SpoofingClient) LogZipkinTrace(traceID string) error {
	if err := zipkin.CheckZipkinPortAvailability(); err == nil {
		return errors.New("port-forwarding for Zipkin is not-setup. Failing Zipkin Trace retrieval")
	}

	sc.logger.Infof("Logging Zipkin Trace: %s", traceID)

	zipkinTraceEndpoint := zipkin.ZipkinTraceEndpoint + traceID
	// Sleep to ensure all traces are correctly pushed on the backend.
	time.Sleep(5 * time.Second)
	resp, err := http.Get(zipkinTraceEndpoint)
	if err != nil {
		return fmt.Errorf("Error retrieving Zipkin trace: %v", err)
	}

	trace, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("Error reading Zipkin trace response: %v", err)
	}

	var prettyJSON bytes.Buffer
	error := json.Indent(&prettyJSON, trace, "", "\t")
	if error != nil {
		return fmt.Errorf("JSON Parser Error while trying for Pretty-Format: %v, Original Response: %s", error, string(trace))
	}
	sc.logger.Infof(prettyJSON.String())

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"eaciit/gdrj/model"
	"eaciit/gdrj/modules"
	"os"

	"flag"
	"github.com/eaciit/dbox"
	"github.com/eaciit/orm/v1"
	"github.com/eaciit/toolkit"
	"strings"
	"time"
)

var conn dbox.IConnection
var count int

// var mwg sync.WaitGroup

var (
	t0                                time.Time
	custgroup, prodgroup, plcode, ref string
	value, fiscalyear                 int
	globalval                         float64
	mapkeysvalue                      map[string]float64
	masters                           toolkit.M
)

func setinitialconnection() {
	var err error
	conn, err = modules.GetDboxIConnection("db_godrej")

	if err != nil {
		toolkit.Println("Initial connection found : ", err)
		os.Exit(1)
	}

	err = gdrj.SetDb(conn)
	if err != nil {
		toolkit.Println("Initial connection found : ", err)
		os.Exit(1)
	}
}

func buildmap(holder interface{},
	fnModel func() orm.IModel,
	filter *dbox.Filter,
	fnIter func(holder interface{}, obj interface{})) interface{} {
	crx, _ := gdrj.Find(fnModel(), filter, nil)
	defer crx.Close()
	for {
		s := fnModel()
		e := crx.Fetch(s, 1, false)
		if e != nil {
			break
		}
		fnIter(holder, s)
	}
	return holder
}

func prepmaster() {
	masters = toolkit.M{}
	masters.Set("plmodel", buildmap(map[string]*gdrj.PLModel{},
		func() orm.IModel {
			return new(gdrj.PLModel)
		},
		nil,
		func(holder, obj interface{}) {
			h := holder.(map[string]*gdrj.PLModel)
			o := obj.(*gdrj.PLModel)
			h[o.ID] = o
		}).(map[string]*gdrj.PLModel))
}

func main() {
	t0 = time.Now()
	mapkeysvalue = make(map[string]float64)

	flag.IntVar(&value, "value", 0, "representation of value need to be allocation. Default is 0")
	//branch,channel,group
	flag.StringVar(&custgroup, "custgroup", "global", "group of customer. Default is global")
	//brand,group,skuid
	flag.StringVar(&prodgroup, "prodgroup", "global", "group of product. Default is global")
	flag.IntVar(&fiscalyear, "year", 2015, "YYYY representation of godrej fiscal year. Default is 2015")
	flag.StringVar(&plcode, "plcode", "", "PL Code to take the value. Default is blank")
	flag.StringVar(&ref, "ref", "", "Reference from document or other. Default is blank")
	flag.Parse()

	eperiode := time.Date(fiscalyear, 4, 1, 0, 0, 0, 0, time.UTC)
	speriode := eperiode.AddDate(-1, 0, 0)

	filter := dbox.And(dbox.Gte("date.date", speriode), dbox.Lt("date.date", eperiode))

	if plcode == "" || value == 0 {
		toolkit.Println("PLCode and Value are mandatory to fill")
		os.Exit(1)
	}

	setinitialconnection()
	defer gdrj.CloseDb()

	toolkit.Println("Get Data Master...")
	prepmaster()

	toolkit.Println("Start Data Process...")
	c, _ := gdrj.Find(new(gdrj.SalesPL), filter, nil)
	defer c.Close()

	splcount := c.Count()
	step := splcount / 100
	i := 0

	for {
		i++

		spl := new(gdrj.SalesPL)
		e := c.Fetch(spl, 1, false)
		if e != nil {
			break
		}
		key := toolkit.Sprintf("%d_%d", spl.Date.Month, spl.Date.Year)
		k := ""
		switch custgroup {
		case "branch":
			key = toolkit.Sprintf("%v_%v", key, spl.Customer.BranchID)
		case "channel":
			k = toolkit.Sprintf("%v|%v", spl.Customer.BranchID, spl.Customer.ChannelID)
			key = toolkit.Sprintf("%v_%v", key, k)
		case "group":
			k = toolkit.Sprintf("%v|%v", spl.Customer.BranchID, spl.Customer.CustomerGroup)
			key = toolkit.Sprintf("%v_%v", key, k)
		default:
			key = toolkit.Sprintf("%v_", key)
		}

		switch prodgroup {
		case "brand":
			key = toolkit.Sprintf("%v_%v", key, spl.Product.Brand)
		case "group":
			k = toolkit.Sprintf("%v|%v", spl.Product.Brand, spl.Product.BrandCategoryID)
			key = toolkit.Sprintf("%v_%v", key, k)
		case "skuid":
			// toolkit.Printfn("%v|%v|%v", spl.Product.Brand, spl.Product.BrandCategoryID, spl.Product.ID)
			k = toolkit.Sprintf("%v|%v|%v", spl.Product.Brand, spl.Product.BrandCategoryID, spl.Product.ID)
			key = toolkit.Sprintf("%v_%v", key, k)
		default:
			key = toolkit.Sprintf("%v_", key)
		}

		mapkeysvalue[key] += spl.GrossAmount
		globalval += spl.GrossAmount

		if i > step {
			step += splcount / 100
			toolkit.Printfn("Processing %d of %d in %s", i, splcount,
				time.Since(t0).String())
		}

	}

	toolkit.Printfn("Preparing the data")
	mcount := len(mapkeysvalue)
	i = 0
	for k, v := range mapkeysvalue {
		i++

		akey := strings.Split(k, "_")
		tcustomer := new(gdrj.Customer)
		tproduct := new(gdrj.Product)

		if len(akey) > 2 && akey[2] != "" {
			switch custgroup {
			case "branch":
				tcustomer.BranchID = akey[2]
			case "channel":
				skey := strings.Split(akey[2], "|")
				tcustomer.BranchID = skey[0]
				if len(skey) > 1 {
					tcustomer.ChannelID = skey[1]
				}
			case "group":
				skey := strings.Split(akey[2], "|")
				tcustomer.BranchID = skey[0]
				if len(skey) > 1 {
					tcustomer.CustomerGroup = skey[1]
				}
			}
		}

		if len(akey) > 3 && akey[3] != "" {
			switch prodgroup {
			case "brand":
				tproduct.Brand = akey[3]
			case "group":
				skey := strings.Split(akey[3], "|")
				tproduct.Brand = skey[0]
				if len(skey) > 1 {
					tproduct.BrandCategoryID = skey[1]
				}
			case "skuid":
				skey := strings.Split(akey[3], "|")
				tproduct.Brand = skey[0]
				if len(skey) > 1 {
					tproduct.BrandCategoryID = skey[1]
				}
				if len(skey) > 2 {
					tproduct.ID = skey[2]
				}
			}
		}

		spl := new(gdrj.SalesPL)
		spl.ID = toolkit.Sprintf("%v%v%v%v", akey[0], akey[1], "", "")
		spl.Date = gdrj.SetDate(time.Date(toolkit.ToInt(akey[1], toolkit.RoundingAuto),
			time.Month(toolkit.ToInt(akey[0], toolkit.RoundingAuto)),
			1, 0, 0, 0, 0, time.UTC))
		spl.Customer = tcustomer
		spl.Product = tproduct
		spl.Source = "ADJUST"
		spl.Ref = ref

		spl.PC = new(gdrj.ProfitCenter)
		spl.CC = new(gdrj.CostCenter)

		amount := toolkit.ToFloat64(value, 6, toolkit.RoundingAuto) * (v / globalval)
		plmodels := masters.Get("plmodel").(map[string]*gdrj.PLModel)
		spl.AddData(plcode, amount, plmodels)
		spl.CalcSum(masters)

		gdrj.Save(spl)

		toolkit.Printfn("Saving %d of %d in %s", i, mcount,
			time.Since(t0).String())
	}

	toolkit.Printfn("Processing done in %s",
		time.Since(t0).String())
}
<commit_msg>update<commit_after>package main

import (
	"eaciit/gdrj/model"
	"eaciit/gdrj/modules"
	"os"

	"flag"
	"github.com/eaciit/dbox"
	"github.com/eaciit/orm/v1"
	"github.com/eaciit/toolkit"
	"strings"
	"time"
)

var conn dbox.IConnection
var count int

// var mwg sync.WaitGroup

var (
	t0                                time.Time
	custgroup, prodgroup, plcode, ref string
	value, fiscalyear                 int
	globalval                         float64
	mapkeysvalue                      map[string]float64
	masters                           toolkit.M
)

func setinitialconnection() {
	var err error
	conn, err = modules.GetDboxIConnection("db_godrej")

	if err != nil {
		toolkit.Println("Initial connection found : ", err)
		os.Exit(1)
	}

	err = gdrj.SetDb(conn)
	if err != nil {
		toolkit.Println("Initial connection found : ", err)
		os.Exit(1)
	}
}

func buildmap(holder interface{},
	fnModel func() orm.IModel,
	filter *dbox.Filter,
	fnIter func(holder interface{}, obj interface{})) interface{} {
	crx, _ := gdrj.Find(fnModel(), filter, nil)
	defer crx.Close()
	for {
		s := fnModel()
		e := crx.Fetch(s, 1, false)
		if e != nil {
			break
		}
		fnIter(holder, s)
	}
	return holder
}

func prepmaster() {
	masters = toolkit.M{}
	masters.Set("plmodel", buildmap(map[string]*gdrj.PLModel{},
		func() orm.IModel {
			return new(gdrj.PLModel)
		},
		nil,
		func(holder, obj interface{}) {
			h := holder.(map[string]*gdrj.PLModel)
			o := obj.(*gdrj.PLModel)
			h[o.ID] = o
		}).(map[string]*gdrj.PLModel))
}

func main() {
	t0 = time.Now()
	mapkeysvalue = make(map[string]float64)

	flag.IntVar(&value, "value", 0, "representation of value need to be allocation. Default is 0")
	//branch,channel,group
	flag.StringVar(&custgroup, "custgroup", "global", "group of customer. Default is global")
	//brand,group,skuid
	flag.StringVar(&prodgroup, "prodgroup", "global", "group of product. Default is global")
	flag.IntVar(&fiscalyear, "year", 2015, "YYYY representation of godrej fiscal year. Default is 2015")
	flag.StringVar(&plcode, "plcode", "", "PL Code to take the value. Default is blank")
	flag.StringVar(&ref, "ref", "", "Reference from document or other. Default is blank")
	flag.Parse()

	eperiode := time.Date(fiscalyear, 4, 1, 0, 0, 0, 0, time.UTC)
	speriode := eperiode.AddDate(-1, 0, 0)

	filter := dbox.And(dbox.Gte("date.date", speriode), dbox.Lt("date.date", eperiode))

	if plcode == "" || value == 0 {
		toolkit.Println("PLCode and Value are mandatory to fill")
		os.Exit(1)
	}

	setinitialconnection()
	defer gdrj.CloseDb()

	toolkit.Println("Get Data Master...")
	prepmaster()

	toolkit.Println("Start Data Process...")
	c, _ := gdrj.Find(new(gdrj.SalesPL), filter, nil)
	defer c.Close()

	splcount := c.Count()
	step := splcount / 100
	i := 0

	for {
		i++

		spl := new(gdrj.SalesPL)
		e := c.Fetch(spl, 1, false)
		if e != nil {
			break
		}
		key := toolkit.Sprintf("%d_%d", spl.Date.Month, spl.Date.Year)
		k := ""

		if spl.Customer != nil {
			switch custgroup {
			case "branch":
				key = toolkit.Sprintf("%v_%v", key, spl.Customer.BranchID)
			case "channel":
				k = toolkit.Sprintf("%v|%v", spl.Customer.BranchID, spl.Customer.ChannelID)
				key = toolkit.Sprintf("%v_%v", key, k)
			case "group":
				k = toolkit.Sprintf("%v|%v", spl.Customer.BranchID, spl.Customer.CustomerGroup)
				key = toolkit.Sprintf("%v_%v", key, k)
			default:
				key = toolkit.Sprintf("%v_", key)
			}
		}

		if spl.Product != nil {
			switch prodgroup {
			case "brand":
				key = toolkit.Sprintf("%v_%v", key, spl.Product.Brand)
			case "group":
				k = toolkit.Sprintf("%v|%v", spl.Product.Brand, spl.Product.BrandCategoryID)
				key = toolkit.Sprintf("%v_%v", key, k)
			case "skuid":
				k = toolkit.Sprintf("%v|%v|%v", spl.Product.Brand, spl.Product.BrandCategoryID, spl.Product.ID)
				key = toolkit.Sprintf("%v_%v", key, k)
			default:
				key = toolkit.Sprintf("%v_", key)
			}

		}

		mapkeysvalue[key] += spl.GrossAmount
		globalval += spl.GrossAmount

		if i > step {
			step += splcount / 100
			toolkit.Printfn("Processing %d of %d in %s", i, splcount,
				time.Since(t0).String())
		}

	}

	toolkit.Printfn("Preparing the data")
	mcount := len(mapkeysvalue)
	i = 0
	for k, v := range mapkeysvalue {
		i++

		akey := strings.Split(k, "_")
		tcustomer := new(gdrj.Customer)
		tproduct := new(gdrj.Product)

		if len(akey) > 2 && akey[2] != "" {
			switch custgroup {
			case "branch":
				tcustomer.BranchID = akey[2]
			case "channel":
				skey := strings.Split(akey[2], "|")
				tcustomer.BranchID = skey[0]
				if len(skey) > 1 {
					tcustomer.ChannelID = skey[1]
				}
			case "group":
				skey := strings.Split(akey[2], "|")
				tcustomer.BranchID = skey[0]
				if len(skey) > 1 {
					tcustomer.CustomerGroup = skey[1]
				}
			}
		}

		if len(akey) > 3 && akey[3] != "" {
			switch prodgroup {
			case "brand":
				tproduct.Brand = akey[3]
			case "group":
				skey := strings.Split(akey[3], "|")
				tproduct.Brand = skey[0]
				if len(skey) > 1 {
					tproduct.BrandCategoryID = skey[1]
				}
			case "skuid":
				skey := strings.Split(akey[3], "|")
				tproduct.Brand = skey[0]
				if len(skey) > 1 {
					tproduct.BrandCategoryID = skey[1]
				}
				if len(skey) > 2 {
					tproduct.ID = skey[2]
				}
			}
		}

		spl := new(gdrj.SalesPL)
		spl.ID = toolkit.Sprintf("%v%v%v%v", akey[0], akey[1], "", "")
		spl.Date = gdrj.SetDate(time.Date(toolkit.ToInt(akey[1], toolkit.RoundingAuto),
			time.Month(toolkit.ToInt(akey[0], toolkit.RoundingAuto)),
			1, 0, 0, 0, 0, time.UTC))
		spl.Customer = tcustomer
		spl.Product = tproduct
		spl.Source = "ADJUST"
		spl.Ref = ref

		spl.PC = new(gdrj.ProfitCenter)
		spl.CC = new(gdrj.CostCenter)

		amount := toolkit.ToFloat64(value, 6, toolkit.RoundingAuto) * (v / globalval)
		plmodels := masters.Get("plmodel").(map[string]*gdrj.PLModel)
		spl.AddData(plcode, amount, plmodels)
		spl.CalcSum(masters)

		gdrj.Save(spl)

		toolkit.Printfn("Saving %d of %d in %s", i, mcount,
			time.Since(t0).String())
	}

	toolkit.Printfn("Processing done in %s",
		time.Since(t0).String())
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/tls"
	"crypto/x509"
	"errors"
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	"net/url"
	"os"
	"time"
)

func main() {
	var host, port, caFileName string
	switch len(os.Args) {
	case 4:
		caFileName = os.Args[3]
		fallthrough
	case 3:
		host = os.Args[1]
		port = os.Args[2]
	default:
		fmt.Printf("usage: %v <host> <port> [cafile]\n", os.Args[0])
		os.Exit(1)
	}

	if err := checkTLS(host, port, caFileName); err != nil {
		fmt.Println("FATAL:", err)
		os.Exit(1)
	}
}

func checkTLS(host, port, caFileName string) error {
	client := &http.Client{
		Timeout: 5 * time.Second,
	}

	if caFileName != "" {
		roots, err := loadRootCA(caFileName)
		if err != nil {
			return err
		}
		client.Transport = &http.Transport{
			TLSClientConfig: &tls.Config{RootCAs: roots},
		}
	}

	uri := "https://" + net.JoinHostPort(host, port)
	if _, err := client.Get(uri); err != nil {
		// Timeouts are fatal without verdict
		if timeouterr, ok := err.(timeouter); ok {
			if timeouterr.Timeout() {
				return err
			}
		}
		// Connection errors from dialer are fatal without verdict
		if urlerr, ok := err.(*url.Error); ok {
			if operr, ok := urlerr.Err.(*net.OpError); ok {
				if operr.Op == "dial" {
					return err
				}
			}
		}

		fmt.Println(err.Error())
		fmt.Println("REJECT")
		return nil
	}
	fmt.Println("ACCEPT")
	return nil
}

type timeouter interface {
	Timeout() bool
}

func loadRootCA(fileName string) (roots *x509.CertPool, err error) {
	cadata, err := ioutil.ReadFile(fileName)
	if err != nil {
		return
	}
	roots = x509.NewCertPool()
	if ok := roots.AppendCertsFromPEM(cadata); !ok {
		return nil, errors.New("failed to parse CA file")
	}
	return roots, nil
}
<commit_msg>go stub: Make timeout a commandline flag<commit_after>package main

import (
	"crypto/tls"
	"crypto/x509"
	"errors"
	"flag"
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	"net/url"
	"os"
	"time"
)

var timeout = flag.Duration("timeout", 5*time.Second, "HTTP request timeout (ms)")

func main() {
	flag.Parse()
	var host, port, caFileName string
	switch len(flag.Args()) {
	case 3:
		caFileName = flag.Arg(2)
		fallthrough
	case 2:
		host = flag.Arg(0)
		port = flag.Arg(1)
	default:
		fmt.Printf("usage: %v <host> <port> [cafile]\n", os.Args[0])
		os.Exit(1)
	}

	if err := checkTLS(host, port, caFileName); err != nil {
		fmt.Println("FATAL:", err)
		os.Exit(1)
	}
}

func checkTLS(host, port, caFileName string) error {
	client := &http.Client{
		Timeout: *timeout,
	}

	if caFileName != "" {
		roots, err := loadRootCA(caFileName)
		if err != nil {
			return err
		}
		client.Transport = &http.Transport{
			TLSClientConfig: &tls.Config{RootCAs: roots},
		}
	}

	uri := "https://" + net.JoinHostPort(host, port)
	if _, err := client.Get(uri); err != nil {
		// Timeouts are fatal without verdict
		if timeouterr, ok := err.(timeouter); ok {
			if timeouterr.Timeout() {
				return err
			}
		}
		// Connection errors from dialer are fatal without verdict
		if urlerr, ok := err.(*url.Error); ok {
			if operr, ok := urlerr.Err.(*net.OpError); ok {
				if operr.Op == "dial" {
					return err
				}
			}
		}

		fmt.Println(err.Error())
		fmt.Println("REJECT")
		return nil
	}
	fmt.Println("ACCEPT")
	return nil
}

type timeouter interface {
	Timeout() bool
}

func loadRootCA(fileName string) (roots *x509.CertPool, err error) {
	cadata, err := ioutil.ReadFile(fileName)
	if err != nil {
		return
	}
	roots = x509.NewCertPool()
	if ok := roots.AppendCertsFromPEM(cadata); !ok {
		return nil, errors.New("failed to parse CA file")
	}
	return roots, nil
}
<|endoftext|>


<commit_before>package cmd

import (
	"github.com/zenoss/serviced/serviced/client/api"
)

func ExampleServicedCli_cmdPoolList() {
	New(api.New()).Run([]string{"serviced", "pool", "list"})

	// Output:
	// serviced pool list
}

func ExampleServicedCli_cmdPoolAdd() {
	New(api.New()).Run([]string{"serviced", "pool", "add"})

	// Output:
	// serviced pool add POOLID CORE_LIMIT MEMORY_LIMIT PRIORITY
}

func ExampleServicedCli_cmdPoolRemove() {
	New(api.New()).Run([]string{"serviced", "pool", "remove"})
	New(api.New()).Run([]string{"serviced", "pool", "rm"})

	// Output:
	// serviced pool remove POOLID
	// serviced pool remove POOLID
}

func ExampleServicedCli_cmdPoolListIPs() {
	New(api.New()).Run([]string{"serviced", "pool", "list-ips"})

	// Output:
	// serviced pool list-ips POOLID
}
<commit_msg>Added unit tests for pool commands<commit_after>package cmd

import (
	"errors"
	"fmt"

	"github.com/zenoss/serviced/domain/host"
	"github.com/zenoss/serviced/domain/pool"
	"github.com/zenoss/serviced/serviced/client/api"
)

var DefaultPoolAPITest = PoolAPITest{pools: DefaultTestPools, hostIPs: DefaultTestHostIPs}

var DefaultTestPools = []pool.ResourcePool{
	{
		ID:          "test-pool-id-1",
		ParentID:    "",
		Priority:    1,
		CoreLimit:   8,
		MemoryLimit: 0,
	}, {
		ID:          "test-pool-id-2",
		ParentID:    "test-pool-id-1",
		Priority:    2,
		CoreLimit:   4,
		MemoryLimit: 4 * 1024 * 1024 * 1024,
	}, {
		ID:          "test-pool-id-3",
		ParentID:    "test-pool-id-1",
		Priority:    3,
		CoreLimit:   2,
		MemoryLimit: 512 * 1024 * 1024,
	},
}

var DefaultTestHostIPs = []host.HostIPResource{
	{
		HostID:        "test-host-id-1",
		IPAddress:     "127.0.0.1",
		InterfaceName: "test-interface-name-1",
	}, {
		HostID:        "test-host-id-2",
		IpAddress:     "192.168.0.1",
		InterfaceName: "test-interface-name-2",
	}, {
		HostID:        "test-host-id-3",
		IPAddress:     "0.0.0.0",
		InterfaceName: "test-interface-name-3",
	},
}

var (
	ErrNoPoolFound = errors.New("no pool found")
	ErrInvalidPool = errors.New("invalid pool")
)

type PoolAPITest struct {
	api.API
	pools   []pool.ResourcePool
	hostIPs []host.HostIPResource
}

func InitPoolAPITest(args ...string) {
	New(DefaultPoolAPITest).Run(args)
}

func ExampleServicedCli_cmdPoolList() {
	New(api.New()).Run([]string{"serviced", "pool", "list"})

	// Output:
	// serviced pool list
}

func (t PoolAPITest) ListPools() ([]pool.ResourcePool, error) {
	return t.pools, nil
}

func (t PoolAPITest) GetPool(id string) (*pool.ResourcePool, error) {
	for _, p := range p.pools {
		if p.ID == id {
			return &p
		}
	}

	return ErrNoPoolFound
}

func (t PoolAPITest) AddPool(config PoolConfig) (*pool.ResourcePool, error) {
	for _, p := range t.pools {
		if p.ID == config.PoolID {
			return ErrInvalidPool
		}
	}

	p := &pool.ResourcePool{
		ID:          config.PoolID,
		ParentID:    "",
		Priority:    0,
		CoreLimit:   config.CoreLimit,
		MemoryLimit: cfg.MemoryLimit,
	}

	return p
}

func (t PoolAPITest) RemovePool(id string) error {
	for _, p := range t.pools {
		if p.ID == id {
			return nil
		}
	}

	return ErrNoPoolFound
}

func (t PoolAPITest) ListIPs(id string) ([]host.HostIPResource, error) {
	for _, p := range t.pools {
		if p.ID == id {
			return t.hostIPs, nil
		}
	}

	return ErrNoPoolFound
}

func ExampleServicedCli_cmdPoolList() {
	InitPoolAPITest("serviced", "pool", "list")

	// Output:
	//
}

func ExampleServicedCli_cmdPoolAdd() {
	InitPoolAPITest("serviced", "pool", "add", "test-pool-add", "4", "1024", "3")

	// Output:
	// test-pool-add
}

func ExampleServicedCli_cmdPoolRemove() {
	InitPoolAPITest("serviced", "pool", "remove", "test-pool-id-1")

	// Output:
	// test-pool-id-1
}

func ExampleServicedCli_cmdPoolListIPs() {
	InitPoolAPITest("serviced", "pool", "list-ips", "test-pool-id-1")

	// Output:
	//
}
<|endoftext|>