<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": &schema.Schema{
			//   Type:     schema.TypeString,
			//   Description: "The class associated to the vlan.",
			//   Optional: true,
			//   ForceNew: false,
			//   Default:  "",
			// },
			// "class_parameters": &schema.Schema{
			//   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))
		//parameters.Add("hostdev_class_name", d.Get("class").(string))
		//parameters.Add("hostdev_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_vlan_id", d.Get("vlan_id").(string))
	parameters.Add("vlmvlan_name", d.Get("name").(string))
	//parameters.Add("hostdev_class_name", d.Get("class").(string))
	//parameters.Add("hostdev_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)
			//d.Set("class",buf[0]["hostdev_class_name"].(string))

			// Updating local class_parameters
			//currentClassParameters := d.Get("class_parameters").(map[string]interface{})
			//retrievedClassParameters, _ := url.ParseQuery(buf[0]["hostdev_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)

			//d.Set("class",buf[0]["hostdev_class_name"].(string))

			// Updating local class_parameters
			//currentClassParameters := d.Get("class_parameters").(map[string]interface{})
			//retrievedClassParameters, _ := url.ParseQuery(buf[0]["hostdev_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>Adding support for vlan class_parameter starting with SOLIDserver 7.3.0<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{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_vlan_id", d.Get("vlan_id").(string))
	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 main

import (
	"fmt"
)

func main() {
	fmt.Printf("[hello log]\n")
	var log Log
	err := log.Init()
	if err != nil {
		return
	}
	log, err = NewLog()
	if err != nil {
		return
	}
	fmt.Printf("[log = %#v]\n", log)
	//log.Write(LOG_DEBUG, "hellvo lua:\n")
	//log.Write(LOG_DEBUG, "hellvo lua:%s\n", "sdjfld")
	log.Write(LOG_DEBUG, "hellvo lua:")
	log.Write(LOG_DEBUG, "hellvo lua:%s", "sdjfld")
	log.Flush()
	return
}
<commit_msg>Delete main.go<commit_after><|endoftext|>


<commit_before>package processors

import (
	"fmt"
	"os"

	"github.com/nanobox-io/nanobox/commands/registry"
	"github.com/nanobox-io/nanobox/models"
	"github.com/nanobox-io/nanobox/processors/env"
	"github.com/nanobox-io/nanobox/processors/provider"
	"github.com/nanobox-io/nanobox/processors/server"
	"github.com/nanobox-io/nanobox/util"
	"github.com/nanobox-io/nanobox/util/config"
	"github.com/nanobox-io/nanobox/util/display"
	util_provider "github.com/nanobox-io/nanobox/util/provider"
)

// Implode destroys the provider and cleans nanobox off of the system
func Implode() error {

	display.OpenContext("Imploding Nanobox")
	defer display.CloseContext()

	// remove all environments
	envModels, _ := models.AllEnvs()
	for _, envModel := range envModels {
		// remove all environments
		if err := env.Destroy(envModel); err != nil {
			fmt.Printf("unable to remove mounts: %s", err)
		}
	}

	// destroy the provider
	if err := provider.Destroy(); err != nil {
		return util.ErrorAppend(err, "failed to destroy the provider")
	}

	// destroy the provider (VM), remove images, remove containers
	if err := util_provider.Implode(); err != nil {
		return util.ErrorAppend(err, "failed to implode the provider")
	}

	// check to see if we need to uninstall nanobox
	// or just remove apps
	if registry.GetBool("full-implode") {

		// teardown the server
		if err := server.Teardown(); err != nil {
			return util.ErrorAppend(err, "failed to remove server")
		}

		purgeConfiguration()
	}

	return nil
}

// purges the config data and dns entries
func purgeConfiguration() error {

	display.StartTask("Purging configuration")
	defer display.StopTask()

	// implode the global dir
	if err := os.RemoveAll(config.GlobalDir()); err != nil {
		return util.ErrorAppend(util.ErrorQuiet(err), "failed to purge the data directory")
	}

	return nil
}
<commit_msg>remove server shut down errors when the server doesnt exist<commit_after>package processors

import (
	"fmt"
	"os"

	"github.com/nanobox-io/nanobox/commands/registry"
	"github.com/nanobox-io/nanobox/models"
	"github.com/nanobox-io/nanobox/processors/env"
	"github.com/nanobox-io/nanobox/processors/provider"
	"github.com/nanobox-io/nanobox/processors/server"
	"github.com/nanobox-io/nanobox/util"
	"github.com/nanobox-io/nanobox/util/config"
	"github.com/nanobox-io/nanobox/util/display"
	util_provider "github.com/nanobox-io/nanobox/util/provider"
)

// Implode destroys the provider and cleans nanobox off of the system
func Implode() error {

	display.OpenContext("Imploding Nanobox")
	defer display.CloseContext()

	// remove all environments
	envModels, _ := models.AllEnvs()
	for _, envModel := range envModels {
		// remove all environments
		if err := env.Destroy(envModel); err != nil {
			fmt.Printf("unable to remove mounts: %s", err)
		}
	}

	// destroy the provider
	if err := provider.Destroy(); err != nil {
		return util.ErrorAppend(err, "failed to destroy the provider")
	}

	// destroy the provider (VM), remove images, remove containers
	if err := util_provider.Implode(); err != nil {
		return util.ErrorAppend(err, "failed to implode the provider")
	}

	// check to see if we need to uninstall nanobox
	// or just remove apps
	if registry.GetBool("full-implode") {

		// teardown the server
		if err := server.Teardown(); err != nil {
			// if we cant tear down the server dont worry about it
			// return util.ErrorAppend(err, "failed to remove server")
		}

		purgeConfiguration()
	}

	return nil
}

// purges the config data and dns entries
func purgeConfiguration() error {

	display.StartTask("Purging configuration")
	defer display.StopTask()

	// implode the global dir
	if err := os.RemoveAll(config.GlobalDir()); err != nil {
		return util.ErrorAppend(util.ErrorQuiet(err), "failed to purge the data directory")
	}

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"github.com/hashicorp/consul/api"
	"github.com/nsqio/go-nsq"
	"io"
	"log"
	"os"
	"strings"
	"time"
)

type message struct {
	topic string
	body  [][]byte
}

type LogTask struct {
	Writer        *nsq.Producer
	LogStat       map[string]chan int
	CurrentConfig map[string]string
	Setting       map[string]string
	msgChan       chan *message
	client        *api.Client
	exitChan      chan int
}

func (m *LogTask) Run() {
	m.exitChan = make(chan int)
	m.msgChan = make(chan *message)
	ticker := time.Tick(time.Second * 600)
	config := api.DefaultConfig()
	config.Address = m.Setting["consul_address"]
	config.Datacenter = m.Setting["datacenter"]
	config.Token = m.Setting["consul_token"]
	var err error
	m.client, err = api.NewClient(config)
	if err != nil {
		fmt.Println("reload consul setting failed", err)
	}
	err = m.CheckReload()
	if err != nil {
		fmt.Println("reload consul setting failed", err)
	}
	for {
		select {
		case <-ticker:
			err = m.CheckReload()
			if err != nil {
				fmt.Println("reload consul setting failed", err)
			}
		case <-m.exitChan:
			return
		}
	}
}
func (m *LogTask) Stop() {
	close(m.exitChan)
	for _, v := range m.LogStat {
		close(v)
	}
	m.Writer.Stop()
}
func (m *LogTask) ReadConfigFromConsul() (map[string]string, error) {
	consulSetting := make(map[string]string)
	kv := m.client.KV()
	pairs, _, err := kv.List(m.Setting["cluster"], nil)
	if err != nil {
		return consulSetting, err
	}
	size := len(m.Setting["cluster"]) + 1
	for _, value := range pairs {
		if len(value.Key) > size {
			consulSetting[value.Key[size:]] = string(value.Value)
		}
	}
	return consulSetting, err

}
func (m *LogTask) CheckReload() error {
	newConf, err := m.ReadConfigFromConsul()
	if err != nil {
		return err
	}
	for k, _ := range newConf {
		if m.CurrentConfig[k] != newConf[k] {
			if len(m.CurrentConfig[k]) > 0 {
				close(m.LogStat[k])
				delete(m.LogStat, k)
				delete(m.CurrentConfig, k)
			}
			if len(newConf[k]) > 0 {
				fileNames := strings.Split(newConf[k], ",")
				m.LogStat[k] = make(chan int)
				for _, fileName := range fileNames {
					go m.WriteLoop(m.LogStat[k])
					go m.ReadLog(fileName, k, m.LogStat[k])
				}
			}
		}
	}
	for k, _ := range m.CurrentConfig {
		if m.CurrentConfig[k] != newConf[k] {
			if len(newConf[k]) == 0 {
				close(m.LogStat[k])
				delete(m.LogStat, k)
			}
		}
	}
	m.CurrentConfig = newConf
	return nil
}

func (m *LogTask) ReadLog(file string, topic string, exitchan chan int) {
	fd, err := os.Open(file)
	if err != nil {
		log.Println(err)
		return
	}
	defer fd.Close()
	_, err = fd.Seek(0, os.SEEK_END)
	if err != nil {
		return
	}
	log.Println("reading ", file)
	reader := bufio.NewReader(fd)
	var body [][]byte
	for {
		select {
		case <-exitchan:
			return
		default:
			line, err := reader.ReadString('\n')
			if err != nil {
				time.Sleep(time.Second)
				line, err = reader.ReadString('\n')
			}
			if err == io.EOF {
				log.Println(file, "READ EOF")
				size0, err := fd.Seek(0, os.SEEK_CUR)
				if err != nil {
					return
				}
				fd, err = os.Open(file)
				if err != nil {
					log.Println("open failed", err)
					return
				}
				size1, err := fd.Seek(0, os.SEEK_END)
				if err != nil {
					log.Println(err)
				}
				if size1 < size0 {
					fd.Seek(0, os.SEEK_SET)
				} else {
					fd.Seek(size0, os.SEEK_SET)
				}
				reader = bufio.NewReader(fd)
				continue
			}
			if err != nil {
				log.Println(err)
				return
			}
			body = append(body, []byte(line))
			if len(body) > 100 {
				msg := &message{
					topic: topic,
					body:  body,
				}
				m.msgChan <- msg
				body = body[:0]
			}
		}
	}
}

func (m *LogTask) WriteLoop(exitchan chan int) {
	for {
		select {
		case <-m.exitChan:
			return
		case <-exitchan:
			return
		case msg := <-m.msgChan:
			m.Writer.MultiPublish(msg.topic, msg.body)
		}
	}
}
<commit_msg>add option to read all setting<commit_after>package main

import (
	"bufio"
	"fmt"
	"github.com/hashicorp/consul/api"
	"github.com/nsqio/go-nsq"
	"io"
	"log"
	"os"
	"strings"
	"time"
)

type message struct {
	topic string
	body  [][]byte
}

type LogTask struct {
	Writer        *nsq.Producer
	LogStat       map[string]chan int
	CurrentConfig map[string]string
	Setting       map[string]string
	msgChan       chan *message
	client        *api.Client
	exitChan      chan int
}

func (m *LogTask) Run() {
	m.exitChan = make(chan int)
	m.msgChan = make(chan *message)
	ticker := time.Tick(time.Second * 600)
	config := api.DefaultConfig()
	config.Address = m.Setting["consul_address"]
	config.Datacenter = m.Setting["datacenter"]
	config.Token = m.Setting["consul_token"]
	var err error
	m.client, err = api.NewClient(config)
	if err != nil {
		fmt.Println("reload consul setting failed", err)
	}
	err = m.CheckReload()
	if err != nil {
		fmt.Println("reload consul setting failed", err)
	}
	for {
		select {
		case <-ticker:
			err = m.CheckReload()
			if err != nil {
				fmt.Println("reload consul setting failed", err)
			}
		case <-m.exitChan:
			return
		}
	}
}
func (m *LogTask) Stop() {
	close(m.exitChan)
	for _, v := range m.LogStat {
		close(v)
	}
	m.Writer.Stop()
}
func (m *LogTask) ReadConfigFromConsul() (map[string]string, error) {
	consulSetting := make(map[string]string)
	kv := m.client.KV()
	pairs, _, err := kv.List(m.Setting["cluster"], nil)
	if err != nil {
		return consulSetting, err
	}
	size := len(m.Setting["cluster"]) + 1
	for _, value := range pairs {
		if len(value.Key) > size {
			consulSetting[value.Key[size:]] = string(value.Value)
		}
	}
	return consulSetting, err

}
func (m *LogTask) CheckReload() error {
	newConf, err := m.ReadConfigFromConsul()
	if err != nil {
		return err
	}
	for k, _ := range newConf {
		if m.CurrentConfig[k] != newConf[k] {
			if len(m.CurrentConfig[k]) > 0 {
				close(m.LogStat[k])
				delete(m.LogStat, k)
				delete(m.CurrentConfig, k)
			}
			if len(newConf[k]) > 0 {
				fileNames := strings.Split(newConf[k], ",")
				m.LogStat[k] = make(chan int)
				for _, fileName := range fileNames {
					go m.WriteLoop(m.LogStat[k])
					go m.ReadLog(fileName, k, m.LogStat[k])
				}
			}
		}
	}
	for k, _ := range m.CurrentConfig {
		if m.CurrentConfig[k] != newConf[k] {
			if len(newConf[k]) == 0 {
				close(m.LogStat[k])
				delete(m.LogStat, k)
			}
		}
	}
	m.CurrentConfig = newConf
	return nil
}

func (m *LogTask) ReadLog(file string, topic string, exitchan chan int) {
	fd, err := os.Open(file)
	if err != nil {
		log.Println(err)
		return
	}
	defer fd.Close()
	if len(m.Setting["read_all"]) == 0 {
		_, err = fd.Seek(0, os.SEEK_END)
		if err != nil {
			return
		}
	}
	log.Println("reading ", file)
	reader := bufio.NewReader(fd)
	var body [][]byte
	for {
		select {
		case <-exitchan:
			return
		default:
			line, err := reader.ReadString('\n')
			if err != nil {
				time.Sleep(time.Second)
				line, err = reader.ReadString('\n')
			}
			if err == io.EOF {
				log.Println(file, "READ EOF")
				size0, err := fd.Seek(0, os.SEEK_CUR)
				if err != nil {
					return
				}
				fd, err = os.Open(file)
				if err != nil {
					log.Println("open failed", err)
					return
				}
				size1, err := fd.Seek(0, os.SEEK_END)
				if err != nil {
					log.Println(err)
				}
				if size1 < size0 {
					fd.Seek(0, os.SEEK_SET)
				} else {
					fd.Seek(size0, os.SEEK_SET)
				}
				reader = bufio.NewReader(fd)
				continue
			}
			if err != nil {
				log.Println(err)
				return
			}
			body = append(body, []byte(line))
			if len(body) > 100 {
				msg := &message{
					topic: topic,
					body:  body,
				}
				m.msgChan <- msg
				body = body[:0]
			}
		}
	}
}

func (m *LogTask) WriteLoop(exitchan chan int) {
	for {
		select {
		case <-m.exitChan:
			return
		case <-exitchan:
			return
		case msg := <-m.msgChan:
			m.Writer.MultiPublish(msg.topic, msg.body)
		}
	}
}
<|endoftext|>


<commit_before>package dns

// Everything is assumed in the ClassINET class. If
// you need other classes you are on your own.

// SetReply creates a reply packet from a request message.
func (dns *Msg) SetReply(request *Msg) {
	dns.MsgHdr.Id = request.MsgHdr.Id
	dns.MsgHdr.Authoritative = true
	dns.MsgHdr.Response = true
	dns.MsgHdr.Opcode = OpcodeQuery
	dns.MsgHdr.Rcode = RcodeSuccess
	dns.Question = make([]Question, 1)
	dns.Question[0] = request.Question[0]
}

// SetQuestion creates a question packet.
func (dns *Msg) SetQuestion(z string, t uint16) {
	dns.MsgHdr.Id = Id()
	dns.MsgHdr.RecursionDesired = true
	dns.Question = make([]Question, 1)
	dns.Question[0] = Question{z, t, ClassINET}
}

// SetNotify creates a notify packet.
func (dns *Msg) SetNotify(z string) {
	dns.MsgHdr.Opcode = OpcodeNotify
	dns.MsgHdr.Authoritative = true
	dns.MsgHdr.Id = Id()
	dns.Question = make([]Question, 1)
	dns.Question[0] = Question{z, TypeSOA, ClassINET}
}

// SetRcode creates an error packet.
func (dns *Msg) SetRcode(request *Msg, rcode int) {
	dns.MsgHdr.Rcode = rcode
	dns.MsgHdr.Opcode = OpcodeQuery
	dns.MsgHdr.Response = true
	dns.MsgHdr.Authoritative = false
	dns.MsgHdr.Id = request.MsgHdr.Id
	dns.Question = make([]Question, 1)
	dns.Question[0] = request.Question[0]
}

// SetRcodeFormatError creates a packet with FormError set.
func (dns *Msg) SetRcodeFormatError(request *Msg) {
	dns.MsgHdr.Rcode = RcodeFormatError
	dns.MsgHdr.Opcode = OpcodeQuery
	dns.MsgHdr.Response = true
	dns.MsgHdr.Authoritative = false
	dns.MsgHdr.Id = request.MsgHdr.Id
}

// SetUpdate makes the message a dynamic update packet. It
// sets the ZONE section to: z, TypeSOA, classINET.
func (dns *Msg) SetUpdate(z string) {
        return NewUpdate(z, ClassINET)
}

// SetIxfr creates dns msg suitable for requesting an ixfr.
func (dns *Msg) SetIxfr(z string, serial uint32) {
	dns.MsgHdr.Id = Id()
	dns.Question = make([]Question, 1)
	dns.Ns = make([]RR, 1)
	s := new(RR_SOA)
	s.Hdr = RR_Header{z, TypeSOA, ClassINET, DefaultTtl, 0}
	s.Serial = serial

	dns.Question[0] = Question{z, TypeIXFR, ClassINET}
	dns.Ns[0] = s
}

// SetAxfr creates dns msg suitable for requesting an axfr.
func (dns *Msg) SetAxfr(z string) {
	dns.MsgHdr.Id = Id()
	dns.Question = make([]Question, 1)
	dns.Question[0] = Question{z, TypeAXFR, ClassINET}
}

// SetTsig appends a TSIG RR to the message.
// This is only a skeleton Tsig RR that is added as the last RR in the
// additional section. The caller should then call TsigGenerate,
// to generate the complete TSIG with the secret.
func (dns *Msg) SetTsig(z, algo string, fudge uint16, timesigned uint64) {
	t := new(RR_TSIG)
	t.Hdr = RR_Header{z, TypeTSIG, ClassANY, 0, 0}
	t.Algorithm = algo
	t.Fudge = 300
	t.TimeSigned = timesigned
	dns.Extra = append(dns.Extra, t)
}

// SetEdns0 appends a EDNS0 OPT RR to the message.
// TSIG should always the last RR in a message.
func (dns *Msg) SetEdns0(udpsize uint16, do bool) {
	e := new(RR_OPT)
	e.Hdr.Name = "."
	e.Hdr.Rrtype = TypeOPT
	e.SetUDPSize(udpsize)
	if do {
		e.SetDo()
	}
	dns.Extra = append(dns.Extra, e)
}

// IsRcode checks if the header of the packet has rcode set.
func (dns *Msg) IsRcode(rcode int) (ok bool) {
	if len(dns.Question) == 0 {
		return false
	}
	ok = dns.MsgHdr.Rcode == rcode
	return
}

// IsQuestion returns true if the packet is a question.
func (dns *Msg) IsQuestion() (ok bool) {
	if len(dns.Question) == 0 {
		return false
	}
	ok = dns.MsgHdr.Response == false
	return
}

// IsRcodeFormatError checks if the message has FormErr set.
func (dns *Msg) IsRcodeFormatError() (ok bool) {
	if len(dns.Question) == 0 {
		return false
	}
	ok = dns.MsgHdr.Rcode == RcodeFormatError
	return
}

// IsUpdate checks if the message is a dynamic update packet.
func (dns *Msg) IsUpdate() (ok bool) {
	if len(dns.Question) == 0 {
		return false
	}
	ok = dns.MsgHdr.Opcode == OpcodeUpdate
	ok = ok && dns.Question[0].Qtype == TypeSOA
	return
}

// IsNotify checks if the message is a valid notify packet.
func (dns *Msg) IsNotify() (ok bool) {
	if len(dns.Question) == 0 {
		return false
	}
	ok = dns.MsgHdr.Opcode == OpcodeNotify
	ok = ok && dns.Question[0].Qclass == ClassINET
	ok = ok && dns.Question[0].Qtype == TypeSOA
	return
}

// IsAxfr checks if the message is a valid axfr request packet.
func (dns *Msg) IsAxfr() (ok bool) {
	if len(dns.Question) == 0 {
		return false
	}
	ok = dns.MsgHdr.Opcode == OpcodeQuery
	ok = ok && dns.Question[0].Qclass == ClassINET
	ok = ok && dns.Question[0].Qtype == TypeAXFR
	return
}

// IsIXfr checks if the message is a valid ixfr request packet.
func (dns *Msg) IsIxfr() (ok bool) {
	if len(dns.Question) == 0 {
		return false
	}
	ok = dns.MsgHdr.Opcode == OpcodeQuery
	ok = ok && dns.Question[0].Qclass == ClassINET
	ok = ok && dns.Question[0].Qtype == TypeIXFR
	return
}

// IsTsig checks if the message has a TSIG record as the last record
// in the additional section.
func (dns *Msg) IsTsig() (ok bool) {
	if len(dns.Extra) > 0 {
		return dns.Extra[len(dns.Extra)-1].Header().Rrtype == TypeTSIG
	}
	return
}

// IsEdns0 checks if the message has a Edns0 record, any EDNS0
// record in the additional section will do
func (dns *Msg) IsEdns0() (ok bool) {
	for _, r := range dns.Extra {
		if r.Header().Rrtype == TypeOPT {
			return true
		}
	}
	return
}

// IsDomainName checks if s is a valid domainname, it returns
// the number of labels and true, when a domain name is valid. When false
// the returned labelcount isn't specified.
func IsDomainName(s string) (uint8, bool) { // copied from net package.
	// See RFC 1035, RFC 3696.
	if len(s) == 0 {
		return 0, false
	}
	if len(s) > 255 { // Not true...?
		return 0, false
	}
	s = Fqdn(s) // simplify checking loop: make name end in dot
	last := byte('.')
	ok := false // ok once we've seen a letter
	partlen := 0
	labels := uint8(0)
	for i := 0; i < len(s); i++ {
		c := s[i]
		switch {
		default:
			return 0, false
		case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || c == '_' || c == '*':
			ok = true
			partlen++
		case c == '\\':
			// Ok
		case '0' <= c && c <= '9':
			// fine
			partlen++
		case c == '-':
			// byte before dash cannot be dot
			if last == '.' {
				return 0, false
			}
			partlen++
		case c == '.':
			// byte before dot cannot be dot, dash
			if last == '.' || last == '-' {
				return 0, false
			}
			if last == '\\' { // Ok, escaped dot.
				partlen++
				break
			}
			if partlen > 63 || partlen == 0 {
				return 0, false
			}
			partlen = 0
			labels++
		}
		last = c
	}

	return labels, ok
}

// IsFqdn checks if a domain name is fully qualified
func IsFqdn(s string) bool {
	if len(s) == 0 {
		return false // ?
	}
	return s[len(s)-1] == '.'
}

// Fqdns return the fully qualified domain name from s.
// Is s is already fq, then it behaves as the identity function.
func Fqdn(s string) string {
	if IsFqdn(s) {
		return s
	}
	return s + "."
}
<commit_msg>Doesnt return anything<commit_after>package dns

// Everything is assumed in the ClassINET class. If
// you need other classes you are on your own.

// SetReply creates a reply packet from a request message.
func (dns *Msg) SetReply(request *Msg) {
	dns.MsgHdr.Id = request.MsgHdr.Id
	dns.MsgHdr.Authoritative = true
	dns.MsgHdr.Response = true
	dns.MsgHdr.Opcode = OpcodeQuery
	dns.MsgHdr.Rcode = RcodeSuccess
	dns.Question = make([]Question, 1)
	dns.Question[0] = request.Question[0]
}

// SetQuestion creates a question packet.
func (dns *Msg) SetQuestion(z string, t uint16) {
	dns.MsgHdr.Id = Id()
	dns.MsgHdr.RecursionDesired = true
	dns.Question = make([]Question, 1)
	dns.Question[0] = Question{z, t, ClassINET}
}

// SetNotify creates a notify packet.
func (dns *Msg) SetNotify(z string) {
	dns.MsgHdr.Opcode = OpcodeNotify
	dns.MsgHdr.Authoritative = true
	dns.MsgHdr.Id = Id()
	dns.Question = make([]Question, 1)
	dns.Question[0] = Question{z, TypeSOA, ClassINET}
}

// SetRcode creates an error packet.
func (dns *Msg) SetRcode(request *Msg, rcode int) {
	dns.MsgHdr.Rcode = rcode
	dns.MsgHdr.Opcode = OpcodeQuery
	dns.MsgHdr.Response = true
	dns.MsgHdr.Authoritative = false
	dns.MsgHdr.Id = request.MsgHdr.Id
	dns.Question = make([]Question, 1)
	dns.Question[0] = request.Question[0]
}

// SetRcodeFormatError creates a packet with FormError set.
func (dns *Msg) SetRcodeFormatError(request *Msg) {
	dns.MsgHdr.Rcode = RcodeFormatError
	dns.MsgHdr.Opcode = OpcodeQuery
	dns.MsgHdr.Response = true
	dns.MsgHdr.Authoritative = false
	dns.MsgHdr.Id = request.MsgHdr.Id
}

// SetUpdate makes the message a dynamic update packet. It
// sets the ZONE section to: z, TypeSOA, classINET.
func (dns *Msg) SetUpdate(z string) {
       dns.MsgHdr.Id = Id()
       dns.MsgHdr.Opcode = OpcodeUpdate
       dns.Question = make([]Question, 1)
       dns.Question[0] = Question{z, TypeSOA, ClassINET}
}

// SetIxfr creates dns msg suitable for requesting an ixfr.
func (dns *Msg) SetIxfr(z string, serial uint32) {
	dns.MsgHdr.Id = Id()
	dns.Question = make([]Question, 1)
	dns.Ns = make([]RR, 1)
	s := new(RR_SOA)
	s.Hdr = RR_Header{z, TypeSOA, ClassINET, DefaultTtl, 0}
	s.Serial = serial

	dns.Question[0] = Question{z, TypeIXFR, ClassINET}
	dns.Ns[0] = s
}

// SetAxfr creates dns msg suitable for requesting an axfr.
func (dns *Msg) SetAxfr(z string) {
	dns.MsgHdr.Id = Id()
	dns.Question = make([]Question, 1)
	dns.Question[0] = Question{z, TypeAXFR, ClassINET}
}

// SetTsig appends a TSIG RR to the message.
// This is only a skeleton Tsig RR that is added as the last RR in the
// additional section. The caller should then call TsigGenerate,
// to generate the complete TSIG with the secret.
func (dns *Msg) SetTsig(z, algo string, fudge uint16, timesigned uint64) {
	t := new(RR_TSIG)
	t.Hdr = RR_Header{z, TypeTSIG, ClassANY, 0, 0}
	t.Algorithm = algo
	t.Fudge = 300
	t.TimeSigned = timesigned
	dns.Extra = append(dns.Extra, t)
}

// SetEdns0 appends a EDNS0 OPT RR to the message.
// TSIG should always the last RR in a message.
func (dns *Msg) SetEdns0(udpsize uint16, do bool) {
	e := new(RR_OPT)
	e.Hdr.Name = "."
	e.Hdr.Rrtype = TypeOPT
	e.SetUDPSize(udpsize)
	if do {
		e.SetDo()
	}
	dns.Extra = append(dns.Extra, e)
}

// IsRcode checks if the header of the packet has rcode set.
func (dns *Msg) IsRcode(rcode int) (ok bool) {
	if len(dns.Question) == 0 {
		return false
	}
	ok = dns.MsgHdr.Rcode == rcode
	return
}

// IsQuestion returns true if the packet is a question.
func (dns *Msg) IsQuestion() (ok bool) {
	if len(dns.Question) == 0 {
		return false
	}
	ok = dns.MsgHdr.Response == false
	return
}

// IsRcodeFormatError checks if the message has FormErr set.
func (dns *Msg) IsRcodeFormatError() (ok bool) {
	if len(dns.Question) == 0 {
		return false
	}
	ok = dns.MsgHdr.Rcode == RcodeFormatError
	return
}

// IsUpdate checks if the message is a dynamic update packet.
func (dns *Msg) IsUpdate() (ok bool) {
	if len(dns.Question) == 0 {
		return false
	}
	ok = dns.MsgHdr.Opcode == OpcodeUpdate
	ok = ok && dns.Question[0].Qtype == TypeSOA
	return
}

// IsNotify checks if the message is a valid notify packet.
func (dns *Msg) IsNotify() (ok bool) {
	if len(dns.Question) == 0 {
		return false
	}
	ok = dns.MsgHdr.Opcode == OpcodeNotify
	ok = ok && dns.Question[0].Qclass == ClassINET
	ok = ok && dns.Question[0].Qtype == TypeSOA
	return
}

// IsAxfr checks if the message is a valid axfr request packet.
func (dns *Msg) IsAxfr() (ok bool) {
	if len(dns.Question) == 0 {
		return false
	}
	ok = dns.MsgHdr.Opcode == OpcodeQuery
	ok = ok && dns.Question[0].Qclass == ClassINET
	ok = ok && dns.Question[0].Qtype == TypeAXFR
	return
}

// IsIXfr checks if the message is a valid ixfr request packet.
func (dns *Msg) IsIxfr() (ok bool) {
	if len(dns.Question) == 0 {
		return false
	}
	ok = dns.MsgHdr.Opcode == OpcodeQuery
	ok = ok && dns.Question[0].Qclass == ClassINET
	ok = ok && dns.Question[0].Qtype == TypeIXFR
	return
}

// IsTsig checks if the message has a TSIG record as the last record
// in the additional section.
func (dns *Msg) IsTsig() (ok bool) {
	if len(dns.Extra) > 0 {
		return dns.Extra[len(dns.Extra)-1].Header().Rrtype == TypeTSIG
	}
	return
}

// IsEdns0 checks if the message has a Edns0 record, any EDNS0
// record in the additional section will do
func (dns *Msg) IsEdns0() (ok bool) {
	for _, r := range dns.Extra {
		if r.Header().Rrtype == TypeOPT {
			return true
		}
	}
	return
}

// IsDomainName checks if s is a valid domainname, it returns
// the number of labels and true, when a domain name is valid. When false
// the returned labelcount isn't specified.
func IsDomainName(s string) (uint8, bool) { // copied from net package.
	// See RFC 1035, RFC 3696.
	if len(s) == 0 {
		return 0, false
	}
	if len(s) > 255 { // Not true...?
		return 0, false
	}
	s = Fqdn(s) // simplify checking loop: make name end in dot
	last := byte('.')
	ok := false // ok once we've seen a letter
	partlen := 0
	labels := uint8(0)
	for i := 0; i < len(s); i++ {
		c := s[i]
		switch {
		default:
			return 0, false
		case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || c == '_' || c == '*':
			ok = true
			partlen++
		case c == '\\':
			// Ok
		case '0' <= c && c <= '9':
			// fine
			partlen++
		case c == '-':
			// byte before dash cannot be dot
			if last == '.' {
				return 0, false
			}
			partlen++
		case c == '.':
			// byte before dot cannot be dot, dash
			if last == '.' || last == '-' {
				return 0, false
			}
			if last == '\\' { // Ok, escaped dot.
				partlen++
				break
			}
			if partlen > 63 || partlen == 0 {
				return 0, false
			}
			partlen = 0
			labels++
		}
		last = c
	}

	return labels, ok
}

// IsFqdn checks if a domain name is fully qualified
func IsFqdn(s string) bool {
	if len(s) == 0 {
		return false // ?
	}
	return s[len(s)-1] == '.'
}

// Fqdns return the fully qualified domain name from s.
// Is s is already fq, then it behaves as the identity function.
func Fqdn(s string) string {
	if IsFqdn(s) {
		return s
	}
	return s + "."
}
<|endoftext|>


<commit_before>package dns

import (
	"errors"
	"net"
	"strconv"
)

const hexDigit = "0123456789abcdef"

// Everything is assumed in ClassINET.

// SetReply creates a reply message from a request message.
func (dns *Msg) SetReply(request *Msg) *Msg {
	dns.Id = request.Id
	dns.RecursionDesired = request.RecursionDesired // Copy rd bit
	dns.Response = true
	dns.Opcode = OpcodeQuery
	dns.Rcode = RcodeSuccess
	if len(request.Question) > 0 {
		dns.Question = make([]Question, 1)
		dns.Question[0] = request.Question[0]
	}
	return dns
}

// SetQuestion creates a question message.
func (dns *Msg) SetQuestion(z string, t uint16) *Msg {
	dns.Id = Id()
	dns.RecursionDesired = true
	dns.Question = make([]Question, 1)
	dns.Question[0] = Question{z, t, ClassINET}
	return dns
}

// SetNotify creates a notify message.
func (dns *Msg) SetNotify(z string) *Msg {
	dns.Opcode = OpcodeNotify
	dns.Authoritative = true
	dns.Id = Id()
	dns.Question = make([]Question, 1)
	dns.Question[0] = Question{z, TypeSOA, ClassINET}
	return dns
}

// SetRcode creates an error message suitable for the request.
func (dns *Msg) SetRcode(request *Msg, rcode int) *Msg {
	dns.SetReply(request)
	dns.Rcode = rcode
	return dns
}

// SetRcodeFormatError creates a message with FormError set.
func (dns *Msg) SetRcodeFormatError(request *Msg) *Msg {
	dns.Rcode = RcodeFormatError
	dns.Opcode = OpcodeQuery
	dns.Response = true
	dns.Authoritative = false
	dns.Id = request.Id
	return dns
}

// SetUpdate makes the message a dynamic update message. It
// sets the ZONE section to: z, TypeSOA, ClassINET.
func (dns *Msg) SetUpdate(z string) *Msg {
	dns.Id = Id()
	dns.Response = false
	dns.Opcode = OpcodeUpdate
	dns.Compress = false // BIND9 cannot handle compression
	dns.Question = make([]Question, 1)
	dns.Question[0] = Question{z, TypeSOA, ClassINET}
	return dns
}

// SetIxfr creates message for requesting an IXFR.
func (dns *Msg) SetIxfr(z string, serial uint32) *Msg {
	dns.Id = Id()
	dns.Question = make([]Question, 1)
	dns.Ns = make([]RR, 1)
	s := new(SOA)
	s.Hdr = RR_Header{z, TypeSOA, ClassINET, defaultTtl, 0}
	s.Serial = serial
	dns.Question[0] = Question{z, TypeIXFR, ClassINET}
	dns.Ns[0] = s
	return dns
}

// SetAxfr creates message for requesting an AXFR.
func (dns *Msg) SetAxfr(z string) *Msg {
	dns.Id = Id()
	dns.Question = make([]Question, 1)
	dns.Question[0] = Question{z, TypeAXFR, ClassINET}
	return dns
}

// SetTsig appends a TSIG RR to the message.
// This is only a skeleton TSIG RR that is added as the last RR in the
// additional section. The Tsig is calculated when the message is being send.
func (dns *Msg) SetTsig(z, algo string, fudge, timesigned int64) *Msg {
	t := new(TSIG)
	t.Hdr = RR_Header{z, TypeTSIG, ClassANY, 0, 0}
	t.Algorithm = algo
	t.Fudge = 300
	t.TimeSigned = uint64(timesigned)
	t.OrigId = dns.Id
	dns.Extra = append(dns.Extra, t)
	return dns
}

// SetEdns0 appends a EDNS0 OPT RR to the message.
// TSIG should always the last RR in a message.
func (dns *Msg) SetEdns0(udpsize uint16, do bool) *Msg {
	e := new(OPT)
	e.Hdr.Name = "."
	e.Hdr.Rrtype = TypeOPT
	e.SetUDPSize(udpsize)
	if do {
		e.SetDo()
	}
	dns.Extra = append(dns.Extra, e)
	return dns
}

// IsTsig checks if the message has a TSIG record as the last record
// in the additional section. It returns the TSIG record found or nil.
func (dns *Msg) IsTsig() *TSIG {
	if len(dns.Extra) > 0 {
		if dns.Extra[len(dns.Extra)-1].Header().Rrtype == TypeTSIG {
			return dns.Extra[len(dns.Extra)-1].(*TSIG)
		}
	}
	return nil
}

// IsEdns0 checks if the message has a EDNS0 (OPT) record, any EDNS0
// record in the additional section will do. It returns the OPT record
// found or nil.
func (dns *Msg) IsEdns0() *OPT {
	for _, r := range dns.Extra {
		if r.Header().Rrtype == TypeOPT {
			return r.(*OPT)
		}
	}
	return nil
}

// IsDomainName checks if s is a valid domainname, it returns
// the number of labels and true, when a domain name is valid.
// Note that non fully qualified domain name is considered valid, in this case the
// last label is counted in the number of labels.
// When false is returned the number of labels is not defined.
func IsDomainName(s string) (labels int, ok bool) {
	_, labels, err := packDomainName(s, nil, 0, nil, false)
	return labels, err == nil
}

// IsSubDomain checks if child is indeed a child of the parent. Both child and
// parent are *not* downcased before doing the comparison.
func IsSubDomain(parent, child string) bool {
	// Entire child is contained in parent
	return CompareDomainName(parent, child) == CountLabel(parent)
}

// IsMsg sanity checks buf and returns an error if it isn't a valid DNS packet.
// The checking is performed on the binary payload.
func IsMsg(buf []byte) error {
	// Header
	if len(buf) < 12 {
		return errors.New("dns: bad message header")
	}
	// Header: Opcode
	// TODO(miek): more checks here, e.g. check all header bits.
	return nil
}

// IsFqdn checks if a domain name is fully qualified.
func IsFqdn(s string) bool {
	l := len(s)
	if l == 0 {
		return false
	}
	return s[l-1] == '.'
}

// Fqdns return the fully qualified domain name from s.
// If s is already fully qualified, it behaves as the identity function.
func Fqdn(s string) string {
	if IsFqdn(s) {
		return s
	}
	return s + "."
}

// Copied from the official Go code.

// ReverseAddr returns the in-addr.arpa. or ip6.arpa. hostname of the IP
// address suitable for reverse DNS (PTR) record lookups or an error if it fails
// to parse the IP address.
func ReverseAddr(addr string) (arpa string, err error) {
	ip := net.ParseIP(addr)
	if ip == nil {
		return "", &Error{err: "unrecognized address: " + addr}
	}
	if ip.To4() != nil {
		return strconv.Itoa(int(ip[15])) + "." + strconv.Itoa(int(ip[14])) + "." + strconv.Itoa(int(ip[13])) + "." +
			strconv.Itoa(int(ip[12])) + ".in-addr.arpa.", nil
	}
	// Must be IPv6
	buf := make([]byte, 0, len(ip)*4+len("ip6.arpa."))
	// Add it, in reverse, to the buffer
	for i := len(ip) - 1; i >= 0; i-- {
		v := ip[i]
		buf = append(buf, hexDigit[v&0xF])
		buf = append(buf, '.')
		buf = append(buf, hexDigit[v>>4])
		buf = append(buf, '.')
	}
	// Append "ip6.arpa." and return (buf already has the final .)
	buf = append(buf, "ip6.arpa."...)
	return string(buf), nil
}

// String returns the string representation for the type t.
func (t Type) String() string {
	if t1, ok := TypeToString[uint16(t)]; ok {
		return t1
	}
	return "TYPE" + strconv.Itoa(int(t))
}

// String returns the string representation for the class c.
func (c Class) String() string {
	if c1, ok := ClassToString[uint16(c)]; ok {
		return c1
	}
	return "CLASS" + strconv.Itoa(int(c))
}

// String returns the string representation for the name n.
func (n Name) String() string {
	return sprintName(string(n))
}
<commit_msg>Fix SetIxfr<commit_after>package dns

import (
	"errors"
	"net"
	"strconv"
)

const hexDigit = "0123456789abcdef"

// Everything is assumed in ClassINET.

// SetReply creates a reply message from a request message.
func (dns *Msg) SetReply(request *Msg) *Msg {
	dns.Id = request.Id
	dns.RecursionDesired = request.RecursionDesired // Copy rd bit
	dns.Response = true
	dns.Opcode = OpcodeQuery
	dns.Rcode = RcodeSuccess
	if len(request.Question) > 0 {
		dns.Question = make([]Question, 1)
		dns.Question[0] = request.Question[0]
	}
	return dns
}

// SetQuestion creates a question message.
func (dns *Msg) SetQuestion(z string, t uint16) *Msg {
	dns.Id = Id()
	dns.RecursionDesired = true
	dns.Question = make([]Question, 1)
	dns.Question[0] = Question{z, t, ClassINET}
	return dns
}

// SetNotify creates a notify message.
func (dns *Msg) SetNotify(z string) *Msg {
	dns.Opcode = OpcodeNotify
	dns.Authoritative = true
	dns.Id = Id()
	dns.Question = make([]Question, 1)
	dns.Question[0] = Question{z, TypeSOA, ClassINET}
	return dns
}

// SetRcode creates an error message suitable for the request.
func (dns *Msg) SetRcode(request *Msg, rcode int) *Msg {
	dns.SetReply(request)
	dns.Rcode = rcode
	return dns
}

// SetRcodeFormatError creates a message with FormError set.
func (dns *Msg) SetRcodeFormatError(request *Msg) *Msg {
	dns.Rcode = RcodeFormatError
	dns.Opcode = OpcodeQuery
	dns.Response = true
	dns.Authoritative = false
	dns.Id = request.Id
	return dns
}

// SetUpdate makes the message a dynamic update message. It
// sets the ZONE section to: z, TypeSOA, ClassINET.
func (dns *Msg) SetUpdate(z string) *Msg {
	dns.Id = Id()
	dns.Response = false
	dns.Opcode = OpcodeUpdate
	dns.Compress = false // BIND9 cannot handle compression
	dns.Question = make([]Question, 1)
	dns.Question[0] = Question{z, TypeSOA, ClassINET}
	return dns
}

// SetIxfr creates message for requesting an IXFR.
func (dns *Msg) SetIxfr(z string, serial uint32, ns, mbox string) *Msg {
	dns.Id = Id()
	dns.Question = make([]Question, 1)
	dns.Ns = make([]RR, 1)
	s := new(SOA)
	s.Hdr = RR_Header{z, TypeSOA, ClassINET, defaultTtl, 0}
	s.Serial = serial
	s.Ns = ns
	s.Mbox = mbox
	dns.Question[0] = Question{z, TypeIXFR, ClassINET}
	dns.Ns[0] = s
	return dns
}

// SetAxfr creates message for requesting an AXFR.
func (dns *Msg) SetAxfr(z string) *Msg {
	dns.Id = Id()
	dns.Question = make([]Question, 1)
	dns.Question[0] = Question{z, TypeAXFR, ClassINET}
	return dns
}

// SetTsig appends a TSIG RR to the message.
// This is only a skeleton TSIG RR that is added as the last RR in the
// additional section. The Tsig is calculated when the message is being send.
func (dns *Msg) SetTsig(z, algo string, fudge, timesigned int64) *Msg {
	t := new(TSIG)
	t.Hdr = RR_Header{z, TypeTSIG, ClassANY, 0, 0}
	t.Algorithm = algo
	t.Fudge = 300
	t.TimeSigned = uint64(timesigned)
	t.OrigId = dns.Id
	dns.Extra = append(dns.Extra, t)
	return dns
}

// SetEdns0 appends a EDNS0 OPT RR to the message.
// TSIG should always the last RR in a message.
func (dns *Msg) SetEdns0(udpsize uint16, do bool) *Msg {
	e := new(OPT)
	e.Hdr.Name = "."
	e.Hdr.Rrtype = TypeOPT
	e.SetUDPSize(udpsize)
	if do {
		e.SetDo()
	}
	dns.Extra = append(dns.Extra, e)
	return dns
}

// IsTsig checks if the message has a TSIG record as the last record
// in the additional section. It returns the TSIG record found or nil.
func (dns *Msg) IsTsig() *TSIG {
	if len(dns.Extra) > 0 {
		if dns.Extra[len(dns.Extra)-1].Header().Rrtype == TypeTSIG {
			return dns.Extra[len(dns.Extra)-1].(*TSIG)
		}
	}
	return nil
}

// IsEdns0 checks if the message has a EDNS0 (OPT) record, any EDNS0
// record in the additional section will do. It returns the OPT record
// found or nil.
func (dns *Msg) IsEdns0() *OPT {
	for _, r := range dns.Extra {
		if r.Header().Rrtype == TypeOPT {
			return r.(*OPT)
		}
	}
	return nil
}

// IsDomainName checks if s is a valid domainname, it returns
// the number of labels and true, when a domain name is valid.
// Note that non fully qualified domain name is considered valid, in this case the
// last label is counted in the number of labels.
// When false is returned the number of labels is not defined.
func IsDomainName(s string) (labels int, ok bool) {
	_, labels, err := packDomainName(s, nil, 0, nil, false)
	return labels, err == nil
}

// IsSubDomain checks if child is indeed a child of the parent. Both child and
// parent are *not* downcased before doing the comparison.
func IsSubDomain(parent, child string) bool {
	// Entire child is contained in parent
	return CompareDomainName(parent, child) == CountLabel(parent)
}

// IsMsg sanity checks buf and returns an error if it isn't a valid DNS packet.
// The checking is performed on the binary payload.
func IsMsg(buf []byte) error {
	// Header
	if len(buf) < 12 {
		return errors.New("dns: bad message header")
	}
	// Header: Opcode
	// TODO(miek): more checks here, e.g. check all header bits.
	return nil
}

// IsFqdn checks if a domain name is fully qualified.
func IsFqdn(s string) bool {
	l := len(s)
	if l == 0 {
		return false
	}
	return s[l-1] == '.'
}

// Fqdns return the fully qualified domain name from s.
// If s is already fully qualified, it behaves as the identity function.
func Fqdn(s string) string {
	if IsFqdn(s) {
		return s
	}
	return s + "."
}

// Copied from the official Go code.

// ReverseAddr returns the in-addr.arpa. or ip6.arpa. hostname of the IP
// address suitable for reverse DNS (PTR) record lookups or an error if it fails
// to parse the IP address.
func ReverseAddr(addr string) (arpa string, err error) {
	ip := net.ParseIP(addr)
	if ip == nil {
		return "", &Error{err: "unrecognized address: " + addr}
	}
	if ip.To4() != nil {
		return strconv.Itoa(int(ip[15])) + "." + strconv.Itoa(int(ip[14])) + "." + strconv.Itoa(int(ip[13])) + "." +
			strconv.Itoa(int(ip[12])) + ".in-addr.arpa.", nil
	}
	// Must be IPv6
	buf := make([]byte, 0, len(ip)*4+len("ip6.arpa."))
	// Add it, in reverse, to the buffer
	for i := len(ip) - 1; i >= 0; i-- {
		v := ip[i]
		buf = append(buf, hexDigit[v&0xF])
		buf = append(buf, '.')
		buf = append(buf, hexDigit[v>>4])
		buf = append(buf, '.')
	}
	// Append "ip6.arpa." and return (buf already has the final .)
	buf = append(buf, "ip6.arpa."...)
	return string(buf), nil
}

// String returns the string representation for the type t.
func (t Type) String() string {
	if t1, ok := TypeToString[uint16(t)]; ok {
		return t1
	}
	return "TYPE" + strconv.Itoa(int(t))
}

// String returns the string representation for the class c.
func (c Class) String() string {
	if c1, ok := ClassToString[uint16(c)]; ok {
		return c1
	}
	return "CLASS" + strconv.Itoa(int(c))
}

// String returns the string representation for the name n.
func (n Name) String() string {
	return sprintName(string(n))
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	//	"fmt"
	"crypto/sha512"
	"encoding/hex"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"strconv"
	"strings"
	"time"
)

//Image contains data we got from API that we are using to filter and fetch said image next
type Image struct {
	Imgid          int    `json:"id_number"`
	URL            string `json:"image"`
	Filename       string
	Score          int    `json:"score"`
	OriginalFormat string `json:"original_format"`
	Hashval        string `json:"sha512_hash"`
}

//Search returns to us array of searched images...
type Search struct {
	Images []Image `json:"search"`
}

//ImageCh is a channel of image data. You can put images into channel by parsing
//Derpibooru API by id(s) or  by tags and you can download images that are already
//in channel
type ImageCh chan Image

//Push gets unmarchalled JSON info, massages it and plugs it into channel so it
//would be processed in other places
func (imgchan ImageCh) push(dat Image) {
	dat.Filename = strconv.Itoa(dat.Imgid) + "." + dat.OriginalFormat
	dat.URL = "https:" + dat.URL
	if dat.OriginalFormat == "svg" {
		i := strings.LastIndex(dat.URL, ".")
		if i != -1 {
			dat.URL = dat.URL[:i] + ".svg" //Was afraid to extract things I needed from the date field, so extracting them from URL.
		}
	}
	imgchan <- dat
}

//ParseImg gets image IDs, fetches information about those images from Derpibooru and pushes them into the channel.
func (imgchan ImageCh) ParseImg() {

	for _, imgid := range opts.Args.IDs {
		source := "https://derpiboo.ru/images/" + strconv.Itoa(imgid) + ".json"
		if opts.Key != "" {
			source = source + "?key=" + opts.Key
		}

		log.Println("Getting image info at:", source)

		response, err := http.Get(source) //Getting our nice http response. Needs checking for 404 and other responses that are... less expected
		if err != nil {
			elog.Println(err)
			return
		}

		defer func() {
			err = response.Body.Close() //and not forgetting to close it when it's done
			if err != nil {
				elog.Fatalln("Could  not close server response")
			}
		}()
		var dat Image

		body, err := ioutil.ReadAll(response.Body) //stolen from official documentation
		if err != nil {
			elog.Println(err)
			return
		}

		if err := json.Unmarshal(body, &dat); //transforming json into native map

		err != nil {
			elog.Println(err)
			return
		}

		imgchan.push(dat)
	}

	close(imgchan) //closing channel, we are done here

	return
}

//DlImg reads image data from channel and downloads specified images to disc
func (imgchan ImageCh) DlImg() {

	log.Println("Worker started; reading channel") //nice notification that we are not forgotten

	hasher := sha512.New()

	for {

		imgdata, more := <-imgchan

		if !more { //checking that there is an image in channel
			done <- true //well, there is no images in channel, it means we got them all, so synchronization is kicking in and ending the process
			break        //Just in case, so it would not stupidly die when program finishes - it will die smartly
		}

		if imgdata.Filename == "" {
			elog.Println("Empty filename. Oops?") //something somewhere had gone wrong, not a cause to die, going to the next image
			continue
		}

		log.Println("Saving as", imgdata.Filename)

		func() { // To not hold all the files open when there is no need. All pointers to files are in the scope of this function.

			output, err := os.Create(opts.ImageDir + string(os.PathSeparator) + imgdata.Filename) //And now, THE FILE!
			if err != err {
				elog.Println("Error when creating file for image" + strconv.Itoa(imgdata.Imgid))
				elog.Println(err) //Either we got no permisson or no space, end of line
				return
			}
			defer func() {
				err = output.Close() //Not forgetting to deal with it after completing download
				if err != nil {
					elog.Fatalln("Could  not close downloaded file")
				}
			}()
			start := time.Now()

			response, err := http.Get(imgdata.URL)
			if err != nil {
				elog.Println("Error when getting image", imgdata.Imgid)
				elog.Println(err)
				return
			}
			defer func() {
				err = response.Body.Close() //Same, we shall not listen to the void when we finished getting image
				if err != nil {
					elog.Fatalln("Could  not close server response")
				}
			}()

			size, err := io.Copy(output, io.TeeReader(response.Body, hasher)) //	Writing things we got from Derpibooru into the file and into hasher
			if err != nil {
				elog.Println("Unable to write image on disk, id ", imgdata.Imgid)
				elog.Println(err)
				return
			}
			timed := time.Since(start).Seconds()

			hash := hex.EncodeToString(hasher.Sum(nil))

			if hash != imgdata.Hashval {
				elog.Println("Hash mismatch, got ", hash, " instead of ", imgdata.Hashval)
			}

			hasher.Reset()

			log.Printf("Downloaded %d bytes in %.2fs, speed %s/s\n", size, timed, fmtbytes(float64(size)/timed))
		}()

		//fmt.Println("\n", hex.EncodeToString(hash.Sum(nil)), "\n", imgdata.hash )

	}
}

//ParseTag gets image tags, fetches information about all images it could from Derpibooru and pushes them into the channel.
func (imgchan ImageCh) ParseTag() {

	source := "https://derpiboo.ru/search.json?q=" + opts.Tag //yay hardwiring url strings!

	if opts.Key != "" {
		source = source + "&key=" + opts.Key
	}

	log.Println("Searching as", source)

	for i := opts.StartPage; opts.StopPage == 0 || i <= opts.StopPage; i++ {
		//I suspect that all those returns could be dealt with in some way. But lazy.
		log.Println("Searching page", i)

		response, err := http.Get(source + "&page=" + strconv.Itoa(i))
		//Getting our nice http response. Needs checking for 404 and other responses that are... less expected

		defer func() {
			err = response.Body.Close() //and not forgetting to close it when it's done. And before we panic and die horribly.
			if err != nil {
				elog.Fatalln("Could  not close server response")
			}
		}()

		if err != nil {
			elog.Println("Error while getting search page", i)
			elog.Println(err)
			continue
		}

		var dats Search //Because we got array incoming instead of single object, we using an slive of maps!

		//fmt.Println(resp)

		body, err := ioutil.ReadAll(response.Body) //stolen from official documentation
		if err != nil {
			elog.Println("Error while reading search page", i)
			elog.Println(err)
			continue
		}

		//fmt.Println(body)

		err = json.Unmarshal(body, &dats) //transforming json into native slice of maps

		if err != nil {
			elog.Println("Error while parsing search page", i)
			elog.Println(err)
			continue

		}

		if len(dats.Images) == 0 {
			log.Println("Pages are over") //Does not mean that process is over.
			break
		} //exit due to finishing all pages

		for _, dat := range dats.Images {
			imgchan.push(dat)
		}

	}

	close(imgchan)
}
<commit_msg>if we got an error, we chug along after writing it, not dying<commit_after>package main

import (
	"encoding/json"
	//	"fmt"
	"crypto/sha512"
	"encoding/hex"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"strconv"
	"strings"
	"time"
)

//Image contains data we got from API that we are using to filter and fetch said image next
type Image struct {
	Imgid          int    `json:"id_number"`
	URL            string `json:"image"`
	Filename       string
	Score          int    `json:"score"`
	OriginalFormat string `json:"original_format"`
	Hashval        string `json:"sha512_hash"`
}

//Search returns to us array of searched images...
type Search struct {
	Images []Image `json:"search"`
}

//ImageCh is a channel of image data. You can put images into channel by parsing
//Derpibooru API by id(s) or  by tags and you can download images that are already
//in channel
type ImageCh chan Image

//Push gets unmarchalled JSON info, massages it and plugs it into channel so it
//would be processed in other places
func (imgchan ImageCh) push(dat Image) {
	dat.Filename = strconv.Itoa(dat.Imgid) + "." + dat.OriginalFormat
	dat.URL = "https:" + dat.URL
	if dat.OriginalFormat == "svg" {
		i := strings.LastIndex(dat.URL, ".")
		if i != -1 {
			dat.URL = dat.URL[:i] + ".svg" //Was afraid to extract things I needed from the date field, so extracting them from URL.
		}
	}
	imgchan <- dat
}

//ParseImg gets image IDs, fetches information about those images from Derpibooru and pushes them into the channel.
func (imgchan ImageCh) ParseImg() {

	for _, imgid := range opts.Args.IDs {
		source := "https://derpiboo.ru/images/" + strconv.Itoa(imgid) + ".json"
		if opts.Key != "" {
			source = source + "?key=" + opts.Key
		}

		log.Println("Getting image info at:", source)

		response, err := http.Get(source) //Getting our nice http response. Needs checking for 404 and other responses that are... less expected
		if err != nil {
			elog.Println(err)
			continue
		}

		defer func() {
			err = response.Body.Close() //and not forgetting to close it when it's done
			if err != nil {
				elog.Fatalln("Could  not close server response")
			}
		}()
		var dat Image

		body, err := ioutil.ReadAll(response.Body) //stolen from official documentation
		if err != nil {
			elog.Println(err)
			continue
		}

		if err := json.Unmarshal(body, &dat); //transforming json into native map

		err != nil {
			elog.Println(err)
			return
		}

		imgchan.push(dat)
	}

	close(imgchan) //closing channel, we are done here

	return
}

//DlImg reads image data from channel and downloads specified images to disc
func (imgchan ImageCh) DlImg() {

	log.Println("Worker started; reading channel") //nice notification that we are not forgotten

	hasher := sha512.New()

	for {

		imgdata, more := <-imgchan

		if !more { //checking that there is an image in channel
			done <- true //well, there is no images in channel, it means we got them all, so synchronization is kicking in and ending the process
			break        //Just in case, so it would not stupidly die when program finishes - it will die smartly
		}

		if imgdata.Filename == "" {
			elog.Println("Empty filename. Oops?") //something somewhere had gone wrong, not a cause to die, going to the next image
			continue
		}

		log.Println("Saving as", imgdata.Filename)

		func() { // To not hold all the files open when there is no need. All pointers to files are in the scope of this function.

			output, err := os.Create(opts.ImageDir + string(os.PathSeparator) + imgdata.Filename) //And now, THE FILE!
			if err != err {
				elog.Println("Error when creating file for image" + strconv.Itoa(imgdata.Imgid))
				elog.Println(err) //Either we got no permisson or no space, end of line
				return
			}
			defer func() {
				err = output.Close() //Not forgetting to deal with it after completing download
				if err != nil {
					elog.Fatalln("Could  not close downloaded file")
				}
			}()
			start := time.Now()

			response, err := http.Get(imgdata.URL)
			if err != nil {
				elog.Println("Error when getting image", imgdata.Imgid)
				elog.Println(err)
				return
			}
			defer func() {
				err = response.Body.Close() //Same, we shall not listen to the void when we finished getting image
				if err != nil {
					elog.Fatalln("Could  not close server response")
				}
			}()

			size, err := io.Copy(output, io.TeeReader(response.Body, hasher)) //	Writing things we got from Derpibooru into the file and into hasher
			if err != nil {
				elog.Println("Unable to write image on disk, id ", imgdata.Imgid)
				elog.Println(err)
				return
			}
			timed := time.Since(start).Seconds()

			hash := hex.EncodeToString(hasher.Sum(nil))

			if hash != imgdata.Hashval {
				elog.Println("Hash mismatch, got ", hash, " instead of ", imgdata.Hashval)
			}

			hasher.Reset()

			log.Printf("Downloaded %d bytes in %.2fs, speed %s/s\n", size, timed, fmtbytes(float64(size)/timed))
		}()

		//fmt.Println("\n", hex.EncodeToString(hash.Sum(nil)), "\n", imgdata.hash )

	}
}

//ParseTag gets image tags, fetches information about all images it could from Derpibooru and pushes them into the channel.
func (imgchan ImageCh) ParseTag() {

	source := "https://derpiboo.ru/search.json?q=" + opts.Tag //yay hardwiring url strings!

	if opts.Key != "" {
		source = source + "&key=" + opts.Key
	}

	log.Println("Searching as", source)

	for i := opts.StartPage; opts.StopPage == 0 || i <= opts.StopPage; i++ {
		//I suspect that all those returns could be dealt with in some way. But lazy.
		log.Println("Searching page", i)

		response, err := http.Get(source + "&page=" + strconv.Itoa(i))
		//Getting our nice http response. Needs checking for 404 and other responses that are... less expected

		defer func() {
			err = response.Body.Close() //and not forgetting to close it when it's done. And before we panic and die horribly.
			if err != nil {
				elog.Fatalln("Could  not close server response")
			}
		}()

		if err != nil {
			elog.Println("Error while getting search page", i)
			elog.Println(err)
			continue
		}

		var dats Search //Because we got array incoming instead of single object, we using an slive of maps!

		//fmt.Println(resp)

		body, err := ioutil.ReadAll(response.Body) //stolen from official documentation
		if err != nil {
			elog.Println("Error while reading search page", i)
			elog.Println(err)
			continue
		}

		//fmt.Println(body)

		err = json.Unmarshal(body, &dats) //transforming json into native slice of maps

		if err != nil {
			elog.Println("Error while parsing search page", i)
			elog.Println(err)
			continue

		}

		if len(dats.Images) == 0 {
			log.Println("Pages are over") //Does not mean that process is over.
			break
		} //exit due to finishing all pages

		for _, dat := range dats.Images {
			imgchan.push(dat)
		}

	}

	close(imgchan)
}
<|endoftext|>


<commit_before>package es

import (
	"github.com/mattbaird/elastigo/lib"
)

//elasticsearch config struct
type ElasticConf struct {
	Server string
	Port   string
	User   string
	Pass   string
	Index  string
	Type   string
}

//elasticsearch client stuct
type Client struct {
	Conn *elastigo.Conn
	Conf ElasticConf
}

//struct to store data before sent request to elasticserach
type Elasticsearch struct {
	Id        string
	Data      map[string]interface{}
	Operation string
}

//create connection
func Connect(conf ElasticConf) *Client {
	client := new(Client)

	client.Conf = conf

	client.Conn = elastigo.NewConn()
	client.Conn.SetPort(conf.Port)

	return client
}

//insert, update or delete index
func (c *Client) Execute(esdata Elasticsearch) {
	if esdata.Operation != "d" {
		c.Conn.Index(c.Conf.Index, c.Conf.Type, esdata.Id, nil, esdata.Data)
	} else {
		c.Conn.Delete(c.Conf.Index, c.Conf.Type, esdata.Id, nil)
	}
}
<commit_msg>add check index exists and health of the cluster<commit_after>package es

import (
	"fmt"
	"github.com/mattbaird/elastigo/lib"
)

//elasticsearch config struct
type ElasticConf struct {
	Server string
	Port   string
	User   string
	Pass   string
	Index  string
	Type   string
}

//elasticsearch client stuct
type Client struct {
	Conn *elastigo.Conn
	Conf ElasticConf
}

//struct to store data before sent request to elasticserach
type Elasticsearch struct {
	Id        string
	Data      map[string]interface{}
	Operation string
}

//create connection
func Connect(conf ElasticConf) *Client {
	client := new(Client)

	client.Conf = conf

	client.Conn = elastigo.NewConn()
	client.Conn.SetPort(conf.Port)

	//check if index exists
	exists, _ := client.Conn.IndicesExists(conf.Index)
	if exists == false {
		client.Conn.CreateIndex(conf.Index)
	}

	//check health of the cluster
	health, _ := client.Conn.Health(conf.Index)
	if health.Status != "green" {
		client.Conn.DoCommand("PUT", "/_settings", nil, map[string]map[string]int{"index": {"number_of_replicas": 0}})
	}

	return client
}

//insert, update or delete index
func (c *Client) Execute(esdata Elasticsearch) {
	if esdata.Operation != "d" {
		c.Conn.Index(c.Conf.Index, c.Conf.Type, esdata.Id, nil, esdata.Data)
	} else {
		c.Conn.Delete(c.Conf.Index, c.Conf.Type, esdata.Id, nil)
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2016 The Fission Authors.

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

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

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

package main

import (
	"fmt"
	"os"
	"strconv"
	"text/tabwriter"

	"github.com/urfave/cli"
	"k8s.io/apimachinery/pkg/api/resource"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/pkg/api/v1"

	"github.com/fission/fission"
	"github.com/fission/fission/crd"
)

func envCreate(c *cli.Context) error {
	client := getClient(c.GlobalString("server"))

	envName := c.String("name")
	if len(envName) == 0 {
		fatal("Need a name, use --name.")
	}

	var poolsize int
	if c.IsSet("poolsize") {
		poolsize = c.Int("poolsize")
	} else {
		poolsize = 3
	}

	envImg := c.String("image")
	if len(envImg) == 0 {
		fatal("Need an image, use --image.")
	}

	envVersion := c.Int("version")
	envBuilderImg := c.String("builder")
	envBuildCmd := c.String("buildcmd")
	envExternalNetwork := c.Bool("externalnetwork")

	if len(envBuilderImg) > 0 {
		envVersion = 2
		if len(envBuildCmd) == 0 {
			envBuildCmd = "build"
		}
	}

	resourceReq := getResourceReq(c)

	// Environment API interface version is not specified and
	// builder image is empty, set default interface version
	if envVersion == 0 {
		envVersion = 1
	}

	env := &crd.Environment{
		Metadata: metav1.ObjectMeta{
			Name:      envName,
			Namespace: metav1.NamespaceDefault,
		},
		Spec: fission.EnvironmentSpec{
			Version: envVersion,
			Runtime: fission.Runtime{
				Image: envImg,
			},
			Builder: fission.Builder{
				Image:   envBuilderImg,
				Command: envBuildCmd,
			},
			Poolsize:                     poolsize,
			Resources:                    resourceReq,
			AllowAccessToExternalNetwork: envExternalNetwork,
		},
	}

	_, err := client.EnvironmentCreate(env)
	checkErr(err, "create environment")

	fmt.Printf("environment '%v' created\n", envName)
	return err
}

func envGet(c *cli.Context) error {
	client := getClient(c.GlobalString("server"))

	envName := c.String("name")
	if len(envName) == 0 {
		fatal("Need a name, use --name.")
	}

	m := &metav1.ObjectMeta{
		Name:      envName,
		Namespace: metav1.NamespaceDefault,
	}
	env, err := client.EnvironmentGet(m)
	checkErr(err, "get environment")

	w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0)
	fmt.Fprintf(w, "%v\t%v\t%v\n", "NAME", "UID", "IMAGE")
	fmt.Fprintf(w, "%v\t%v\t%v\n",
		env.Metadata.Name, env.Metadata.UID, env.Spec.Runtime.Image)
	w.Flush()
	return nil
}

func envUpdate(c *cli.Context) error {
	client := getClient(c.GlobalString("server"))

	envName := c.String("name")
	if len(envName) == 0 {
		fatal("Need a name, use --name.")
	}

	envImg := c.String("image")
	envBuilderImg := c.String("builder")
	envBuildCmd := c.String("buildcmd")
	envExternalNetwork := c.Bool("externalnetwork")

	if len(envImg) == 0 && len(envBuilderImg) == 0 && len(envBuildCmd) == 0 {
		fatal("Need --image to specify env image, or use --builder to specify env builder, or use --buildcmd to specify new build command.")
	}

	env, err := client.EnvironmentGet(&metav1.ObjectMeta{
		Name:      envName,
		Namespace: metav1.NamespaceDefault,
	})
	checkErr(err, "find environment")

	if len(envImg) > 0 {
		env.Spec.Runtime.Image = envImg
	}

	if env.Spec.Version == 1 && (len(envBuilderImg) > 0 || len(envBuildCmd) > 0) {
		fatal("Version 1 Environments do not support builders. Must specify --version=2.")
	}

	if len(envBuilderImg) > 0 {
		env.Spec.Builder.Image = envBuilderImg
	}
	if len(envBuildCmd) > 0 {
		env.Spec.Builder.Command = envBuildCmd
	}

	if c.IsSet("poolsize") {
		env.Spec.Poolsize = c.Int("poolsize")
	}

	env.Spec.AllowAccessToExternalNetwork = envExternalNetwork

	_, err = client.EnvironmentUpdate(env)
	checkErr(err, "update environment")

	fmt.Printf("environment '%v' updated\n", envName)
	return nil
}

func envDelete(c *cli.Context) error {
	client := getClient(c.GlobalString("server"))

	envName := c.String("name")
	if len(envName) == 0 {
		fatal("Need a name , use --name.")
	}

	m := &metav1.ObjectMeta{
		Name:      envName,
		Namespace: metav1.NamespaceDefault,
	}
	err := client.EnvironmentDelete(m)
	checkErr(err, "delete environment")

	fmt.Printf("environment '%v' deleted\n", envName)
	return nil
}

func envList(c *cli.Context) error {
	client := getClient(c.GlobalString("server"))

	envs, err := client.EnvironmentList()
	checkErr(err, "list environments")

	w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0)
	fmt.Fprintf(w, "%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\n", "NAME", "UID", "IMAGE", "POOLSIZE", "MINCPU", "MAXCPU", "MINMEMORY", "MAXMEMORY")
	for _, env := range envs {
		fmt.Fprintf(w, "%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\n",
			env.Metadata.Name, env.Metadata.UID, env.Spec.Runtime.Image, env.Spec.Poolsize,
			env.Spec.Resources.Requests.Cpu(), env.Spec.Resources.Limits.Cpu(),
			env.Spec.Resources.Requests.Memory(), env.Spec.Resources.Limits.Memory())
	}
	w.Flush()

	return nil
}

func getResourceReq(c *cli.Context) v1.ResourceRequirements {
	if c.IsSet("mincpu") || c.IsSet("maxcpu") || c.IsSet("minmemory") || c.IsSet("maxmemory") {
		mincpu := c.Int("mincpu")
		maxcpu := c.Int("maxcpu")
		minmem := c.Int("minmemory")
		maxmem := c.Int("maxmemory")

		requestResources := make(map[v1.ResourceName]resource.Quantity)

		if mincpu != 0 {
			cpuRequest, err := resource.ParseQuantity(strconv.Itoa(mincpu) + "m")
			if err != nil {
				fatal("Failed to parse mincpu")
			}
			requestResources[v1.ResourceCPU] = cpuRequest
		}

		if minmem != 0 {
			memRequest, err := resource.ParseQuantity(strconv.Itoa(minmem) + "Mi")
			if err != nil {
				fatal("Failed to parse minmemory")
			}
			requestResources[v1.ResourceMemory] = memRequest
		}

		limitResources := make(map[v1.ResourceName]resource.Quantity)

		if maxcpu != 0 {
			cpuLimit, err := resource.ParseQuantity(strconv.Itoa(maxcpu) + "m")
			if err != nil {
				fatal("Failed to parse maxcpu")
			}
			limitResources[v1.ResourceCPU] = cpuLimit
		}

		if maxmem != 0 {
			memLimit, err := resource.ParseQuantity(strconv.Itoa(maxmem) + "Mi")
			if err != nil {
				fatal("Failed to parse maxmemory")
			}
			limitResources[v1.ResourceMemory] = memLimit
		}

		resources := v1.ResourceRequirements{
			Requests: requestResources,
			Limits:   limitResources,
		}
		return resources
	}
	return v1.ResourceRequirements{}
}
<commit_msg>Fixes the issue #559 with env versions (#569)<commit_after>/*
Copyright 2016 The Fission Authors.

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

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

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

package main

import (
	"fmt"
	"os"
	"strconv"
	"text/tabwriter"

	"github.com/urfave/cli"
	"k8s.io/apimachinery/pkg/api/resource"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/pkg/api/v1"

	"github.com/fission/fission"
	"github.com/fission/fission/crd"
)

func envCreate(c *cli.Context) error {
	client := getClient(c.GlobalString("server"))

	envName := c.String("name")
	if len(envName) == 0 {
		fatal("Need a name, use --name.")
	}

	var poolsize int
	if c.IsSet("poolsize") {
		poolsize = c.Int("poolsize")
	} else {
		poolsize = 3
	}

	envImg := c.String("image")
	if len(envImg) == 0 {
		fatal("Need an image, use --image.")
	}

	envVersion := c.Int("version")
	envBuilderImg := c.String("builder")
	envBuildCmd := c.String("buildcmd")
	envExternalNetwork := c.Bool("externalnetwork")

	if len(envBuilderImg) > 0 {
		if !c.IsSet("version") {
			envVersion = 2
		}
		if len(envBuildCmd) == 0 {
			envBuildCmd = "build"
		}
	}

	// Environment API interface version is not specified and
	// builder image is empty, set default interface version
	if envVersion == 0 {
		envVersion = 1
	}

	resourceReq := getResourceReq(c)

	env := &crd.Environment{
		Metadata: metav1.ObjectMeta{
			Name:      envName,
			Namespace: metav1.NamespaceDefault,
		},
		Spec: fission.EnvironmentSpec{
			Version: envVersion,
			Runtime: fission.Runtime{
				Image: envImg,
			},
			Builder: fission.Builder{
				Image:   envBuilderImg,
				Command: envBuildCmd,
			},
			Poolsize:                     poolsize,
			Resources:                    resourceReq,
			AllowAccessToExternalNetwork: envExternalNetwork,
		},
	}

	_, err := client.EnvironmentCreate(env)
	checkErr(err, "create environment")

	fmt.Printf("environment '%v' created\n", envName)
	return err
}

func envGet(c *cli.Context) error {
	client := getClient(c.GlobalString("server"))

	envName := c.String("name")
	if len(envName) == 0 {
		fatal("Need a name, use --name.")
	}

	m := &metav1.ObjectMeta{
		Name:      envName,
		Namespace: metav1.NamespaceDefault,
	}
	env, err := client.EnvironmentGet(m)
	checkErr(err, "get environment")

	w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0)
	fmt.Fprintf(w, "%v\t%v\t%v\n", "NAME", "UID", "IMAGE")
	fmt.Fprintf(w, "%v\t%v\t%v\n",
		env.Metadata.Name, env.Metadata.UID, env.Spec.Runtime.Image)
	w.Flush()
	return nil
}

func envUpdate(c *cli.Context) error {
	client := getClient(c.GlobalString("server"))

	envName := c.String("name")
	if len(envName) == 0 {
		fatal("Need a name, use --name.")
	}

	envImg := c.String("image")
	envBuilderImg := c.String("builder")
	envBuildCmd := c.String("buildcmd")
	envExternalNetwork := c.Bool("externalnetwork")

	if len(envImg) == 0 && len(envBuilderImg) == 0 && len(envBuildCmd) == 0 {
		fatal("Need --image to specify env image, or use --builder to specify env builder, or use --buildcmd to specify new build command.")
	}

	env, err := client.EnvironmentGet(&metav1.ObjectMeta{
		Name:      envName,
		Namespace: metav1.NamespaceDefault,
	})
	checkErr(err, "find environment")

	if len(envImg) > 0 {
		env.Spec.Runtime.Image = envImg
	}

	if env.Spec.Version == 1 && (len(envBuilderImg) > 0 || len(envBuildCmd) > 0) {
		fatal("Version 1 Environments do not support builders. Must specify --version=2.")
	}

	if len(envBuilderImg) > 0 {
		env.Spec.Builder.Image = envBuilderImg
	}
	if len(envBuildCmd) > 0 {
		env.Spec.Builder.Command = envBuildCmd
	}

	if c.IsSet("poolsize") {
		env.Spec.Poolsize = c.Int("poolsize")
	}

	env.Spec.AllowAccessToExternalNetwork = envExternalNetwork

	_, err = client.EnvironmentUpdate(env)
	checkErr(err, "update environment")

	fmt.Printf("environment '%v' updated\n", envName)
	return nil
}

func envDelete(c *cli.Context) error {
	client := getClient(c.GlobalString("server"))

	envName := c.String("name")
	if len(envName) == 0 {
		fatal("Need a name , use --name.")
	}

	m := &metav1.ObjectMeta{
		Name:      envName,
		Namespace: metav1.NamespaceDefault,
	}
	err := client.EnvironmentDelete(m)
	checkErr(err, "delete environment")

	fmt.Printf("environment '%v' deleted\n", envName)
	return nil
}

func envList(c *cli.Context) error {
	client := getClient(c.GlobalString("server"))

	envs, err := client.EnvironmentList()
	checkErr(err, "list environments")

	w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0)
	fmt.Fprintf(w, "%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\n", "NAME", "UID", "IMAGE", "POOLSIZE", "MINCPU", "MAXCPU", "MINMEMORY", "MAXMEMORY")
	for _, env := range envs {
		fmt.Fprintf(w, "%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\n",
			env.Metadata.Name, env.Metadata.UID, env.Spec.Runtime.Image, env.Spec.Poolsize,
			env.Spec.Resources.Requests.Cpu(), env.Spec.Resources.Limits.Cpu(),
			env.Spec.Resources.Requests.Memory(), env.Spec.Resources.Limits.Memory())
	}
	w.Flush()

	return nil
}

func getResourceReq(c *cli.Context) v1.ResourceRequirements {
	if c.IsSet("mincpu") || c.IsSet("maxcpu") || c.IsSet("minmemory") || c.IsSet("maxmemory") {
		mincpu := c.Int("mincpu")
		maxcpu := c.Int("maxcpu")
		minmem := c.Int("minmemory")
		maxmem := c.Int("maxmemory")

		requestResources := make(map[v1.ResourceName]resource.Quantity)

		if mincpu != 0 {
			cpuRequest, err := resource.ParseQuantity(strconv.Itoa(mincpu) + "m")
			if err != nil {
				fatal("Failed to parse mincpu")
			}
			requestResources[v1.ResourceCPU] = cpuRequest
		}

		if minmem != 0 {
			memRequest, err := resource.ParseQuantity(strconv.Itoa(minmem) + "Mi")
			if err != nil {
				fatal("Failed to parse minmemory")
			}
			requestResources[v1.ResourceMemory] = memRequest
		}

		limitResources := make(map[v1.ResourceName]resource.Quantity)

		if maxcpu != 0 {
			cpuLimit, err := resource.ParseQuantity(strconv.Itoa(maxcpu) + "m")
			if err != nil {
				fatal("Failed to parse maxcpu")
			}
			limitResources[v1.ResourceCPU] = cpuLimit
		}

		if maxmem != 0 {
			memLimit, err := resource.ParseQuantity(strconv.Itoa(maxmem) + "Mi")
			if err != nil {
				fatal("Failed to parse maxmemory")
			}
			limitResources[v1.ResourceMemory] = memLimit
		}

		resources := v1.ResourceRequirements{
			Requests: requestResources,
			Limits:   limitResources,
		}
		return resources
	}
	return v1.ResourceRequirements{}
}
<|endoftext|>


<commit_before>package ethcrypto

import (
	"code.google.com/p/go.crypto/ripemd160"
	"code.google.com/p/go.crypto/sha3"
	"crypto/sha256"
	"github.com/ethereum/eth-go/ethutil"
)

func Sha256Bin(data []byte) []byte {
	hash := sha256.Sum256(data)

	return hash[:]
}

func Ripemd160(data []byte) []byte {
	ripemd := ripemd160.New()
	ripemd.Write(data)

	return ripemd.Sum(nil)
}

func Sha3Bin(data []byte) []byte {
	d := sha3.NewKeccak256()
	d.Write(data)

	return d.Sum(nil)
}

// Creates an ethereum address given the bytes and the nonce
func CreateAddress(b []byte, nonce uint64) []byte {
	return Sha3Bin(ethutil.NewValue([]interface{}{b, nonce}).Encode())[12:]
}
<commit_msg>fi crypto<commit_after>package ethcrypto

import (
	//"code.google.com/p/go.crypto/sha3"
	"github.com/ethereum/eth-go/ethutil"
	"github.com/obscuren/sha3"
)

func Sha3Bin(data []byte) []byte {
	d := sha3.NewKeccak256()
	d.Write(data)

	return d.Sum(nil)
}

// Creates an ethereum address given the bytes and the nonce
func CreateAddress(b []byte, nonce uint64) []byte {
	return Sha3Bin(ethutil.NewValue([]interface{}{b, nonce}).Encode())[12:]
}
<|endoftext|>


<commit_before>package tls

import (
	"fmt"
	"log"
	"net/http"
	"os"
	"path/filepath"
)

// EnableDev generates self-signed SSL certificates to use HTTPS & HTTP/2 while
// working in a development environment. The certs are saved in a different
// directory than the production certs (from Let's Encrypt), so that the
// acme/autocert package doesn't mistake them for it's own.
// Additionally, a TLS server is started using the default http mux.
func EnableDev() {
	setupDev()

	pwd, err := os.Getwd()
	if err != nil {
		log.Fatalln("Couldn't find working directory to activate dev certificates:", err)
	}

	vendorPath := filepath.Join(pwd, "cmd", "ponzu", "vendor", "github.com", "ponzu-cms", "ponzu", "system", "tls")

	cert := filepath.Join(vendorPath, "devcerts", "cert.pem")
	key := filepath.Join(vendorPath, "devcerts", "key.pem")

	go log.Fatalln(http.ListenAndServeTLS(":10443", cert, key, nil))
	fmt.Println("Server listening on :10443 for HTTPS requests... [DEV]")
}
<commit_msg>adding hint to troubleshoot ssl cert issues on chrome<commit_after>package tls

import (
	"fmt"
	"log"
	"net/http"
	"os"
	"path/filepath"
)

// EnableDev generates self-signed SSL certificates to use HTTPS & HTTP/2 while
// working in a development environment. The certs are saved in a different
// directory than the production certs (from Let's Encrypt), so that the
// acme/autocert package doesn't mistake them for it's own.
// Additionally, a TLS server is started using the default http mux.
func EnableDev() {
	setupDev()

	pwd, err := os.Getwd()
	if err != nil {
		log.Fatalln("Couldn't find working directory to activate dev certificates:", err)
	}

	vendorPath := filepath.Join(pwd, "cmd", "ponzu", "vendor", "github.com", "ponzu-cms", "ponzu", "system", "tls")

	cert := filepath.Join(vendorPath, "devcerts", "cert.pem")
	key := filepath.Join(vendorPath, "devcerts", "key.pem")

	go log.Fatalln(http.ListenAndServeTLS(":10443", cert, key, nil))
	fmt.Println("Server listening on https://localhost:10443 for requests... [DEV]")
	fmt.Println("----")
	fmt.Println("If your browser rejects HTTPS requests, try allowing insecure connections on localhost.")
	fmt.Println("on Chrome, visit chrome://flags/#allow-insecure-localhost")
}
<|endoftext|>