<commit_before>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"mime/multipart"
	"net/http"
	"net/http/cookiejar"
	"net/url"
	"os"
	"path/filepath"
	"strings"

	"bytes"

	"bitbucket.org/ghchinoy/atmotool/zip"
	"github.com/docopt/docopt-go"
)

// Configuration
type Configuration struct {
	Url      string `json:"url"`
	Email    string `json:"email"`
	Password string `json:"password"`
}

type Auth struct {
	Email    string `json:"email"`
	Password string `json:"password"`
}

const LESS_URI = "/resources/theme/default/less?unpack=false"

var (
	config Configuration
	client *http.Client
)

func main() {

	usage := `Akana Community Manager Helper Tool.

Usage:
  atmosphere zip --prefix <prefix> --config <config> [--dir <dir>]
  atmosphere upload less <file> --config <config>
  atmosphere upload file --path <path> --config <config> <files>...
  atmosphere upload all --config <config> [--dir <dir>]
  atmosphere -h | --help
  atmosphere --version

Options:
  -h --help  Show help message and exit.
  --version  Show version and exit.
  --dir=<dir>  Directory. [default: .]
  --path=<cms_path>  CM CMS path.
`
	arguments, _ := docopt.Parse(usage, nil, true, "1.0 cirrus", false)

	// Debug for command-line args
	/*
		var keys []string
		for k := range arguments {
			keys = append(keys, k)
		}
		sort.Strings(keys)
		// print the argument keys and values
		for _, k := range keys {
			fmt.Printf("%9s %v\n", k, arguments[k])
		}
	*/

	configLocation, _ := arguments["<config>"].(string)
	configBytes, err := ioutil.ReadFile(configLocation)
	if err != nil {
		fmt.Printf("Error opening config file %s\n", err)
		flag.Usage()
		os.Exit(1)
	}
	//var config Configuration
	err = json.Unmarshal(configBytes, &config)
	if err != nil {
		fmt.Printf("Unable to parse configuration file. %s\n", err)
		os.Exit(1)
	}

	if len(config.Password) < 1 {
		fmt.Printf("Missing or blank password.")
		os.Exit(1)
	}

	if arguments["upload"] == true {
		if arguments["less"] == true {
			uploadFilePath := arguments["<file>"].(string)
			uploadLessFile(uploadFilePath, config)
		} else if arguments["all"] == true {
			dir, _ := arguments["--dir"].(string)
			uploadAllHelper(dir, config)
		} else if arguments["file"] == true {
			var files []string
			for _, v := range arguments["<files>"].([]string) {
				files = append(files, v)
			}
			path, _ := arguments["--path"].(string)
			upload(files, config, path)
		}
	} else if arguments["zip"] == true {
		prefix, _ := arguments["<prefix>"].(string)
		dir, _ := arguments["--dir"].(string)
		zip.ZipPredefinedPath(prefix, dir)
	}
}

// Convenience method
func uploadLessFile(uploadFilePath string, config Configuration) {
	log.Printf("Uploading Less file %s to %s\n", uploadFilePath, config.Url)

	err := loginToCM()
	if err != nil {
		log.Fatalln(err)
		return
	}

	// Upload
	log.Println("Uploading custom.less ...")
	extraParams := map[string]string{
		"none": "really",
	}
	uploadUri := config.Url + LESS_URI

	statusCode, err := uploadFile(uploadFilePath, extraParams, uploadUri)
	if err != nil {
		log.Fatalf("Issues. %v : %s", statusCode, err)
	}

	log.Printf("Upload status %v", statusCode)

	if statusCode == 200 {
		err = rebuildStyles("default")
		if err != nil {
			log.Fatalln(err)
		}
	}

}

func uploadFile(uploadFilePath string, extras map[string]string, uploadUri string) (int, error) {

	var uploadStatus int

	//uploadUri := config.Url + LESS_URI

	var request *http.Request
	request, err := newFileUploadRequest(uploadUri, extras, "File", uploadFilePath)
	if err != nil {
		log.Fatalln(err)
		return uploadStatus, err
	}
	request.Header.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")

	resp, err := client.Do(request)
	if err != nil {
		log.Fatal(err)
		return uploadStatus, err
	} else {
		body := &bytes.Buffer{}
		_, err := body.ReadFrom(resp.Body)
		if err != nil {
			log.Fatalln(err)
		}
		resp.Body.Close()

		uploadStatus = resp.StatusCode

		//log.Printf("Upload status %v", resp.StatusCode)
	}
	return uploadStatus, nil
}

func loginToCM() error {
	// Login
	log.Println("Logging in...")
	client = &http.Client{}
	jar, err := cookiejar.New(nil)
	if err != nil {
		log.Fatalln(err)
		return err
	}
	client.Jar = jar

	loginUri := config.Url + "/api/login"
	auth := Auth{config.Email, config.Password}
	buf, err := json.Marshal(auth)
	if err != nil {
		log.Fatalln(err)
		return err
	}
	req, err := http.NewRequest("POST", loginUri, bytes.NewReader(buf))
	req.Header.Add("Accept", "application/json")
	req.Header.Add("Content-Type", "application/json")

	resp, err := client.Do(req)
	if err != nil {
		log.Fatalln(err)
		return err
	}
	log.Printf("Login %s", resp.Status)

	return nil

}

func rebuildStyles(theme string) error {

	// call rebuild styles API
	// POST CM_URI/resources/branding/generatestyles
	// Form Data
	// theme: default
	log.Println("Rebuilding styles...")
	rebuildStylesUri := config.Url + "/resources/branding/generatestyles"
	resp, err := http.PostForm(rebuildStylesUri, url.Values{"theme": {theme}})

	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Fatalln(err)
		return err
	}
	var results map[string]interface{}
	err = json.Unmarshal(data, &results)
	status := results["result"]
	log.Printf("Rebuild styles: %s", status)
	return nil
}

func newFileUploadRequest(uri string, params map[string]string, paramName string, path string) (*http.Request, error) {

	file, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer file.Close()

	body := &bytes.Buffer{}
	writer := multipart.NewWriter(body)

	part, err := writer.CreateFormFile(paramName, filepath.Base(path))
	if err != nil {
		return nil, err
	}

	_, err = io.Copy(part, file)
	if err != nil {
		log.Fatalln(err)
		return nil, err
	}

	/*
		for key, val := range params {
			_ = writer.WriteField(key, val)
		}
	*/

	err = writer.Close()
	if err != nil {
		return nil, err
	}

	req, _ := http.NewRequest("POST", uri, body)
	req.Header.Add("Content-Type", writer.FormDataContentType())

	return req, nil
}

// Convenience method
func uploadAllHelper(dir string, config Configuration) {
	fmt.Printf("Uploading all in %s to %s\n", dir, config.Url)
	// upload PREFIX_resourcesThemeDefault.zip to CMS /resources/theme/default
	// upload PREFIX_contentHomeLanding.zip to CMS /content/home/landing
	// upload less file to CMS ??
	// call rebuild styles API

}

// basic upload to CMS
func upload(files []string, config Configuration, path string) {
	fmt.Printf("Uploading to %s cms location %s these: %s\n", config.Url, path, files)
	// upload FILE to CMS path PATH
	// iterate through []FILE

	err := loginToCM()
	if err != nil {
		log.Fatalln(err)
		return
	}

	uploadUri := config.Url + path

	extraParams := map[string]string{
		"none": "really",
	}

	for _, v := range files {
		log.Printf("Uploading %s ...\n", v)
		if strings.HasSuffix(v, ".zip") {
			uploadUri += "?unpack=true"
		}
		log.Println(uploadUri)
		statusCode, err := uploadFile(v, extraParams, uploadUri)
		if err != nil {
			log.Fatalf("Issues. %v : %s", statusCode, err)
		}
		log.Printf("Upload status %v", statusCode)
	}

}
<commit_msg>added zip functionality<commit_after>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"mime/multipart"
	"net/http"
	"net/http/cookiejar"
	"net/url"
	"os"
	"path/filepath"
	"strings"

	"bitbucket.org/apihussain/atmotool/zip"

	"bytes"

	"github.com/docopt/docopt-go"
)

// Configuration
type Configuration struct {
	Url      string `json:"url"`
	Email    string `json:"email"`
	Password string `json:"password"`
}

type Auth struct {
	Email    string `json:"email"`
	Password string `json:"password"`
}

const LESS_URI = "/resources/theme/default/less?unpack=false"

var (
	config Configuration
	client *http.Client
)

func main() {

	usage := `Akana Community Manager Helper Tool.

Usage:
  atmosphere zip --prefix <prefix> [--dir <dir>] --config <config>
  atmosphere upload less <file> --config <config>
  atmosphere upload file --path <path> --config <config> <files>...
  atmosphere upload all --config <config> [--dir <dir>]
  atmosphere -h | --help
  atmosphere --version

Options:
  -h --help  Show help message and exit.
  --version  Show version and exit.
  --dir=<dir>  Directory. [default: .]
  --path=<cms_path>  CM CMS path.
`
	arguments, _ := docopt.Parse(usage, nil, true, "1.0 cirrus", false)

	// Debug for command-line args
	/*
		var keys []string
		for k := range arguments {
			keys = append(keys, k)
		}
		sort.Strings(keys)
		// print the argument keys and values
		for _, k := range keys {
			fmt.Printf("%9s %v\n", k, arguments[k])
		}
	*/

	configLocation, _ := arguments["<config>"].(string)
	configBytes, err := ioutil.ReadFile(configLocation)
	if err != nil {
		fmt.Printf("Error opening config file %s\n", err)
		flag.Usage()
		os.Exit(1)
	}
	//var config Configuration
	err = json.Unmarshal(configBytes, &config)
	if err != nil {
		fmt.Printf("Unable to parse configuration file. %s\n", err)
		os.Exit(1)
	}

	if len(config.Password) < 1 {
		fmt.Printf("Missing or blank password.")
		os.Exit(1)
	}

	if arguments["upload"] == true {
		if arguments["less"] == true {
			uploadFilePath := arguments["<file>"].(string)
			uploadLessFile(uploadFilePath, config)
		} else if arguments["all"] == true {
			dir, _ := arguments["--dir"].(string)
			uploadAllHelper(dir, config)
		} else if arguments["file"] == true {
			var files []string
			for _, v := range arguments["<files>"].([]string) {
				files = append(files, v)
			}
			path, _ := arguments["--path"].(string)
			upload(files, config, path)
		}
	} else if arguments["zip"] == true {
		prefix, _ := arguments["<prefix>"].(string)
		dir, _ := arguments["--dir"].(string)
		//zip.ZipPredefinedPath(prefix, dir)
		var fn string
		if dir == "." {
			fn = "this"
		} else {
			fn = strings.Replace(dir, "/", "-", -1)
		}
		fn = prefix + "_" + fn + ".zip"
		fmt.Printf("Zipping %s as %s...\n", dir, fn)

		zip.ZipFolder(dir, fn)
	}
}

// Convenience method
func uploadLessFile(uploadFilePath string, config Configuration) {
	log.Printf("Uploading Less file %s to %s\n", uploadFilePath, config.Url)

	err := loginToCM()
	if err != nil {
		log.Fatalln(err)
		return
	}

	// Upload
	log.Println("Uploading custom.less ...")
	extraParams := map[string]string{
		"none": "really",
	}
	uploadUri := config.Url + LESS_URI

	statusCode, err := uploadFile(uploadFilePath, extraParams, uploadUri)
	if err != nil {
		log.Fatalf("Issues. %v : %s", statusCode, err)
	}

	log.Printf("Upload status %v", statusCode)

	if statusCode == 200 {
		err = rebuildStyles("default")
		if err != nil {
			log.Fatalln(err)
		}
	}

}

func uploadFile(uploadFilePath string, extras map[string]string, uploadUri string) (int, error) {

	var uploadStatus int

	//uploadUri := config.Url + LESS_URI

	var request *http.Request
	request, err := newFileUploadRequest(uploadUri, extras, "File", uploadFilePath)
	if err != nil {
		log.Fatalln(err)
		return uploadStatus, err
	}
	request.Header.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")

	resp, err := client.Do(request)
	if err != nil {
		log.Fatal(err)
		return uploadStatus, err
	} else {
		body := &bytes.Buffer{}
		_, err := body.ReadFrom(resp.Body)
		if err != nil {
			log.Fatalln(err)
		}
		resp.Body.Close()

		uploadStatus = resp.StatusCode

		//log.Printf("Upload status %v", resp.StatusCode)
	}
	return uploadStatus, nil
}

func loginToCM() error {
	// Login
	log.Println("Logging in...")
	client = &http.Client{}
	jar, err := cookiejar.New(nil)
	if err != nil {
		log.Fatalln(err)
		return err
	}
	client.Jar = jar

	loginUri := config.Url + "/api/login"
	auth := Auth{config.Email, config.Password}
	buf, err := json.Marshal(auth)
	if err != nil {
		log.Fatalln(err)
		return err
	}
	req, err := http.NewRequest("POST", loginUri, bytes.NewReader(buf))
	req.Header.Add("Accept", "application/json")
	req.Header.Add("Content-Type", "application/json")

	resp, err := client.Do(req)
	if err != nil {
		log.Fatalln(err)
		return err
	}
	log.Printf("Login %s", resp.Status)

	return nil

}

func rebuildStyles(theme string) error {

	// call rebuild styles API
	// POST CM_URI/resources/branding/generatestyles
	// Form Data
	// theme: default
	log.Println("Rebuilding styles...")
	rebuildStylesUri := config.Url + "/resources/branding/generatestyles"
	resp, err := http.PostForm(rebuildStylesUri, url.Values{"theme": {theme}})

	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Fatalln(err)
		return err
	}
	var results map[string]interface{}
	err = json.Unmarshal(data, &results)
	status := results["result"]
	log.Printf("Rebuild styles: %s", status)
	return nil
}

func newFileUploadRequest(uri string, params map[string]string, paramName string, path string) (*http.Request, error) {

	file, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer file.Close()

	body := &bytes.Buffer{}
	writer := multipart.NewWriter(body)

	part, err := writer.CreateFormFile(paramName, filepath.Base(path))
	if err != nil {
		return nil, err
	}

	_, err = io.Copy(part, file)
	if err != nil {
		log.Fatalln(err)
		return nil, err
	}

	/*
		for key, val := range params {
			_ = writer.WriteField(key, val)
		}
	*/

	err = writer.Close()
	if err != nil {
		return nil, err
	}

	req, _ := http.NewRequest("POST", uri, body)
	req.Header.Add("Content-Type", writer.FormDataContentType())

	return req, nil
}

// Convenience method
func uploadAllHelper(dir string, config Configuration) {
	fmt.Printf("Uploading all in %s to %s\n", dir, config.Url)
	// upload PREFIX_resourcesThemeDefault.zip to CMS /resources/theme/default
	// upload PREFIX_contentHomeLanding.zip to CMS /content/home/landing
	// upload less file to CMS ??
	// call rebuild styles API

}

// basic upload to CMS
func upload(files []string, config Configuration, path string) {
	fmt.Printf("Uploading to %s cms location %s these: %s\n", config.Url, path, files)
	// upload FILE to CMS path PATH
	// iterate through []FILE

	err := loginToCM()
	if err != nil {
		log.Fatalln(err)
		return
	}

	uploadUri := config.Url + path

	extraParams := map[string]string{
		"none": "really",
	}

	for _, v := range files {
		log.Printf("Uploading %s ...\n", v)
		if strings.HasSuffix(v, ".zip") {
			uploadUri += "?unpack=true"
		}
		log.Println(uploadUri)
		statusCode, err := uploadFile(v, extraParams, uploadUri)
		if err != nil {
			log.Fatalf("Issues. %v : %s", statusCode, err)
		}
		log.Printf("Upload status %v", statusCode)
	}

}
<|endoftext|>


<commit_before>package abkzeromq

import (
  "fmt"
  "strings"
  zmq "github.com/alecthomas/gozmq"
)

type READ func(key string) string
type PUSH func(key string, val string) bool
type DELETE func(key string) bool

func ZmqRep(req_port int, rep_port int, read READ, push PUSH, del DELETE) {
  context, _ := zmq.NewContext()
  socket, _ := context.NewSocket(zmq.REP)
  socket.Bind(fmt.Sprintf("tcp://127.0.0.1:%d", req_port))
  socket.Bind(fmt.Sprintf("tcp://127.0.0.1:%d", rep_port))

  fmt.Printf("ZMQ REQ/REP Daemon at port %d and %d\n", req_port, rep_port)
  for {
    msg, _ := socket.Recv(0)
    fmt.Println("Got:", string(msg))
    msg_arr := strings.Fields(string(msg))
    if msg_arr[0] == "read" {
      read(msg_arr[1])
    } else if msg_arr[0] == "push" {
      push(msg_arr[1], strings.Join(msg_arr[2:], " "))
    } else if msg_arr[0] == "delete" {
      del(msg_arr[1])
    } else {
      fmt.Printf("unhandled request sent: %s" % msg)
    }
    socket.Send(msg, 0)
  }
}

func ZmqReq(req_port int, rep_port int, dat ...string) {
  fmt.Printf("ZMQ REQ/REP Client at port %d and %d\n", req_port, rep_port)
  context, _ := zmq.NewContext()
  socket, _ := context.NewSocket(zmq.REQ)
  socket.Connect(fmt.Sprintf("tcp://127.0.0.1:%d", req_port))
  socket.Connect(fmt.Sprintf("tcp://127.0.0.1:%d", rep_port))

  var msg string
  msg = strings.Join(dat, " ")
  socket.Send([]byte(msg), 0)
  fmt.Printf("msg: %s\n", msg)
  socket.Recv(0)
}
<commit_msg>zeromq/zeromq string interpolation corrected, from python-way :sleepy:<commit_after>package abkzeromq

import (
  "fmt"
  "strings"
  zmq "github.com/alecthomas/gozmq"
)

type READ func(key string) string
type PUSH func(key string, val string) bool
type DELETE func(key string) bool

func ZmqRep(req_port int, rep_port int, read READ, push PUSH, del DELETE) {
  context, _ := zmq.NewContext()
  socket, _ := context.NewSocket(zmq.REP)
  socket.Bind(fmt.Sprintf("tcp://127.0.0.1:%d", req_port))
  socket.Bind(fmt.Sprintf("tcp://127.0.0.1:%d", rep_port))

  fmt.Printf("ZMQ REQ/REP Daemon at port %d and %d\n", req_port, rep_port)
  for {
    msg, _ := socket.Recv(0)
    fmt.Println("Got:", string(msg))
    msg_arr := strings.Fields(string(msg))
    if msg_arr[0] == "read" {
      read(msg_arr[1])
    } else if msg_arr[0] == "push" {
      push(msg_arr[1], strings.Join(msg_arr[2:], " "))
    } else if msg_arr[0] == "delete" {
      del(msg_arr[1])
    } else {
      fmt.Printf("unhandled request sent: %s", msg)
    }
    socket.Send(msg, 0)
  }
}

func ZmqReq(req_port int, rep_port int, dat ...string) {
  fmt.Printf("ZMQ REQ/REP Client at port %d and %d\n", req_port, rep_port)
  context, _ := zmq.NewContext()
  socket, _ := context.NewSocket(zmq.REQ)
  socket.Connect(fmt.Sprintf("tcp://127.0.0.1:%d", req_port))
  socket.Connect(fmt.Sprintf("tcp://127.0.0.1:%d", rep_port))

  var msg string
  msg = strings.Join(dat, " ")
  socket.Send([]byte(msg), 0)
  fmt.Printf("msg: %s\n", msg)
  socket.Recv(0)
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 Pani Networks
// All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.

package kubernetes

/* disabled since it tries to mimic kubernets which
   and now we are using k8s.io/client-go which is would
   make us to mimic tooo much of kubernetes to pass the test.
import (
	"encoding/json"
	"fmt"
	"github.com/go-check/check"
	log "github.com/romana/rlog"
	"github.com/romana/core/common"
	"github.com/romana/core/tenant"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"testing"
	"time"
)

func Test(t *testing.T) {
	check.TestingT(t)
}

type MySuite struct {
	serviceURL  string
	servicePort int
	kubeURL     string
	c           *check.C
}

var _ = check.Suite(&MySuite{})

type kubeSimulator struct {
	mockSvc *mockSvc
}

// ServeHTTP is a handler that will be used to simulate Kubernetes
func (ks *kubeSimulator) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	//	w.Header().Set("Connection", "Keep-Alive")
	//	w.Header().Set("Transfer-Encoding", "chunked")
	log.Info("Test: Entered kubeSimulator ServeHTTP()")
	// flusher, _ := w.(http.Flusher)

	//	flusher, _ := w.(http.Flusher)
	reqURI, _ := url.Parse(r.RequestURI)
	path := fmt.Sprintf("%s?%s", reqURI.Path, reqURI.RawQuery)
	log.Infof("KubeSimulator: At %s", path)

	var ns Event
	err := json.Unmarshal([]byte(addNamespace1), &ns)
	if err != nil {
		log.Infof("KubeSimulator: At %s: failed to unmarshall kube event %s", path, err)
		return
	}

	var pol Event
	err = json.Unmarshal([]byte(addPolicy1), &pol)
	if err != nil {
		log.Infof("KubeSimulator: At %s: failed to unmarshall kube event %sl", path, err)
		return
	}

	if path == "/api/v1/namespaces/?watch=true" {
		log.Infof("KubeSimulator: At %s: Sending namespace event %s", path, addNamespace1)
		//		fmt.Fprintf(w, addNamespace1)
		enc := json.NewEncoder(w)
		for {
			err = enc.Encode(ns)
			if err != nil {
				log.Infof("KubeSimulator: At %s: failed to encode namespace event %s", path, err)
				return
			}
			time.Sleep(100 * time.Millisecond)
		}
	}

	if strings.HasPrefix(path, "/apis/extensions/v1beta1/namespaces/") && strings.HasSuffix(path, "/networkpolicies?") {
		log.Infof("KubeSimulator: At %s", path)
		flusher, _ := w.(http.Flusher)
		w.Write([]byte("{ \"metadata\" : { \"resourceVersion\" : \"1\" } }"))
		flusher.Flush()

		return
	}

	m := make(map[string]string)
	m["x"] = "y"
	if strings.HasPrefix(path, "/apis/extensions/v1beta1/namespaces/") && strings.HasSuffix(path, "/networkpolicies?watch=true&resourceVersion=1") {
		log.Infof("KubeSimulator: At %s", path)
		uriArr := strings.Split(path, "/")
		if len(uriArr) != 7 {
			log.Infof("KubeSimulator: At %s, exiting expected 8 parts in url, got %d", path, len(uriArr))
			w.WriteHeader(http.StatusNotFound)
			w.Write([]byte(fmt.Sprintf("{\"error\" : \"Not found: %s (expected 9, got %d parts of the URL: %v)\"}", path, len(uriArr), uriArr)))
			return
		}

		for {
			log.Infof("KubeSimulator: At %s: have %d tenants", path, len(ks.mockSvc.tenants))
			// Wait until sentNamespaceEvent is true
			if len(ks.mockSvc.tenants) == 1 {
				log.Infof("KubeSimulator: At %s: tenants[1]: %+v", path, *ks.mockSvc.tenants[1])
				break
			}

			flusher, _ := w.(http.Flusher)
			w.Write([]byte("{}"))
			flusher.Flush()

			if err != nil {
				log.Infof("KubeSimulator: At %s: failed to encode empty event %s", path, err)
				return
			}
			time.Sleep(100 * time.Millisecond)
		}

		enc := json.NewEncoder(w)
		for {
			err = enc.Encode(pol)
			if err != nil {
				log.Infof("KubeSimulator: At %s: failed to encode policy event %s", path, err)
				return
			}
			time.Sleep(100 * time.Millisecond)
		}
	}
	w.WriteHeader(http.StatusNotFound)
	w.Write([]byte(fmt.Sprintf("Not found: %s", path)))
	return
}

// mockSvc is a Romana Service used in tests.
type mockSvc struct {
	mySuite *MySuite
	// To simulate tenant/segment database.
	// tenantCounter will provide tenant IDs
	tenantCounter uint64
	// Map of tenant ID Tenant
	tenants map[uint64]*tenant.Tenant

	segmentCounter uint64

	segments map[uint64]*tenant.Segment
	policies []common.Policy
}

func (s *mockSvc) SetConfig(config common.ServiceConfig) error {
	return nil
}

func (s *mockSvc) Name() string {
	return common.ServiceRoot
}

func (s *mockSvc) Initialize() error {
	return nil
}

func (s *mockSvc) Routes() common.Routes {
	addPolicyRoute := common.Route{
		Method:  "POST",
		Pattern: "/policies",
		Handler: func(input interface{}, ctx common.RestContext) (interface{}, error) {
			log.Infof("MockService: Entering POST /policies\n")
			j, _ := json.Marshal(input)
			log.Infof("Mock policy received: %T %s", input, j)
			switch input := input.(type) {
			case *common.Policy:
				for _, p := range s.policies {
					if p.Name == input.Name {
						return input, common.NewErrorConflict(fmt.Sprintf("Policy with name %s already exists", input.Name))
					}
				}
				s.policies = append(s.policies, *input)
				return input, nil
			default:
				panic(common.NewError("Expected common.Policy, got %+v", input))
			}
		},
		MakeMessage: func() interface{} { return &common.Policy{} },
	}

	deletePolicyRoute := common.Route{
		Method:  "DELETE",
		Pattern: "/policies/{policyID}",
		Handler: func(input interface{}, ctx common.RestContext) (interface{}, error) {
			idStr := ctx.PathVariables["policyID"]
			log.Infof("MockService: Entering DELETE /policies/%s\n", idStr)
			id, err := strconv.ParseUint(idStr, 10, 64)
			if err != nil {
				return nil, common.NewError400(fmt.Sprintf("Bad ID %s", idStr))
			}
			delete := func(i int, a []common.Policy) []common.Policy {
				return append(a[:i], a[i+1:]...)
			}
			var ret *common.Policy
			for n, _ := range s.policies {
				log.Tracef(4,"Delete policy by id, comparing %d and %d", s.policies[n].ID, id)
				if s.policies[n].ID == id {
					ret = &s.policies[n]
					s.policies = delete(n, s.policies)
					break
				}
			}

			if ret == nil {
				return nil, common.NewError404("policies", idStr)
			}
			return ret, nil
		},
	}

	policyGetAll := common.Route{
		Method:  "GET",
		Pattern: "/policies",
		Handler: func(input interface{}, ctx common.RestContext) (interface{}, error) {
			log.Infof("MockService: Entering GET /policies\n")

			return s.policies, nil
		},
	}

	findLastTenantRoute := common.Route{
		Method:  "GET",
		Pattern: "/findLast/tenants",
		Handler: func(input interface{}, ctx common.RestContext) (interface{}, error) {
			log.Infof("MockService: Entering GET /findLast/tenants with %+v\n", ctx.QueryVariables)
			name := ctx.QueryVariables["name"][0]
			var found *tenant.Tenant
			for _, v := range s.tenants {
				if name == v.Name {
					found = v
				}
			}
			if found == nil {
				return nil, common.NewError404("tenant", fmt.Sprintf("name=%s", name))
			}
			return found, nil
		},
		MakeMessage: nil,
	}

	findExactlyOneSegmentRoute := common.Route{
		Method:  "GET",
		Pattern: "/findExactlyOne/segments",
		Handler: func(input interface{}, ctx common.RestContext) (interface{}, error) {
			log.Infof("MockService: Entering GET /findExactlyOne/segments with %+v\n", ctx.QueryVariables)
			name := ctx.QueryVariables["name"][0]
			var found *tenant.Segment
			for _, v := range s.segments {
				if name == v.Name {
					if found != nil {
						return nil, common.NewError500(fmt.Sprintf("Multiple results found for %s", name))
					}
					found = v
				}
			}
			if found == nil {
				return nil, common.NewError404("segment", fmt.Sprintf("name=%s", name))
			}
			return found, nil
		},
		MakeMessage: nil,
	}

	kubeListenerConfigRoute := common.Route{
		Method:  "GET",
		Pattern: "/config/kubernetesListener",
		Handler: func(input interface{}, ctx common.RestContext) (interface{}, error) {
			log.Infof("MockService: Entering GET /config/kubernetesListener\n")
			json := `{"common":{"api":{"host":"0.0.0.0","port":9606}},
			"config":{"kubernetes_url":"http://localhost",
			"segment_label_name":"tier",
			"namespace_notification_path: "/api/v1/namespaces",
			"policy_notification_path_prefix : "apis/extensions/v1beta1/namespaces",
			"policy_notification_path_postfix : "networkpolicies",
      		}}`
			return common.Raw{Body: json}, nil
		},
	}

	tenantAddRoute := common.Route{
		Method:  "POST",
		Pattern: "/tenants",
		Handler: func(input interface{}, ctx common.RestContext) (interface{}, error) {
			log.Info("MockService: Entering POST /tenants with %+v\n", input)
			newTenant := input.(*tenant.Tenant)
			for _, v := range s.tenants {
				if v.ExternalID == newTenant.ExternalID {
					return nil, common.NewErrorConflict(newTenant)
				}
			}
			s.tenantCounter++
			newTenant.ID = s.tenantCounter
			s.tenants[newTenant.ID] = newTenant
			str := ""
			for k, v := range s.tenants {
				str += fmt.Sprintf("\t%d => %+v\n", k, v)
			}
			log.Infof("MockService: Have tenants: %s", str)
			return newTenant, nil
		},
		MakeMessage: func() interface{} { return &tenant.Tenant{} },
	}

	tenantGetRoute := common.Route{
		Method:  "GET",
		Pattern: "/tenants/{tenantID}",
		Handler: func(input interface{}, ctx common.RestContext) (interface{}, error) {
			idStr := ctx.PathVariables["tenantID"]
			log.Infof("MockService: Entering GET /tenants/%s\n", idStr)
			id, err := strconv.ParseUint(idStr, 10, 64)
			if err != nil {
				return nil, common.NewError400(fmt.Sprintf("Bad ID %s", idStr))
			}
			tenant := s.tenants[id]
			if tenant == nil {
				return nil, common.NewError404("tenant", idStr)
			}
			return tenant, nil
		},
	}

	tenantGetAllRoute := common.Route{
		Method:  "GET",
		Pattern: "/tenants",
		Handler: func(input interface{}, ctx common.RestContext) (interface{}, error) {
			log.Infof("MockService: Entering GET /tenants")
			var tr []tenant.Tenant
			for tk, _ := range s.tenants {
				tr = append(tr, *s.tenants[tk])
			}

			return tr, nil
		},
	}

	segmentAddRoute := common.Route{
		Method: "POST",
		// For the purpose of this test, we are going to ignore tenantID and pretend
		// it's the correct one.
		Pattern: "/tenants/{tenantID}/segments",
		Handler: func(input interface{}, ctx common.RestContext) (interface{}, error) {
			tenantIDStr := ctx.PathVariables["tenantID"]
			log.Info("MockService: Entering POST /tenants/%s/segment\n", tenantIDStr)
			newSegment := input.(*tenant.Segment)
			tenantID, _ := strconv.Atoi(tenantIDStr)
			newSegment.TenantID = uint64(tenantID)
			for _, v := range s.segments {
				if newSegment.ExternalID == v.ExternalID && newSegment.Name == v.Name {
					return nil, common.NewErrorConflict(newSegment)
				}
			}

			s.segmentCounter++
			newSegment.ID = s.segmentCounter
			s.segments[s.segmentCounter] = newSegment
			str := ""
			for k, v := range s.segments {
				str += fmt.Sprintf("\t%d => %+v\n", k, v)
			}
			log.Infof("MockService: Have segments: %s", str)
			return newSegment, nil
		},
		MakeMessage: func() interface{} { return &tenant.Segment{} },
	}

	segmentGetAllRoute := common.Route{
		Method:  "GET",
		Pattern: "/tenants/{tenantID}/segments",
		Handler: func(input interface{}, ctx common.RestContext) (interface{}, error) {
			var sr []tenant.Segment
			tenantIDStr := ctx.PathVariables["tenantID"]
			id, err := strconv.ParseUint(tenantIDStr, 10, 64)
			if err != nil {
				return nil, common.NewError400(fmt.Sprintf("Bad ID %s", tenantIDStr))
			}
			for sn, sv := range s.segments {
				if sv.TenantID == id {
					sr = append(sr, *s.segments[sn])
				}
			}

			return sr, nil
		},
	}

	segmentGetRoute := common.Route{
		Method:  "GET",
		Pattern: "/tenants/{tenantID}/segments/{segmentID}",
		Handler: func(input interface{}, ctx common.RestContext) (interface{}, error) {
			tenantIDStr := ctx.PathVariables["tenantID"]
			segmentIDStr := ctx.PathVariables["segmentID"]
			log.Infof("MockService: Entering GET /tenants/%s/segment/%s\n", tenantIDStr, segmentIDStr)
			segmentID, err := strconv.ParseUint(segmentIDStr, 10, 64)
			if err != nil {
				return nil, common.NewError400(fmt.Sprintf("Bad ID %s", segmentIDStr))
			}
			segment := s.segments[segmentID]
			if segment == nil {
				return nil, common.NewError404("segment", segmentIDStr)
			}
			return segment, nil
		},
	}

	rootRoute := common.Route{
		Method:  "GET",
		Pattern: "/",
		Handler: func(input interface{}, ctx common.RestContext) (interface{}, error) {
			log.Infof("MockService: Entering GET /\n")
			json := `{"serviceName":"root",
			"Links":
			[
			{"Href":"/config/root","Rel":"root-config"},
			{"Href":"/config/ipam","Rel":"ipam-config"},
			{"Href":"/config/tenant","Rel":"tenant-config"},
			{"Href":"/config/topology","Rel":"topology-config"},
			{"Href":"/config/agent","Rel":"agent-config"},
			{"Href":"/config/policy","Rel":"policy-config"},
			{"Href":"/config/kubernetesListener","Rel":"kubernetesListener-config"},
			{"Href":"SERVICE_URL","Rel":"self"}
			],
			"Services":
			[
			{"Name":"root","Links":[{"Href":"SERVICE_URL","Rel":"service"}]},
			{"Name":"ipam","Links":[{"Href":"SERVICE_URL","Rel":"service"}]},
			{"Name":"tenant","Links":[{"Href":"SERVICE_URL","Rel":"service"}]},
			{"Name":"topology","Links":[{"Href":"SERVICE_URL","Rel":"service"}]},
			{"Name":"agent","Links":[{"Href":"SERVICE_URL:PORT","Rel":"service"}]},
			{"Name":"policy","Links":[{"Href":"SERVICE_URL","Rel":"service"}]},
			{"Name":"kubernetesListener","Links":[{"Href":"SERVICE_URL","Rel":"service"}]}
			]
			}
			`
			retval := fmt.Sprintf(strings.Replace(json, "SERVICE_URL", s.mySuite.serviceURL, -1))
			//			log.Infof("Using %s->SERVICE_URL, replaced\n\t%swith\n\t%s", s.mySuite.serviceURL, json, retval)
			return common.Raw{Body: retval}, nil
		},
	}

	registerPortRoute := common.Route{
		Method:  "POST",
		Pattern: "/config/kubernetes-listener/port",
		Handler: func(input interface{}, ctx common.RestContext) (interface{}, error) {
			log.Infof("Received %+v", input)
			return "OK", nil
		},
	}

	routes := common.Routes{
		addPolicyRoute,
		deletePolicyRoute,
		policyGetAll,
		rootRoute,
		tenantAddRoute,
		tenantGetRoute,
		tenantGetAllRoute,
		segmentGetRoute,
		segmentGetAllRoute,
		segmentAddRoute,
		kubeListenerConfigRoute,
		registerPortRoute,
		findExactlyOneSegmentRoute,
		findLastTenantRoute,
	}
	log.Infof("mockService: Set up routes: %+v", routes)
	return routes
}

func (s *MySuite) getKubeListenerServiceConfig() *common.ServiceConfig {
	url, _ := url.Parse(s.serviceURL)
	hostPort := strings.Split(url.Host, ":")
	port, _ := strconv.ParseUint(hostPort[1], 10, 64)
	api := &common.Api{Host: "localhost", Port: port, RootServiceUrl: s.serviceURL}
	commonConfig := common.CommonConfig{Api: api}
	kubeListenerConfig := make(map[string]interface{})
	kubeListenerConfig["kubernetes_url"] = s.kubeURL
	kubeListenerConfig["namespace_notification_path"] = "/api/v1/namespaces"
	kubeListenerConfig["policy_notification_path_prefix"] = "apis/extensions/v1beta1/namespaces"
	kubeListenerConfig["policy_notification_path_postfix"] = "networkpolicies"
	kubeListenerConfig["segment_label_name"] = "tier"

	svcConfig := common.ServiceConfig{Common: commonConfig, ServiceSpecific: kubeListenerConfig}
	log.Infof("Test: Returning KubernetesListener config %+v", svcConfig.ServiceSpecific)
	return &svcConfig

}

type RomanaT struct {
	testing.T
}

func (s *MySuite) startListener() error {
	clientConfig := common.GetDefaultRestClientConfig(s.serviceURL)
	client, err := common.NewRestClient(clientConfig)
	if err != nil {
		return err
	}
	kubeListener := &kubeListener{}
	kubeListener.restClient = client
	config := s.getKubeListenerServiceConfig()

	_, err = common.InitializeService(kubeListener, *config)
	if err != nil {
		return err
	}

	// DEBUG </
	tc := PTranslator.GetClient()
	if tc == nil {
		log.Error("DEBUG Translator has nil client before Init")
	}

	PTranslator.Init(client, kubeListener.segmentLabelName)
	tc = PTranslator.GetClient()
	if tc == nil {
		log.Fatal("DEBUG Translator has nil client after Init")
	}

	// DEBUG />

	return nil
}

func (s *MySuite) TestListener(c *check.C) {
	var err error
	cfg := &common.ServiceConfig{Common: common.CommonConfig{Api: &common.Api{Port: 0, RestTimeoutMillis: 100}}}
	log.Infof("Test: Mock service config:\n\t%+v\n\t%+v\n", cfg.Common.Api, cfg.ServiceSpecific)
	svc := &mockSvc{mySuite: s}
	svc.tenants = make(map[uint64]*tenant.Tenant)
	svc.segments = make(map[uint64]*tenant.Segment)
	svc.policies = make([]common.Policy, 0)
	svc.policies = append(svc.policies, makeTestPolicy2())
	svcInfo, err := common.InitializeService(svc, *cfg)
	if err != nil {
		c.Error(err)
	}
	msg := <-svcInfo.Channel
	log.Infof("Test: Mock service says %s\n", msg)
	s.serviceURL = fmt.Sprintf("http://%s", svcInfo.Address)
	log.Infof("Test: Mock service listens at %s\n", s.serviceURL)

	// Start Kubernetes simulator
	svr := &http.Server{}
	svr.Handler = &kubeSimulator{mockSvc: svc}
	log.Infof("TestListener: Calling ListenAndServe(%p)", svr)
	svcInfo, err = common.ListenAndServe(svr)
	if err != nil {
		c.Error(err)
	}
	msg = <-svcInfo.Channel
	log.Infof("TestListener: Kubernetes said %s", msg)
	s.kubeURL = fmt.Sprintf("http://%s", svcInfo.Address)
	log.Infof("Test: Kubernetes listening on %s (%s)", s.kubeURL, svcInfo.Address)

	// Start listener
	err = s.startListener()
	if err != nil {
		c.Error(err)
	}
	log.Infof("Test: KubeListener started\n")
	time.Sleep(5 * time.Second)
	log.Infof("Policies: %+v\n", svc.policies)
	c.Assert(len(svc.policies), check.Equals, 2)
	c.Assert(svc.policies[0].Name, check.Equals, "ns0")
	c.Assert(svc.policies[1].Name, check.Equals, "kube.default.pol1")
}

func makeTestPolicy2() common.Policy {
	TestPolicy2 := common.Policy{
		Description: "Predefined test policy to test listener sync",
		Direction:   "ingress",
		Name:        "kube.default.pol2",
		ID:          999,
		AppliedTo: []common.Endpoint{
			common.Endpoint{
				Dest: "host",
			},
		},
		Peers: []common.Endpoint{
			common.Endpoint{
				Peer: "local",
			},
		},
		Rules: []common.Rule{
			common.Rule{
				Ports:    []uint{67},
				Protocol: "UPD",
			},
		},
	}
	return TestPolicy2
}

const (
	addPolicy1 = `{
		"type":"ADDED",
		"object":
			{
				"apiVersion":"romana.io/demo/v1",
				"kind":"NetworkPolicy",
				"metadata":
					{
						"name":"pol1",
						"namespace":"default",
						"selfLink":"/apis/extensions/v1beta1/namespaces/default/networkpolicies/pol1",
						"uid":"d7036130-e119-11e5-aab8-0213e1312dc5",
						"resourceVersion":"119875",
						"creationTimestamp":"2016-03-03T08:28:00Z",
						"labels":
									{
									"owner":"t1"
									}
					},
				"spec":
					{
						"ingress":
						    [
							{
								"from": [
										    { "podSelector": { "matchLabels" :
										    	{"tier":"frontend"}
										    	}
											}
										],
								"ports":[
											{
												"port":80,
												"protocol":"TCP"

											}
											]

							}
							],
						"podSelector": {
							"matchLabels" : {
								"tier":"backend"
							}
							}
						}
					}
			}`
	addNamespace1 = `{"type":"ADDED","object":{
	 				"kind":"Namespace",
	 				"apiVersion":"v1",
	 				"metadata":{
	 						"name":"default",
	 						"selfLink":"/api/v1/namespaces/tenant1",
	 						"uid":"d10db271-dc03-11e5-9c86-0213e1312dc5",
	 						"resourceVersion":"6",
	 						"creationTimestamp":"2016-02-25T21:07:45Z"
	 						},
	 				"spec":{"finalizers":["kubernetes"]},"status":{"phase":"Active"}}}`
)
*/
<commit_msg>listener: remove file which has only comment code in it.<commit_after><|endoftext|>


<commit_before>package main

import (
	"encoding/xml"
	"flag"
	"image"
	"image/draw"
	"image/png"
	"io"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
)

var (
	root = "../../../"
)

var (
	flagRoot string
)

func init() {
	flag.StringVar(&flagRoot, "root", "", "setup liteide root")
}

func main() {
	flag.Parse()
	if flagRoot != "" {
		root = flagRoot
	}
	root, _ := filepath.Abs(root)
	log.Println("process qrc files in liteide root", root)
	var p Process
	p.ProcessDir(filepath.Join(root, "src/liteapp"))
	p.ProcessDir(filepath.Join(root, "src/plugins"))
	p.Export(filepath.Join(root, "deploy/liteapp/qrc/default"), CopyFile)
	p.Export(filepath.Join(root, "deploy/liteapp/qrc/gray"), GrayImage)
}

type Process struct {
	rccs []RCC
}

func (p *Process) ProcessDir(dir string) {
	filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
		if filepath.Ext(path) == ".qrc" {
			p.ProcessQrc(path)
		}
		return nil
	})
}

type QResource struct {
	Prefix string   `xml:"prefix,attr"`
	Files  []string `xml:"file"`
}

type RCC struct {
	Dir      string
	DirName  string
	FileName string
	XMLName  xml.Name  `xml:"RCC"`
	Resource QResource `xml:"qresource"`
}

func (rcc *RCC) IsEmtpy() bool {
	return len(rcc.Resource.Files) == 0
}

func (rcc *RCC) ImagesFiles() (images []string) {
	for _, file := range rcc.Resource.Files {
		if filepath.Ext(file) == ".png" {
			image := filepath.Join(rcc.Dir, file)
			_, err := os.Lstat(image)
			if err != nil {
				log.Println("warning, not find image", image)
			}
			images = append(images, image)
		}
	}
	return
}

func (p *Process) ProcessQrc(path string) error {
	data, err := ioutil.ReadFile(path)
	if err != nil {
		return err
	}
	var rcc RCC
	err = xml.Unmarshal(data, &rcc)
	if err != nil {
		log.Println(err)
		return err
	}
	rcc.Dir, rcc.FileName = filepath.Split(path)
	_, rcc.DirName = filepath.Split(filepath.Clean(rcc.Dir))
	p.rccs = append(p.rccs, rcc)
	return nil
}

func (p *Process) Export(outdir string, copyFn CopyFunc) error {
	for _, rcc := range p.rccs {
		p.ExportQrc(outdir, rcc, copyFn)
	}
	return nil
}

func (p *Process) ExportQrc(outdir string, rcc RCC, copyFn CopyFunc) error {
	images := rcc.ImagesFiles()
	if len(images) == 0 {
		log.Println("skip empty rcc", rcc.FileName)
		return nil
	}
	outpath := filepath.Join(outdir, rcc.DirName)
	os.MkdirAll(outpath, 0777)
	for _, file := range images {
		target := file[len(rcc.Dir):]
		dest := filepath.Join(outpath, target)
		d, _ := filepath.Split(dest)
		os.MkdirAll(d, 0777)
		err := copyFn(file, dest)
		if err != nil {
			log.Println(file, err)
		}
	}
	return nil
}

type CopyFunc func(string, string) error

func GrayImage(source string, dest string) error {
	f, err := os.Open(source)
	if err != nil {
		return err
	}
	srcImage, err := png.Decode(f)
	if err != nil {
		return err
	}
	dstImage := image.NewRGBA(srcImage.Bounds())
	draw.Draw(dstImage, dstImage.Bounds(), srcImage, srcImage.Bounds().Min, draw.Src)
	//	dstImage.
	b := dstImage.Bounds()
	for y := b.Min.Y; y < b.Max.Y; y++ {
		for x := b.Min.X; x < b.Max.X; x++ {
			c := dstImage.RGBAAt(x, y)
			var avg uint8 = uint8((int(c.R) + int(c.G) + int(c.B)) / 3)
			//c.R = c.G = c.B = avg
			c.R = avg
			c.G = avg
			c.B = avg
			dstImage.SetRGBA(x, y, c)
		}
	}

	w, err := os.Create(dest)
	if err != nil {
		return err
	}
	err = png.Encode(w, dstImage)
	if err != nil {
		return err
	}
	return nil
}

func CopyFile(source string, dest string) (err error) {
	sourcefile, err := os.Open(source)
	if err != nil {
		return err
	}
	defer sourcefile.Close()
	destfile, err := os.Create(dest)
	if err != nil {
		return err
	}
	defer destfile.Close()
	_, err = io.Copy(destfile, sourcefile)
	if err == nil {
		sourceinfo, err := os.Stat(source)
		if err != nil {
			err = os.Chmod(dest, sourceinfo.Mode())
		}
	}
	return
}
<commit_msg>tools/exportqrc gray convert YUV<commit_after>package main

import (
	"encoding/xml"
	"flag"
	"image"
	"image/draw"
	"image/png"
	"io"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
)

var (
	root = "../../../"
)

var (
	flagRoot string
)

func init() {
	flag.StringVar(&flagRoot, "root", "", "setup liteide root")
}

func main() {
	flag.Parse()
	if flagRoot != "" {
		root = flagRoot
	}
	root, _ := filepath.Abs(root)
	log.Println("process qrc files in liteide root", root)
	var p Process
	p.ProcessDir(filepath.Join(root, "src/liteapp"))
	p.ProcessDir(filepath.Join(root, "src/plugins"))
	p.Export(filepath.Join(root, "deploy/liteapp/qrc/default"), CopyFile)
	p.Export(filepath.Join(root, "deploy/liteapp/qrc/gray"), GrayImage)
}

type Process struct {
	rccs []RCC
}

func (p *Process) ProcessDir(dir string) {
	filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
		if filepath.Ext(path) == ".qrc" {
			p.ProcessQrc(path)
		}
		return nil
	})
}

type QResource struct {
	Prefix string   `xml:"prefix,attr"`
	Files  []string `xml:"file"`
}

type RCC struct {
	Dir      string
	DirName  string
	FileName string
	XMLName  xml.Name  `xml:"RCC"`
	Resource QResource `xml:"qresource"`
}

func (rcc *RCC) IsEmtpy() bool {
	return len(rcc.Resource.Files) == 0
}

func (rcc *RCC) ImagesFiles() (images []string) {
	for _, file := range rcc.Resource.Files {
		if filepath.Ext(file) == ".png" {
			image := filepath.Join(rcc.Dir, file)
			_, err := os.Lstat(image)
			if err != nil {
				log.Println("warning, not find image", image)
			}
			images = append(images, image)
		}
	}
	return
}

func (p *Process) ProcessQrc(path string) error {
	data, err := ioutil.ReadFile(path)
	if err != nil {
		return err
	}
	var rcc RCC
	err = xml.Unmarshal(data, &rcc)
	if err != nil {
		log.Println(err)
		return err
	}
	rcc.Dir, rcc.FileName = filepath.Split(path)
	_, rcc.DirName = filepath.Split(filepath.Clean(rcc.Dir))
	p.rccs = append(p.rccs, rcc)
	return nil
}

func (p *Process) Export(outdir string, copyFn CopyFunc) error {
	log.Println("export", outdir)
	for _, rcc := range p.rccs {
		p.ExportQrc(outdir, rcc, copyFn)
	}
	return nil
}

func (p *Process) ExportQrc(outdir string, rcc RCC, copyFn CopyFunc) error {
	images := rcc.ImagesFiles()
	if len(images) == 0 {
		//log.Println("skip empty rcc", rcc.FileName)
		return nil
	}
	outpath := filepath.Join(outdir, rcc.DirName)
	os.MkdirAll(outpath, 0777)
	log.Println(rcc.DirName, "->", len(images))
	for _, file := range images {
		target := file[len(rcc.Dir):]
		dest := filepath.Join(outpath, target)
		d, _ := filepath.Split(dest)
		os.MkdirAll(d, 0777)
		err := copyFn(file, dest)
		if err != nil {
			log.Println(file, err)
		}
	}
	return nil
}

type CopyFunc func(string, string) error

func GrayImage(source string, dest string) error {
	f, err := os.Open(source)
	if err != nil {
		return err
	}
	srcImage, err := png.Decode(f)
	if err != nil {
		return err
	}
	dstImage := image.NewRGBA(srcImage.Bounds())
	draw.Draw(dstImage, dstImage.Bounds(), srcImage, srcImage.Bounds().Min, draw.Src)
	//	dstImage.
	b := dstImage.Bounds()
	for y := b.Min.Y; y < b.Max.Y; y++ {
		for x := b.Min.X; x < b.Max.X; x++ {
			c := dstImage.RGBAAt(x, y)
			r := float64(c.R)
			g := float64(c.G)
			b := float64(c.B)
			var avg uint8 = uint8(r*0.299 + g*0.587 + b*0.114)
			//var avg uint8 = uint8((int(c.R) + int(c.G) + int(c.B)) / 3)
			//c.R = c.G = c.B = avg
			c.R = avg
			c.G = avg
			c.B = avg
			dstImage.SetRGBA(x, y, c)
		}
	}

	w, err := os.Create(dest)
	if err != nil {
		return err
	}
	err = png.Encode(w, dstImage)
	if err != nil {
		return err
	}
	return nil
}

func CopyFile(source string, dest string) (err error) {
	sourcefile, err := os.Open(source)
	if err != nil {
		return err
	}
	defer sourcefile.Close()
	destfile, err := os.Create(dest)
	if err != nil {
		return err
	}
	defer destfile.Close()
	_, err = io.Copy(destfile, sourcefile)
	if err == nil {
		sourceinfo, err := os.Stat(source)
		if err != nil {
			err = os.Chmod(dest, sourceinfo.Mode())
		}
	}
	return
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"regexp"

	"github.com/flynn/flynn/Godeps/_workspace/src/github.com/flynn/go-sql"
	"github.com/flynn/flynn/Godeps/_workspace/src/github.com/flynn/pq/hstore"
	ct "github.com/flynn/flynn/controller/types"
	"github.com/flynn/flynn/controller/utils"
	strowgerc "github.com/flynn/flynn/router/client"
	"github.com/flynn/flynn/router/types"
)

type AppRepo struct {
	router        strowgerc.Client
	defaultDomain string

	db *DB
}

func NewAppRepo(db *DB, defaultDomain string, router strowgerc.Client) *AppRepo {
	return &AppRepo{db: db, defaultDomain: defaultDomain, router: router}
}

var appNamePattern = regexp.MustCompile(`^[a-z\d]+(-[a-z\d]+)*$`)

func (r *AppRepo) Add(data interface{}) error {
	app := data.(*ct.App)
	if app.Name == "" {
		return ct.ValidationError{"name", "must not be blank"}
	}
	if len(app.Name) > 30 || !appNamePattern.MatchString(app.Name) {
		return ct.ValidationError{"name", "is invalid"}
	}
	if app.ID == "" {
		app.ID = utils.UUID()
	}
	var meta hstore.Hstore
	if len(app.Meta) > 0 {
		meta.Map = make(map[string]sql.NullString, len(app.Meta))
		for k, v := range app.Meta {
			meta.Map[k] = sql.NullString{String: v, Valid: true}
		}
	}
	err := r.db.QueryRow("INSERT INTO apps (app_id, name, protected, meta) VALUES ($1, $2, $3, $4) RETURNING created_at, updated_at", app.ID, app.Name, app.Protected, meta).Scan(&app.CreatedAt, &app.UpdatedAt)
	app.ID = cleanUUID(app.ID)
	if !app.Protected && r.defaultDomain != "" {
		route := (&strowger.HTTPRoute{
			Domain:  fmt.Sprintf("%s.%s", app.Name, r.defaultDomain),
			Service: app.Name + "-web",
		}).ToRoute()
		route.ParentRef = routeParentRef(app)
		if err := r.router.CreateRoute(route); err != nil {
			log.Printf("Error creating default route for %s: %s", app.Name, err)
		}
	}
	return err
}

func scanApp(s Scanner) (*ct.App, error) {
	app := &ct.App{}
	var meta hstore.Hstore
	err := s.Scan(&app.ID, &app.Name, &app.Protected, &meta, &app.CreatedAt, &app.UpdatedAt)
	if err == sql.ErrNoRows {
		err = ErrNotFound
	}
	if len(meta.Map) > 0 {
		app.Meta = make(map[string]string, len(meta.Map))
		for k, v := range meta.Map {
			app.Meta[k] = v.String
		}
	}
	app.ID = cleanUUID(app.ID)
	return app, err
}

var idPattern = regexp.MustCompile(`^[a-f0-9]{8}-?([a-f0-9]{4}-?){3}[a-f0-9]{12}$`)

type rowQueryer interface {
	QueryRow(query string, args ...interface{}) Scanner
}

func selectApp(db rowQueryer, id string, update bool) (*ct.App, error) {
	var row Scanner
	query := "SELECT app_id, name, protected, meta, created_at, updated_at FROM apps WHERE deleted_at IS NULL AND "
	var suffix string
	if update {
		suffix = " FOR UPDATE"
	}
	if idPattern.MatchString(id) {
		row = db.QueryRow(query+"(app_id = $1 OR name = $2) LIMIT 1"+suffix, id, id)
	} else {
		row = db.QueryRow(query+"name = $1"+suffix, id)
	}
	return scanApp(row)
}

func (r *AppRepo) Get(id string) (interface{}, error) {
	return selectApp(r.db, id, false)
}

func (r *AppRepo) Update(id string, data map[string]interface{}) (interface{}, error) {
	tx, err := r.db.Begin()
	if err != nil {
		return nil, err
	}
	app, err := selectApp(tx, id, true)
	if err != nil {
		tx.Rollback()
		return nil, err
	}

	for k, v := range data {
		switch k {
		case "protected":
			protected, ok := v.(bool)
			if !ok {
				tx.Rollback()
				return nil, fmt.Errorf("controller: expected bool, got %T", v)
			}
			if app.Protected != protected {
				if _, err := tx.Exec("UPDATE apps SET protected = $2, updated_at = now() WHERE app_id = $1", app.ID, protected); err != nil {
					tx.Rollback()
					return nil, err
				}
				app.Protected = protected
			}
		case "meta":
			data, ok := v.(map[string]interface{})
			if !ok {
				tx.Rollback()
				return nil, fmt.Errorf("controller: expected map[string]interface{}, got %T", v)
			}
			var meta hstore.Hstore
			meta.Map = make(map[string]sql.NullString, len(data))
			app.Meta = make(map[string]string, len(data))
			for k, v := range data {
				s, ok := v.(string)
				if !ok {
					tx.Rollback()
					return nil, fmt.Errorf("controller: expected string, got %T", v)
				}
				meta.Map[k] = sql.NullString{String: s, Valid: true}
				app.Meta[k] = s
			}
			if _, err := tx.Exec("UPDATE apps SET meta = $2, updated_at = now() WHERE app_id = $1", app.ID, meta); err != nil {
				tx.Rollback()
				return nil, err
			}
		}
	}

	return app, tx.Commit()
}

func (r *AppRepo) Remove(id string) error {
	tx, err := r.db.Begin()
	if err != nil {
		return err
	}

	_, err = tx.Exec("UPDATE apps SET deleted_at = now() WHERE app_id = $1 AND deleted_at IS NULL", id)
	if err != nil {
		tx.Rollback()
		return err
	}

	_, err = tx.Exec("UPDATE formations SET deleted_at = now(), processes = NULL, updated_at = now() WHERE app_id = $1 AND deleted_at IS NULL", id)
	if err != nil {
		tx.Rollback()
		return err
	}
	_, err = tx.Exec("UPDATE app_resources SET deleted_at = now() WHERE app_id = $1 AND deleted_at IS NULL", id)
	if err != nil {
		tx.Rollback()
		return err
	}
	return tx.Commit()
}

func (r *AppRepo) List() (interface{}, error) {
	rows, err := r.db.Query("SELECT app_id, name, protected, meta, created_at, updated_at FROM apps WHERE deleted_at IS NULL ORDER BY created_at DESC")
	if err != nil {
		return nil, err
	}
	apps := []*ct.App{}
	for rows.Next() {
		app, err := scanApp(rows)
		if err != nil {
			rows.Close()
			return nil, err
		}
		apps = append(apps, app)
	}
	return apps, rows.Err()
}

func (r *AppRepo) SetRelease(appID string, releaseID string) error {
	return r.db.Exec("UPDATE apps SET release_id = $2, updated_at = now() WHERE app_id = $1", appID, releaseID)
}

func (r *AppRepo) GetRelease(id string) (*ct.Release, error) {
	row := r.db.QueryRow("SELECT r.release_id, r.artifact_id, r.data, r.created_at FROM apps a JOIN releases r USING (release_id) WHERE a.app_id = $1", id)
	return scanRelease(row)
}
<commit_msg>controller: Explicitly name fields in ValidationError<commit_after>package main

import (
	"fmt"
	"log"
	"regexp"

	"github.com/flynn/flynn/Godeps/_workspace/src/github.com/flynn/go-sql"
	"github.com/flynn/flynn/Godeps/_workspace/src/github.com/flynn/pq/hstore"
	ct "github.com/flynn/flynn/controller/types"
	"github.com/flynn/flynn/controller/utils"
	strowgerc "github.com/flynn/flynn/router/client"
	"github.com/flynn/flynn/router/types"
)

type AppRepo struct {
	router        strowgerc.Client
	defaultDomain string

	db *DB
}

func NewAppRepo(db *DB, defaultDomain string, router strowgerc.Client) *AppRepo {
	return &AppRepo{db: db, defaultDomain: defaultDomain, router: router}
}

var appNamePattern = regexp.MustCompile(`^[a-z\d]+(-[a-z\d]+)*$`)

func (r *AppRepo) Add(data interface{}) error {
	app := data.(*ct.App)
	if app.Name == "" {
		return ct.ValidationError{Field: "name", Message: "must not be blank"}
	}
	if len(app.Name) > 30 || !appNamePattern.MatchString(app.Name) {
		return ct.ValidationError{Field: "name", Message: "is invalid"}
	}
	if app.ID == "" {
		app.ID = utils.UUID()
	}
	var meta hstore.Hstore
	if len(app.Meta) > 0 {
		meta.Map = make(map[string]sql.NullString, len(app.Meta))
		for k, v := range app.Meta {
			meta.Map[k] = sql.NullString{String: v, Valid: true}
		}
	}
	err := r.db.QueryRow("INSERT INTO apps (app_id, name, protected, meta) VALUES ($1, $2, $3, $4) RETURNING created_at, updated_at", app.ID, app.Name, app.Protected, meta).Scan(&app.CreatedAt, &app.UpdatedAt)
	app.ID = cleanUUID(app.ID)
	if !app.Protected && r.defaultDomain != "" {
		route := (&strowger.HTTPRoute{
			Domain:  fmt.Sprintf("%s.%s", app.Name, r.defaultDomain),
			Service: app.Name + "-web",
		}).ToRoute()
		route.ParentRef = routeParentRef(app)
		if err := r.router.CreateRoute(route); err != nil {
			log.Printf("Error creating default route for %s: %s", app.Name, err)
		}
	}
	return err
}

func scanApp(s Scanner) (*ct.App, error) {
	app := &ct.App{}
	var meta hstore.Hstore
	err := s.Scan(&app.ID, &app.Name, &app.Protected, &meta, &app.CreatedAt, &app.UpdatedAt)
	if err == sql.ErrNoRows {
		err = ErrNotFound
	}
	if len(meta.Map) > 0 {
		app.Meta = make(map[string]string, len(meta.Map))
		for k, v := range meta.Map {
			app.Meta[k] = v.String
		}
	}
	app.ID = cleanUUID(app.ID)
	return app, err
}

var idPattern = regexp.MustCompile(`^[a-f0-9]{8}-?([a-f0-9]{4}-?){3}[a-f0-9]{12}$`)

type rowQueryer interface {
	QueryRow(query string, args ...interface{}) Scanner
}

func selectApp(db rowQueryer, id string, update bool) (*ct.App, error) {
	var row Scanner
	query := "SELECT app_id, name, protected, meta, created_at, updated_at FROM apps WHERE deleted_at IS NULL AND "
	var suffix string
	if update {
		suffix = " FOR UPDATE"
	}
	if idPattern.MatchString(id) {
		row = db.QueryRow(query+"(app_id = $1 OR name = $2) LIMIT 1"+suffix, id, id)
	} else {
		row = db.QueryRow(query+"name = $1"+suffix, id)
	}
	return scanApp(row)
}

func (r *AppRepo) Get(id string) (interface{}, error) {
	return selectApp(r.db, id, false)
}

func (r *AppRepo) Update(id string, data map[string]interface{}) (interface{}, error) {
	tx, err := r.db.Begin()
	if err != nil {
		return nil, err
	}
	app, err := selectApp(tx, id, true)
	if err != nil {
		tx.Rollback()
		return nil, err
	}

	for k, v := range data {
		switch k {
		case "protected":
			protected, ok := v.(bool)
			if !ok {
				tx.Rollback()
				return nil, fmt.Errorf("controller: expected bool, got %T", v)
			}
			if app.Protected != protected {
				if _, err := tx.Exec("UPDATE apps SET protected = $2, updated_at = now() WHERE app_id = $1", app.ID, protected); err != nil {
					tx.Rollback()
					return nil, err
				}
				app.Protected = protected
			}
		case "meta":
			data, ok := v.(map[string]interface{})
			if !ok {
				tx.Rollback()
				return nil, fmt.Errorf("controller: expected map[string]interface{}, got %T", v)
			}
			var meta hstore.Hstore
			meta.Map = make(map[string]sql.NullString, len(data))
			app.Meta = make(map[string]string, len(data))
			for k, v := range data {
				s, ok := v.(string)
				if !ok {
					tx.Rollback()
					return nil, fmt.Errorf("controller: expected string, got %T", v)
				}
				meta.Map[k] = sql.NullString{String: s, Valid: true}
				app.Meta[k] = s
			}
			if _, err := tx.Exec("UPDATE apps SET meta = $2, updated_at = now() WHERE app_id = $1", app.ID, meta); err != nil {
				tx.Rollback()
				return nil, err
			}
		}
	}

	return app, tx.Commit()
}

func (r *AppRepo) Remove(id string) error {
	tx, err := r.db.Begin()
	if err != nil {
		return err
	}

	_, err = tx.Exec("UPDATE apps SET deleted_at = now() WHERE app_id = $1 AND deleted_at IS NULL", id)
	if err != nil {
		tx.Rollback()
		return err
	}

	_, err = tx.Exec("UPDATE formations SET deleted_at = now(), processes = NULL, updated_at = now() WHERE app_id = $1 AND deleted_at IS NULL", id)
	if err != nil {
		tx.Rollback()
		return err
	}
	_, err = tx.Exec("UPDATE app_resources SET deleted_at = now() WHERE app_id = $1 AND deleted_at IS NULL", id)
	if err != nil {
		tx.Rollback()
		return err
	}
	return tx.Commit()
}

func (r *AppRepo) List() (interface{}, error) {
	rows, err := r.db.Query("SELECT app_id, name, protected, meta, created_at, updated_at FROM apps WHERE deleted_at IS NULL ORDER BY created_at DESC")
	if err != nil {
		return nil, err
	}
	apps := []*ct.App{}
	for rows.Next() {
		app, err := scanApp(rows)
		if err != nil {
			rows.Close()
			return nil, err
		}
		apps = append(apps, app)
	}
	return apps, rows.Err()
}

func (r *AppRepo) SetRelease(appID string, releaseID string) error {
	return r.db.Exec("UPDATE apps SET release_id = $2, updated_at = now() WHERE app_id = $1", appID, releaseID)
}

func (r *AppRepo) GetRelease(id string) (*ct.Release, error) {
	row := r.db.QueryRow("SELECT r.release_id, r.artifact_id, r.data, r.created_at FROM apps a JOIN releases r USING (release_id) WHERE a.app_id = $1", id)
	return scanRelease(row)
}
<|endoftext|>


<commit_before>package controller

import (
	"errors"
	"math/rand"
	"strconv"
	"strings"
	"sync"
	"sync/atomic"
	"time"

	"github.com/tidwall/resp"
	"github.com/tidwall/tile38/controller/log"
	"github.com/tidwall/tile38/controller/server"
)

const useRandField = true

func (c *Controller) cmdMassInsert(msg *server.Message) (res string, err error) {
	start := time.Now()
	vs := msg.Values[1:]

	var snumCols, snumPoints string
	var cols, objs int
	var ok bool
	if vs, snumCols, ok = tokenval(vs); !ok || snumCols == "" {
		return "", errInvalidNumberOfArguments
	}
	if vs, snumPoints, ok = tokenval(vs); !ok || snumPoints == "" {
		return "", errInvalidNumberOfArguments
	}
	if len(vs) != 0 {
		return "", errors.New("invalid number of arguments")
	}
	n, err := strconv.ParseUint(snumCols, 10, 64)
	if err != nil {
		return "", errInvalidArgument(snumCols)
	}
	cols = int(n)
	n, err = strconv.ParseUint(snumPoints, 10, 64)
	if err != nil {
		return "", errInvalidArgument(snumPoints)
	}
	docmd := func(values []resp.Value) error {
		c.mu.Lock()
		defer c.mu.Unlock()
		nmsg := &server.Message{}
		*nmsg = *msg
		nmsg.Values = values
		nmsg.Command = strings.ToLower(values[0].String())

		_, d, err := c.command(nmsg, nil)
		if err != nil {
			return err
		}
		if err := c.writeAOF(resp.ArrayValue(nmsg.Values), &d); err != nil {
			return err
		}
		return nil
	}
	rand.Seed(time.Now().UnixNano())
	objs = int(n)
	var wg sync.WaitGroup
	var k uint64
	wg.Add(cols)
	for i := 0; i < cols; i++ {
		key := "mi:" + strconv.FormatInt(int64(i), 10)
		go func(key string) {
			defer func() {
				wg.Done()
			}()

			for j := 0; j < objs; j++ {
				id := strconv.FormatInt(int64(j), 10)
				lat, lon := rand.Float64()*180-90, rand.Float64()*360-180
				values := make([]resp.Value, 0, 16)
				values = append(values, resp.StringValue("set"), resp.StringValue(key), resp.StringValue(id))
				if useRandField {
					values = append(values, resp.StringValue("FIELD"), resp.StringValue("field"), resp.FloatValue(rand.Float64()*10))
				}
				values = append(values, resp.StringValue("POINT"), resp.FloatValue(lat), resp.FloatValue(lon))
				if err := docmd(values); err != nil {
					log.Fatal(err)
					return
				}
				atomic.AddUint64(&k, 1)
				if j%10000 == 10000-1 {
					log.Infof("massinsert: %s %d/%d", key, atomic.LoadUint64(&k), cols*objs)
				}
			}
		}(key)
	}
	wg.Wait()
	log.Infof("massinsert: done %d objects", atomic.LoadUint64(&k))
	return server.OKMessage(msg, start), nil
}
<commit_msg>dev mi bounds<commit_after>package controller

import (
	"errors"
	"math/rand"
	"strconv"
	"strings"
	"sync"
	"sync/atomic"
	"time"

	"github.com/tidwall/resp"
	"github.com/tidwall/tile38/controller/log"
	"github.com/tidwall/tile38/controller/server"
)

const useRandField = true

func randMassInsertPosition(minLat, minLon, maxLat, maxLon float64) (float64, float64) {
	lat, lon := (rand.Float64()*(maxLat-minLat))+minLat, (rand.Float64()*(maxLon-minLon))+minLon
	return lat, lon
}

func (c *Controller) cmdMassInsert(msg *server.Message) (res string, err error) {
	start := time.Now()
	vs := msg.Values[1:]

	minLat, minLon, maxLat, maxLon := -90.0, -180.0, 90.0, 180.0 //37.10776, -122.67145, 38.19502, -121.62775

	var snumCols, snumPoints string
	var cols, objs int
	var ok bool
	if vs, snumCols, ok = tokenval(vs); !ok || snumCols == "" {
		return "", errInvalidNumberOfArguments
	}
	if vs, snumPoints, ok = tokenval(vs); !ok || snumPoints == "" {
		return "", errInvalidNumberOfArguments
	}
	if len(vs) != 0 {
		var sminLat, sminLon, smaxLat, smaxLon string
		if vs, sminLat, ok = tokenval(vs); !ok || sminLat == "" {
			return "", errInvalidNumberOfArguments
		}
		if vs, sminLon, ok = tokenval(vs); !ok || sminLon == "" {
			return "", errInvalidNumberOfArguments
		}
		if vs, smaxLat, ok = tokenval(vs); !ok || smaxLat == "" {
			return "", errInvalidNumberOfArguments
		}
		if vs, smaxLon, ok = tokenval(vs); !ok || smaxLon == "" {
			return "", errInvalidNumberOfArguments
		}
		var err error
		if minLat, err = strconv.ParseFloat(sminLat, 64); err != nil {
			return "", err
		}
		if minLon, err = strconv.ParseFloat(sminLon, 64); err != nil {
			return "", err
		}
		if maxLat, err = strconv.ParseFloat(smaxLat, 64); err != nil {
			return "", err
		}
		if maxLon, err = strconv.ParseFloat(smaxLon, 64); err != nil {
			return "", err
		}
		if len(vs) != 0 {
			return "", errors.New("invalid number of arguments")
		}
	}
	n, err := strconv.ParseUint(snumCols, 10, 64)
	if err != nil {
		return "", errInvalidArgument(snumCols)
	}
	cols = int(n)
	n, err = strconv.ParseUint(snumPoints, 10, 64)
	if err != nil {
		return "", errInvalidArgument(snumPoints)
	}
	docmd := func(values []resp.Value) error {
		c.mu.Lock()
		defer c.mu.Unlock()
		nmsg := &server.Message{}
		*nmsg = *msg
		nmsg.Values = values
		nmsg.Command = strings.ToLower(values[0].String())

		_, d, err := c.command(nmsg, nil)
		if err != nil {
			return err
		}
		if err := c.writeAOF(resp.ArrayValue(nmsg.Values), &d); err != nil {
			return err
		}
		return nil
	}
	rand.Seed(time.Now().UnixNano())
	objs = int(n)
	var wg sync.WaitGroup
	var k uint64
	wg.Add(cols)
	for i := 0; i < cols; i++ {
		key := "mi:" + strconv.FormatInt(int64(i), 10)
		go func(key string) {
			defer func() {
				wg.Done()
			}()

			for j := 0; j < objs; j++ {
				id := strconv.FormatInt(int64(j), 10)
				lat, lon := randMassInsertPosition(minLat, minLon, maxLat, maxLon)
				values := make([]resp.Value, 0, 16)
				values = append(values, resp.StringValue("set"), resp.StringValue(key), resp.StringValue(id))
				if useRandField {
					values = append(values, resp.StringValue("FIELD"), resp.StringValue("field"), resp.FloatValue(rand.Float64()*10))
				}
				values = append(values, resp.StringValue("POINT"), resp.FloatValue(lat), resp.FloatValue(lon))
				if err := docmd(values); err != nil {
					log.Fatal(err)
					return
				}
				atomic.AddUint64(&k, 1)
				if j%10000 == 10000-1 {
					log.Infof("massinsert: %s %d/%d", key, atomic.LoadUint64(&k), cols*objs)
				}
			}
		}(key)
	}
	wg.Wait()
	log.Infof("massinsert: done %d objects", atomic.LoadUint64(&k))
	return server.OKMessage(msg, start), nil
}
<|endoftext|>


<commit_before>package core

import (
	"fmt"
	"log"
	"net/http"
	"net/http/pprof"
	"os"
	"runtime"
	"strconv"
	"strings"

	"github.com/mdlayher/wavepipe/api"
	"github.com/mdlayher/wavepipe/api/auth"
	"github.com/mdlayher/wavepipe/config"

	"github.com/go-martini/martini"
	"github.com/martini-contrib/gzip"
	"github.com/martini-contrib/render"
)

// apiRouter sets up the instance of martini
func apiRouter(apiKillChan chan struct{}) {
	log.Println("api: starting...")

	// Initialize martini
	m := martini.New()

	// Set up middleware
	// GZIP all requests to drastically reduce size
	m.Use(gzip.All())
	m.Use(render.Renderer(render.Options{
		// Output human-readable JSON. GZIP will essentially negate the size increase, and this
		// makes the API much more developer-friendly
		IndentJSON: true,
	}))

	// Enable graceful shutdown when triggered by manager
	stopAPI := false
	m.Use(func(req *http.Request, res http.ResponseWriter, r render.Render) {
		// On debug, log everything
		if os.Getenv("WAVEPIPE_DEBUG") == "1" {
			log.Println(req.Header)
			log.Println(req.URL)
		}

		// Send a Server header with all responses
		res.Header().Set("Server", fmt.Sprintf("%s/%s (%s_%s)", App, Version, runtime.GOOS, runtime.GOARCH))

		// If API is stopping, render a HTTP 503
		if stopAPI {
			r.JSON(503, api.Error{
				Code:    503,
				Message: "service is shutting down",
			})
			return
		}
	})

	// Authenticate all API calls
	m.Use(func(req *http.Request, res http.ResponseWriter, c martini.Context, r render.Render) {
		// Use factory to determine the proper authentication method for this path
		method := auth.Factory(req.URL.Path)
		if method == nil {
			// If no method returned, path is not authenticated
			return
		}

		// Attempt authentication
		user, session, clientErr, serverErr := method.Authenticate(req)

		// Check for client error
		if clientErr != nil {
			// If debug mode, and no username or password, send a WWW-Authenticate header to prompt request
			// This allows for manual exploration of the API if needed
			if os.Getenv("WAVEPIPE_DEBUG") == "1" && (clientErr == auth.ErrNoUsername || clientErr == auth.ErrNoPassword) {
				res.Header().Set("WWW-Authenticate", "Basic")
			}

			r.JSON(401, api.Error{
				Code:    401,
				Message: "authentication failed: " + clientErr.Error(),
			})
			return
		}

		// Check for server error
		if serverErr != nil {
			log.Println(serverErr)

			r.JSON(500, api.Error{
				Code:    500,
				Message: "server error",
			})
			return
		}

		// Successful login, map session user and session to martini context
		c.Map(user)
		c.Map(session)

		// Print information about this API call
		log.Printf("api: [%s] %s?%s", req.RemoteAddr, req.URL.Path, req.URL.Query().Encode())
	})

	// Set up API routes
	r := martini.NewRouter()

	// Set up API information route
	r.Get("/api", api.APIInfo)

	// Set up API group routes, with API version parameter
	r.Group("/api/:version", apiRoutes)

	// On debug mode, enable pprof debug endpoints
	// Thanks: https://github.com/go-martini/martini/issues/228
	if os.Getenv("WAVEPIPE_DEBUG") == "1" {
		r.Group("/debug/pprof", func(r martini.Router) {
			r.Any("/", pprof.Index)
			r.Any("/cmdline", pprof.Cmdline)
			r.Any("/profile", pprof.Profile)
			r.Any("/symbol", pprof.Symbol)
			r.Any("/block", pprof.Handler("block").ServeHTTP)
			r.Any("/heap", pprof.Handler("heap").ServeHTTP)
			r.Any("/goroutine", pprof.Handler("goroutine").ServeHTTP)
			r.Any("/threadcreate", pprof.Handler("threadcreate").ServeHTTP)
		})
	}

	// Add router action, start server
	m.Action(r.Handle)
	go func() {
		// Load config
		conf, err := config.C.Load()
		if err != nil {
			log.Println(err)
			return
		}

		// Start server
		log.Println("api: listening on port", conf.Port)
		if err := http.ListenAndServe(":"+strconv.Itoa(conf.Port), m); err != nil {
			// Check if address in use
			if strings.Contains(err.Error(), "address already in use") {
				log.Fatalf("api: cannot bind to :%d, is wavepipe already running?", conf.Port)
			}

			log.Println(err)
		}
	}()

	// Trigger events via channel
	for {
		select {
		// Stop API
		case <-apiKillChan:
			// Stop serving requests
			stopAPI = true

			// Inform manager that shutdown is complete
			log.Println("api: stopped!")
			apiKillChan <- struct{}{}
			return
		}
	}
}

// apiRoutes sets up the API routes required by wavepipe
func apiRoutes(r martini.Router) {
	// Root API, containing information and help
	r.Get("", api.APIInfo)

	// Albums API
	r.Get("/albums", api.GetAlbums)
	r.Get("/albums/:id", api.GetAlbums)

	// Art API
	r.Get("/art", api.GetArt)
	r.Get("/art/:id", api.GetArt)

	// Artists API
	r.Get("/artists", api.GetArtists)
	r.Get("/artists/:id", api.GetArtists)

	// Folders API
	r.Get("/folders", api.GetFolders)
	r.Get("/folders/:id", api.GetFolders)

	// LastFM API
	r.Get("/lastfm", api.GetLastFM)
	r.Get("/lastfm/:action", api.GetLastFM)
	r.Get("/lastfm/:action/:id", api.GetLastFM)

	// Login API
	r.Get("/login", api.GetLogin)

	// Logout API
	r.Get("/logout", api.GetLogout)

	// Search API
	r.Get("/search", api.GetSearch)
	r.Get("/search/:query", api.GetSearch)

	// Songs API
	r.Get("/songs", api.GetSongs)
	r.Get("/songs/:id", api.GetSongs)

	// Status API
	r.Get("/status", api.GetStatus)

	// Stream API
	r.Get("/stream", api.GetStream)
	r.Get("/stream/:id", api.GetStream)

	// Transcode API
	r.Get("/transcode", api.GetTranscode)
	r.Get("/transcode/:id", api.GetTranscode)
}
<commit_msg>core/apiRouter: add /robots.txt route to disallow crawling<commit_after>package core

import (
	"fmt"
	"log"
	"net/http"
	"net/http/pprof"
	"os"
	"runtime"
	"strconv"
	"strings"

	"github.com/mdlayher/wavepipe/api"
	"github.com/mdlayher/wavepipe/api/auth"
	"github.com/mdlayher/wavepipe/config"

	"github.com/go-martini/martini"
	"github.com/martini-contrib/gzip"
	"github.com/martini-contrib/render"
)

// apiRouter sets up the instance of martini
func apiRouter(apiKillChan chan struct{}) {
	log.Println("api: starting...")

	// Initialize martini
	m := martini.New()

	// Set up middleware
	// GZIP all requests to drastically reduce size
	m.Use(gzip.All())
	m.Use(render.Renderer(render.Options{
		// Output human-readable JSON. GZIP will essentially negate the size increase, and this
		// makes the API much more developer-friendly
		IndentJSON: true,
	}))

	// Enable graceful shutdown when triggered by manager
	stopAPI := false
	m.Use(func(req *http.Request, res http.ResponseWriter, r render.Render) {
		// On debug, log everything
		if os.Getenv("WAVEPIPE_DEBUG") == "1" {
			log.Println(req.Header)
			log.Println(req.URL)
		}

		// Send a Server header with all responses
		res.Header().Set("Server", fmt.Sprintf("%s/%s (%s_%s)", App, Version, runtime.GOOS, runtime.GOARCH))

		// If API is stopping, render a HTTP 503
		if stopAPI {
			r.JSON(503, api.Error{
				Code:    503,
				Message: "service is shutting down",
			})
			return
		}
	})

	// Authenticate all API calls
	m.Use(func(req *http.Request, res http.ResponseWriter, c martini.Context, r render.Render) {
		// Use factory to determine the proper authentication method for this path
		method := auth.Factory(req.URL.Path)
		if method == nil {
			// If no method returned, path is not authenticated
			return
		}

		// Attempt authentication
		user, session, clientErr, serverErr := method.Authenticate(req)

		// Check for client error
		if clientErr != nil {
			// If debug mode, and no username or password, send a WWW-Authenticate header to prompt request
			// This allows for manual exploration of the API if needed
			if os.Getenv("WAVEPIPE_DEBUG") == "1" && (clientErr == auth.ErrNoUsername || clientErr == auth.ErrNoPassword) {
				res.Header().Set("WWW-Authenticate", "Basic")
			}

			r.JSON(401, api.Error{
				Code:    401,
				Message: "authentication failed: " + clientErr.Error(),
			})
			return
		}

		// Check for server error
		if serverErr != nil {
			log.Println(serverErr)

			r.JSON(500, api.Error{
				Code:    500,
				Message: "server error",
			})
			return
		}

		// Successful login, map session user and session to martini context
		c.Map(user)
		c.Map(session)

		// Print information about this API call
		log.Printf("api: [%s] %s?%s", req.RemoteAddr, req.URL.Path, req.URL.Query().Encode())
	})

	// Set up API routes
	r := martini.NewRouter()

	// Set up robots.txt to disallow crawling, since this is a dynamic service which users self-host
	r.Get("/robots.txt", func(res http.ResponseWriter) {
		res.Write([]byte("# wavepipe media server\n" +
			"# https://github.com/mdlayher/wavepipe\n" +
			"User-agent: *\n" +
			"Disallow: /"))
	})

	// Set up API information route
	r.Get("/api", api.APIInfo)

	// Set up API group routes, with API version parameter
	r.Group("/api/:version", apiRoutes)

	// On debug mode, enable pprof debug endpoints
	// Thanks: https://github.com/go-martini/martini/issues/228
	if os.Getenv("WAVEPIPE_DEBUG") == "1" {
		r.Group("/debug/pprof", func(r martini.Router) {
			r.Any("/", pprof.Index)
			r.Any("/cmdline", pprof.Cmdline)
			r.Any("/profile", pprof.Profile)
			r.Any("/symbol", pprof.Symbol)
			r.Any("/block", pprof.Handler("block").ServeHTTP)
			r.Any("/heap", pprof.Handler("heap").ServeHTTP)
			r.Any("/goroutine", pprof.Handler("goroutine").ServeHTTP)
			r.Any("/threadcreate", pprof.Handler("threadcreate").ServeHTTP)
		})
	}

	// Add router action, start server
	m.Action(r.Handle)
	go func() {
		// Load config
		conf, err := config.C.Load()
		if err != nil {
			log.Println(err)
			return
		}

		// Start server
		log.Println("api: listening on port", conf.Port)
		if err := http.ListenAndServe(":"+strconv.Itoa(conf.Port), m); err != nil {
			// Check if address in use
			if strings.Contains(err.Error(), "address already in use") {
				log.Fatalf("api: cannot bind to :%d, is wavepipe already running?", conf.Port)
			}

			log.Println(err)
		}
	}()

	// Trigger events via channel
	for {
		select {
		// Stop API
		case <-apiKillChan:
			// Stop serving requests
			stopAPI = true

			// Inform manager that shutdown is complete
			log.Println("api: stopped!")
			apiKillChan <- struct{}{}
			return
		}
	}
}

// apiRoutes sets up the API routes required by wavepipe
func apiRoutes(r martini.Router) {
	// Root API, containing information and help
	r.Get("", api.APIInfo)

	// Albums API
	r.Get("/albums", api.GetAlbums)
	r.Get("/albums/:id", api.GetAlbums)

	// Art API
	r.Get("/art", api.GetArt)
	r.Get("/art/:id", api.GetArt)

	// Artists API
	r.Get("/artists", api.GetArtists)
	r.Get("/artists/:id", api.GetArtists)

	// Folders API
	r.Get("/folders", api.GetFolders)
	r.Get("/folders/:id", api.GetFolders)

	// LastFM API
	r.Get("/lastfm", api.GetLastFM)
	r.Get("/lastfm/:action", api.GetLastFM)
	r.Get("/lastfm/:action/:id", api.GetLastFM)

	// Login API
	r.Get("/login", api.GetLogin)

	// Logout API
	r.Get("/logout", api.GetLogout)

	// Search API
	r.Get("/search", api.GetSearch)
	r.Get("/search/:query", api.GetSearch)

	// Songs API
	r.Get("/songs", api.GetSongs)
	r.Get("/songs/:id", api.GetSongs)

	// Status API
	r.Get("/status", api.GetStatus)

	// Stream API
	r.Get("/stream", api.GetStream)
	r.Get("/stream/:id", api.GetStream)

	// Transcode API
	r.Get("/transcode", api.GetTranscode)
	r.Get("/transcode/:id", api.GetTranscode)
}
<|endoftext|>


<commit_before>package cfutil

import (
	"errors"
	"fmt"
	consul "github.com/hashicorp/consul/api"
	"net/url"
)

func ServiceRegister(name string, tags ...string) error {
	appEnv, _ := Current()
	client, err := NewConsulClient()
	if err != nil {
		return err
	}
	err = client.Agent().ServiceRegister(&consul.AgentServiceRegistration{
		Name:    name,
		Address: appEnv.ApplicationURIs[0],
		Check: &consul.AgentServiceCheck{
			HTTP:     fmt.Sprintf(schemaForConsul() + "://" + appEnv.ApplicationURIs[0] + "/health"),
			Interval: "30s",
		},
	})
	if err != nil {
		return err
	}
	return nil
}

func NewConsulClient() (*consul.Client, error) {
	dialString, err := consulDialstring("consul")
	if err != nil {
		return nil, err
	}
	client, consulErr := consul.NewClient(&consul.Config{
		Address: dialString,
		Scheme:  schemaForConsul(),
	})
	if consulErr != nil {
		return nil, consulErr
	}
	return client, nil
}

func consulDialstring(serviceName string) (string, error) {
	appEnv, _ := Current()
	consulService, err := appEnv.Services.WithName(serviceName)
	if err != nil {
		return "", err
	}
	port := "8500"

	uri, ok := consulService.Credentials["uri"].(string)
	if ok {
		u, err := url.Parse(uri)
		if err == nil {
			return fmt.Sprintf("%s", u.Host), nil
		}
		// Fallback to hostname/port lookup
	}

	hostname, ok := consulService.Credentials["hostname"].(string)
	if !ok {
		return "", errors.New("consul service not available")
	}
	port, ok = consulService.Credentials["port"].(string)
	if ok {
		return fmt.Sprintf("%s:%s", hostname, port), nil
	}
	return fmt.Sprintf("%s:8500", hostname), nil
}

func schemaForConsul() string {
	if ForceHTTP() {
		return "http"
	}
	return "https"
}
<commit_msg>Consul is HTTP only for now<commit_after>package cfutil

import (
	"errors"
	"fmt"
	consul "github.com/hashicorp/consul/api"
	"net/url"
)

func ServiceRegister(name string, tags ...string) error {
	appEnv, _ := Current()
	client, err := NewConsulClient()
	if err != nil {
		return err
	}
	err = client.Agent().ServiceRegister(&consul.AgentServiceRegistration{
		Name:    name,
		Address: appEnv.ApplicationURIs[0],
		Check: &consul.AgentServiceCheck{
			HTTP:     fmt.Sprintf(schemaForConsul() + "://" + appEnv.ApplicationURIs[0] + "/health"),
			Interval: "30s",
		},
	})
	if err != nil {
		return err
	}
	return nil
}

func NewConsulClient() (*consul.Client, error) {
	dialString, err := consulDialstring("consul")
	if err != nil {
		return nil, err
	}
	client, consulErr := consul.NewClient(&consul.Config{
		Address: dialString,
		Scheme:  schemaForConsul(),
	})
	if consulErr != nil {
		return nil, consulErr
	}
	return client, nil
}

func consulDialstring(serviceName string) (string, error) {
	appEnv, _ := Current()
	consulService, err := appEnv.Services.WithName(serviceName)
	if err != nil {
		return "", err
	}
	port := "8500"

	uri, ok := consulService.Credentials["uri"].(string)
	if ok {
		u, err := url.Parse(uri)
		if err == nil {
			return fmt.Sprintf("%s", u.Host), nil
		}
		// Fallback to hostname/port lookup
	}

	hostname, ok := consulService.Credentials["hostname"].(string)
	if !ok {
		return "", errors.New("consul service not available")
	}
	port, ok = consulService.Credentials["port"].(string)
	if ok {
		return fmt.Sprintf("%s:%s", hostname, port), nil
	}
	return fmt.Sprintf("%s:8500", hostname), nil
}

func schemaForConsul() string {
	return "http"
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"

	"github.com/spf13/cobra"
	"github.com/teemow/loopback/image"
	"github.com/teemow/loopback/loop"
)

var (
	createCmd = &cobra.Command{
		Use:   "create",
		Short: "Create a loopback device",
		Long: `Create a loopback device.

Images are created in /var/lib/loopback. Then attached to a loopback, formatted and then mounted.
`,
		Run: createRun,
	}

	createFlags struct {
		name      string
		imagePath string
		size      int
		fs        string
	}
)

func init() {
	createCmd.Flags().StringVar(&createFlags.name, "name", "", "Name of the volume")
	createCmd.Flags().StringVar(&createFlags.imagePath, "image-path", "/var/lib/loopback", "Path for the loopback images")
	createCmd.Flags().IntVar(&createFlags.size, "size", 1, "Size of the volume (in gigabytes)")
	createCmd.Flags().StringVar(&createFlags.fs, "fs", "btrfs", "Filesystem")
}

func createRun(cmd *cobra.Command, args []string) {
	if len(args) < 1 {
		fmt.Fprintln(os.Stderr, "Mount path parameter missing.")
		os.Exit(1)
	}

	mountPath := args[0]

	_, err := os.Stat(mountPath)
	if err != nil {
		fmt.Fprintln(os.Stderr, "Mount path does not exist.")
		os.Exit(1)
	}

	err = image.Create(createFlags.name, createFlags.imagePath, createFlags.size)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Couldn't create image: %s\n", err)
		os.Exit(1)
	}

	var device string
	device, err = loop.Create(createFlags.name, createFlags.imagePath)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Couldn't create loopback: %s\n", err)
		os.Exit(1)
	}

	loop.Format(device, createFlags.fs)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Couldn't format loopback: %s\n", err)
		os.Exit(1)
	}

	loop.Mount(device, mountPath)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Couldn't mount loopback: %s\n", err)
		os.Exit(1)
	}

	os.Exit(0)
}
<commit_msg>added flags to suppress mounting on create command<commit_after>package main

import (
	"fmt"
	"os"

	"github.com/spf13/cobra"
	"github.com/teemow/loopback/image"
	"github.com/teemow/loopback/loop"
)

var (
	createCmd = &cobra.Command{
		Use:   "create",
		Short: "Create a loopback device",
		Long: `Create a loopback device.

Images are created in /var/lib/loopback. Then attached to a loopback, formatted and then mounted.
`,
		Run: createRun,
	}

	createFlags struct {
		name      string
		imagePath string
		size      int
		fs        string
		noMount   bool
	}
)

func init() {
	createCmd.Flags().StringVar(&createFlags.name, "name", "", "Name of the volume")
	createCmd.Flags().StringVar(&createFlags.imagePath, "image-path", "/var/lib/loopback", "Path for the loopback images")
	createCmd.Flags().IntVar(&createFlags.size, "size", 1, "Size of the volume (in gigabytes)")
	createCmd.Flags().StringVar(&createFlags.fs, "fs", "btrfs", "Filesystem")
	createCmd.Flags().BoolVar(&createFlags.noMount, "no-mount", false, "Do not mount the created loopback device")
}

func createRun(cmd *cobra.Command, args []string) {
	if len(args) < 1 {
		fmt.Fprintln(os.Stderr, "Mount path parameter missing.")
		os.Exit(1)
	}

	mountPath := args[0]

	_, err := os.Stat(mountPath)
	if err != nil {
		fmt.Fprintln(os.Stderr, "Mount path does not exist.")
		os.Exit(1)
	}

	err = image.Create(createFlags.name, createFlags.imagePath, createFlags.size)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Couldn't create image: %s\n", err)
		os.Exit(1)
	}

	var device string
	device, err = loop.Create(createFlags.name, createFlags.imagePath)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Couldn't create loopback: %s\n", err)
		os.Exit(1)
	}

	loop.Format(device, createFlags.fs)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Couldn't format loopback: %s\n", err)
		os.Exit(1)
	}

	if createFlags.noMount == false {
		loop.Mount(device, mountPath)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Couldn't mount loopback: %s\n", err)
			os.Exit(1)
		}
	}

	os.Exit(0)
}
<|endoftext|>


<commit_before>package parse

import (
	"encoding/json"
	"errors"
	"net/url"
	"reflect"
)

type createT struct {
	v                  interface{}
	shouldUseMasterKey bool
	currentSession     *sessionT

	isUser   bool
	username string
	password string
}

func (c *createT) method() string {
	return "POST"
}

func (c *createT) endpoint() (string, error) {
	p := getEndpointBase(c.v)
	u := url.URL{}
	u.Scheme = "https"
	u.Host = parseHost
	u.Path = p

	return u.String(), nil
}

func (c *createT) body() (string, error) {
	payload := map[string]interface{}{}

	if c.isUser {
		payload["username"] = c.username
		payload["password"] = c.password
	}

	rv := reflect.ValueOf(c.v)
	rvi := reflect.Indirect(rv)
	rt := rvi.Type()
	fields := getFields(rt)

	for _, f := range fields {
		var name string
		var fv reflect.Value

		if n, o := parseTag(f.Tag.Get("parse")); n == "-" || n == "objectId" || f.Name == "Id" || f.Type == reflect.TypeOf(Base{}) {
			continue
		} else if fv = rvi.FieldByName(f.Name); !fv.IsValid() || o == "omitempty" && isEmptyValue(fv) {
			continue
		} else {
			name = n
		}

		var fname string
		if name != "" {
			fname = name
		} else {
			fname = firstToLower(f.Name)
		}

		if canBeNil(fv) && fv.IsNil() {
			payload[fname] = nil
		} else {
			payload[fname] = encodeForRequest(fv.Interface())
		}
	}

	b, err := json.Marshal(payload)
	if err != nil {
		return "", err
	}

	return string(b), nil
}

func (c *createT) useMasterKey() bool {
	return c.shouldUseMasterKey
}

func (c *createT) session() *sessionT {
	return c.currentSession
}

func (c *createT) contentType() string {
	return "application/json"
}

// Save a new instance of the type pointed to by v to the Parse database. If
// useMasteKey=true, the Master Key will be used for the creation request. On a
// successful request, the CreatedAt field will be set on v.
//
// Note: v should be a pointer to a struct whose name represents a Parse class,
// or that implements the ClassName method
func Create(v interface{}, useMasterKey bool) error {
	return create(v, useMasterKey, nil)
}

func Signup(username string, password string, user interface{}) error {
	cr := &createT{
		v:                  user,
		shouldUseMasterKey: false,
		currentSession:     nil,
		isUser:             true,
	}
	if b, err := defaultClient.doRequest(cr); err != nil {
		return err
	} else {
		return handleResponse(b, user)
	}
}

func create(v interface{}, useMasterKey bool, currentSession *sessionT) error {
	rv := reflect.ValueOf(v)
	if rv.Kind() != reflect.Ptr || rv.IsNil() {
		return errors.New("v must be a non-nil pointer")
	}

	cr := &createT{
		v:                  v,
		shouldUseMasterKey: useMasterKey,
		currentSession:     currentSession,
	}
	if b, err := defaultClient.doRequest(cr); err != nil {
		return err
	} else {
		return handleResponse(b, v)
	}
}
<commit_msg>adding in ommitted password parameter to complete user creation with specified pass<commit_after>package parse

import (
	"encoding/json"
	"errors"
	"net/url"
	"reflect"
)

type createT struct {
	v                  interface{}
	shouldUseMasterKey bool
	currentSession     *sessionT

	isUser   bool
	username string
	password string
}

func (c *createT) method() string {
	return "POST"
}

func (c *createT) endpoint() (string, error) {
	p := getEndpointBase(c.v)
	u := url.URL{}
	u.Scheme = "https"
	u.Host = parseHost
	u.Path = p

	return u.String(), nil
}

func (c *createT) body() (string, error) {
	payload := map[string]interface{}{}

	if c.isUser {
		payload["username"] = c.username
		payload["password"] = c.password
	}

	rv := reflect.ValueOf(c.v)
	rvi := reflect.Indirect(rv)
	rt := rvi.Type()
	fields := getFields(rt)

	for _, f := range fields {
		var name string
		var fv reflect.Value

		if n, o := parseTag(f.Tag.Get("parse")); n == "-" || n == "objectId" || f.Name == "Id" || f.Type == reflect.TypeOf(Base{}) {
			continue
		} else if fv = rvi.FieldByName(f.Name); !fv.IsValid() || o == "omitempty" && isEmptyValue(fv) {
			continue
		} else {
			name = n
		}

		var fname string
		if name != "" {
			fname = name
		} else {
			fname = firstToLower(f.Name)
		}

		if canBeNil(fv) && fv.IsNil() {
			payload[fname] = nil
		} else {
			payload[fname] = encodeForRequest(fv.Interface())
		}
	}

	b, err := json.Marshal(payload)
	if err != nil {
		return "", err
	}

	return string(b), nil
}

func (c *createT) useMasterKey() bool {
	return c.shouldUseMasterKey
}

func (c *createT) session() *sessionT {
	return c.currentSession
}

func (c *createT) contentType() string {
	return "application/json"
}

// Save a new instance of the type pointed to by v to the Parse database. If
// useMasteKey=true, the Master Key will be used for the creation request. On a
// successful request, the CreatedAt field will be set on v.
//
// Note: v should be a pointer to a struct whose name represents a Parse class,
// or that implements the ClassName method
func Create(v interface{}, useMasterKey bool) error {
	return create(v, useMasterKey, nil)
}

func Signup(username string, password string, user interface{}) error {
	cr := &createT{
		v:                  	user,
		shouldUseMasterKey: 	false,
		currentSession:     	nil,
		isUser:             	true,
		username:		username,
		password:           	password,
	}
	if b, err := defaultClient.doRequest(cr); err != nil {
		return err
	} else {
		return handleResponse(b, user)
	}
}

func create(v interface{}, useMasterKey bool, currentSession *sessionT) error {
	rv := reflect.ValueOf(v)
	if rv.Kind() != reflect.Ptr || rv.IsNil() {
		return errors.New("v must be a non-nil pointer")
	}

	cr := &createT{
		v:                  v,
		shouldUseMasterKey: useMasterKey,
		currentSession:     currentSession,
	}
	if b, err := defaultClient.doRequest(cr); err != nil {
		return err
	} else {
		return handleResponse(b, v)
	}
}
<|endoftext|>