<commit_before>/* This example show a basic menu similar to that found in the ncurses
 * examples from TLDP */

package main

import . "goncurses.googlecode.com/hg/goncurses"

const (
	HEIGHT = 10
	WIDTH  = 30
)

func main() {
	var active int
	menu := []string{"Choice 1", "Choice 2", "Choice 3", "Choice 4", "Exit"}

	stdscr, _ := Init()
	defer End()

	Raw(true)
	Echo(false)
	Cursor(0)
	stdscr.Clear()
	stdscr.Keypad(true)

	rows, cols := stdscr.Maxyx()
	y, x := (rows-HEIGHT)/2, (cols-WIDTH)/2

	win, _ := NewWindow(HEIGHT, WIDTH, y, x)
	win.Keypad(true)
	stdscr.Print(0, 0,
		"Use arrow keys to go up and down, Press enter to select")
	stdscr.Refresh()

	printmenu(win, menu, active)
	MouseMask(M_B1_CLICKED, nil)

	for {
		ch := stdscr.GetChar()
		switch ch {
		case 'q':
			return
		case KEY_UP:
			if active == 0 {
				active = len(menu) - 1
			} else {
				active -= 1
			}
		case KEY_DOWN:
			if active == len(menu)-1 {
				active = 0
			} else {
				active += 1
			}
		case KEY_MOUSE:
			md, _ := GetMouse()
			new := getactive(x, y, md[0], md[1], menu)
			if new != -1 {
				active = new
			}
			stdscr.Print(23, 0, "Choice #%d: %s selected", active+1,
				menu[active])
			stdscr.ClearToEOL()
			stdscr.Refresh()
		case KEY_RETURN:
			stdscr.Print(23, 0, "Choice #%d: %s selected", active+1,
				menu[active])
			stdscr.ClearToEOL()
			stdscr.Refresh()
		default:
			stdscr.Print(23, 0, "Character pressed = %3d/%c", ch, ch)
			stdscr.ClearToEOL()
			stdscr.Refresh()
		}

		printmenu(win, menu, active)
	}
}

func getactive(x, y, mx, my int, menu []string) int {
	row := my - y - 2
	col := mx - x - 2

	if row < 0 || row > len(menu)-1 {
		return -1
	}

	l := menu[row]

	if col >= 0 && col < len(l) {
		return row
	}
	return -1
}

func printmenu(w Window, menu []string, active int) {
	y, x := 2, 2
	w.Box(0, 0)
	for i, s := range menu {
		if i == active {
			w.AttrOn(A_REVERSE)
			w.Print(y+i, x, s)
			w.AttrOff(A_REVERSE)
		} else {
			w.Print(y+i, x, s)
		}
	}
	w.Refresh()
}
<commit_msg>Update mouse example<commit_after>/* This example show a basic menu similar to that found in the ncurses
 * examples from TLDP */

package main

import gc "code.google.com/p/goncurses"

const (
	HEIGHT = 10
	WIDTH  = 30
)

func main() {
	var active int
	menu := []string{"Choice 1", "Choice 2", "Choice 3", "Choice 4", "Exit"}

	stdscr, _ := gc.Init()
	defer gc.End()

	gc.Raw(true)
	gc.Echo(false)
	gc.Cursor(0)
	stdscr.Clear()
	stdscr.Keypad(true)

	rows, cols := stdscr.Maxyx()
	y, x := (rows-HEIGHT)/2, (cols-WIDTH)/2

	win, _ := gc.NewWindow(HEIGHT, WIDTH, y, x)
	win.Keypad(true)
	stdscr.Print(0, 0,
		"Use arrow keys to go up and down, Press enter to select")
	stdscr.Refresh()

	printmenu(win, menu, active)
	gc.MouseMask(gc.M_B1_CLICKED, nil)

	for {
		ch := stdscr.GetChar()
		switch ch {
		case 'q':
			return
		case gc.KEY_UP:
			if active == 0 {
				active = len(menu) - 1
			} else {
				active -= 1
			}
		case gc.KEY_DOWN:
			if active == len(menu)-1 {
				active = 0
			} else {
				active += 1
			}
		case gc.KEY_MOUSE:
			md, _ := gc.GetMouse()
			new := getactive(x, y, md[0], md[1], menu)
			if new != -1 {
				active = new
			}
			stdscr.Print(23, 0, "Choice #%d: %s selected", active+1,
				menu[active])
			stdscr.ClearToEOL()
			stdscr.Refresh()
		case gc.KEY_RETURN:
			stdscr.Print(23, 0, "Choice #%d: %s selected", active+1,
				menu[active])
			stdscr.ClearToEOL()
			stdscr.Refresh()
		default:
			stdscr.Print(23, 0, "Character pressed = %3d/%c", ch, ch)
			stdscr.ClearToEOL()
			stdscr.Refresh()
		}

		printmenu(win, menu, active)
	}
}

func getactive(x, y, mx, my int, menu []string) int {
	row := my - y - 2
	col := mx - x - 2

	if row < 0 || row > len(menu)-1 {
		return -1
	}

	l := menu[row]

	if col >= 0 && col < len(l) {
		return row
	}
	return -1
}

func printmenu(w gc.Window, menu []string, active int) {
	y, x := 2, 2
	w.Box(0, 0)
	for i, s := range menu {
		if i == active {
			w.AttrOn(gc.A_REVERSE)
			w.Print(y+i, x, s)
			w.AttrOff(gc.A_REVERSE)
		} else {
			w.Print(y+i, x, s)
		}
	}
	w.Refresh()
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"regexp"
	"strconv"
	"time"
)

const VERSION string = "1.0.5"
const SUCCESS_EXIT int = 0
const ERROR_EXIT int = 1
const LIMIT_WAIT_COUNT int = 600 // 20sec * 600 = 3.3 hours
const API_SERVER string = "https://api.vaddy.net"

type CrawlSearch struct {
	Total int               `json:"total"`
	Items []CrawlSearchItem `json:"items"`
}

type CrawlSearchItem struct {
	CrawlId int `json:"id"`
}

type StartScan struct {
	ScanID string `json:"scan_id"`
}

type ScanResult struct {
	Status        string `json:"status"`
	AlertCount    int    `json:"alert_count"`
	ScanCount     int    `json:"scan_count"`
	ScanResultUrl string `json:"scan_result_url"`
}

func main() {
	fmt.Println("==== Start VAddy Scan (Version " + VERSION + ")====")

	var auth_key, user, fqdn, crawl, verification_code, project_id string = getApiParamsFromArgsOrEnv()

	if checkNeedToGetCrawlId(crawl) {
		fmt.Println("Start to get crawl ID from keyword: " + crawl)
		crawl = getCrawlId(auth_key, user, fqdn, crawl, verification_code, project_id)
	}

	scan_id := startScan(auth_key, user, fqdn, crawl, verification_code, project_id)

	var wait_count int = 0
	var sleep_sec int = 20

	for {
		checkScanResult(auth_key, user, fqdn, scan_id, wait_count, verification_code, project_id)

		sleep_sec = 20
		if wait_count < 10 {
			sleep_sec = 3
		}
		time.Sleep(time.Duration(sleep_sec) * time.Second)

		wait_count++
		if wait_count > LIMIT_WAIT_COUNT {
			fmt.Println("Error: time out")
			os.Exit(ERROR_EXIT)
		}
	}
}

func getApiParamsFromArgsOrEnv() (string, string, string, string, string, string) {
	var auth_key, user, fqdn, crawl, verification_code string
	verification_code, _ = os.LookupEnv("VADDY_VERIFICATION_CODE")

	if len(os.Args) < 4 {
		return getArgsFromEnv(verification_code)
	}

	auth_key = os.Args[1]
	user = os.Args[2]
	fqdn = os.Args[3]
	if len(os.Args) >= 5 {
		crawl = os.Args[4]
	}
	return auth_key, user, fqdn, crawl, verification_code, ""
}

func getArgsFromEnv(verification_code string) (string, string, string, string, string, string) {
	var auth_key, user, fqdn, crawl string
	auth_key, ok1 := os.LookupEnv("VADDY_TOKEN")
	user, ok2 := os.LookupEnv("VADDY_USER")
	fqdn, ok3 := os.LookupEnv("VADDY_HOST")
	crawl, _ = os.LookupEnv("VADDY_CRAWL")
	project_id, ok4 := os.LookupEnv("VADDY_PROJECT_ID")

	// v1
	if ok1 && ok2 && ok3 {
		return auth_key, user, fqdn, crawl, verification_code, ""
	}
	// v2
	if ok1 && ok2 && ok4 {
		return auth_key, user, "", crawl, verification_code, project_id
	}

	fmt.Println("Missing arguments or system env.")
	fmt.Println("USAGE: vaddy.go ApiKey UserId FQDN CrawlID/Label(optional)")
	os.Exit(ERROR_EXIT)

	return "", "", "", "", "", ""
}

func startScan(auth_key string, user string, fqdn string, crawl string, verification_code, project_id string) string {
	values := url.Values{}
	values.Add("auth_key", auth_key)
	values.Add("user", user)
	values.Add("fqdn", fqdn)
	values.Add("action", "start")
	values.Add("verification_code", verification_code)
	if len(crawl) > 0 {
		values.Add("crawl_id", crawl)
	}
	if len(project_id) > 0 {
		values.Add("project_id", project_id)
	}

	api_server := getApiServerName()
	api_version := detectApiVersion(project_id)
	res, err := http.PostForm(api_server+"/" + api_version + "/scan", values)
	if err != nil {
		fmt.Println(err)
		os.Exit(ERROR_EXIT)
	}
	defer res.Body.Close()
	json_response := getResponseData(res)
	scanId := getScanId(json_response)
	//fmt.Println("scanId: " + scanId)
	return scanId
}

func getScanResult(auth_key string, user string, fqdn string, scan_id string, verification_code, project_id string) []byte {
	values := url.Values{}
	values.Add("auth_key", auth_key)
	values.Add("user", user)
	values.Add("fqdn", fqdn)
	values.Add("scan_id", scan_id)
	values.Add("verification_code", verification_code)
	if len(project_id) > 0 {
		values.Add("project_id", project_id)
	}

	api_server := getApiServerName()
	api_version := detectApiVersion(project_id)
	res, err := http.Get(api_server + "/" + api_version + "/scan/result?" + values.Encode())
	if err != nil {
		fmt.Println(err)
		os.Exit(ERROR_EXIT)
	}
	defer res.Body.Close()

	json_response := getResponseData(res)
	return json_response
}

func checkScanResult(auth_key string, user string, fqdn string, scan_id string, count int, verification_code, project_id string) {
	json_response := getScanResult(auth_key, user, fqdn, scan_id, verification_code, project_id)

	var scan_result ScanResult
	convertJsonToStruct(json_response, &scan_result)

	status := scan_result.Status
	switch status {
	case "scanning":
		if count > 0 && (count%60 == 0) { //wrap every 60 dots.
			fmt.Println(".")
		} else {
			fmt.Print(".")
		}
	case "canceled":
		fmt.Println(scan_result.Status)
		os.Exit(ERROR_EXIT)
	case "finish":
		//fmt.Println(string(json_response) + "\n")
		fmt.Println(".")
		fmt.Println("Server: " + fqdn)
		fmt.Println("scanId: " + scan_id)
		fmt.Println("Result URL: " + scan_result.ScanResultUrl)

		if scan_result.AlertCount > 0 {
			fmt.Print("Vulnerabilities: ")
			fmt.Println(scan_result.AlertCount)
			fmt.Println("Warning!!!")
			postSlackWarning(scan_result.AlertCount, fqdn, scan_id, scan_result.ScanResultUrl)
			os.Exit(ERROR_EXIT)
		} else if scan_result.ScanCount == 0 {
			fmt.Println("ERROR: VAddy was not able to scan your sever. Check the result on the Result URL.")
			os.Exit(ERROR_EXIT)
		} else {
			fmt.Println("Scan Success. No vulnerabilities!")
			os.Exit(SUCCESS_EXIT)
		}
	}
}

func getCrawlId(auth_key string, user string, fqdn string, search_label string, verification_code, project_id string) string {
	json_response := doCrawlSearch(auth_key, user, fqdn, search_label, verification_code, project_id)
	//fmt.Println(string(json_response))

	var crawl_result CrawlSearch
	convertJsonToStruct(json_response, &crawl_result)
	if crawl_result.Total == 0 {
		fmt.Println("can not find crawl id. using latest crawl id.")
		return ""
	}
	var crawl_id int = crawl_result.Items[0].CrawlId
	fmt.Printf("Found %d results. Using CrawlID: %d \n\n", crawl_result.Total, crawl_id)
	return strconv.Itoa(crawl_id)
}

func doCrawlSearch(auth_key string, user string, fqdn string, search_label string, verification_code, project_id string) []byte {
	values := url.Values{}
	values.Add("auth_key", auth_key)
	values.Add("user", user)
	values.Add("fqdn", fqdn)
	values.Add("search_label", search_label)
	values.Add("verification_code", verification_code)
	if len(project_id) > 0 {
		values.Add("project_id", project_id)
	}

	api_server := getApiServerName()
	api_version := detectApiVersion(project_id)
	res, err := http.Get(api_server + "/" + api_version + "/crawl?" + values.Encode())
	if err != nil {
		fmt.Println(err)
		os.Exit(ERROR_EXIT)
	}
	defer res.Body.Close()

	json_response := getResponseData(res)
	return json_response
}

func getResponseData(resp *http.Response) []byte {
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println(string(body))
		os.Exit(ERROR_EXIT)
	}
	status_code := resp.StatusCode
	//fmt.Println(status_code)
	if status_code != 200 {
		fmt.Println("Network/Auth error\n" + string(body))
		os.Exit(ERROR_EXIT)
	}
	return []byte(body)
}

func getScanId(jsonByteData []byte) string {
	var scan_result StartScan
	convertJsonToStruct(jsonByteData, &scan_result)
	return scan_result.ScanID
}

func convertJsonToStruct(jsonByteData []byte, structData interface{}) {
	err := json.Unmarshal(jsonByteData, structData)
	if err != nil {
		fmt.Println(err)
		os.Exit(ERROR_EXIT)
	}
}

func getApiServerName() string {
	api_server, ok := os.LookupEnv("VADDY_API_SERVER")
	if ok {
		//if api server does not contain protocol name, add https://
		var regex string = `^https://.*$`
		if regexp.MustCompile(regex).Match([]byte(api_server)) {
			return api_server
		}
		return "https://" + api_server
	}
	return API_SERVER
}

func checkNeedToGetCrawlId(str string) bool {
	if len(str) == 0 || str == "" {
		return false
	}
	var regex string = `[^0-9]`
	return regexp.MustCompile(regex).Match([]byte(str))
}

func postSlackWarning(alertCount int, fqdn string, scanID string, scanResultURL string) {
	slackWebhookURL, ok1 := os.LookupEnv("SLACK_WEBHOOK_URL")

	if ok1 {
		slackUsername, ok2 := os.LookupEnv("SLACK_USERNAME")
		if !ok2 {
			slackUsername = ""
		}
		slackChannel, ok3 := os.LookupEnv("SLACK_CHANNEL")
		if !ok3 {
			slackChannel = ""
		}
		iconEmoji, ok4 := os.LookupEnv("SLACK_ICON_EMOJI")
		if !ok4 {
			iconEmoji = ""
		}
		iconURL, ok5 := os.LookupEnv("SLACK_ICON_URL")
		if !ok5 {
			iconURL = ""
		}
		title := "VAddy Scan Vulnerabilities: " + string(alertCount) + " Warning!!!\n"
		text := "Server: " + fqdn + "\n"
		text += "Scan ID: " + scanID + "\n"
		text += "Result URL: " + scanResultURL

		type attachments struct {
			Color string `json:"color"`
			Title string `json:"title"`
			Text  string `json:"text"`
		}

		type slack struct {
			Username     string        `json:"username"`
			IconEmoji    string        `json:"icon_emoji"`
			IconURL      string        `json:"icon_url"`
			Channel      string        `json:"channel"`
			Text         string        `json:"text"`
			Attachements []attachments `json:"attachments"`
		}

		webhooks := slack{
			Username:  slackUsername,
			IconEmoji: iconEmoji,
			IconURL:   iconURL,
			Channel:   slackChannel,
			Text:      "VAddy Scan (Version " + VERSION + ")",
			Attachements: []attachments{
				{
					Color: "warning",
					Title: title,
					Text:  text,
				},
			},
		}

		params, _ := json.Marshal(webhooks)
		resp, err := http.PostForm(
			slackWebhookURL,
			url.Values{"payload": {string(params)}},
		)
		if err == nil {
			defer resp.Body.Close()
		}
	}
}

func detectApiVersion(project_id string) string {
	if len(project_id) > 0 {
		return "v2"
	}

	return "v1"
}
<commit_msg>Added flag to show version which are "v" and "version".<commit_after>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"regexp"
	"strconv"
	"time"
)

const VERSION string = "1.0.5"
const SUCCESS_EXIT int = 0
const ERROR_EXIT int = 1
const LIMIT_WAIT_COUNT int = 600 // 20sec * 600 = 3.3 hours
const API_SERVER string = "https://api.vaddy.net"

type CrawlSearch struct {
	Total int               `json:"total"`
	Items []CrawlSearchItem `json:"items"`
}

type CrawlSearchItem struct {
	CrawlId int `json:"id"`
}

type StartScan struct {
	ScanID string `json:"scan_id"`
}

type ScanResult struct {
	Status        string `json:"status"`
	AlertCount    int    `json:"alert_count"`
	ScanCount     int    `json:"scan_count"`
	ScanResultUrl string `json:"scan_result_url"`
}

func init() {
	var showVersion bool
	flag.BoolVar(&showVersion, "version", false, "Show version")
	flag.BoolVar(&showVersion, "v", false, "Show version")
	flag.Parse()

	if showVersion {
		fmt.Printf("Current version is %s", VERSION)
		os.Exit(SUCCESS_EXIT)
	}
}

func main() {
	fmt.Println("==== Start VAddy Scan (Version " + VERSION + ")====")

	var auth_key, user, fqdn, crawl, verification_code, project_id string = getApiParamsFromArgsOrEnv()

	if checkNeedToGetCrawlId(crawl) {
		fmt.Println("Start to get crawl ID from keyword: " + crawl)
		crawl = getCrawlId(auth_key, user, fqdn, crawl, verification_code, project_id)
	}

	scan_id := startScan(auth_key, user, fqdn, crawl, verification_code, project_id)

	var wait_count int = 0
	var sleep_sec int = 20

	for {
		checkScanResult(auth_key, user, fqdn, scan_id, wait_count, verification_code, project_id)

		sleep_sec = 20
		if wait_count < 10 {
			sleep_sec = 3
		}
		time.Sleep(time.Duration(sleep_sec) * time.Second)

		wait_count++
		if wait_count > LIMIT_WAIT_COUNT {
			fmt.Println("Error: time out")
			os.Exit(ERROR_EXIT)
		}
	}
}

func getApiParamsFromArgsOrEnv() (string, string, string, string, string, string) {
	var auth_key, user, fqdn, crawl, verification_code string
	verification_code, _ = os.LookupEnv("VADDY_VERIFICATION_CODE")

	if len(os.Args) < 4 {
		return getArgsFromEnv(verification_code)
	}

	auth_key = os.Args[1]
	user = os.Args[2]
	fqdn = os.Args[3]
	if len(os.Args) >= 5 {
		crawl = os.Args[4]
	}
	return auth_key, user, fqdn, crawl, verification_code, ""
}

func getArgsFromEnv(verification_code string) (string, string, string, string, string, string) {
	var auth_key, user, fqdn, crawl string
	auth_key, ok1 := os.LookupEnv("VADDY_TOKEN")
	user, ok2 := os.LookupEnv("VADDY_USER")
	fqdn, ok3 := os.LookupEnv("VADDY_HOST")
	crawl, _ = os.LookupEnv("VADDY_CRAWL")
	project_id, ok4 := os.LookupEnv("VADDY_PROJECT_ID")

	// v1
	if ok1 && ok2 && ok3 {
		return auth_key, user, fqdn, crawl, verification_code, ""
	}
	// v2
	if ok1 && ok2 && ok4 {
		return auth_key, user, "", crawl, verification_code, project_id
	}

	fmt.Println("Missing arguments or system env.")
	fmt.Println("USAGE: vaddy.go ApiKey UserId FQDN CrawlID/Label(optional)")
	os.Exit(ERROR_EXIT)

	return "", "", "", "", "", ""
}

func startScan(auth_key string, user string, fqdn string, crawl string, verification_code, project_id string) string {
	values := url.Values{}
	values.Add("auth_key", auth_key)
	values.Add("user", user)
	values.Add("fqdn", fqdn)
	values.Add("action", "start")
	values.Add("verification_code", verification_code)
	if len(crawl) > 0 {
		values.Add("crawl_id", crawl)
	}
	if len(project_id) > 0 {
		values.Add("project_id", project_id)
	}

	api_server := getApiServerName()
	api_version := detectApiVersion(project_id)
	res, err := http.PostForm(api_server+"/"+api_version+"/scan", values)
	if err != nil {
		fmt.Println(err)
		os.Exit(ERROR_EXIT)
	}
	defer res.Body.Close()
	json_response := getResponseData(res)
	scanId := getScanId(json_response)
	//fmt.Println("scanId: " + scanId)
	return scanId
}

func getScanResult(auth_key string, user string, fqdn string, scan_id string, verification_code, project_id string) []byte {
	values := url.Values{}
	values.Add("auth_key", auth_key)
	values.Add("user", user)
	values.Add("fqdn", fqdn)
	values.Add("scan_id", scan_id)
	values.Add("verification_code", verification_code)
	if len(project_id) > 0 {
		values.Add("project_id", project_id)
	}

	api_server := getApiServerName()
	api_version := detectApiVersion(project_id)
	res, err := http.Get(api_server + "/" + api_version + "/scan/result?" + values.Encode())
	if err != nil {
		fmt.Println(err)
		os.Exit(ERROR_EXIT)
	}
	defer res.Body.Close()

	json_response := getResponseData(res)
	return json_response
}

func checkScanResult(auth_key string, user string, fqdn string, scan_id string, count int, verification_code, project_id string) {
	json_response := getScanResult(auth_key, user, fqdn, scan_id, verification_code, project_id)

	var scan_result ScanResult
	convertJsonToStruct(json_response, &scan_result)

	status := scan_result.Status
	switch status {
	case "scanning":
		if count > 0 && (count%60 == 0) { //wrap every 60 dots.
			fmt.Println(".")
		} else {
			fmt.Print(".")
		}
	case "canceled":
		fmt.Println(scan_result.Status)
		os.Exit(ERROR_EXIT)
	case "finish":
		//fmt.Println(string(json_response) + "\n")
		fmt.Println(".")
		fmt.Println("Server: " + fqdn)
		fmt.Println("scanId: " + scan_id)
		fmt.Println("Result URL: " + scan_result.ScanResultUrl)

		if scan_result.AlertCount > 0 {
			fmt.Print("Vulnerabilities: ")
			fmt.Println(scan_result.AlertCount)
			fmt.Println("Warning!!!")
			postSlackWarning(scan_result.AlertCount, fqdn, scan_id, scan_result.ScanResultUrl)
			os.Exit(ERROR_EXIT)
		} else if scan_result.ScanCount == 0 {
			fmt.Println("ERROR: VAddy was not able to scan your sever. Check the result on the Result URL.")
			os.Exit(ERROR_EXIT)
		} else {
			fmt.Println("Scan Success. No vulnerabilities!")
			os.Exit(SUCCESS_EXIT)
		}
	}
}

func getCrawlId(auth_key string, user string, fqdn string, search_label string, verification_code, project_id string) string {
	json_response := doCrawlSearch(auth_key, user, fqdn, search_label, verification_code, project_id)
	//fmt.Println(string(json_response))

	var crawl_result CrawlSearch
	convertJsonToStruct(json_response, &crawl_result)
	if crawl_result.Total == 0 {
		fmt.Println("can not find crawl id. using latest crawl id.")
		return ""
	}
	var crawl_id int = crawl_result.Items[0].CrawlId
	fmt.Printf("Found %d results. Using CrawlID: %d \n\n", crawl_result.Total, crawl_id)
	return strconv.Itoa(crawl_id)
}

func doCrawlSearch(auth_key string, user string, fqdn string, search_label string, verification_code, project_id string) []byte {
	values := url.Values{}
	values.Add("auth_key", auth_key)
	values.Add("user", user)
	values.Add("fqdn", fqdn)
	values.Add("search_label", search_label)
	values.Add("verification_code", verification_code)
	if len(project_id) > 0 {
		values.Add("project_id", project_id)
	}

	api_server := getApiServerName()
	api_version := detectApiVersion(project_id)
	res, err := http.Get(api_server + "/" + api_version + "/crawl?" + values.Encode())
	if err != nil {
		fmt.Println(err)
		os.Exit(ERROR_EXIT)
	}
	defer res.Body.Close()

	json_response := getResponseData(res)
	return json_response
}

func getResponseData(resp *http.Response) []byte {
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println(string(body))
		os.Exit(ERROR_EXIT)
	}
	status_code := resp.StatusCode
	//fmt.Println(status_code)
	if status_code != 200 {
		fmt.Println("Network/Auth error\n" + string(body))
		os.Exit(ERROR_EXIT)
	}
	return []byte(body)
}

func getScanId(jsonByteData []byte) string {
	var scan_result StartScan
	convertJsonToStruct(jsonByteData, &scan_result)
	return scan_result.ScanID
}

func convertJsonToStruct(jsonByteData []byte, structData interface{}) {
	err := json.Unmarshal(jsonByteData, structData)
	if err != nil {
		fmt.Println(err)
		os.Exit(ERROR_EXIT)
	}
}

func getApiServerName() string {
	api_server, ok := os.LookupEnv("VADDY_API_SERVER")
	if ok {
		//if api server does not contain protocol name, add https://
		var regex string = `^https://.*$`
		if regexp.MustCompile(regex).Match([]byte(api_server)) {
			return api_server
		}
		return "https://" + api_server
	}
	return API_SERVER
}

func checkNeedToGetCrawlId(str string) bool {
	if len(str) == 0 || str == "" {
		return false
	}
	var regex string = `[^0-9]`
	return regexp.MustCompile(regex).Match([]byte(str))
}

func postSlackWarning(alertCount int, fqdn string, scanID string, scanResultURL string) {
	slackWebhookURL, ok1 := os.LookupEnv("SLACK_WEBHOOK_URL")

	if ok1 {
		slackUsername, ok2 := os.LookupEnv("SLACK_USERNAME")
		if !ok2 {
			slackUsername = ""
		}
		slackChannel, ok3 := os.LookupEnv("SLACK_CHANNEL")
		if !ok3 {
			slackChannel = ""
		}
		iconEmoji, ok4 := os.LookupEnv("SLACK_ICON_EMOJI")
		if !ok4 {
			iconEmoji = ""
		}
		iconURL, ok5 := os.LookupEnv("SLACK_ICON_URL")
		if !ok5 {
			iconURL = ""
		}
		title := "VAddy Scan Vulnerabilities: " + string(alertCount) + " Warning!!!\n"
		text := "Server: " + fqdn + "\n"
		text += "Scan ID: " + scanID + "\n"
		text += "Result URL: " + scanResultURL

		type attachments struct {
			Color string `json:"color"`
			Title string `json:"title"`
			Text  string `json:"text"`
		}

		type slack struct {
			Username     string        `json:"username"`
			IconEmoji    string        `json:"icon_emoji"`
			IconURL      string        `json:"icon_url"`
			Channel      string        `json:"channel"`
			Text         string        `json:"text"`
			Attachements []attachments `json:"attachments"`
		}

		webhooks := slack{
			Username:  slackUsername,
			IconEmoji: iconEmoji,
			IconURL:   iconURL,
			Channel:   slackChannel,
			Text:      "VAddy Scan (Version " + VERSION + ")",
			Attachements: []attachments{
				{
					Color: "warning",
					Title: title,
					Text:  text,
				},
			},
		}

		params, _ := json.Marshal(webhooks)
		resp, err := http.PostForm(
			slackWebhookURL,
			url.Values{"payload": {string(params)}},
		)
		if err == nil {
			defer resp.Body.Close()
		}
	}
}

func detectApiVersion(project_id string) string {
	if len(project_id) > 0 {
		return "v2"
	}

	return "v1"
}
<|endoftext|>


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

/*
	Package fmt implements formatted I/O with functions analogous
	to C's printf and scanf.  The format 'verbs' are derived from C's but
	are simpler.

	Printing

	The verbs:

	General:
		%v	the value in a default format.
			when printing structs, the plus flag (%+v) adds field names
		%#v	a Go-syntax representation of the value
		%T	a Go-syntax representation of the type of the value
		%%	a literal percent sign; consumes no value

	Boolean:
		%t	the word true or false
	Integer:
		%b	base 2
		%c	the character represented by the corresponding Unicode code point
		%d	base 10
		%o	base 8
		%q	a single-quoted character literal safely escaped with Go syntax.
		%x	base 16, with lower-case letters for a-f
		%X	base 16, with upper-case letters for A-F
		%U	Unicode format: U+1234; same as "U+%04X"
	Floating-point and complex constituents:
		%b	decimalless scientific notation with exponent a power of two,
			in the manner of strconv.FormatFloat with the 'b' format,
			e.g. -123456p-78
		%e	scientific notation, e.g. -1234.456e+78
		%E	scientific notation, e.g. -1234.456E+78
		%f	decimal point but no exponent, e.g. 123.456
		%g	whichever of %e or %f produces more compact output
		%G	whichever of %E or %f produces more compact output
	String and slice of bytes:
		%s	the uninterpreted bytes of the string or slice
		%q	a double-quoted string safely escaped with Go syntax
		%x	base 16, lower-case, two characters per byte
		%X	base 16, upper-case, two characters per byte
	Pointer:
		%p	base 16 notation, with leading 0x

	There is no 'u' flag.  Integers are printed unsigned if they have unsigned type.
	Similarly, there is no need to specify the size of the operand (int8, int64).

	The width and precision control formatting and are in units of Unicode
	code points.  (This differs from C's printf where the units are numbers
	of bytes.) Either or both of the flags may be replaced with the
	character '*', causing their values to be obtained from the next
	operand, which must be of type int.

	For numeric values, width sets the minimum width of the field and
	precision sets the number of places after the decimal, if appropriate,
	except that for %g/%G it sets the total number of digits. For example,
	given 123.45 the format %6.2f prints 123.45 while %.4g prints 123.5.
	The default precision for %e and %f is 6; for %g it is the smallest
	number of digits necessary to identify the value uniquely.

	For most values, width is the minimum number of characters to output,
	padding the formatted form with spaces if necessary.
	For strings, precision is the maximum number of characters to output,
	truncating if necessary.

	Other flags:
		+	always print a sign for numeric values;
			guarantee ASCII-only output for %q (%+q)
		-	pad with spaces on the right rather than the left (left-justify the field)
		#	alternate format: add leading 0 for octal (%#o), 0x for hex (%#x);
			0X for hex (%#X); suppress 0x for %p (%#p);
			for %q, print a raw (backquoted) string if strconv.CanBackquote
			returns true;
			write e.g. U+0078 'x' if the character is printable for %U (%#U).
		' '	(space) leave a space for elided sign in numbers (% d);
			put spaces between bytes printing strings or slices in hex (% x, % X)
		0	pad with leading zeros rather than spaces;
			for numbers, this moves the padding after the sign

	Flags are ignored by verbs that do not expect them.
	For example there is no alternate decimal format, so %#d and %d
	behave identically.

	For each Printf-like function, there is also a Print function
	that takes no format and is equivalent to saying %v for every
	operand.  Another variant Println inserts blanks between
	operands and appends a newline.

	Regardless of the verb, if an operand is an interface value,
	the internal concrete value is used, not the interface itself.
	Thus:
		var i interface{} = 23
		fmt.Printf("%v\n", i)
	will print 23.

	If an operand implements interface Formatter, that interface
	can be used for fine control of formatting.

	If the format (which is implicitly %v for Println etc.) is valid
	for a string (%s %q %v %x %X), the following two rules also apply:

	1. If an operand implements the error interface, the Error method
	will be used to convert the object to a string, which will then
	be formatted as required by the verb (if any).

	2. If an operand implements method String() string, that method
	will be used to convert the object to a string, which will then
	be formatted as required by the verb (if any).

	To avoid recursion in cases such as
		type X string
		func (x X) String() string { return Sprintf("<%s>", x) }
	convert the value before recurring:
		func (x X) String() string { return Sprintf("<%s>", string(x)) }

	Format errors:

	If an invalid argument is given for a verb, such as providing
	a string to %d, the generated string will contain a
	description of the problem, as in these examples:

		Wrong type or unknown verb: %!verb(type=value)
			Printf("%d", hi):          %!d(string=hi)
		Too many arguments: %!(EXTRA type=value)
			Printf("hi", "guys"):      hi%!(EXTRA string=guys)
		Too few arguments: %!verb(MISSING)
			Printf("hi%d"):            hi %!d(MISSING)
		Non-int for width or precision: %!(BADWIDTH) or %!(BADPREC)
			Printf("%*s", 4.5, "hi"):  %!(BADWIDTH)hi
			Printf("%.*s", 4.5, "hi"): %!(BADPREC)hi

	All errors begin with the string "%!" followed sometimes
	by a single character (the verb) and end with a parenthesized
	description.

	Scanning

	An analogous set of functions scans formatted text to yield
	values.  Scan, Scanf and Scanln read from os.Stdin; Fscan,
	Fscanf and Fscanln read from a specified io.Reader; Sscan,
	Sscanf and Sscanln read from an argument string.  Scanln,
	Fscanln and Sscanln stop scanning at a newline and require that
	the items be followed by one; Scanf, Fscanf and Sscanf require
	newlines in the input to match newlines in the format; the other
	routines treat newlines as spaces.

	Scanf, Fscanf, and Sscanf parse the arguments according to a
	format string, analogous to that of Printf.  For example, %x
	will scan an integer as a hexadecimal number, and %v will scan
	the default representation format for the value.

	The formats behave analogously to those of Printf with the
	following exceptions:

		%p is not implemented
		%T is not implemented
		%e %E %f %F %g %G are all equivalent and scan any floating point or complex value
		%s and %v on strings scan a space-delimited token
		Flags # and + are not implemented.

	The familiar base-setting prefixes 0 (octal) and 0x
	(hexadecimal) are accepted when scanning integers without a
	format or with the %v verb.

	Width is interpreted in the input text (%5s means at most
	five runes of input will be read to scan a string) but there
	is no syntax for scanning with a precision (no %5.2f, just
	%5f).

	When scanning with a format, all non-empty runs of space
	characters (except newline) are equivalent to a single
	space in both the format and the input.  With that proviso,
	text in the format string must match the input text; scanning
	stops if it does not, with the return value of the function
	indicating the number of arguments scanned.

	In all the scanning functions, if an operand implements method
	Scan (that is, it implements the Scanner interface) that
	method will be used to scan the text for that operand.  Also,
	if the number of arguments scanned is less than the number of
	arguments provided, an error is returned.

	All arguments to be scanned must be either pointers to basic
	types or implementations of the Scanner interface.

	Note: Fscan etc. can read one character (rune) past the input
	they return, which means that a loop calling a scan routine
	may skip some of the input.  This is usually a problem only
	when there is no space between input values.  If the reader
	provided to Fscan implements ReadRune, that method will be used
	to read characters.  If the reader also implements UnreadRune,
	that method will be used to save the character and successive
	calls will not lose data.  To attach ReadRune and UnreadRune
	methods to a reader without that capability, use
	bufio.NewReader.
*/
package fmt
<commit_msg>fmt: document that if String or Error panics, that value is printed<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/*
	Package fmt implements formatted I/O with functions analogous
	to C's printf and scanf.  The format 'verbs' are derived from C's but
	are simpler.

	Printing

	The verbs:

	General:
		%v	the value in a default format.
			when printing structs, the plus flag (%+v) adds field names
		%#v	a Go-syntax representation of the value
		%T	a Go-syntax representation of the type of the value
		%%	a literal percent sign; consumes no value

	Boolean:
		%t	the word true or false
	Integer:
		%b	base 2
		%c	the character represented by the corresponding Unicode code point
		%d	base 10
		%o	base 8
		%q	a single-quoted character literal safely escaped with Go syntax.
		%x	base 16, with lower-case letters for a-f
		%X	base 16, with upper-case letters for A-F
		%U	Unicode format: U+1234; same as "U+%04X"
	Floating-point and complex constituents:
		%b	decimalless scientific notation with exponent a power of two,
			in the manner of strconv.FormatFloat with the 'b' format,
			e.g. -123456p-78
		%e	scientific notation, e.g. -1234.456e+78
		%E	scientific notation, e.g. -1234.456E+78
		%f	decimal point but no exponent, e.g. 123.456
		%g	whichever of %e or %f produces more compact output
		%G	whichever of %E or %f produces more compact output
	String and slice of bytes:
		%s	the uninterpreted bytes of the string or slice
		%q	a double-quoted string safely escaped with Go syntax
		%x	base 16, lower-case, two characters per byte
		%X	base 16, upper-case, two characters per byte
	Pointer:
		%p	base 16 notation, with leading 0x

	There is no 'u' flag.  Integers are printed unsigned if they have unsigned type.
	Similarly, there is no need to specify the size of the operand (int8, int64).

	The width and precision control formatting and are in units of Unicode
	code points.  (This differs from C's printf where the units are numbers
	of bytes.) Either or both of the flags may be replaced with the
	character '*', causing their values to be obtained from the next
	operand, which must be of type int.

	For numeric values, width sets the minimum width of the field and
	precision sets the number of places after the decimal, if appropriate,
	except that for %g/%G it sets the total number of digits. For example,
	given 123.45 the format %6.2f prints 123.45 while %.4g prints 123.5.
	The default precision for %e and %f is 6; for %g it is the smallest
	number of digits necessary to identify the value uniquely.

	For most values, width is the minimum number of characters to output,
	padding the formatted form with spaces if necessary.
	For strings, precision is the maximum number of characters to output,
	truncating if necessary.

	Other flags:
		+	always print a sign for numeric values;
			guarantee ASCII-only output for %q (%+q)
		-	pad with spaces on the right rather than the left (left-justify the field)
		#	alternate format: add leading 0 for octal (%#o), 0x for hex (%#x);
			0X for hex (%#X); suppress 0x for %p (%#p);
			for %q, print a raw (backquoted) string if strconv.CanBackquote
			returns true;
			write e.g. U+0078 'x' if the character is printable for %U (%#U).
		' '	(space) leave a space for elided sign in numbers (% d);
			put spaces between bytes printing strings or slices in hex (% x, % X)
		0	pad with leading zeros rather than spaces;
			for numbers, this moves the padding after the sign

	Flags are ignored by verbs that do not expect them.
	For example there is no alternate decimal format, so %#d and %d
	behave identically.

	For each Printf-like function, there is also a Print function
	that takes no format and is equivalent to saying %v for every
	operand.  Another variant Println inserts blanks between
	operands and appends a newline.

	Regardless of the verb, if an operand is an interface value,
	the internal concrete value is used, not the interface itself.
	Thus:
		var i interface{} = 23
		fmt.Printf("%v\n", i)
	will print 23.

	If an operand implements interface Formatter, that interface
	can be used for fine control of formatting.

	If the format (which is implicitly %v for Println etc.) is valid
	for a string (%s %q %v %x %X), the following two rules also apply:

	1. If an operand implements the error interface, the Error method
	will be used to convert the object to a string, which will then
	be formatted as required by the verb (if any).

	2. If an operand implements method String() string, that method
	will be used to convert the object to a string, which will then
	be formatted as required by the verb (if any).

	To avoid recursion in cases such as
		type X string
		func (x X) String() string { return Sprintf("<%s>", x) }
	convert the value before recurring:
		func (x X) String() string { return Sprintf("<%s>", string(x)) }

	Format errors:

	If an invalid argument is given for a verb, such as providing
	a string to %d, the generated string will contain a
	description of the problem, as in these examples:

		Wrong type or unknown verb: %!verb(type=value)
			Printf("%d", hi):          %!d(string=hi)
		Too many arguments: %!(EXTRA type=value)
			Printf("hi", "guys"):      hi%!(EXTRA string=guys)
		Too few arguments: %!verb(MISSING)
			Printf("hi%d"):            hi %!d(MISSING)
		Non-int for width or precision: %!(BADWIDTH) or %!(BADPREC)
			Printf("%*s", 4.5, "hi"):  %!(BADWIDTH)hi
			Printf("%.*s", 4.5, "hi"): %!(BADPREC)hi

	All errors begin with the string "%!" followed sometimes
	by a single character (the verb) and end with a parenthesized
	description.

	If an Error or String method triggers a panic when called by a
	print routine, the fmt package reformats the error message
	from the panic, decorating it with an indication that it came
	through the fmt package.  For example, if a String method
	calls panic("bad"), the resulting formatted message will look
	like
		%s(PANIC=bad)

	The %s just shows the print verb in use when the failure
	occurred.

	Scanning

	An analogous set of functions scans formatted text to yield
	values.  Scan, Scanf and Scanln read from os.Stdin; Fscan,
	Fscanf and Fscanln read from a specified io.Reader; Sscan,
	Sscanf and Sscanln read from an argument string.  Scanln,
	Fscanln and Sscanln stop scanning at a newline and require that
	the items be followed by one; Scanf, Fscanf and Sscanf require
	newlines in the input to match newlines in the format; the other
	routines treat newlines as spaces.

	Scanf, Fscanf, and Sscanf parse the arguments according to a
	format string, analogous to that of Printf.  For example, %x
	will scan an integer as a hexadecimal number, and %v will scan
	the default representation format for the value.

	The formats behave analogously to those of Printf with the
	following exceptions:

		%p is not implemented
		%T is not implemented
		%e %E %f %F %g %G are all equivalent and scan any floating point or complex value
		%s and %v on strings scan a space-delimited token
		Flags # and + are not implemented.

	The familiar base-setting prefixes 0 (octal) and 0x
	(hexadecimal) are accepted when scanning integers without a
	format or with the %v verb.

	Width is interpreted in the input text (%5s means at most
	five runes of input will be read to scan a string) but there
	is no syntax for scanning with a precision (no %5.2f, just
	%5f).

	When scanning with a format, all non-empty runs of space
	characters (except newline) are equivalent to a single
	space in both the format and the input.  With that proviso,
	text in the format string must match the input text; scanning
	stops if it does not, with the return value of the function
	indicating the number of arguments scanned.

	In all the scanning functions, if an operand implements method
	Scan (that is, it implements the Scanner interface) that
	method will be used to scan the text for that operand.  Also,
	if the number of arguments scanned is less than the number of
	arguments provided, an error is returned.

	All arguments to be scanned must be either pointers to basic
	types or implementations of the Scanner interface.

	Note: Fscan etc. can read one character (rune) past the input
	they return, which means that a loop calling a scan routine
	may skip some of the input.  This is usually a problem only
	when there is no space between input values.  If the reader
	provided to Fscan implements ReadRune, that method will be used
	to read characters.  If the reader also implements UnreadRune,
	that method will be used to save the character and successive
	calls will not lose data.  To attach ReadRune and UnreadRune
	methods to a reader without that capability, use
	bufio.NewReader.
*/
package fmt
<|endoftext|>


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

// Package net provides a portable interface to Unix networks sockets,
// including TCP/IP, UDP, domain name resolution, and Unix domain sockets.
package net

// TODO(rsc):
//	support for raw ethernet sockets

import (
	"errors"
	"time"
)

// Addr represents a network end point address.
type Addr interface {
	Network() string // name of the network
	String() string  // string form of address
}

// Conn is a generic stream-oriented network connection.
type Conn interface {
	// Read reads data from the connection.
	// Read can be made to time out and return a net.Error with Timeout() == true
	// after a fixed time limit; see SetTimeout and SetReadTimeout.
	Read(b []byte) (n int, err error)

	// Write writes data to the connection.
	// Write can be made to time out and return a net.Error with Timeout() == true
	// after a fixed time limit; see SetTimeout and SetWriteTimeout.
	Write(b []byte) (n int, err error)

	// Close closes the connection.
	Close() error

	// LocalAddr returns the local network address.
	LocalAddr() Addr

	// RemoteAddr returns the remote network address.
	RemoteAddr() Addr

	// SetDeadline sets the read and write deadlines associated
	// with the connection.
	SetDeadline(t time.Time) error

	// SetReadDeadline sets the deadline for all Read calls to return.
	// If the deadline is reached, Read will fail with a timeout
	// (see type Error) instead of blocking.
	// A zero value for t means Read will not time out.
	SetReadDeadline(t time.Time) error

	// SetWriteDeadline sets the deadline for all Write calls to return.
	// If the deadline is reached, Write will fail with a timeout
	// (see type Error) instead of blocking.
	// A zero value for t means Write will not time out.
	// Even if write times out, it may return n > 0, indicating that
	// some of the data was successfully written.
	SetWriteDeadline(t time.Time) error
}

// An Error represents a network error.
type Error interface {
	error
	Timeout() bool   // Is the error a timeout?
	Temporary() bool // Is the error temporary?
}

// PacketConn is a generic packet-oriented network connection.
type PacketConn interface {
	// ReadFrom reads a packet from the connection,
	// copying the payload into b.  It returns the number of
	// bytes copied into b and the return address that
	// was on the packet.
	// ReadFrom can be made to time out and return
	// an error with Timeout() == true after a fixed time limit;
	// see SetDeadline and SetReadDeadline.
	ReadFrom(b []byte) (n int, addr Addr, err error)

	// WriteTo writes a packet with payload b to addr.
	// WriteTo can be made to time out and return
	// an error with Timeout() == true after a fixed time limit;
	// see SetDeadline and SetWriteDeadline.
	// On packet-oriented connections, write timeouts are rare.
	WriteTo(b []byte, addr Addr) (n int, err error)

	// Close closes the connection.
	Close() error

	// LocalAddr returns the local network address.
	LocalAddr() Addr

	// SetDeadline sets the read and write deadlines associated
	// with the connection.
	SetDeadline(t time.Time) error

	// SetReadDeadline sets the deadline for all Read calls to return.
	// If the deadline is reached, Read will fail with a timeout
	// (see type Error) instead of blocking.
	// A zero value for t means Read will not time out.
	SetReadDeadline(t time.Time) error

	// SetWriteDeadline sets the deadline for all Write calls to return.
	// If the deadline is reached, Write will fail with a timeout
	// (see type Error) instead of blocking.
	// A zero value for t means Write will not time out.
	// Even if write times out, it may return n > 0, indicating that
	// some of the data was successfully written.
	SetWriteDeadline(t time.Time) error
}

// A Listener is a generic network listener for stream-oriented protocols.
type Listener interface {
	// Accept waits for and returns the next connection to the listener.
	Accept() (c Conn, err error)

	// Close closes the listener.
	Close() error

	// Addr returns the listener's network address.
	Addr() Addr
}

var errMissingAddress = errors.New("missing address")

type OpError struct {
	Op   string
	Net  string
	Addr Addr
	Err  error
}

func (e *OpError) Error() string {
	if e == nil {
		return "<nil>"
	}
	s := e.Op
	if e.Net != "" {
		s += " " + e.Net
	}
	if e.Addr != nil {
		s += " " + e.Addr.String()
	}
	s += ": " + e.Err.Error()
	return s
}

type temporary interface {
	Temporary() bool
}

func (e *OpError) Temporary() bool {
	t, ok := e.Err.(temporary)
	return ok && t.Temporary()
}

type timeout interface {
	Timeout() bool
}

func (e *OpError) Timeout() bool {
	t, ok := e.Err.(timeout)
	return ok && t.Timeout()
}

type timeoutError struct{}

func (e *timeoutError) Error() string   { return "i/o timeout" }
func (e *timeoutError) Timeout() bool   { return true }
func (e *timeoutError) Temporary() bool { return true }

var errTimeout error = &timeoutError{}

type AddrError struct {
	Err  string
	Addr string
}

func (e *AddrError) Error() string {
	if e == nil {
		return "<nil>"
	}
	s := e.Err
	if e.Addr != "" {
		s += " " + e.Addr
	}
	return s
}

func (e *AddrError) Temporary() bool {
	return false
}

func (e *AddrError) Timeout() bool {
	return false
}

type UnknownNetworkError string

func (e UnknownNetworkError) Error() string   { return "unknown network " + string(e) }
func (e UnknownNetworkError) Temporary() bool { return false }
func (e UnknownNetworkError) Timeout() bool   { return false }
<commit_msg>net: fix comments<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package net provides a portable interface to Unix networks sockets,
// including TCP/IP, UDP, domain name resolution, and Unix domain sockets.
package net

// TODO(rsc):
//	support for raw ethernet sockets

import (
	"errors"
	"time"
)

// Addr represents a network end point address.
type Addr interface {
	Network() string // name of the network
	String() string  // string form of address
}

// Conn is a generic stream-oriented network connection.
type Conn interface {
	// Read reads data from the connection.
	// Read can be made to time out and return a net.Error with Timeout() == true
	// after a fixed time limit; see SetDeadline and SetReadDeadline.
	Read(b []byte) (n int, err error)

	// Write writes data to the connection.
	// Write can be made to time out and return a net.Error with Timeout() == true
	// after a fixed time limit; see SetDeadline and SetWriteDeadline.
	Write(b []byte) (n int, err error)

	// Close closes the connection.
	Close() error

	// LocalAddr returns the local network address.
	LocalAddr() Addr

	// RemoteAddr returns the remote network address.
	RemoteAddr() Addr

	// SetDeadline sets the read and write deadlines associated
	// with the connection.
	SetDeadline(t time.Time) error

	// SetReadDeadline sets the deadline for all Read calls to return.
	// If the deadline is reached, Read will fail with a timeout
	// (see type Error) instead of blocking.
	// A zero value for t means Read will not time out.
	SetReadDeadline(t time.Time) error

	// SetWriteDeadline sets the deadline for all Write calls to return.
	// If the deadline is reached, Write will fail with a timeout
	// (see type Error) instead of blocking.
	// A zero value for t means Write will not time out.
	// Even if write times out, it may return n > 0, indicating that
	// some of the data was successfully written.
	SetWriteDeadline(t time.Time) error
}

// An Error represents a network error.
type Error interface {
	error
	Timeout() bool   // Is the error a timeout?
	Temporary() bool // Is the error temporary?
}

// PacketConn is a generic packet-oriented network connection.
type PacketConn interface {
	// ReadFrom reads a packet from the connection,
	// copying the payload into b.  It returns the number of
	// bytes copied into b and the return address that
	// was on the packet.
	// ReadFrom can be made to time out and return
	// an error with Timeout() == true after a fixed time limit;
	// see SetDeadline and SetReadDeadline.
	ReadFrom(b []byte) (n int, addr Addr, err error)

	// WriteTo writes a packet with payload b to addr.
	// WriteTo can be made to time out and return
	// an error with Timeout() == true after a fixed time limit;
	// see SetDeadline and SetWriteDeadline.
	// On packet-oriented connections, write timeouts are rare.
	WriteTo(b []byte, addr Addr) (n int, err error)

	// Close closes the connection.
	Close() error

	// LocalAddr returns the local network address.
	LocalAddr() Addr

	// SetDeadline sets the read and write deadlines associated
	// with the connection.
	SetDeadline(t time.Time) error

	// SetReadDeadline sets the deadline for all Read calls to return.
	// If the deadline is reached, Read will fail with a timeout
	// (see type Error) instead of blocking.
	// A zero value for t means Read will not time out.
	SetReadDeadline(t time.Time) error

	// SetWriteDeadline sets the deadline for all Write calls to return.
	// If the deadline is reached, Write will fail with a timeout
	// (see type Error) instead of blocking.
	// A zero value for t means Write will not time out.
	// Even if write times out, it may return n > 0, indicating that
	// some of the data was successfully written.
	SetWriteDeadline(t time.Time) error
}

// A Listener is a generic network listener for stream-oriented protocols.
type Listener interface {
	// Accept waits for and returns the next connection to the listener.
	Accept() (c Conn, err error)

	// Close closes the listener.
	Close() error

	// Addr returns the listener's network address.
	Addr() Addr
}

var errMissingAddress = errors.New("missing address")

type OpError struct {
	Op   string
	Net  string
	Addr Addr
	Err  error
}

func (e *OpError) Error() string {
	if e == nil {
		return "<nil>"
	}
	s := e.Op
	if e.Net != "" {
		s += " " + e.Net
	}
	if e.Addr != nil {
		s += " " + e.Addr.String()
	}
	s += ": " + e.Err.Error()
	return s
}

type temporary interface {
	Temporary() bool
}

func (e *OpError) Temporary() bool {
	t, ok := e.Err.(temporary)
	return ok && t.Temporary()
}

type timeout interface {
	Timeout() bool
}

func (e *OpError) Timeout() bool {
	t, ok := e.Err.(timeout)
	return ok && t.Timeout()
}

type timeoutError struct{}

func (e *timeoutError) Error() string   { return "i/o timeout" }
func (e *timeoutError) Timeout() bool   { return true }
func (e *timeoutError) Temporary() bool { return true }

var errTimeout error = &timeoutError{}

type AddrError struct {
	Err  string
	Addr string
}

func (e *AddrError) Error() string {
	if e == nil {
		return "<nil>"
	}
	s := e.Err
	if e.Addr != "" {
		s += " " + e.Addr
	}
	return s
}

func (e *AddrError) Temporary() bool {
	return false
}

func (e *AddrError) Timeout() bool {
	return false
}

type UnknownNetworkError string

func (e UnknownNetworkError) Error() string   { return "unknown network " + string(e) }
func (e UnknownNetworkError) Temporary() bool { return false }
func (e UnknownNetworkError) Timeout() bool   { return false }
<|endoftext|>


<commit_before>package checks

import (
	"math/rand"
	"sync"
	"time"

	"github.com/abrander/gansoi/logger"
)

type (
	// Scheduler takes care of scheduling checks on the local node. For now
	// it will tick every second.
	Scheduler struct {
		run       bool
		node      db
		nodeName  string
		ticker    *time.Ticker
		metaStore map[string]*checkMeta
	}

	// checkMeta is used internally in the scheduler to keep track of check
	// metadata.
	checkMeta struct {
		LastCheck time.Time
		NextCheck time.Time
	}

	// db defines the database interface that the scheduler can read checks
	// from and store results to.
	db interface {
		// Save will save an object to the database.
		Save(data interface{}) error

		// One will retrieve one record from the database.
		One(fieldName string, value interface{}, to interface{}) error

		// All lists all kinds of a type.
		All(to interface{}, limit int, skip int, reverse bool) error
	}
)

// NewScheduler starts a new scheduler.
func NewScheduler(n db, nodeName string, run bool) *Scheduler {
	s := &Scheduler{
		node:      n,
		nodeName:  nodeName,
		ticker:    time.NewTicker(time.Millisecond * 1000),
		run:       run,
		metaStore: make(map[string]*checkMeta),
	}

	go s.loop()

	return s
}

// Run will start the event loop.
func (s *Scheduler) Run() {
	s.run = true
}

// Stop will stp the event loop.
func (s *Scheduler) Stop() {
	s.run = false
}

func (s *Scheduler) meta(check *Check) *checkMeta {
	meta, found := s.metaStore[check.ID]
	if !found {
		meta = &checkMeta{}
		s.metaStore[check.ID] = meta
	}

	return meta
}

func (s *Scheduler) loop() {
	// inFlight is a list of check id's currently running
	inFlight := make(map[string]bool)
	inFlightLock := sync.RWMutex{}

	for t := range s.ticker.C {
		if !s.run {
			continue
		}

		// We start by extracting a list of all checks. If this gets too
		// expensive at some point, we can do it less frequent or more
		// efficient.
		var allChecks []Check
		err := s.node.All(&allChecks, -1, 0, false)
		if err != nil {
			logger.Red("scheduler", "%s", err.Error())
			continue
		}

		// We iterate the list of checks, to see if anything needs to be done.
		for _, check := range allChecks {
			meta := s.meta(&check)

			// Calculate the age of the last check, if the age is positive, it's
			// in the past.
			age := t.Sub(meta.LastCheck)

			// Calculate how much we should wait before executing the check. If
			// the value is positive, it's in the future.
			wait := meta.NextCheck.Sub(t)

			// Check if the check is already executing.
			inFlightLock.RLock()
			_, found := inFlight[check.ID]
			inFlightLock.RUnlock()

			if found {
				continue
			}

			// If the check is older than two intervals, we treat it as new.
			if age > check.Interval*2 && wait < -check.Interval {
				checkIn := time.Duration(rand.Int63n(int64(check.Interval)))
				meta.NextCheck = t.Add(checkIn)

				logger.Green("scheduler", "%s start delayed for %s", check.ID, checkIn.String())
			} else if wait < 0 {
				// If we arrive here, wait is sub-zero, which means that we
				// should execute now.
				inFlightLock.Lock()
				inFlight[check.ID] = true
				inFlightLock.Unlock()

				// Execute the check in its own go routine.
				go func(check Check) {
					// Run the job.
					start := time.Now()

					checkResult := RunCheck(&check)
					checkResult.Node = s.nodeName

					if checkResult.Error != "" {
						logger.Yellow("scheduler", "%s failed in %s: %s", check.ID, time.Now().Sub(start), checkResult.Error)
					} else {
						logger.Green("scheduler", "%s ran in %s: %+v", check.ID, time.Now().Sub(start), checkResult.Results)
					}

					s.node.Save(checkResult)

					// Save the check time and schedule next check. It should be
					// safe to update meta from a go routine. We shouldn't
					// execute the same check more than once at a time.
					meta.LastCheck = t
					meta.NextCheck = t.Add(check.Interval)

					// Remove the check from the inFlight map.
					inFlightLock.Lock()
					delete(inFlight, check.ID)
					inFlightLock.Unlock()
				}(check)
			}
		}
	}
}
<commit_msg>Let the scheduler tick two times each second (instead of one).<commit_after>package checks

import (
	"math/rand"
	"sync"
	"time"

	"github.com/abrander/gansoi/logger"
)

type (
	// Scheduler takes care of scheduling checks on the local node. For now
	// it will tick two times each second.
	Scheduler struct {
		run       bool
		node      db
		nodeName  string
		ticker    *time.Ticker
		metaStore map[string]*checkMeta
	}

	// checkMeta is used internally in the scheduler to keep track of check
	// metadata.
	checkMeta struct {
		LastCheck time.Time
		NextCheck time.Time
	}

	// db defines the database interface that the scheduler can read checks
	// from and store results to.
	db interface {
		// Save will save an object to the database.
		Save(data interface{}) error

		// One will retrieve one record from the database.
		One(fieldName string, value interface{}, to interface{}) error

		// All lists all kinds of a type.
		All(to interface{}, limit int, skip int, reverse bool) error
	}
)

// NewScheduler starts a new scheduler.
func NewScheduler(n db, nodeName string, run bool) *Scheduler {
	s := &Scheduler{
		node:      n,
		nodeName:  nodeName,
		ticker:    time.NewTicker(time.Millisecond * 500),
		run:       run,
		metaStore: make(map[string]*checkMeta),
	}

	go s.loop()

	return s
}

// Run will start the event loop.
func (s *Scheduler) Run() {
	s.run = true
}

// Stop will stp the event loop.
func (s *Scheduler) Stop() {
	s.run = false
}

func (s *Scheduler) meta(check *Check) *checkMeta {
	meta, found := s.metaStore[check.ID]
	if !found {
		meta = &checkMeta{}
		s.metaStore[check.ID] = meta
	}

	return meta
}

func (s *Scheduler) loop() {
	// inFlight is a list of check id's currently running
	inFlight := make(map[string]bool)
	inFlightLock := sync.RWMutex{}

	for t := range s.ticker.C {
		if !s.run {
			continue
		}

		// We start by extracting a list of all checks. If this gets too
		// expensive at some point, we can do it less frequent or more
		// efficient.
		var allChecks []Check
		err := s.node.All(&allChecks, -1, 0, false)
		if err != nil {
			logger.Red("scheduler", "%s", err.Error())
			continue
		}

		// We iterate the list of checks, to see if anything needs to be done.
		for _, check := range allChecks {
			meta := s.meta(&check)

			// Calculate the age of the last check, if the age is positive, it's
			// in the past.
			age := t.Sub(meta.LastCheck)

			// Calculate how much we should wait before executing the check. If
			// the value is positive, it's in the future.
			wait := meta.NextCheck.Sub(t)

			// Check if the check is already executing.
			inFlightLock.RLock()
			_, found := inFlight[check.ID]
			inFlightLock.RUnlock()

			if found {
				continue
			}

			// If the check is older than two intervals, we treat it as new.
			if age > check.Interval*2 && wait < -check.Interval {
				checkIn := time.Duration(rand.Int63n(int64(check.Interval)))
				meta.NextCheck = t.Add(checkIn)

				logger.Green("scheduler", "%s start delayed for %s", check.ID, checkIn.String())
			} else if wait < 0 {
				// If we arrive here, wait is sub-zero, which means that we
				// should execute now.
				inFlightLock.Lock()
				inFlight[check.ID] = true
				inFlightLock.Unlock()

				// Execute the check in its own go routine.
				go func(check Check) {
					// Run the job.
					start := time.Now()

					checkResult := RunCheck(&check)
					checkResult.Node = s.nodeName

					if checkResult.Error != "" {
						logger.Yellow("scheduler", "%s failed in %s: %s", check.ID, time.Now().Sub(start), checkResult.Error)
					} else {
						logger.Green("scheduler", "%s ran in %s: %+v", check.ID, time.Now().Sub(start), checkResult.Results)
					}

					s.node.Save(checkResult)

					// Save the check time and schedule next check. It should be
					// safe to update meta from a go routine. We shouldn't
					// execute the same check more than once at a time.
					meta.LastCheck = t
					meta.NextCheck = t.Add(check.Interval)

					// Remove the check from the inFlight map.
					inFlightLock.Lock()
					delete(inFlight, check.ID)
					inFlightLock.Unlock()
				}(check)
			}
		}
	}
}
<|endoftext|>


<commit_before>package fluxd

import (
	"errors"
	"github.com/bitly/go-nsq"
	"net/http"
)

var (
	// DefaultConfig is the default configuration used for NSQ communications by each binding if one is not specified.
	DefaultConfig *nsq.Config
)

func init() {
	DefaultConfig = nsq.NewConfig()
	_ = DefaultConfig.Set("max_in_flight", 25)
}

// Server represents a collection of bindings
// to an NSQlookupd instance.
type Server struct {
	// Config used for NSQ connections; defaults to DefaultConfig
	NSQConfig *nsq.Config
	// Address(es) of nsqlookupd(s)
	Lookupdaddrs []string
	bindings     []*Binding
}

// Stop ends all of the server processes gracefully. It does not block.
func (s *Server) Stop() {
	for _, b := range s.bindings {
		go func(b *Binding) {
			b.cons.Stop()
			return
		}(b)
	}
}

// use server config and addrs to configure a binding
// and start the consumer, client, and handler
func (s *Server) startrun(b *Binding) error {
	var err error
	b.cons, err = nsq.NewConsumer(b.Topic, b.Channel, s.NSQConfig)
	if err != nil {
		return err
	}

	err = b.cons.ConnectToNSQLookupds(s.Lookupdaddrs)
	if err != nil {
		return err
	}

	// default client
	b.dcl = &http.Client{}
	if b.Workers <= 0 {
		b.Workers = 1
	}
	b.cons.SetConcurrentHandlers(b, b.Workers)
	return nil
}

// Run blocks until all bindings exit gracefully, usually after a call to Stop.
// Run immediately returns an error if the server is not configured correctly.
func (s *Server) Run() error {
	var err error
	if s.NSQConfig == nil {
		s.NSQConfig = DefaultConfig
	}
	err = s.NSQConfig.Validate()
	if err != nil {
		return err
	}

	if len(s.bindings) == 0 {
		return errors.New("No bindings registered.")
	}

	for _, b := range s.bindings {
		err = s.startrun(b)
		if err != nil {
			return err
		}
	}
	// block until graceful stop
	for _, b := range s.bindings {
		<-b.cons.StopChan
	}
	return nil
}

// Binding types connect NSQ channels, flux/msg schemas, and database endpoints.
type Binding struct {
	// Topic is the NSQ topic to listen on
	Topic string
	// Channel is the NSQ channel to listen on
	Channel string
	// Endpoint is the database and decode logic used for this topic & channel
	Endpoint DB
	// Workers sets the number of concurrent goroutines serving this binding; defaults to 1
	Workers int
	dcl     *http.Client  //used for database communication
	cons    *nsq.Consumer //used for nsq communication
}

// HandleMessage implements the nsq.Handler interface
func (b *Binding) HandleMessage(msg *nsq.Message) error {
	return dbHandle(b.Endpoint, msg.Body, b.dcl)
}
<commit_msg>Added Bind()<commit_after>package fluxd

import (
	"errors"
	"github.com/bitly/go-nsq"
	"net/http"
)

var (
	// DefaultConfig is the default configuration used for NSQ communications by each binding if one is not specified.
	DefaultConfig *nsq.Config
)

func init() {
	DefaultConfig = nsq.NewConfig()
	_ = DefaultConfig.Set("max_in_flight", 25)
}

// Server represents a collection of bindings
// to an NSQlookupd instance.
type Server struct {
	// Config used for NSQ connections; defaults to DefaultConfig
	NSQConfig *nsq.Config
	// Address(es) of nsqlookupd(s)
	Lookupdaddrs []string
	bindings     []*Binding
}

// Stop ends all of the server processes gracefully. It does not block.
func (s *Server) Stop() {
	for _, b := range s.bindings {
		go func(b *Binding) {
			b.cons.Stop()
			return
		}(b)
	}
}

// Bind adds a binding to the server. Bind must be called before Run.
func (s *Server) Bind(b *Binding) { s.bindings = append(s.bindings, b) }

// use server config and addrs to configure a binding
// and start the consumer, client, and handler
func (s *Server) startrun(b *Binding) error {
	var err error
	b.cons, err = nsq.NewConsumer(b.Topic, b.Channel, s.NSQConfig)
	if err != nil {
		return err
	}

	err = b.cons.ConnectToNSQLookupds(s.Lookupdaddrs)
	if err != nil {
		return err
	}

	// default client
	b.dcl = &http.Client{}
	if b.Workers <= 0 {
		b.Workers = 1
	}
	b.cons.SetConcurrentHandlers(b, b.Workers)
	return nil
}

// Run blocks until all bindings exit gracefully, usually after a call to Stop.
// Run immediately returns an error if the server is not configured correctly.
func (s *Server) Run() error {
	var err error
	if s.NSQConfig == nil {
		s.NSQConfig = DefaultConfig
	}
	err = s.NSQConfig.Validate()
	if err != nil {
		return err
	}

	if s.bindings == nil || len(s.bindings) == 0 {
		return errors.New("No bindings registered.")
	}

	for _, b := range s.bindings {
		err = s.startrun(b)
		if err != nil {
			return err
		}
	}
	// block until graceful stop
	for _, b := range s.bindings {
		<-b.cons.StopChan
	}
	return nil
}

// Binding types connect NSQ channels, flux/msg schemas, and database endpoints.
type Binding struct {
	// Topic is the NSQ topic to listen on
	Topic string
	// Channel is the NSQ channel to listen on
	Channel string
	// Endpoint is the database and decode logic used for this topic & channel
	Endpoint DB
	// Workers sets the number of concurrent goroutines serving this binding; defaults to 1
	Workers int
	dcl     *http.Client  //used for database communication
	cons    *nsq.Consumer //used for nsq communication
}

// HandleMessage implements the nsq.Handler interface
func (b *Binding) HandleMessage(msg *nsq.Message) error {
	return dbHandle(b.Endpoint, msg.Body, b.dcl)
}
<|endoftext|>


<commit_before>package main

import (
	"archive/tar"
	"compress/gzip"
	"crypto/sha1"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"path"
	"strings"
)

type ForgeModule struct {
	name    string
	version string
	// version_requirement string  ignored for now
	targetFolder string
	cacheFolder  string
}

func (m *ForgeModule) SetCacheFolder(folder string) {
	m.cacheFolder = folder
}

func (m *ForgeModule) IsUpToDate() bool {
	_, err := os.Stat(m.TargetFolder())
	return err == nil
}

func (m *ForgeModule) Hash() string {
	hasher := sha1.New()
	hasher.Write([]byte(m.name))
	return base64.URLEncoding.EncodeToString(hasher.Sum(nil))
}

type ForgeDownloadError struct {
	error
	retryable bool
}

func (fde *ForgeDownloadError) Retryable() bool {
	return true
}

func (m *ForgeModule) Name() string {
	return m.name
}

func (m *ForgeModule) SetTargetFolder(folder string) {
	m.targetFolder = folder
}

func (m *ForgeModule) TargetFolder() string {
	return m.targetFolder
}

type ModuleReleases struct {
	Results []struct {
		File_uri string
		Version  string
	}
}

func (m *ForgeModule) gunzip(r io.Reader, targetFolder string) error {
	gzf, err := gzip.NewReader(r)
	if err != nil {
		return &ForgeDownloadError{err, true}
	}

	tarReader := tar.NewReader(gzf)
	i := 0

	if _, err = os.Stat(m.TargetFolder()); err != nil {
		if err := os.MkdirAll(m.TargetFolder(), 0755); err != nil {
			return &ForgeDownloadError{err, false}
		}
	}

	for {
		header, err := tarReader.Next()

		if err == io.EOF {
			break
		}

		if err != nil {
			return &ForgeDownloadError{err, true}
		}

		name := header.Name

		// The files in the archive are all in a parent folder,
		// we want to extract all files directly to TargetFolder
		namePath := strings.Split(name, "/")
		switch len(namePath) {
		case 0:
			break
		case 1:
			name = "/"
		default:
			name = strings.Join(namePath[1:], "/")
		}

		switch header.Typeflag {
		case tar.TypeDir:
			if err = os.MkdirAll(path.Join(m.TargetFolder(), name), 0755); err != nil {
				return &ForgeDownloadError{fmt.Errorf("Error creating %s: %s", m.TargetFolder()+"/"+name, err.Error()), false}
			}
			continue

		case tar.TypeReg:
			data := make([]byte, header.Size)
			_, err := tarReader.Read(data)
			if err != nil {
				return &ForgeDownloadError{err, true}
			}
			ioutil.WriteFile(m.TargetFolder()+"/"+name, data, 0755)

		default:
			return &ForgeDownloadError{fmt.Errorf("Error extracting Tar file: %s", err.Error()), false}
		}

		i++
	}

	return nil
}

func (m *ForgeModule) Download() error {
	var err error

	forgeUrl := "https://forgeapi.puppetlabs.com:443/"
	ApiVersion := "v3"

	url := forgeUrl + ApiVersion + "/releases?" +
		"module=" + m.Name() +
		"&sort_by=release_date" +
		"&limit=100"

	resp, err := http.Get(url)
	if err != nil {
		return &ForgeDownloadError{err, true}
	}

	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return &ForgeDownloadError{err, true}
	}

	var mr ModuleReleases
	err = json.Unmarshal(body, &mr)

	if err != nil {
		return &ForgeDownloadError{err, true}
	} else if len(mr.Results) == 0 {
		return &ForgeDownloadError{fmt.Errorf("Could not find module %s", m.Name()), false}
	}

	// If version is not specified, we pick the latest version
	index := 0
	if m.version != "" {
		versionFound := false
		for i, result := range mr.Results {
			if m.version == result.Version {
				versionFound = true
				index = i
				break
			}
		}
		if !versionFound {
			return &ForgeDownloadError{fmt.Errorf("Could not find version %s for module %s", m.version, m.Name()), false}
		}
	}

	forgeArchive, err := http.Get(forgeUrl + mr.Results[index].File_uri)
	if err != nil {
		return &ForgeDownloadError{fmt.Errorf("Failed retrieving %s", forgeUrl+mr.Results[index].File_uri), true}
	}
	defer forgeArchive.Body.Close()
	if err = m.gunzip(forgeArchive.Body, m.TargetFolder()); err != nil {
		return &ForgeDownloadError{err, true}
	}
	return nil
}
<commit_msg>Beginning cache logic for forge modules<commit_after>package main

import (
	"archive/tar"
	"compress/gzip"
	"crypto/sha1"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"path"
	"strings"
)

type ForgeModule struct {
	name    string
	version string
	// version_requirement string  ignored for now
	targetFolder string
	cacheFolder  string
}

func (m *ForgeModule) SetCacheFolder(folder string) {
	m.cacheFolder = folder
}

func (m *ForgeModule) IsUpToDate() bool {
	_, err := os.Stat(m.TargetFolder())
	return err == nil
}

func (m *ForgeModule) Hash() string {
	hasher := sha1.New()
	hasher.Write([]byte(m.name))
	return base64.URLEncoding.EncodeToString(hasher.Sum(nil))
}

type ForgeDownloadError struct {
	error
	retryable bool
}

func (fde *ForgeDownloadError) Retryable() bool {
	return true
}

func (m *ForgeModule) Name() string {
	return m.name
}

func (m *ForgeModule) SetTargetFolder(folder string) {
	m.targetFolder = folder
}

func (m *ForgeModule) TargetFolder() string {
	return m.targetFolder
}

type ModuleReleases struct {
	Results []struct {
		File_uri string
		Version  string
	}
}

func (m *ForgeModule) downloadToCache(r io.Reader) error {
	os.MkdirAll(path.Join(m.cacheFolder), 0755)

	out, err := os.Create(path.Join(m.cacheFolder, m.version+".tar.gz"))
	defer out.Close()

	_, err = io.Copy(out, r)

	return err
}

func (m *ForgeModule) gunzip(r io.Reader, targetFolder string) error {
	gzf, err := gzip.NewReader(r)
	if err != nil {
		return &ForgeDownloadError{err, true}
	}

	tarReader := tar.NewReader(gzf)
	i := 0

	if _, err = os.Stat(m.TargetFolder()); err != nil {
		if err := os.MkdirAll(m.TargetFolder(), 0755); err != nil {
			return &ForgeDownloadError{err, false}
		}
	}

	for {
		header, err := tarReader.Next()

		if err == io.EOF {
			break
		}

		if err != nil {
			return &ForgeDownloadError{err, true}
		}

		name := header.Name

		// The files in the archive are all in a parent folder,
		// we want to extract all files directly to TargetFolder
		namePath := strings.Split(name, "/")
		switch len(namePath) {
		case 0:
			break
		case 1:
			name = "/"
		default:
			name = strings.Join(namePath[1:], "/")
		}

		switch header.Typeflag {
		case tar.TypeDir:
			if err = os.MkdirAll(path.Join(m.TargetFolder(), name), 0755); err != nil {
				return &ForgeDownloadError{fmt.Errorf("Error creating %s: %s", m.TargetFolder()+"/"+name, err.Error()), false}
			}
			continue

		case tar.TypeReg:
			data := make([]byte, header.Size)
			_, err := tarReader.Read(data)
			if err != nil {
				return &ForgeDownloadError{err, true}
			}
			ioutil.WriteFile(m.TargetFolder()+"/"+name, data, 0755)

		default:
			return &ForgeDownloadError{fmt.Errorf("Error extracting Tar file: %s", err.Error()), false}
		}

		i++
	}

	return nil
}

func (m *ForgeModule) Download() error {
	var err error

	forgeUrl := "https://forgeapi.puppetlabs.com:443/"
	ApiVersion := "v3"

	url := forgeUrl + ApiVersion + "/releases?" +
		"module=" + m.Name() +
		"&sort_by=release_date" +
		"&limit=100"

	resp, err := http.Get(url)
	if err != nil {
		return &ForgeDownloadError{err, true}
	}

	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return &ForgeDownloadError{err, true}
	}

	var mr ModuleReleases
	err = json.Unmarshal(body, &mr)

	if err != nil {
		return &ForgeDownloadError{err, true}
	} else if len(mr.Results) == 0 {
		return &ForgeDownloadError{fmt.Errorf("Could not find module %s", m.Name()), false}
	}

	// If version is not specified, we pick the latest version
	index := 0
	if m.version != "" {
		versionFound := false
		for i, result := range mr.Results {
			if m.version == result.Version {
				versionFound = true
				index = i
				break
			}
		}
		if !versionFound {
			return &ForgeDownloadError{fmt.Errorf("Could not find version %s for module %s", m.version, m.Name()), false}
		}
	} else {
		m.version = mr.Results[0].Version
	}

	forgeArchive, err := http.Get(forgeUrl + mr.Results[index].File_uri)
	if err != nil {
		return &ForgeDownloadError{fmt.Errorf("Failed retrieving %s", forgeUrl+mr.Results[index].File_uri), true}
	}
	defer forgeArchive.Body.Close()

	m.downloadToCache(forgeArchive.Body)

	r, _ := os.Open(path.Join(m.cacheFolder, m.version+".tar.gz"))
	defer r.Close()

	if err = m.gunzip(r, m.TargetFolder()); err != nil {
		return &ForgeDownloadError{err, true}
	}
	return nil
}
<|endoftext|>


<commit_before>package Mongo

import (
	"GoShare"
	"time"

	"gopkg.in/mgo.v2/bson"
)

// Tenant model
type Tenant struct {
	// (ReadOnly) Id of the document, created by system utilizing Mongo Bson Id
	ID string `json:"Id"  bson:"_id" binding:"required"`
	// (ReadOnly) Date the document was created (UTC)
	DateCreated time.Time `json:"DateCreated" bson:"DateCreated" binding:"required"`
	// (ReadOnly) Date the document was modified (UTC)
	DateModified time.Time `json:"DateModified" bson:"DateModified"`
	// (ReadOnly) What user modified the document
	UserModified string `json:"UserModified" bson:"UserModified,omitempty"`
	// (ReadOnly) Has the record been deleted
	IsDeleted bool `json:"IsDeleted" bson:"IsDeleted,omitempty"`
	// (Migration/Sync only)ExternalId is used to sync with external systems (Not used for anything internally)
	ExternalID string `json:"ExternalId" bson:"ExternalId,omitempty"`
	// (Migration/Sync only)ExternalNumber is used to sync with external systems (Not used for anything internally)
	ExternalNumber string `json:"ExternalNumber" bson:"ExternalNumber,omitempty"`
	// TenantID pertains to the tenant the document belongs to.  this is not serialized out
	TenantID string `json:"-" bson:"TenantId"`

	APIKey           string      `json:"ApiKey" bson:"ApiKey" binding:"required"`
	Name             string      `json:"Name"  bson:"Name" binding:"required"`
	FullName         string      `json:"FullName"  bson:"FullName" binding:"required"`
	SubDomain        string      `json:"SubDomain"  bson:"SubDomain" binding:"required"`
	Comments         string      `json:"Comments"  bson:"Comments"`
	DatabaseNode     string      `json:"DatabaseNode"  bson:"DatabaseNode"`
	DatabaseName     string      `json:"DatabaseName"  bson:"DatabaseName"`
	IsEnabled        bool        `json:"IsEnabled"  bson:"IsEnabled"`
	PrimaryContactID string      `json:"PrimaryContactId"  bson:"PrimaryContactId"`
	Status           string      `json:"Status"  bson:"Status"`
	CustomerCode     string      `json:"CustomerCode"  bson:"CustomerCode"`
	Address          interface{} `json:"Address"  bson:"Address"`
	PhoneNumber      interface{} `json:"PhoneNumber"  bson:"PhoneNumber"`
	DispatchSystem   string      `json:"DispatchSystem"  bson:"DispatchSystem"`
}

// InitTenant sets the defaults for a new user
func (p *Tenant) InitTenant() {
	eventTime := time.Now().UTC()
	p.ID = bson.NewObjectId().Hex()
	p.DateCreated = eventTime
	p.DateModified = eventTime
	p.IsDeleted = false
}

// TenantConnectionInfo model
type TenantConnectionInfo struct {
	Tenant           Tenant `json:"-" bson:"-"`
	ConnectionString string `json:"-"  bson:"-"`
	DatabaseNode     string `json:"-"  bson:"-"`
	DatabaseName     string `json:"-"  bson:"-"`
	UserModified     string `json:"-" bson:"-"`
	CollectionName   string `json:"-" bson:"-"`
}

// InitBaseTenantConnectionInfo sets the defaults for a new userlogin
func (p *TenantConnectionInfo) InitBaseTenantConnectionInfo() {
	p.ConnectionString = Shares.MongoConnection
}

// Node model used to hold tenant connection information
type Node struct {
	// (ReadOnly) Id of the document, created by system utilizing Mongo Bson Id
	ID string `json:"Id"  bson:"_id" binding:"required"`
	// (ReadOnly) Date the document was created (UTC)
	DateCreated time.Time `json:"DateCreated" bson:"DateCreated" binding:"required"`
	// (ReadOnly) Date the document was modified (UTC)
	DateModified time.Time `json:"DateModified" bson:"DateModified"`
	// (ReadOnly) What user modified the document
	UserModified string `json:"UserModified" bson:"UserModified,omitempty"`
	// (ReadOnly) Has the record been deleted
	IsDeleted bool `json:"IsDeleted" bson:"IsDeleted,omitempty"`
	// (Migration/Sync only)ExternalId is used to sync with external systems (Not used for anything internally)
	ExternalID string `json:"ExternalId" bson:"ExternalId,omitempty"`
	// (Migration/Sync only)ExternalNumber is used to sync with external systems (Not used for anything internally)
	ExternalNumber string `json:"ExternalNumber" bson:"ExternalNumber,omitempty"`
	// TenantID pertains to the tenant the document belongs to.  this is not serialized out
	TenantID   string `json:"-" bson:"TenantId"`
	Name       string `json:"Name" bson:"Name" binding:"required"`
	Connection string `json:"Connection"  bson:"Connection" binding:"required"`
}

// InitNode sets the defaults for a new node
func (p *Node) InitNode() {
	eventTime := time.Now().UTC()
	p.ID = bson.NewObjectId().Hex()
	p.DateCreated = eventTime
	p.DateModified = eventTime
	p.IsDeleted = false
}

// GetBaseConnectionInformation will attempt to locate the tenant by provided informaiton
func GetBaseConnectionInformation(collectionName string) (*TenantConnectionInfo, error) {
	item := new(Tenant)
	item.ID = "global"
	item.Name = "global"
	baseConnectionInfo := new(TenantConnectionInfo)
	baseConnectionInfo.InitBaseTenantConnectionInfo()
	baseConnectionInfo.Tenant = *item
	baseConnectionInfo.CollectionName = collectionName

	return baseConnectionInfo, nil
}
<commit_msg>updated references to use github instead of local<commit_after>package Mongo

import (
	"time"

	"github.com/chadit/GoShare"

	"gopkg.in/mgo.v2/bson"
)

// Tenant model
type Tenant struct {
	// (ReadOnly) Id of the document, created by system utilizing Mongo Bson Id
	ID string `json:"Id"  bson:"_id" binding:"required"`
	// (ReadOnly) Date the document was created (UTC)
	DateCreated time.Time `json:"DateCreated" bson:"DateCreated" binding:"required"`
	// (ReadOnly) Date the document was modified (UTC)
	DateModified time.Time `json:"DateModified" bson:"DateModified"`
	// (ReadOnly) What user modified the document
	UserModified string `json:"UserModified" bson:"UserModified,omitempty"`
	// (ReadOnly) Has the record been deleted
	IsDeleted bool `json:"IsDeleted" bson:"IsDeleted,omitempty"`
	// (Migration/Sync only)ExternalId is used to sync with external systems (Not used for anything internally)
	ExternalID string `json:"ExternalId" bson:"ExternalId,omitempty"`
	// (Migration/Sync only)ExternalNumber is used to sync with external systems (Not used for anything internally)
	ExternalNumber string `json:"ExternalNumber" bson:"ExternalNumber,omitempty"`
	// TenantID pertains to the tenant the document belongs to.  this is not serialized out
	TenantID string `json:"-" bson:"TenantId"`

	APIKey           string      `json:"ApiKey" bson:"ApiKey" binding:"required"`
	Name             string      `json:"Name"  bson:"Name" binding:"required"`
	FullName         string      `json:"FullName"  bson:"FullName" binding:"required"`
	SubDomain        string      `json:"SubDomain"  bson:"SubDomain" binding:"required"`
	Comments         string      `json:"Comments"  bson:"Comments"`
	DatabaseNode     string      `json:"DatabaseNode"  bson:"DatabaseNode"`
	DatabaseName     string      `json:"DatabaseName"  bson:"DatabaseName"`
	IsEnabled        bool        `json:"IsEnabled"  bson:"IsEnabled"`
	PrimaryContactID string      `json:"PrimaryContactId"  bson:"PrimaryContactId"`
	Status           string      `json:"Status"  bson:"Status"`
	CustomerCode     string      `json:"CustomerCode"  bson:"CustomerCode"`
	Address          interface{} `json:"Address"  bson:"Address"`
	PhoneNumber      interface{} `json:"PhoneNumber"  bson:"PhoneNumber"`
	DispatchSystem   string      `json:"DispatchSystem"  bson:"DispatchSystem"`
}

// InitTenant sets the defaults for a new user
func (p *Tenant) InitTenant() {
	eventTime := time.Now().UTC()
	p.ID = bson.NewObjectId().Hex()
	p.DateCreated = eventTime
	p.DateModified = eventTime
	p.IsDeleted = false
}

// TenantConnectionInfo model
type TenantConnectionInfo struct {
	Tenant           Tenant `json:"-" bson:"-"`
	ConnectionString string `json:"-"  bson:"-"`
	DatabaseNode     string `json:"-"  bson:"-"`
	DatabaseName     string `json:"-"  bson:"-"`
	UserModified     string `json:"-" bson:"-"`
	CollectionName   string `json:"-" bson:"-"`
}

// InitBaseTenantConnectionInfo sets the defaults for a new userlogin
func (p *TenantConnectionInfo) InitBaseTenantConnectionInfo() {
	p.ConnectionString = Shares.MongoConnection
}

// Node model used to hold tenant connection information
type Node struct {
	// (ReadOnly) Id of the document, created by system utilizing Mongo Bson Id
	ID string `json:"Id"  bson:"_id" binding:"required"`
	// (ReadOnly) Date the document was created (UTC)
	DateCreated time.Time `json:"DateCreated" bson:"DateCreated" binding:"required"`
	// (ReadOnly) Date the document was modified (UTC)
	DateModified time.Time `json:"DateModified" bson:"DateModified"`
	// (ReadOnly) What user modified the document
	UserModified string `json:"UserModified" bson:"UserModified,omitempty"`
	// (ReadOnly) Has the record been deleted
	IsDeleted bool `json:"IsDeleted" bson:"IsDeleted,omitempty"`
	// (Migration/Sync only)ExternalId is used to sync with external systems (Not used for anything internally)
	ExternalID string `json:"ExternalId" bson:"ExternalId,omitempty"`
	// (Migration/Sync only)ExternalNumber is used to sync with external systems (Not used for anything internally)
	ExternalNumber string `json:"ExternalNumber" bson:"ExternalNumber,omitempty"`
	// TenantID pertains to the tenant the document belongs to.  this is not serialized out
	TenantID   string `json:"-" bson:"TenantId"`
	Name       string `json:"Name" bson:"Name" binding:"required"`
	Connection string `json:"Connection"  bson:"Connection" binding:"required"`
}

// InitNode sets the defaults for a new node
func (p *Node) InitNode() {
	eventTime := time.Now().UTC()
	p.ID = bson.NewObjectId().Hex()
	p.DateCreated = eventTime
	p.DateModified = eventTime
	p.IsDeleted = false
}

// GetBaseConnectionInformation will attempt to locate the tenant by provided informaiton
func GetBaseConnectionInformation(collectionName string) (*TenantConnectionInfo, error) {
	item := new(Tenant)
	item.ID = "global"
	item.Name = "global"
	baseConnectionInfo := new(TenantConnectionInfo)
	baseConnectionInfo.InitBaseTenantConnectionInfo()
	baseConnectionInfo.Tenant = *item
	baseConnectionInfo.CollectionName = collectionName

	return baseConnectionInfo, nil
}
<|endoftext|>


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

/*

Vet examines Go source code and reports suspicious constructs, such as Printf
calls whose arguments do not align with the format string. Vet uses heuristics
that do not guarantee all reports are genuine problems, but it can find errors
not caught by the compilers.

It can be invoked three ways:

By package, from the go tool:
	go vet package/path/name
vets the package whose path is provided.

By files:
	go tool vet source/directory/*.go
vets the files named, all of which must be in the same package.

By directory:
	go tool vet source/directory
recursively descends the directory, vetting each package it finds.

Vet's exit code is 2 for erroneous invocation of the tool, 1 if a
problem was reported, and 0 otherwise. Note that the tool does not
check every possible problem and depends on unreliable heuristics
so it should be used as guidance only, not as a firm indicator of
program correctness.

By default the -all flag is set so all checks are performed.
If any flags are explicitly set to true, only those tests are run. Conversely, if
any flag is explicitly set to false, only those tests are disabled.  Thus -printf=true
runs the printf check, -printf=false runs all checks except the printf check.

By default vet uses the object files generated by 'go install some/pkg' to typecheck the code.
If the -source flag is provided, vet uses only source code.

Available checks:

Assembly declarations

Flag: -asmdecl

Mismatches between assembly files and Go function declarations.

Useless assignments

Flag: -assign

Check for useless assignments.

Atomic mistakes

Flag: -atomic

Common mistaken usages of the sync/atomic package.

Boolean conditions

Flag: -bool

Mistakes involving boolean operators.

Build tags

Flag: -buildtags

Badly formed or misplaced +build tags.

Invalid uses of cgo

Flag: -cgocall

Detect some violations of the cgo pointer passing rules.

Unkeyed composite literals

Flag: -composites

Composite struct literals that do not use the field-keyed syntax.

Copying locks

Flag: -copylocks

Locks that are erroneously passed by value.

HTTP responses used incorrectly

Flag: -httpresponse

Mistakes deferring a function call on an HTTP response before
checking whether the error returned with the response was nil.

Failure to call the cancelation function returned by WithCancel

Flag: -lostcancel

The cancelation function returned by context.WithCancel, WithTimeout,
and WithDeadline must be called or the new context will remain live
until its parent context is cancelled.
(The background context is never cancelled.)

Methods

Flag: -methods

Non-standard signatures for methods with familiar names, including:
	Format GobEncode GobDecode MarshalJSON MarshalXML
	Peek ReadByte ReadFrom ReadRune Scan Seek
	UnmarshalJSON UnreadByte UnreadRune WriteByte
	WriteTo

Nil function comparison

Flag: -nilfunc

Comparisons between functions and nil.

Printf family

Flag: -printf

Suspicious calls to functions in the Printf family, including any functions
with these names, disregarding case:
	Print Printf Println
	Fprint Fprintf Fprintln
	Sprint Sprintf Sprintln
	Error Errorf
	Fatal Fatalf
	Log Logf
	Panic Panicf Panicln
The -printfuncs flag can be used to redefine this list.
If the function name ends with an 'f', the function is assumed to take
a format descriptor string in the manner of fmt.Printf. If not, vet
complains about arguments that look like format descriptor strings.

It also checks for errors such as using a Writer as the first argument of
Printf.

Range loop variables

Flag: -rangeloops

Incorrect uses of range loop variables in closures.

Shadowed variables

Flag: -shadow=false (experimental; must be set explicitly)

Variables that may have been unintentionally shadowed.

Shifts

Flag: -shift

Shifts equal to or longer than the variable's length.

Struct tags

Flag: -structtags

Struct tags that do not follow the format understood by reflect.StructTag.Get.
Well-known encoding struct tags (json, xml) used with unexported fields.

Tests and documentation examples

Flag: -tests

Mistakes involving tests including functions with incorrect names or signatures
and example tests that document identifiers not in the package.

Unreachable code

Flag: -unreachable

Unreachable code.

Misuse of unsafe Pointers

Flag: -unsafeptr

Likely incorrect uses of unsafe.Pointer to convert integers to pointers.
A conversion from uintptr to unsafe.Pointer is invalid if it implies that
there is a uintptr-typed word in memory that holds a pointer value,
because that word will be invisible to stack copying and to the garbage
collector.

Unused result of certain function calls

Flag: -unusedresult

Calls to well-known functions and methods that return a value that is
discarded.  By default, this includes functions like fmt.Errorf and
fmt.Sprintf and methods like String and Error. The flags -unusedfuncs
and -unusedstringmethods control the set.

Other flags

These flags configure the behavior of vet:

	-all (default true)
		Enable all non-experimental checks.
	-v
		Verbose mode
	-printfuncs
		A comma-separated list of print-like function names
		to supplement the standard list.
		For more information, see the discussion of the -printf flag.
	-shadowstrict
		Whether to be strict about shadowing; can be noisy.
*/
package main
<commit_msg>cmd/vet: change docs to prefer "go vet" over "go tool vet"<commit_after>// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/*

Vet examines Go source code and reports suspicious constructs, such as Printf
calls whose arguments do not align with the format string. Vet uses heuristics
that do not guarantee all reports are genuine problems, but it can find errors
not caught by the compilers.

Vet is normally invoked using the go command by running "go vet":

	go vet
vets the package in the current directory.

	go vet package/path/name
vets the package whose path is provided.

Use "go help packages" to see other ways of specifying which packages to vet.

Vet's exit code is 2 for erroneous invocation of the tool, 1 if a
problem was reported, and 0 otherwise. Note that the tool does not
check every possible problem and depends on unreliable heuristics
so it should be used as guidance only, not as a firm indicator of
program correctness.

By default the -all flag is set so all checks are performed.
If any flags are explicitly set to true, only those tests are run. Conversely, if
any flag is explicitly set to false, only those tests are disabled.  Thus -printf=true
runs the printf check, -printf=false runs all checks except the printf check.

By default vet uses the object files generated by 'go install some/pkg' to typecheck the code.
If the -source flag is provided, vet uses only source code.

Available checks:

Assembly declarations

Flag: -asmdecl

Mismatches between assembly files and Go function declarations.

Useless assignments

Flag: -assign

Check for useless assignments.

Atomic mistakes

Flag: -atomic

Common mistaken usages of the sync/atomic package.

Boolean conditions

Flag: -bool

Mistakes involving boolean operators.

Build tags

Flag: -buildtags

Badly formed or misplaced +build tags.

Invalid uses of cgo

Flag: -cgocall

Detect some violations of the cgo pointer passing rules.

Unkeyed composite literals

Flag: -composites

Composite struct literals that do not use the field-keyed syntax.

Copying locks

Flag: -copylocks

Locks that are erroneously passed by value.

HTTP responses used incorrectly

Flag: -httpresponse

Mistakes deferring a function call on an HTTP response before
checking whether the error returned with the response was nil.

Failure to call the cancelation function returned by WithCancel

Flag: -lostcancel

The cancelation function returned by context.WithCancel, WithTimeout,
and WithDeadline must be called or the new context will remain live
until its parent context is cancelled.
(The background context is never cancelled.)

Methods

Flag: -methods

Non-standard signatures for methods with familiar names, including:
	Format GobEncode GobDecode MarshalJSON MarshalXML
	Peek ReadByte ReadFrom ReadRune Scan Seek
	UnmarshalJSON UnreadByte UnreadRune WriteByte
	WriteTo

Nil function comparison

Flag: -nilfunc

Comparisons between functions and nil.

Printf family

Flag: -printf

Suspicious calls to functions in the Printf family, including any functions
with these names, disregarding case:
	Print Printf Println
	Fprint Fprintf Fprintln
	Sprint Sprintf Sprintln
	Error Errorf
	Fatal Fatalf
	Log Logf
	Panic Panicf Panicln
The -printfuncs flag can be used to redefine this list.
If the function name ends with an 'f', the function is assumed to take
a format descriptor string in the manner of fmt.Printf. If not, vet
complains about arguments that look like format descriptor strings.

It also checks for errors such as using a Writer as the first argument of
Printf.

Range loop variables

Flag: -rangeloops

Incorrect uses of range loop variables in closures.

Shadowed variables

Flag: -shadow=false (experimental; must be set explicitly)

Variables that may have been unintentionally shadowed.

Shifts

Flag: -shift

Shifts equal to or longer than the variable's length.

Struct tags

Flag: -structtags

Struct tags that do not follow the format understood by reflect.StructTag.Get.
Well-known encoding struct tags (json, xml) used with unexported fields.

Tests and documentation examples

Flag: -tests

Mistakes involving tests including functions with incorrect names or signatures
and example tests that document identifiers not in the package.

Unreachable code

Flag: -unreachable

Unreachable code.

Misuse of unsafe Pointers

Flag: -unsafeptr

Likely incorrect uses of unsafe.Pointer to convert integers to pointers.
A conversion from uintptr to unsafe.Pointer is invalid if it implies that
there is a uintptr-typed word in memory that holds a pointer value,
because that word will be invisible to stack copying and to the garbage
collector.

Unused result of certain function calls

Flag: -unusedresult

Calls to well-known functions and methods that return a value that is
discarded.  By default, this includes functions like fmt.Errorf and
fmt.Sprintf and methods like String and Error. The flags -unusedfuncs
and -unusedstringmethods control the set.

Other flags

These flags configure the behavior of vet:

	-all (default true)
		Enable all non-experimental checks.
	-v
		Verbose mode
	-printfuncs
		A comma-separated list of print-like function names
		to supplement the standard list.
		For more information, see the discussion of the -printf flag.
	-shadowstrict
		Whether to be strict about shadowing; can be noisy.

Using vet directly

For testing and debugging vet can be run directly by invoking
"go tool vet" or just running the binary. Run this way, vet might not
have up to date information for imported packages.

	go tool vet source/directory/*.go
vets the files named, all of which must be in the same package.

	go tool vet source/directory
recursively descends the directory, vetting each package it finds.

*/
package main
<|endoftext|>