<commit_before>// master_func
package websql

import (
	"encoding/json"
	"errors"
	"io/ioutil"
	"log"
	"sync"

	"github.com/gorilla/websocket"
)

func (this *WebSQL) processWsCommandMaster(conn *websocket.Conn, message []byte) error {
	wsCommand := &Command{}
	json.Unmarshal(message, wsCommand)

	if wsCommand.Secret != Websql.service.Secret {
		regCommand := &Command{
			Type: "WS_REGISTER",
			Data: "Failed to valid client secret.",
		}
		conn.WriteJSON(regCommand)
		return errors.New(regCommand.Data)
	}

	switch wsCommand.Type {
	case "WS_REGISTER":
		//		log.Println(string(message))

		apiNode := &ApiNode{
			Id:   wsCommand.Data,
			Name: conn.RemoteAddr().String(),
		}
		err := AddApiNode(apiNode)
		if err != nil {
			conn.Close()
			return err
		}

		Websql.wsConns[apiNode.Id] = conn
		regCommand := &Command{
			Type: "WS_REGISTER",
			Data: "OK",
		}
		conn.WriteJSON(regCommand)
		log.Println(conn.RemoteAddr(), "connected.")

		masterDataBytes, err := json.Marshal(this.masterData)
		if err != nil {
			conn.Close()
			return err
		}
		masterDataCommand := &Command{
			Type: "WS_MASTER_DATA",
			Data: string(masterDataBytes),
		}
		err = conn.WriteJSON(masterDataCommand)
		if err != nil {
			conn.Close()
			return err
		}
		log.Println(conn.RemoteAddr(), "master data sent.")
	}
	return nil
}

var masterDataMutex = &sync.Mutex{}

func (this *MasterData) Propagate() error {
	masterDataMutex.Lock()
	var err error
	masterDataBytes, err := json.Marshal(this)
	if err != nil {
		return err
	}
	err = ioutil.WriteFile(Websql.service.DataFile, masterDataBytes, 0644)
	if err != nil {
		return err
	}
	masterDataMutex.Unlock()
	masterDataCommand := &Command{
		Type: "WS_MASTER_DATA",
		Data: string(masterDataBytes),
	}
	for _, conn := range Websql.wsConns {
		err = conn.WriteJSON(masterDataCommand)
		if err != nil {
			log.Println(err)
		}
	}
	return err
}
<commit_msg>Update.<commit_after>// master_func
package websql

import (
	"encoding/json"
	"errors"
	"io/ioutil"
	"log"
	"sync"

	"github.com/gorilla/websocket"
)

func (this *WebSQL) processWsCommandMaster(conn *websocket.Conn, message []byte) error {
	wsCommand := &Command{}
	json.Unmarshal(message, wsCommand)

	if wsCommand.Secret != Websql.service.Secret {
		regCommand := &Command{
			Type: "WS_REGISTER",
			Data: "Failed to valid client secret.",
		}
		conn.WriteJSON(regCommand)
		conn.Close()
		return errors.New(regCommand.Data)
	}

	switch wsCommand.Type {
	case "WS_REGISTER":
		//		log.Println(string(message))

		apiNode := &ApiNode{
			Id:   wsCommand.Data,
			Name: conn.RemoteAddr().String(),
		}
		err := AddApiNode(apiNode)
		if err != nil {
			conn.Close()
			return err
		}

		Websql.wsConns[apiNode.Id] = conn
		regCommand := &Command{
			Type: "WS_REGISTER",
			Data: "OK",
		}
		conn.WriteJSON(regCommand)
		log.Println(conn.RemoteAddr(), "connected.")

		masterDataBytes, err := json.Marshal(this.masterData)
		if err != nil {
			conn.Close()
			return err
		}
		masterDataCommand := &Command{
			Type: "WS_MASTER_DATA",
			Data: string(masterDataBytes),
		}
		err = conn.WriteJSON(masterDataCommand)
		if err != nil {
			conn.Close()
			return err
		}
		log.Println(conn.RemoteAddr(), "master data sent.")
	}
	return nil
}

var masterDataMutex = &sync.Mutex{}

func (this *MasterData) Propagate() error {
	masterDataMutex.Lock()
	var err error
	masterDataBytes, err := json.Marshal(this)
	if err != nil {
		return err
	}
	err = ioutil.WriteFile(Websql.service.DataFile, masterDataBytes, 0644)
	if err != nil {
		return err
	}
	masterDataMutex.Unlock()
	masterDataCommand := &Command{
		Type: "WS_MASTER_DATA",
		Data: string(masterDataBytes),
	}
	for _, conn := range Websql.wsConns {
		err = conn.WriteJSON(masterDataCommand)
		if err != nil {
			log.Println(err)
		}
	}
	return err
}
<|endoftext|>


<commit_before>//: ----------------------------------------------------------------------------
//: Copyright (C) 2017 Verizon.  All Rights Reserved.
//: All Rights Reserved
//:
//: file:    ipv4.go
//: details: TODO
//: author:  Mehrdad Arshad Rad
//: date:    02/01/2017
//:
//: 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 mirror

import (
	"encoding/binary"
	"net"
)

type IPv4 struct {
	Version  uint8
	IHL      uint8
	TOS      uint8
	Length   uint16
	Id       uint16
	TTL      uint8
	Protocol uint8
	Checksum uint16
}

func NewIPv4HeaderTpl(proto int) IPv4 {
	return IPv4{
		Version:  4,
		IHL:      5,
		TOS:      0,
		TTL:      64,
		Protocol: uint8(proto),
	}
}

func (ip IPv4) Marshal() []byte {
	b := make([]byte, IPv4HLen)
	b[0] = byte((ip.Version << 4) | ip.IHL)
	b[1] = byte(ip.TOS)
	binary.BigEndian.PutUint16(b[2:], ip.Length)
	b[6] = byte(0)
	b[7] = byte(0)
	b[8] = byte(ip.TTL)
	b[9] = byte(ip.Protocol)

	return b
}

func (ip IPv4) SetLen(b []byte, n int) {
	binary.BigEndian.PutUint16(b[2:], IPv4HLen+uint16(n))
}

func (ip IPv4) SetAddrs(b []byte, src, dst net.IP) {
	copy(b[12:16], src[12:16])
	copy(b[16:20], dst[12:16])
}
<commit_msg>fix golint and clean up<commit_after>// Package mirror clones IPFIX data to another collector
//: ----------------------------------------------------------------------------
//: Copyright (C) 2017 Verizon.  All Rights Reserved.
//: All Rights Reserved
//:
//: file:    ipv4.go
//: details: TODO
//: author:  Mehrdad Arshad Rad
//: date:    02/01/2017
//:
//: 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 mirror

import (
	"encoding/binary"
	"net"
)

// IPv4 represents the minimum IPV4 fields
// which they need to setup.
type IPv4 struct {
	Version  uint8
	IHL      uint8
	TOS      uint8
	Length   uint16
	TTL      uint8
	Protocol uint8
}

// NewIPv4HeaderTpl constructs IPv4 header template
func NewIPv4HeaderTpl(proto int) IPv4 {
	return IPv4{
		Version:  4,
		IHL:      5,
		TOS:      0,
		TTL:      64,
		Protocol: uint8(proto),
	}
}

// Marshal encodes the IPv4 packet
func (ip IPv4) Marshal() []byte {
	b := make([]byte, IPv4HLen)
	b[0] = byte((ip.Version << 4) | ip.IHL)
	b[1] = byte(ip.TOS)
	binary.BigEndian.PutUint16(b[2:], ip.Length)
	b[6] = byte(0)
	b[7] = byte(0)
	b[8] = byte(ip.TTL)
	b[9] = byte(ip.Protocol)

	return b
}

// SetLen sets the IPv4 header length
func (ip IPv4) SetLen(b []byte, n int) {
	binary.BigEndian.PutUint16(b[2:], IPv4HLen+uint16(n))
}

// SetAddrs sets the source and destination address
func (ip IPv4) SetAddrs(b []byte, src, dst net.IP) {
	copy(b[12:16], src[12:16])
	copy(b[16:20], dst[12:16])
}
<|endoftext|>


<commit_before>package models

// TODO Clean up for unreachable nodes.

import (
	"../app"
	"../utils"
	"errors"
	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
	"log"
)

type Todo struct {
	Id      bson.ObjectId `json:"id" bson:"_id,omitempty"`
	Title   string        `json:"title" bson:"title" binding:"required"`
	DueDate int64         `json:"due_date" bson:"due_date,omitempty"`
}

type TodoGroup struct {
	Id    bson.ObjectId   `json:"id" bson:"_id,omitempty"`
	Title string          `json:"title" bson:"title" binding:"required"`
	Todos []bson.ObjectId `json:"todos" bson:"todos,omitempty"`
}

type TodoMove struct {
	PriorSiblingId string `json:"prior_sibling_id"`
}

func findTodoGroup() (*TodoGroup, error) {
	// TODO CRUD for TodoGroup
	group := TodoGroup{}
	err := app.DB.C("todo_groups").
		Find(bson.M{}).
		Select(bson.M{"todos": 1}).
		One(&group)

	if err == mgo.ErrNotFound {
		group.Id = bson.NewObjectId()
		group.Title = "root"
		err = app.DB.C("todo_groups").Insert(&group)
		if err != nil {
			return nil, err
		}
	}

	return &group, err
}

func FindTodos() ([]Todo, error) {

	group, err := findTodoGroup()
	if err != nil {
		return nil, err
	}

	var todos []Todo
	err = app.DB.C("todos").
		Find(bson.M{"_id": bson.M{"$in": group.Todos}}).
		All(&todos)
	if err != nil {
		return nil, err
	}
	if todos == nil {
		todos = []Todo{}
	}

	N := len(group.Todos)
	sortedTodos := make([]Todo, N)
	idToTodo := make(map[bson.ObjectId]Todo)
	for _, todo := range todos {
		idToTodo[todo.Id] = todo
	}
	ptr := 0
	for i := 0; i < N; i++ {
		if todo, ok := idToTodo[group.Todos[i]]; ok {
			sortedTodos[ptr] = todo
			ptr++
		}
	}

	return sortedTodos[:ptr], err
}

func FindTodoById(id string) (*Todo, error) {
	if !bson.IsObjectIdHex(id) {
		return nil, errors.New("Id is not a valid format")
	}
	todo := Todo{}
	err := app.DB.C("todos").
		Find(bson.M{"_id": bson.ObjectIdHex(id)}).
		One(&todo)
	return &todo, err
}

func (todo *Todo) Create() error {
	group, err := findTodoGroup()
	if err != nil {
		return err
	}

	todo.Id = bson.NewObjectId()
	err = app.DB.C("todos").Insert(&todo)
	if err != nil {
		return err
	}

	err = app.DB.C("todo_groups").Update(bson.M{"_id": group.Id},
		bson.M{"$addToSet": bson.M{"todos": todo.Id}})
	if err != nil {
		return err
	}

	return nil
}

func (todo *Todo) Update() error {
	err := app.DB.C("todos").Update(bson.M{"_id": todo.Id}, &todo)
	return err
}

func (todo *Todo) Delete() error {
	group, err := findTodoGroup()
	if err != nil {
		return err
	}

	err = app.DB.C("todo_groups").Update(bson.M{"_id": group.Id},
		bson.M{"$pull": bson.M{"todos": todo.Id}})
	if err != nil {
		return err
	}

	err = app.DB.C("todos").Remove(bson.M{"_id": todo.Id})
	if err != nil {
		log.Println("Error in removing related todos: " + err.Error())
		// Ignore err
	}

	return nil
}

func (todo *Todo) Move(todoMove *TodoMove) error {
	group, err := findTodoGroup()
	if err != nil {
		return err
	}

	movedTodos, err := utils.MoveInChildren(
		group.Todos, todo.Id, todoMove.PriorSiblingId)
	if err != nil {
		return err
	}
	group.Todos = movedTodos

	err = app.DB.C("todo_groups").Update(bson.M{"_id": group.Id}, &group)
	return err
}
<commit_msg>Add color to todo model<commit_after>package models

// TODO Clean up for unreachable nodes.

import (
	"../app"
	"../utils"
	"errors"
	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
	"log"
)

type Todo struct {
	Id      bson.ObjectId `json:"id" bson:"_id,omitempty"`
	Title   string        `json:"title" bson:"title" binding:"required"`
	DueDate int64         `json:"due_date" bson:"due_date,omitempty"`
	Color   string        `json:"color" bson:"color"`
}

type TodoGroup struct {
	Id    bson.ObjectId   `json:"id" bson:"_id,omitempty"`
	Title string          `json:"title" bson:"title" binding:"required"`
	Todos []bson.ObjectId `json:"todos" bson:"todos,omitempty"`
}

type TodoMove struct {
	PriorSiblingId string `json:"prior_sibling_id"`
}

func findTodoGroup() (*TodoGroup, error) {
	// TODO CRUD for TodoGroup
	group := TodoGroup{}
	err := app.DB.C("todo_groups").
		Find(bson.M{}).
		Select(bson.M{"todos": 1}).
		One(&group)

	if err == mgo.ErrNotFound {
		group.Id = bson.NewObjectId()
		group.Title = "root"
		err = app.DB.C("todo_groups").Insert(&group)
		if err != nil {
			return nil, err
		}
	}

	return &group, err
}

func FindTodos() ([]Todo, error) {

	group, err := findTodoGroup()
	if err != nil {
		return nil, err
	}

	var todos []Todo
	err = app.DB.C("todos").
		Find(bson.M{"_id": bson.M{"$in": group.Todos}}).
		All(&todos)
	if err != nil {
		return nil, err
	}
	if todos == nil {
		todos = []Todo{}
	}

	N := len(group.Todos)
	sortedTodos := make([]Todo, N)
	idToTodo := make(map[bson.ObjectId]Todo)
	for _, todo := range todos {
		idToTodo[todo.Id] = todo
	}
	ptr := 0
	for i := 0; i < N; i++ {
		if todo, ok := idToTodo[group.Todos[i]]; ok {
			sortedTodos[ptr] = todo
			ptr++
		}
	}

	return sortedTodos[:ptr], err
}

func FindTodoById(id string) (*Todo, error) {
	if !bson.IsObjectIdHex(id) {
		return nil, errors.New("Id is not a valid format")
	}
	todo := Todo{}
	err := app.DB.C("todos").
		Find(bson.M{"_id": bson.ObjectIdHex(id)}).
		One(&todo)
	return &todo, err
}

func (todo *Todo) Create() error {
	group, err := findTodoGroup()
	if err != nil {
		return err
	}

	todo.Id = bson.NewObjectId()
	err = app.DB.C("todos").Insert(&todo)
	if err != nil {
		return err
	}

	err = app.DB.C("todo_groups").Update(bson.M{"_id": group.Id},
		bson.M{"$addToSet": bson.M{"todos": todo.Id}})
	if err != nil {
		return err
	}

	return nil
}

func (todo *Todo) Update() error {
	err := app.DB.C("todos").Update(bson.M{"_id": todo.Id}, &todo)
	return err
}

func (todo *Todo) Delete() error {
	group, err := findTodoGroup()
	if err != nil {
		return err
	}

	err = app.DB.C("todo_groups").Update(bson.M{"_id": group.Id},
		bson.M{"$pull": bson.M{"todos": todo.Id}})
	if err != nil {
		return err
	}

	err = app.DB.C("todos").Remove(bson.M{"_id": todo.Id})
	if err != nil {
		log.Println("Error in removing related todos: " + err.Error())
		// Ignore err
	}

	return nil
}

func (todo *Todo) Move(todoMove *TodoMove) error {
	group, err := findTodoGroup()
	if err != nil {
		return err
	}

	movedTodos, err := utils.MoveInChildren(
		group.Todos, todo.Id, todoMove.PriorSiblingId)
	if err != nil {
		return err
	}
	group.Todos = movedTodos

	err = app.DB.C("todo_groups").Update(bson.M{"_id": group.Id}, &group)
	return err
}
<|endoftext|>


<commit_before>package nessie

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"testing"
)

func TestDoRequest(t *testing.T) {
	// Test structure to be serialized.
	type payload struct {
		A int `json:"a"`
	}
	authToken := "some token"
	var tests = []struct {
		method       string
		resource     string
		sentPayload  payload
		wantPayload  string
		serverStatus int
		wantStatus   []int
		wantError    bool
	}{
		// All succeeding methods.
		{"GET", "/test", payload{}, "{\"a\":0}", http.StatusOK, []int{http.StatusOK}, false},
		{"POST", "/test", payload{}, "{\"a\":0}", http.StatusOK, []int{http.StatusOK}, false},
		{"DELETE", "/test", payload{}, "{\"a\":0}", http.StatusOK, []int{http.StatusOK}, false},
		{"PUT", "/test", payload{}, "{\"a\":0}", http.StatusOK, []int{http.StatusOK}, false},
		// Payload test.
		{"GET", "/test", payload{42}, "{\"a\":42}", http.StatusOK, []int{http.StatusOK}, false},
		// Expected failure.
		{"POST", "/test", payload{}, "{\"a\":0}", http.StatusInternalServerError, []int{http.StatusInternalServerError}, false},
		// Unexpected failure
		{"POST", "/test", payload{}, "{\"a\":0}", http.StatusInternalServerError, []int{http.StatusOK}, true},
	}
	for _, tt := range tests {
		ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			w.WriteHeader(tt.serverStatus)
			if r.Header.Get("X-Cookie") != fmt.Sprintf("token=%s", authToken) {
				t.Errorf("invalid auth header, got=%s, want=%s", r.Header.Get("X-Cookie"), authToken)
			}
			body, err := ioutil.ReadAll(r.Body)
			if err != nil {
				t.Errorf("could not read request body: %v", err)
				return
			}
			bodyStr := string(body)
			if bodyStr != tt.wantPayload {
				t.Errorf("unexpected payload, got=%s, want=%s", body, tt.wantPayload)
			}
		}))
		n, err := NewInsecureNessus(ts.URL)
		n.Verbose = true
		if err != nil {
			t.Errorf("could not create nessie instance: %v (%+v)", err, tt)
			continue
		}
		// Increase covered lines.
		n.authCookie = authToken
		resp, err := n.doRequest(tt.method, tt.resource, tt.sentPayload, tt.wantStatus)
		if tt.wantError {
			if err == nil {
				t.Errorf("got no error, expected one (%+v)", tt)
			}
			continue
		}
		if err != nil {
			t.Errorf("error in doRequest: %v (%+v)", err, tt)
			continue
		}
		if resp.StatusCode != tt.serverStatus {
			t.Errorf("got status code=%d, wanted=%d", resp.StatusCode, tt.serverStatus)
		}
	}
}

func TestLogin(t *testing.T) {
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(200)
		w.Header().Set("Content-Type", "application/json")
		j, err := json.Marshal(&loginResp{Token: "some token"})
		if err != nil {
			t.Fatalf("cannot serialize login response: %v", err)
		}
		w.Write(j)
	}))
	defer server.Close()
	n, err := NewInsecureNessus(server.URL)
	if err != nil {
		t.Fatalf("cannot create nessus instance: %v", err)
	}

	if err := n.Login("username", "password"); err != nil {
		t.Fatalf("got error during login: %v", err)
	}
	if got, want := n.authCookie, "some token"; got != want {
		t.Fatalf("wrong auth cookie, got=%q, want=%q", got, want)
	}
}

func TestMethods(t *testing.T) {
	var tests = []struct {
		resp       interface{}
		statusCode int
		call       func(n *Nessus)
	}{
		{&Session{}, http.StatusOK, func(n *Nessus) { n.Session() }},
	}
	for _, tt := range tests {
		server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			w.WriteHeader(tt.statusCode)
			j, err := json.Marshal(tt.resp)
			if err != nil {
				t.Fatalf("cannot serialize response: %v", err)
			}
			w.Write(j)
		}))
		defer server.Close()
		n, err := NewInsecureNessus(server.URL)
		if err != nil {
			t.Fatalf("cannot create nessus instance: %v", err)
		}
		tt.call(n)
	}
}
<commit_msg>added test skeleton for sessions<commit_after>package nessie

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"testing"
)

func TestDoRequest(t *testing.T) {
	// Test structure to be serialized.
	type payload struct {
		A int `json:"a"`
	}
	authToken := "some token"
	var tests = []struct {
		method       string
		resource     string
		sentPayload  payload
		wantPayload  string
		serverStatus int
		wantStatus   []int
		wantError    bool
	}{
		// All succeeding methods.
		{"GET", "/test", payload{}, "{\"a\":0}", http.StatusOK, []int{http.StatusOK}, false},
		{"POST", "/test", payload{}, "{\"a\":0}", http.StatusOK, []int{http.StatusOK}, false},
		{"DELETE", "/test", payload{}, "{\"a\":0}", http.StatusOK, []int{http.StatusOK}, false},
		{"PUT", "/test", payload{}, "{\"a\":0}", http.StatusOK, []int{http.StatusOK}, false},
		// Payload test.
		{"GET", "/test", payload{42}, "{\"a\":42}", http.StatusOK, []int{http.StatusOK}, false},
		// Expected failure.
		{"POST", "/test", payload{}, "{\"a\":0}", http.StatusInternalServerError, []int{http.StatusInternalServerError}, false},
		// Unexpected failure
		{"POST", "/test", payload{}, "{\"a\":0}", http.StatusInternalServerError, []int{http.StatusOK}, true},
	}
	for _, tt := range tests {
		ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			w.WriteHeader(tt.serverStatus)
			if r.Header.Get("X-Cookie") != fmt.Sprintf("token=%s", authToken) {
				t.Errorf("invalid auth header, got=%s, want=%s", r.Header.Get("X-Cookie"), authToken)
			}
			body, err := ioutil.ReadAll(r.Body)
			if err != nil {
				t.Errorf("could not read request body: %v", err)
				return
			}
			bodyStr := string(body)
			if bodyStr != tt.wantPayload {
				t.Errorf("unexpected payload, got=%s, want=%s", body, tt.wantPayload)
			}
		}))
		n, err := NewInsecureNessus(ts.URL)
		n.Verbose = true
		if err != nil {
			t.Errorf("could not create nessie instance: %v (%+v)", err, tt)
			continue
		}
		// Increase covered lines.
		n.authCookie = authToken
		resp, err := n.doRequest(tt.method, tt.resource, tt.sentPayload, tt.wantStatus)
		if tt.wantError {
			if err == nil {
				t.Errorf("got no error, expected one (%+v)", tt)
			}
			continue
		}
		if err != nil {
			t.Errorf("error in doRequest: %v (%+v)", err, tt)
			continue
		}
		if resp.StatusCode != tt.serverStatus {
			t.Errorf("got status code=%d, wanted=%d", resp.StatusCode, tt.serverStatus)
		}
	}
}

func TestLogin(t *testing.T) {
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(200)
		w.Header().Set("Content-Type", "application/json")
		j, err := json.Marshal(&loginResp{Token: "some token"})
		if err != nil {
			t.Fatalf("cannot serialize login response: %v", err)
		}
		w.Write(j)
	}))
	defer server.Close()
	n, err := NewInsecureNessus(server.URL)
	if err != nil {
		t.Fatalf("cannot create nessus instance: %v", err)
	}

	if err := n.Login("username", "password"); err != nil {
		t.Fatalf("got error during login: %v", err)
	}
	if got, want := n.authCookie, "some token"; got != want {
		t.Fatalf("wrong auth cookie, got=%q, want=%q", got, want)
	}
}

func TestMethods(t *testing.T) {
	var tests = []struct {
		resp       interface{}
		statusCode int
		call       func(n *Nessus)
	}{
		{&Session{}, http.StatusOK, func(n *Nessus) { n.Session() }},
		{&ServerProperties{}, http.StatusOK, func(n *Nessus) { n.ServerProperties() }},
	}
	for _, tt := range tests {
		server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			w.WriteHeader(tt.statusCode)
			j, err := json.Marshal(tt.resp)
			if err != nil {
				t.Fatalf("cannot serialize response: %v", err)
			}
			w.Write(j)
		}))
		defer server.Close()
		n, err := NewInsecureNessus(server.URL)
		if err != nil {
			t.Fatalf("cannot create nessus instance: %v", err)
		}
		tt.call(n)
	}
}
<|endoftext|>


<commit_before>// Copyright 2015 Google Inc. 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 main

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path"
)

// Build at the supplied commit (or branch or tag), embedding the given version
// name and returning a path to a directory containing exactly the
// root-relative file system structure we desire.
func build(
	commit string,
	version string,
	osys string) (dir string, err error) {
	log.Printf("Building version %s from %s.", version, commit)

	// Create a directory to hold our outputs. Kill it if we later return in
	// error.
	dir, err = ioutil.TempDir("", "package_gcsfuse_build")
	if err != nil {
		err = fmt.Errorf("TempDir: %v", err)
		return
	}

	defer func() {
		if err != nil {
			os.RemoveAll(dir)
		}
	}()

	// Set up the destination for a call to build_gcsfuse, which writes files
	// like
	//
	//     bin/gcsfuse
	//     sbin/mount.gcsfuse
	//
	// On Linux and OS X we want these to go into different places.
	var buildDir string
	switch osys {
	case "linux":
		buildDir = path.Join(dir, "usr")

	case "darwin":
		buildDir = path.Join(dir, "usr/local")

	default:
		err = fmt.Errorf("Unhandled OS: %q", osys)
		return
	}

	err = os.MkdirAll(buildDir, 0755)
	if err != nil {
		err = fmt.Errorf("MkdirAll: %v", err)
		return
	}

	// Create another directory into which we will clone the git repo bloe.
	gitDir, err := ioutil.TempDir("", "package_gcsfuse_git")
	if err != nil {
		err = fmt.Errorf("TempDir: %v", err)
		return
	}

	defer os.RemoveAll(gitDir)

	// Clone the git repo, checking out the correct tag.
	{
		log.Printf("Cloning into %s", gitDir)

		cmd := exec.Command(
			"git",
			"clone",
			"-b", commit,
			"https://github.com/GoogleCloudPlatform/gcsfuse.git",
			gitDir)

		var output []byte
		output, err = cmd.CombinedOutput()
		if err != nil {
			err = fmt.Errorf("Cloning: %v\nOutput:\n%s", err, output)
			return
		}
	}

	// Build build_gcsfuse.
	buildTool := path.Join(gitDir, "build_gcsfuse")
	{
		log.Printf("Building build_gcsfuse...")

		cmd := exec.Command(
			"go",
			"build",
			"-o", buildTool,
		)

		cmd.Dir = path.Join(gitDir, "tools/build_gcsfuse")
		cmd.Env = []string{
			"GO15VENDOREXPERIMENT=1",
			"GOPATH=/does/not/exist",
		}

		var output []byte
		output, err = cmd.CombinedOutput()
		if err != nil {
			err = fmt.Errorf("Building build_gcsfuse: %v\nOutput:\n%s", err, output)
			return
		}
	}

	// Run build_gcsfuse.
	{
		log.Printf("Running build_gcsfuse...")

		cmd := exec.Command(
			buildTool,
			gitDir,
			buildDir,
			version)

		var output []byte
		output, err = cmd.CombinedOutput()
		if err != nil {
			err = fmt.Errorf("go run build_gcsfuse: %v\nOutput:\n%s", err, output)
			return
		}
	}

	// Add symlink(s) from /sbin to /usr/sbin or /usr/local/sbin, as the case may
	// be.
	{
		symlinks := map[string]string{}
		switch osys {
		case "linux":
			symlinks["sbin/mount.fuse.gcsfuse"] = "/usr/sbin/mount.fuse.gcsfuse"
			symlinks["sbin/mount.gcsfuse"] = "/usr/sbin/mount.gcsfuse"

		case "darwin":
			symlinks["sbin/mount_gcsfuse"] = "/usr/sbin/mount_gcsfuse"

		default:
			err = fmt.Errorf("Unhandled OS: %q", osys)
			return
		}

		for relativeSrc, target := range symlinks {
			src := path.Join(dir, relativeSrc)

			err = os.MkdirAll(path.Dir(src), 0755)
			if err != nil {
				err = fmt.Errorf("MkdirAll: %v", err)
				return
			}

			err = os.Symlink(target, src)
			if err != nil {
				err = fmt.Errorf("Symlink: %v", err)
				return
			}
		}
	}

	return
}
<commit_msg>Fixed darwin link target.<commit_after>// Copyright 2015 Google Inc. 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 main

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path"
)

// Build at the supplied commit (or branch or tag), embedding the given version
// name and returning a path to a directory containing exactly the
// root-relative file system structure we desire.
func build(
	commit string,
	version string,
	osys string) (dir string, err error) {
	log.Printf("Building version %s from %s.", version, commit)

	// Create a directory to hold our outputs. Kill it if we later return in
	// error.
	dir, err = ioutil.TempDir("", "package_gcsfuse_build")
	if err != nil {
		err = fmt.Errorf("TempDir: %v", err)
		return
	}

	defer func() {
		if err != nil {
			os.RemoveAll(dir)
		}
	}()

	// Set up the destination for a call to build_gcsfuse, which writes files
	// like
	//
	//     bin/gcsfuse
	//     sbin/mount.gcsfuse
	//
	// On Linux and OS X we want these to go into different places.
	var buildDir string
	switch osys {
	case "linux":
		buildDir = path.Join(dir, "usr")

	case "darwin":
		buildDir = path.Join(dir, "usr/local")

	default:
		err = fmt.Errorf("Unhandled OS: %q", osys)
		return
	}

	err = os.MkdirAll(buildDir, 0755)
	if err != nil {
		err = fmt.Errorf("MkdirAll: %v", err)
		return
	}

	// Create another directory into which we will clone the git repo bloe.
	gitDir, err := ioutil.TempDir("", "package_gcsfuse_git")
	if err != nil {
		err = fmt.Errorf("TempDir: %v", err)
		return
	}

	defer os.RemoveAll(gitDir)

	// Clone the git repo, checking out the correct tag.
	{
		log.Printf("Cloning into %s", gitDir)

		cmd := exec.Command(
			"git",
			"clone",
			"-b", commit,
			"https://github.com/GoogleCloudPlatform/gcsfuse.git",
			gitDir)

		var output []byte
		output, err = cmd.CombinedOutput()
		if err != nil {
			err = fmt.Errorf("Cloning: %v\nOutput:\n%s", err, output)
			return
		}
	}

	// Build build_gcsfuse.
	buildTool := path.Join(gitDir, "build_gcsfuse")
	{
		log.Printf("Building build_gcsfuse...")

		cmd := exec.Command(
			"go",
			"build",
			"-o", buildTool,
		)

		cmd.Dir = path.Join(gitDir, "tools/build_gcsfuse")
		cmd.Env = []string{
			"GO15VENDOREXPERIMENT=1",
			"GOPATH=/does/not/exist",
		}

		var output []byte
		output, err = cmd.CombinedOutput()
		if err != nil {
			err = fmt.Errorf("Building build_gcsfuse: %v\nOutput:\n%s", err, output)
			return
		}
	}

	// Run build_gcsfuse.
	{
		log.Printf("Running build_gcsfuse...")

		cmd := exec.Command(
			buildTool,
			gitDir,
			buildDir,
			version)

		var output []byte
		output, err = cmd.CombinedOutput()
		if err != nil {
			err = fmt.Errorf("go run build_gcsfuse: %v\nOutput:\n%s", err, output)
			return
		}
	}

	// Add symlink(s) from /sbin to /usr/sbin or /usr/local/sbin, as the case may
	// be.
	{
		symlinks := map[string]string{}
		switch osys {
		case "linux":
			symlinks["sbin/mount.fuse.gcsfuse"] = "/usr/sbin/mount.fuse.gcsfuse"
			symlinks["sbin/mount.gcsfuse"] = "/usr/sbin/mount.gcsfuse"

		case "darwin":
			symlinks["sbin/mount_gcsfuse"] = "/usr/local/sbin/mount_gcsfuse"

		default:
			err = fmt.Errorf("Unhandled OS: %q", osys)
			return
		}

		for relativeSrc, target := range symlinks {
			src := path.Join(dir, relativeSrc)

			err = os.MkdirAll(path.Dir(src), 0755)
			if err != nil {
				err = fmt.Errorf("MkdirAll: %v", err)
				return
			}

			err = os.Symlink(target, src)
			if err != nil {
				err = fmt.Errorf("Symlink: %v", err)
				return
			}
		}
	}

	return
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2018 IBM, Inc.
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 k8s

import (
	"fmt"

	"github.com/skydive-project/skydive/filters"
	"github.com/skydive-project/skydive/logging"
	"github.com/skydive-project/skydive/probe"
	"github.com/skydive-project/skydive/topology/graph"
)

const clusterName = "cluster"

type clusterProbe struct {
	graph.DefaultGraphListener
	graph          *graph.Graph
	clusterIndexer *graph.MetadataIndexer
	objectIndexer  *graph.MetadataIndexer
}

func newClusterLinkedObjectIndexer(g *graph.Graph) *graph.MetadataIndexer {
	filter := filters.NewAndFilter(
		filters.NewTermStringFilter("Manager", managerValue),
		filters.NewOrFilter(
			filters.NewTermStringFilter("Type", "namespace"),
			filters.NewTermStringFilter("Type", "networkpolicy"),
			filters.NewTermStringFilter("Type", "node"),
			filters.NewTermStringFilter("Type", "persistentvolume"),
			filters.NewTermStringFilter("Type", "persistentvolumeclaim"),
		),
	)
	m := graph.NewGraphElementFilter(filter)
	return graph.NewMetadataIndexer(g, m)
}

func newClusterIndexer(g *graph.Graph) *graph.MetadataIndexer {
	filter := filters.NewAndFilter(
		filters.NewTermStringFilter("Manager", managerValue),
		filters.NewTermStringFilter("Type", "cluster"),
		filters.NewNotNullFilter("Name"),
	)
	m := graph.NewGraphElementFilter(filter)
	return graph.NewMetadataIndexer(g, m, "Name")
}

func dumpCluster(name string) string {
	return fmt.Sprintf("cluster{'Name': %s}", name)
}

func (p *clusterProbe) newMetadata(name string) graph.Metadata {
	return newMetadata("cluster", "", name, nil)
}

func (p *clusterProbe) linkObject(objNode, clusterNode *graph.Node) {
	addOwnershipLink(p.graph, clusterNode, objNode)
}

func (p *clusterProbe) addNode(name string) {
	p.graph.Lock()
	defer p.graph.Unlock()

	clusterNode := newNode(p.graph, graph.GenID(), p.newMetadata(name))
	objNodes, _ := p.objectIndexer.Get()
	for _, objNode := range objNodes {
		p.linkObject(objNode, clusterNode)
	}

	logging.GetLogger().Debugf("Added %s", dumpCluster(name))
}

func (p *clusterProbe) delNode(name string) {
	p.graph.Lock()
	defer p.graph.Unlock()

	clusterNodes, _ := p.clusterIndexer.Get(name)
	for _, clusterNode := range clusterNodes {
		p.graph.DelNode(clusterNode)
	}

	logging.GetLogger().Debugf("Deleted %s", dumpCluster(name))
}

func (p *clusterProbe) OnNodeAdded(objNode *graph.Node) {
	logging.GetLogger().Debugf("Got event on adding %s", dumpGraphNode(objNode))
	clusterNodes, _ := p.clusterIndexer.Get(clusterName)
	if len(clusterNodes) > 0 {
		p.linkObject(objNode, clusterNodes[0])
	}
}

func (p *clusterProbe) OnNodeUpdated(objNode *graph.Node) {
	logging.GetLogger().Debugf("Got event on updating %s", dumpGraphNode(objNode))
	clusterNodes, _ := p.clusterIndexer.Get(clusterName)
	if len(clusterNodes) > 0 {
		p.linkObject(objNode, clusterNodes[0])
	}
}

func (p *clusterProbe) Start() {
	p.clusterIndexer.Start()
	p.objectIndexer.AddEventListener(p)
	p.objectIndexer.Start()
	p.addNode(clusterName)
}

func (p *clusterProbe) Stop() {
	p.delNode(clusterName)
	p.clusterIndexer.Stop()
	p.objectIndexer.RemoveEventListener(p)
	p.objectIndexer.Stop()
}

func newClusterProbe(g *graph.Graph) probe.Probe {
	p := &clusterProbe{
		graph:          g,
		clusterIndexer: newClusterIndexer(g),
		objectIndexer:  newClusterLinkedObjectIndexer(g),
	}
	return p
}
<commit_msg>k8s: insert endpoints to cluster's graph entity<commit_after>/*
 * Copyright (C) 2018 IBM, Inc.
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 k8s

import (
	"fmt"

	"github.com/skydive-project/skydive/filters"
	"github.com/skydive-project/skydive/logging"
	"github.com/skydive-project/skydive/probe"
	"github.com/skydive-project/skydive/topology/graph"
)

const clusterName = "cluster"

type clusterProbe struct {
	graph.DefaultGraphListener
	graph          *graph.Graph
	clusterIndexer *graph.MetadataIndexer
	objectIndexer  *graph.MetadataIndexer
}

func newClusterLinkedObjectIndexer(g *graph.Graph) *graph.MetadataIndexer {
	filter := filters.NewAndFilter(
		filters.NewTermStringFilter("Manager", managerValue),
		filters.NewOrFilter(
			filters.NewTermStringFilter("Type", "namespace"),
			filters.NewTermStringFilter("Type", "networkpolicy"),
			filters.NewTermStringFilter("Type", "node"),
			filters.NewTermStringFilter("Type", "persistentvolume"),
			filters.NewTermStringFilter("Type", "persistentvolumeclaim"),
			filters.NewTermStringFilter("Type", "endpoints"),
		),
	)
	m := graph.NewGraphElementFilter(filter)
	return graph.NewMetadataIndexer(g, m)
}

func newClusterIndexer(g *graph.Graph) *graph.MetadataIndexer {
	filter := filters.NewAndFilter(
		filters.NewTermStringFilter("Manager", managerValue),
		filters.NewTermStringFilter("Type", "cluster"),
		filters.NewNotNullFilter("Name"),
	)
	m := graph.NewGraphElementFilter(filter)
	return graph.NewMetadataIndexer(g, m, "Name")
}

func dumpCluster(name string) string {
	return fmt.Sprintf("cluster{'Name': %s}", name)
}

func (p *clusterProbe) newMetadata(name string) graph.Metadata {
	return newMetadata("cluster", "", name, nil)
}

func (p *clusterProbe) linkObject(objNode, clusterNode *graph.Node) {
	addOwnershipLink(p.graph, clusterNode, objNode)
}

func (p *clusterProbe) addNode(name string) {
	p.graph.Lock()
	defer p.graph.Unlock()

	clusterNode := newNode(p.graph, graph.GenID(), p.newMetadata(name))
	objNodes, _ := p.objectIndexer.Get()
	for _, objNode := range objNodes {
		p.linkObject(objNode, clusterNode)
	}

	logging.GetLogger().Debugf("Added %s", dumpCluster(name))
}

func (p *clusterProbe) delNode(name string) {
	p.graph.Lock()
	defer p.graph.Unlock()

	clusterNodes, _ := p.clusterIndexer.Get(name)
	for _, clusterNode := range clusterNodes {
		p.graph.DelNode(clusterNode)
	}

	logging.GetLogger().Debugf("Deleted %s", dumpCluster(name))
}

func (p *clusterProbe) OnNodeAdded(objNode *graph.Node) {
	logging.GetLogger().Debugf("Got event on adding %s", dumpGraphNode(objNode))
	clusterNodes, _ := p.clusterIndexer.Get(clusterName)
	if len(clusterNodes) > 0 {
		p.linkObject(objNode, clusterNodes[0])
	}
}

func (p *clusterProbe) OnNodeUpdated(objNode *graph.Node) {
	logging.GetLogger().Debugf("Got event on updating %s", dumpGraphNode(objNode))
	clusterNodes, _ := p.clusterIndexer.Get(clusterName)
	if len(clusterNodes) > 0 {
		p.linkObject(objNode, clusterNodes[0])
	}
}

func (p *clusterProbe) Start() {
	p.clusterIndexer.Start()
	p.objectIndexer.AddEventListener(p)
	p.objectIndexer.Start()
	p.addNode(clusterName)
}

func (p *clusterProbe) Stop() {
	p.delNode(clusterName)
	p.clusterIndexer.Stop()
	p.objectIndexer.RemoveEventListener(p)
	p.objectIndexer.Stop()
}

func newClusterProbe(g *graph.Graph) probe.Probe {
	p := &clusterProbe{
		graph:          g,
		clusterIndexer: newClusterIndexer(g),
		objectIndexer:  newClusterLinkedObjectIndexer(g),
	}
	return p
}
<|endoftext|>


<commit_before>package db

import "fmt"

//QLQeryer implements the Queryer interface for ql database.
type QLQeryer struct {
}

//CreateSession retruns a Query for creating new session.
func (ql QLQeryer) CreateSession(table string) Query {
	var query = `
	BEGIN TRANSACTION;
	  INSERT INTO %s (key, data, created_on, updated_on, expires_on)
		VALUES ($1,$2,now(),now(),$3);
	COMMIT;
	`
	query = fmt.Sprintf(query, table)
	return NewQuery(query, true, "key", "data", "expires_on")
}

//FindSessionByKey returns a query for finding a session by key.
func (ql QLQeryer) FindSessionByKey(table string) Query {
	var query = `
	SELECT * from %s WHERE key LIKE $1 LIMIT 1;
	`
	query = fmt.Sprintf(query, table)
	return NewQuery(query, false, "key")
}

//UpdateSession updaates session data.
func (ql QLQeryer) UpdateSession(table string) Query {
	var query = `
BEGIN TRANSACTION;
  UPDATE %s
    data = $2,
    updated_on = now(),
  WHERE key==$1;
COMMIT;
	`
	query = fmt.Sprintf(query, table)
	return NewQuery(query, true, "key", "data")
}

//DeleteSession deletes a session.
func (ql QLQeryer) DeleteSession(table string) Query {
	var query = `
BEGIN TRANSACTION;
   DELETE FROM %s
  WHERE key==$1;
COMMIT;
	`
	query = fmt.Sprintf(query, table)
	return NewQuery(query, true, "key")
}

func (ql QLQeryer) CreateUser(table string) Query {
	var query = `
	BEGIN TRANSACTION;
	  INSERT INTO %s (username,password,email,created_at,updated_at)
		VALUES ($1,$2,$3,now(),now());
	COMMIT;
	`
	query = fmt.Sprintf(query, table)
	return NewQuery(query, true, "username", "password", "email")
}

func (ql QLQeryer) FindUserBy(table, field string) Query {
	var query = `
	SELECT * from %s WHERE %s LIKE $1 LIMIT 1;
	`
	query = fmt.Sprintf(query, table, field)
	return NewQuery(query, false, field)
}
<commit_msg>Fix FindUserBy<commit_after>package db

import "fmt"

//QLQeryer implements the Queryer interface for ql database.
type QLQeryer struct {
}

//CreateSession retruns a Query for creating new session.
func (ql QLQeryer) CreateSession(table string) Query {
	var query = `
	BEGIN TRANSACTION;
	  INSERT INTO %s (key, data, created_on, updated_on, expires_on)
		VALUES ($1,$2,now(),now(),$3);
	COMMIT;
	`
	query = fmt.Sprintf(query, table)
	return NewQuery(query, true, "key", "data", "expires_on")
}

//FindSessionByKey returns a query for finding a session by key.
func (ql QLQeryer) FindSessionByKey(table string) Query {
	var query = `
	SELECT * from %s WHERE key=$1 LIMIT 1;
	`
	query = fmt.Sprintf(query, table)
	return NewQuery(query, false, "key")
}

//UpdateSession updaates session data.
func (ql QLQeryer) UpdateSession(table string) Query {
	var query = `
BEGIN TRANSACTION;
  UPDATE %s
    data = $2,
    updated_on = now(),
  WHERE key==$1;
COMMIT;
	`
	query = fmt.Sprintf(query, table)
	return NewQuery(query, true, "key", "data")
}

//DeleteSession deletes a session.
func (ql QLQeryer) DeleteSession(table string) Query {
	var query = `
BEGIN TRANSACTION;
   DELETE FROM %s
  WHERE key==$1;
COMMIT;
	`
	query = fmt.Sprintf(query, table)
	return NewQuery(query, true, "key")
}

func (ql QLQeryer) CreateUser(table string) Query {
	var query = `
	BEGIN TRANSACTION;
	  INSERT INTO %s (username,password,email,created_at,updated_at)
		VALUES ($1,$2,$3,now(),now());
	COMMIT;
	`
	query = fmt.Sprintf(query, table)
	return NewQuery(query, true, "username", "password", "email")
}

func (ql QLQeryer) FindUserBy(table, field string) Query {
	var query = `
	SELECT id(),username,password,email,created_on,updated_on
	from %s WHERE %s LIKE $1 LIMIT 1;
	`
	query = fmt.Sprintf(query, table, field)
	return NewQuery(query, false, field)
}
<|endoftext|>


<commit_before>package server

import (
	"encoding/json"
	"fmt"
	"net/http"
	"strconv"

	"github.com/gorilla/mux"
	"github.com/mch1307/gomotics/db"
	"github.com/mch1307/gomotics/log"
	"github.com/mch1307/gomotics/types"
)

// JeedomCmd handler for POST on /jeedom/{id}/{value}
func JeedomCmd(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	nhcItem, found := db.GetItemByJeedomID(vars["id"])
	if !found {
		w.WriteHeader(http.StatusMethodNotAllowed)
		w.Write([]byte("Item not found"))
		log.Warn("Item not found ", vars)
		return
	}
	val, err := strconv.Atoi(vars["value"])
	if err != nil {
		w.WriteHeader(http.StatusMethodNotAllowed)
		w.Write([]byte("Invalid value"))
		log.Warn("Invalid value ", vars)
		return
	}
	myCmd := new(SimpleCmd)
	myCmd.Cmd = "executeactions"
	myCmd.ID = nhcItem.ID
	myCmd.Value = val
	if err := SendCommand(myCmd.Stringify()); err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		fmt.Fprintln(w, err)
	} else {
		w.WriteHeader(http.StatusOK)
		w.Write([]byte("Success"))
	}

}

// NhcCmd endpoints for sending NHC commands
func NhcCmd(w http.ResponseWriter, r *http.Request) {
	//vars := r.URL.Query()
	vars := mux.Vars(r)
	id, err := strconv.Atoi(vars["id"])
	if err != nil {
		fmt.Println("invalid request: id should be numeric")
	}
	val, err := strconv.Atoi(vars["value"])
	if err != nil {
		fmt.Println("invalid request: value should be numeric")
	}
	var myCmd SimpleCmd
	myCmd.Cmd = "executeactions"
	myCmd.ID = id
	myCmd.Value = val

	if err := SendCommand(myCmd.Stringify()); err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		fmt.Fprintln(w, err)
	} else {
		w.WriteHeader(http.StatusOK)
		w.Write([]byte("Success"))
	}
}

// GetNhcInfo handler for /api/v1/nhc/
func GetNhcInfo(w http.ResponseWriter, r *http.Request) {
	tmp := db.GetNhcSysInfo()
	resp, _ := json.Marshal(tmp)
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusOK)
	w.Write(resp)
}

// GetNhcItems handler for /api/v1/nhc/
func GetNhcItems(w http.ResponseWriter, r *http.Request) {
	tmp := db.GetNHCItems()
	resp, _ := json.Marshal(tmp)
	w.Header().Set("Content-Type", "application/json")
	w.Write(resp)
}

// GetNhcItem handler for /api/v1/nhc/{id}
func GetNhcItem(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	found := false
	params := mux.Vars(r)
	tmp := db.GetNHCItems()
	var resp types.NHCItem
	for _, val := range tmp {
		if i, _ := strconv.Atoi(params["id"]); val.ID == i {
			//fmt.Println("in if", params["id"], i)
			resp = val
			found = true
		}
	}
	if !found {
		w.WriteHeader(http.StatusNoContent)
		fmt.Fprint(w, string("no item matching given id found"))
	} else {
		w.WriteHeader(http.StatusOK)
		rsp, _ := json.Marshal(resp)
		w.Write(rsp)
	}
}
<commit_msg>only update jeedom item state when needed<commit_after>package server

import (
	"encoding/json"
	"fmt"
	"net/http"
	"strconv"

	"github.com/gorilla/mux"
	"github.com/mch1307/gomotics/db"
	"github.com/mch1307/gomotics/log"
	"github.com/mch1307/gomotics/types"
)

// JeedomCmd handler for POST on /jeedom/{id}/{value}
func JeedomCmd(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	nhcItem, found := db.GetItemByJeedomID(vars["id"])
	if !found {
		w.WriteHeader(http.StatusMethodNotAllowed)
		w.Write([]byte("Item not found"))
		log.Warn("Item not found ", vars)
		return
	}
	nhcItem.JeedomState = vars["value"]
	db.SaveNHCItem(nhcItem)
	val, err := strconv.Atoi(vars["value"])
	if err != nil {
		w.WriteHeader(http.StatusMethodNotAllowed)
		w.Write([]byte("Invalid value"))
		log.Warn("Invalid value ", vars)
		return
	}
	myCmd := new(SimpleCmd)
	myCmd.Cmd = "executeactions"
	myCmd.ID = nhcItem.ID
	myCmd.Value = val
	if err := SendCommand(myCmd.Stringify()); err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		fmt.Fprintln(w, err)
	} else {
		w.WriteHeader(http.StatusOK)
		w.Write([]byte("Success"))
	}

}

// NhcCmd endpoints for sending NHC commands
func NhcCmd(w http.ResponseWriter, r *http.Request) {
	//vars := r.URL.Query()
	vars := mux.Vars(r)
	id, err := strconv.Atoi(vars["id"])
	if err != nil {
		fmt.Println("invalid request: id should be numeric")
	}
	val, err := strconv.Atoi(vars["value"])
	if err != nil {
		fmt.Println("invalid request: value should be numeric")
	}
	var myCmd SimpleCmd
	myCmd.Cmd = "executeactions"
	myCmd.ID = id
	myCmd.Value = val

	if err := SendCommand(myCmd.Stringify()); err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		fmt.Fprintln(w, err)
	} else {
		w.WriteHeader(http.StatusOK)
		w.Write([]byte("Success"))
	}
}

// GetNhcInfo handler for /api/v1/nhc/
func GetNhcInfo(w http.ResponseWriter, r *http.Request) {
	tmp := db.GetNhcSysInfo()
	resp, _ := json.Marshal(tmp)
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusOK)
	w.Write(resp)
}

// GetNhcItems handler for /api/v1/nhc/
func GetNhcItems(w http.ResponseWriter, r *http.Request) {
	tmp := db.GetNHCItems()
	resp, _ := json.Marshal(tmp)
	w.Header().Set("Content-Type", "application/json")
	w.Write(resp)
}

// GetNhcItem handler for /api/v1/nhc/{id}
func GetNhcItem(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	found := false
	params := mux.Vars(r)
	tmp := db.GetNHCItems()
	var resp types.NHCItem
	for _, val := range tmp {
		if i, _ := strconv.Atoi(params["id"]); val.ID == i {
			//fmt.Println("in if", params["id"], i)
			resp = val
			found = true
		}
	}
	if !found {
		w.WriteHeader(http.StatusNoContent)
		fmt.Fprint(w, string("no item matching given id found"))
	} else {
		w.WriteHeader(http.StatusOK)
		rsp, _ := json.Marshal(resp)
		w.Write(rsp)
	}
}
<|endoftext|>


<commit_before>/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you 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 container

import (
	"bytes"
	"fmt"
	"io"
	"strings"
	"sync"

	"github.com/fsouza/go-dockerclient"
	"github.com/spf13/viper"
	"golang.org/x/net/context"
)

//abstract virtual image for supporting arbitrary virual machines
type vm interface {
	build(ctxt context.Context, id string, args []string, env []string, attachstdin bool, attachstdout bool, reader io.Reader) error
	start(ctxt context.Context, id string, args []string, env []string, attachstdin bool, attachstdout bool) error
	stop(ctxt context.Context, id string, timeout uint, dontkill bool, dontremove bool) error
}

//dockerVM is a vm. It is identified by an image id
type dockerVM struct {
	id string
}

//create a docker client given endpoint to communicate with docker host
func (vm *dockerVM) newClient() (*docker.Client, error) {
	return newDockerClient()
}

func (vm *dockerVM) createContainer(ctxt context.Context, client *docker.Client, imageID string, containerID string, args []string, env []string, attachstdin bool, attachstdout bool) error {
	config := docker.Config{Cmd: args, Image: imageID, Env: env, AttachStdin: attachstdin, AttachStdout: attachstdout}
	copts := docker.CreateContainerOptions{Name: containerID, Config: &config}
	vmLogger.Debug("Create container: %s", containerID)
	_, err := client.CreateContainer(copts)
	if err != nil {
		return err
	}
	vmLogger.Debug("Created container: %s", imageID)
	return nil
}

//for docker inputbuf is tar reader ready for use by docker.Client
//the stream from end client to peer could directly be this tar stream
//talk to docker daemon using docker Client and build the image
func (vm *dockerVM) build(ctxt context.Context, id string, args []string, env []string, attachstdin bool, attachstdout bool, reader io.Reader) error {
	outputbuf := bytes.NewBuffer(nil)
	opts := docker.BuildImageOptions{
		Name:         id,
		Pull:         true,
		InputStream:  reader,
		OutputStream: outputbuf,
	}
	client, err := vm.newClient()
	switch err {
	case nil:
		if err = client.BuildImage(opts); err != nil {
			vmLogger.Error(fmt.Sprintf("Error building Peer container: %s", err))
			return err
		}
		vmLogger.Debug("Created image: %s", id)
	default:
		return fmt.Errorf("Error creating docker client: %s", err)
	}
	return nil
}

func (vm *dockerVM) start(ctxt context.Context, imageID string, args []string, env []string, attachstdin bool, attachstdout bool) error {
	client, err := vm.newClient()
	if err != nil {
		vmLogger.Debug("start - cannot create client %s", err)
		return err
	}

	containerID := strings.Replace(imageID, ":", "_", -1)

	//stop,force remove if necessary
	vmLogger.Debug("Cleanup container %s", containerID)
	vm.stopInternal(ctxt, client, containerID, 0, false, false)

	vmLogger.Debug("Start container %s", containerID)
	err = vm.createContainer(ctxt, client, imageID, containerID, args, env, attachstdin, attachstdout)
	if err != nil {
		vmLogger.Error(fmt.Sprintf("start-could not recreate container %s", err))
		return err
	}
	err = client.StartContainer(containerID, &docker.HostConfig{NetworkMode: "host"})
	if err != nil {
		vmLogger.Error(fmt.Sprintf("start-could not start container %s", err))
		return err
	}

	vmLogger.Debug("Started container %s", containerID)
	return nil
}

func (vm *dockerVM) stop(ctxt context.Context, id string, timeout uint, dontkill bool, dontremove bool) error {
	client, err := vm.newClient()
	if err != nil {
		vmLogger.Debug("start - cannot create client %s", err)
		return err
	}
	id = strings.Replace(id, ":", "_", -1)

	err = vm.stopInternal(ctxt, client, id, timeout, dontkill, dontremove)

	return err
}

func (vm *dockerVM) stopInternal(ctxt context.Context, client *docker.Client, id string, timeout uint, dontkill bool, dontremove bool) error {
	err := client.StopContainer(id, timeout)
	if err != nil {
		vmLogger.Debug("Stop container %s(%s)", id, err)
	} else {
		vmLogger.Debug("Stopped container %s", id)
	}
	if !dontkill {
		err = client.KillContainer(docker.KillContainerOptions{ID: id})
		if err != nil {
			vmLogger.Debug("Kill container %s (%s)", id, err)
		} else {
			vmLogger.Debug("Killed container %s", id)
		}
	}
	if !dontremove {
		err = client.RemoveContainer(docker.RemoveContainerOptions{ID: id, Force: true})
		if err != nil {
			vmLogger.Debug("Remove container %s (%s)", id, err)
		} else {
			vmLogger.Debug("Removed container %s", id)
		}
	}
	return err
}
//constants for supported containers
const (
	DOCKER = "Docker"
)

type image struct {
	id   string
	args []string
	v    vm
}

type refCountedLock struct {
	refCount int
	lock     *sync.RWMutex
}

//VMController - manages VMs
//   . abstract construction of different types of VMs (we only care about Docker for now)
//   . manage lifecycle of VM (start with build, start, stop ...
//     eventually probably need fine grained management)
type VMController struct {
	sync.RWMutex
	// Handlers for each chaincode
	containerLocks map[string]*refCountedLock
}

//singleton...acess through NewVMController
var vmcontroller *VMController

//NewVMController - creates/returns singleton
func init() {
	vmcontroller = new(VMController)
	vmcontroller.containerLocks = make(map[string]*refCountedLock)
}

func (vmc *VMController) newVM(typ string) vm {
	var (
		v vm
	)

	switch typ {
	case DOCKER:
		v = &dockerVM{}
	case "":
		v = &dockerVM{}
	}
	return v
}

func (vmc *VMController) lockContainer(id string) {
	//get the container lock under global lock
	vmcontroller.Lock()
	var refLck *refCountedLock
	var ok bool
	if refLck, ok = vmcontroller.containerLocks[id]; !ok {
		refLck = &refCountedLock{refCount: 1, lock: &sync.RWMutex{}}
		vmcontroller.containerLocks[id] = refLck
	} else {
		refLck.refCount++
		vmLogger.Debug("refcount %d (%s)", refLck.refCount, id)
	}
	vmcontroller.Unlock()
	vmLogger.Debug("waiting for container(%s) lock", id)
	refLck.lock.Lock()
	vmLogger.Debug("got container (%s) lock", id)
}

func (vmc *VMController) unlockContainer(id string) {
	vmcontroller.Lock()
	if refLck, ok := vmcontroller.containerLocks[id]; ok {
		if refLck.refCount <= 0 {
			panic("refcnt <= 0")
		}
		refLck.lock.Unlock()
		if refLck.refCount--; refLck.refCount == 0 {
			vmLogger.Debug("container lock deleted(%s)", id)
			delete(vmcontroller.containerLocks, id)
		}
	} else {
		vmLogger.Debug("no lock to unlock(%s)!!", id)
	}
	vmcontroller.Unlock()
}

//VMCReqIntf - all requests should implement this interface.
//The context should be passed and tested at each layer till we stop
//note that we'd stop on the first method on the stack that does not
//take context
type VMCReqIntf interface {
	do(ctxt context.Context, v vm) VMCResp
	getID() string
}

//VMCResp - response from requests. resp field is a anon interface.
//It can hold any response. err should be tested first
type VMCResp struct {
	Err  error
	Resp interface{}
}

//CreateImageReq - properties for creating an container image
type CreateImageReq struct {
	ID           string
	Reader       io.Reader
	AttachStdin  bool
	AttachStdout bool
	Args         []string
	Env          []string
}

func (bp CreateImageReq) do(ctxt context.Context, v vm) VMCResp {
	var resp VMCResp
	if err := v.build(ctxt, bp.ID, bp.Args, bp.Env, bp.AttachStdin, bp.AttachStdout, bp.Reader); err != nil {
		resp = VMCResp{Err: err}
	} else {
		resp = VMCResp{}
	}

	return resp
}

func (bp CreateImageReq) getID() string {
	return bp.ID
}

//StartImageReq - properties for starting a container.
type StartImageReq struct {
	ID           string
	Args         []string
	Env          []string
	AttachStdin  bool
	AttachStdout bool
}

func (si StartImageReq) do(ctxt context.Context, v vm) VMCResp {
	var resp VMCResp
	if err := v.start(ctxt, si.ID, si.Args, si.Env, si.AttachStdin, si.AttachStdout); err != nil {
		resp = VMCResp{Err: err}
	} else {
		resp = VMCResp{}
	}

	return resp
}

func (si StartImageReq) getID() string {
	return si.ID
}

//StopImageReq - properties for stopping a container.
type StopImageReq struct {
	ID      string
	Timeout uint
	//by default we will kill the container after stopping
	Dontkill bool
	//by default we will remove the container after killing
	Dontremove bool
}

func (si StopImageReq) do(ctxt context.Context, v vm) VMCResp {
	var resp VMCResp
	if err := v.stop(ctxt, si.ID, si.Timeout, si.Dontkill, si.Dontremove); err != nil {
		resp = VMCResp{Err: err}
	} else {
		resp = VMCResp{}
	}

	return resp
}

func (si StopImageReq) getID() string {
	return si.ID
}

//VMCProcess should be used as follows
//   . construct a context
//   . construct req of the right type (e.g., CreateImageReq)
//   . call it in a go routine
//   . process response in the go routing
//context can be cancelled. VMCProcess will try to cancel calling functions if it can
//For instance docker clients api's such as BuildImage are not cancelable.
//In all cases VMCProcess will wait for the called go routine to return
func VMCProcess(ctxt context.Context, vmtype string, req VMCReqIntf) (interface{}, error) {
	v := vmcontroller.newVM(vmtype)

	if v == nil {
		return nil, fmt.Errorf("Unknown VM type %s", vmtype)
	}

	c := make(chan struct{})
	var resp interface{}
	go func() {
		defer close(c)
		id := req.getID()
		vmcontroller.lockContainer(id)
		resp = req.do(ctxt, v)
		vmcontroller.unlockContainer(id)
	}()

	select {
	case <-c:
		return resp, nil
	case <-ctxt.Done():
		//TODO cancel req.do ... (needed) ?
		<-c
		return nil, ctxt.Err()
	}
}

//GetVMFromName generates the docker image from peer information given the hashcode. This is needed to
//keep image name's unique in a single host, multi-peer environment (such as a development environment)
func GetVMFromName(name string) string {
	vmName := fmt.Sprintf("%s-%s-%s", viper.GetString("peer.networkId"), viper.GetString("peer.id"), name)
	return vmName
}

/*******************
 * OLD ... leavethis here as sample for "client.CreateExec" in case we need it at some point
func (vm *dockerVM) start(ctxt context.Context, id string, args []string, detach bool, instream io.Reader, outstream io.Writer) error {
	client, err := vm.newClient()
	if err != nil {
		fmt.Printf("start - cannot create client %s\n", err)
		return err
	}
	id = strings.Replace(id, ":", "_", -1)
	fmt.Printf("starting container %s\n", id)
	econfig := docker.CreateExecOptions{
		Container:    id,
		Cmd:          args,
		AttachStdout: true,
	}
	execObj, err := client.CreateExec(econfig)
	if err != nil {
		//perhaps container not started
		err = client.StartContainer(id, &docker.HostConfig{})
		if err != nil {
			fmt.Printf("start-could not start container %s\n", err)
			return err
		}
		execObj, err = client.CreateExec(econfig)
	}

	if err != nil {
		fmt.Printf("start-could not create exec %s\n", err)
		return err
	}
	sconfig := docker.StartExecOptions{
		Detach:       detach,
		InputStream:  instream,
		OutputStream: outstream,
	}
	err = client.StartExec(execObj.ID, sconfig)
	if err != nil {
		fmt.Printf("start-could not start exec %s\n", err)
		return err
	}
	fmt.Printf("start-started and execed container for %s\n", id)
	return nil
}
****************************/
<commit_msg>Ability to pull local images for chaincode. Issue #776<commit_after>/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you 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 container

import (
	"bytes"
	"fmt"
	"io"
	"strings"
	"sync"

	"github.com/fsouza/go-dockerclient"
	"github.com/spf13/viper"
	"golang.org/x/net/context"
)

//abstract virtual image for supporting arbitrary virual machines
type vm interface {
	build(ctxt context.Context, id string, args []string, env []string, attachstdin bool, attachstdout bool, reader io.Reader) error
	start(ctxt context.Context, id string, args []string, env []string, attachstdin bool, attachstdout bool) error
	stop(ctxt context.Context, id string, timeout uint, dontkill bool, dontremove bool) error
}

//dockerVM is a vm. It is identified by an image id
type dockerVM struct {
	id string
}

//create a docker client given endpoint to communicate with docker host
func (vm *dockerVM) newClient() (*docker.Client, error) {
	return newDockerClient()
}

func (vm *dockerVM) createContainer(ctxt context.Context, client *docker.Client, imageID string, containerID string, args []string, env []string, attachstdin bool, attachstdout bool) error {
	config := docker.Config{Cmd: args, Image: imageID, Env: env, AttachStdin: attachstdin, AttachStdout: attachstdout}
	copts := docker.CreateContainerOptions{Name: containerID, Config: &config}
	vmLogger.Debug("Create container: %s", containerID)
	_, err := client.CreateContainer(copts)
	if err != nil {
		return err
	}
	vmLogger.Debug("Created container: %s", imageID)
	return nil
}

//for docker inputbuf is tar reader ready for use by docker.Client
//the stream from end client to peer could directly be this tar stream
//talk to docker daemon using docker Client and build the image
func (vm *dockerVM) build(ctxt context.Context, id string, args []string, env []string, attachstdin bool, attachstdout bool, reader io.Reader) error {
	outputbuf := bytes.NewBuffer(nil)
	opts := docker.BuildImageOptions{
		Name:         id,
		Pull:         false,
		InputStream:  reader,
		OutputStream: outputbuf,
	}
	client, err := vm.newClient()
	switch err {
	case nil:
		if err = client.BuildImage(opts); err != nil {
			vmLogger.Error(fmt.Sprintf("Error building Peer container: %s", err))
			return err
		}
		vmLogger.Debug("Created image: %s", id)
	default:
		return fmt.Errorf("Error creating docker client: %s", err)
	}
	return nil
}

func (vm *dockerVM) start(ctxt context.Context, imageID string, args []string, env []string, attachstdin bool, attachstdout bool) error {
	client, err := vm.newClient()
	if err != nil {
		vmLogger.Debug("start - cannot create client %s", err)
		return err
	}

	containerID := strings.Replace(imageID, ":", "_", -1)

	//stop,force remove if necessary
	vmLogger.Debug("Cleanup container %s", containerID)
	vm.stopInternal(ctxt, client, containerID, 0, false, false)

	vmLogger.Debug("Start container %s", containerID)
	err = vm.createContainer(ctxt, client, imageID, containerID, args, env, attachstdin, attachstdout)
	if err != nil {
		vmLogger.Error(fmt.Sprintf("start-could not recreate container %s", err))
		return err
	}
	err = client.StartContainer(containerID, &docker.HostConfig{NetworkMode: "host"})
	if err != nil {
		vmLogger.Error(fmt.Sprintf("start-could not start container %s", err))
		return err
	}

	vmLogger.Debug("Started container %s", containerID)
	return nil
}

func (vm *dockerVM) stop(ctxt context.Context, id string, timeout uint, dontkill bool, dontremove bool) error {
	client, err := vm.newClient()
	if err != nil {
		vmLogger.Debug("start - cannot create client %s", err)
		return err
	}
	id = strings.Replace(id, ":", "_", -1)

	err = vm.stopInternal(ctxt, client, id, timeout, dontkill, dontremove)

	return err
}

func (vm *dockerVM) stopInternal(ctxt context.Context, client *docker.Client, id string, timeout uint, dontkill bool, dontremove bool) error {
	err := client.StopContainer(id, timeout)
	if err != nil {
		vmLogger.Debug("Stop container %s(%s)", id, err)
	} else {
		vmLogger.Debug("Stopped container %s", id)
	}
	if !dontkill {
		err = client.KillContainer(docker.KillContainerOptions{ID: id})
		if err != nil {
			vmLogger.Debug("Kill container %s (%s)", id, err)
		} else {
			vmLogger.Debug("Killed container %s", id)
		}
	}
	if !dontremove {
		err = client.RemoveContainer(docker.RemoveContainerOptions{ID: id, Force: true})
		if err != nil {
			vmLogger.Debug("Remove container %s (%s)", id, err)
		} else {
			vmLogger.Debug("Removed container %s", id)
		}
	}
	return err
}

//constants for supported containers
const (
	DOCKER = "Docker"
)

type image struct {
	id   string
	args []string
	v    vm
}

type refCountedLock struct {
	refCount int
	lock     *sync.RWMutex
}

//VMController - manages VMs
//   . abstract construction of different types of VMs (we only care about Docker for now)
//   . manage lifecycle of VM (start with build, start, stop ...
//     eventually probably need fine grained management)
type VMController struct {
	sync.RWMutex
	// Handlers for each chaincode
	containerLocks map[string]*refCountedLock
}

//singleton...acess through NewVMController
var vmcontroller *VMController

//NewVMController - creates/returns singleton
func init() {
	vmcontroller = new(VMController)
	vmcontroller.containerLocks = make(map[string]*refCountedLock)
}

func (vmc *VMController) newVM(typ string) vm {
	var (
		v vm
	)

	switch typ {
	case DOCKER:
		v = &dockerVM{}
	case "":
		v = &dockerVM{}
	}
	return v
}

func (vmc *VMController) lockContainer(id string) {
	//get the container lock under global lock
	vmcontroller.Lock()
	var refLck *refCountedLock
	var ok bool
	if refLck, ok = vmcontroller.containerLocks[id]; !ok {
		refLck = &refCountedLock{refCount: 1, lock: &sync.RWMutex{}}
		vmcontroller.containerLocks[id] = refLck
	} else {
		refLck.refCount++
		vmLogger.Debug("refcount %d (%s)", refLck.refCount, id)
	}
	vmcontroller.Unlock()
	vmLogger.Debug("waiting for container(%s) lock", id)
	refLck.lock.Lock()
	vmLogger.Debug("got container (%s) lock", id)
}

func (vmc *VMController) unlockContainer(id string) {
	vmcontroller.Lock()
	if refLck, ok := vmcontroller.containerLocks[id]; ok {
		if refLck.refCount <= 0 {
			panic("refcnt <= 0")
		}
		refLck.lock.Unlock()
		if refLck.refCount--; refLck.refCount == 0 {
			vmLogger.Debug("container lock deleted(%s)", id)
			delete(vmcontroller.containerLocks, id)
		}
	} else {
		vmLogger.Debug("no lock to unlock(%s)!!", id)
	}
	vmcontroller.Unlock()
}

//VMCReqIntf - all requests should implement this interface.
//The context should be passed and tested at each layer till we stop
//note that we'd stop on the first method on the stack that does not
//take context
type VMCReqIntf interface {
	do(ctxt context.Context, v vm) VMCResp
	getID() string
}

//VMCResp - response from requests. resp field is a anon interface.
//It can hold any response. err should be tested first
type VMCResp struct {
	Err  error
	Resp interface{}
}

//CreateImageReq - properties for creating an container image
type CreateImageReq struct {
	ID           string
	Reader       io.Reader
	AttachStdin  bool
	AttachStdout bool
	Args         []string
	Env          []string
}

func (bp CreateImageReq) do(ctxt context.Context, v vm) VMCResp {
	var resp VMCResp
	if err := v.build(ctxt, bp.ID, bp.Args, bp.Env, bp.AttachStdin, bp.AttachStdout, bp.Reader); err != nil {
		resp = VMCResp{Err: err}
	} else {
		resp = VMCResp{}
	}

	return resp
}

func (bp CreateImageReq) getID() string {
	return bp.ID
}

//StartImageReq - properties for starting a container.
type StartImageReq struct {
	ID           string
	Args         []string
	Env          []string
	AttachStdin  bool
	AttachStdout bool
}

func (si StartImageReq) do(ctxt context.Context, v vm) VMCResp {
	var resp VMCResp
	if err := v.start(ctxt, si.ID, si.Args, si.Env, si.AttachStdin, si.AttachStdout); err != nil {
		resp = VMCResp{Err: err}
	} else {
		resp = VMCResp{}
	}

	return resp
}

func (si StartImageReq) getID() string {
	return si.ID
}

//StopImageReq - properties for stopping a container.
type StopImageReq struct {
	ID      string
	Timeout uint
	//by default we will kill the container after stopping
	Dontkill bool
	//by default we will remove the container after killing
	Dontremove bool
}

func (si StopImageReq) do(ctxt context.Context, v vm) VMCResp {
	var resp VMCResp
	if err := v.stop(ctxt, si.ID, si.Timeout, si.Dontkill, si.Dontremove); err != nil {
		resp = VMCResp{Err: err}
	} else {
		resp = VMCResp{}
	}

	return resp
}

func (si StopImageReq) getID() string {
	return si.ID
}

//VMCProcess should be used as follows
//   . construct a context
//   . construct req of the right type (e.g., CreateImageReq)
//   . call it in a go routine
//   . process response in the go routing
//context can be cancelled. VMCProcess will try to cancel calling functions if it can
//For instance docker clients api's such as BuildImage are not cancelable.
//In all cases VMCProcess will wait for the called go routine to return
func VMCProcess(ctxt context.Context, vmtype string, req VMCReqIntf) (interface{}, error) {
	v := vmcontroller.newVM(vmtype)

	if v == nil {
		return nil, fmt.Errorf("Unknown VM type %s", vmtype)
	}

	c := make(chan struct{})
	var resp interface{}
	go func() {
		defer close(c)
		id := req.getID()
		vmcontroller.lockContainer(id)
		resp = req.do(ctxt, v)
		vmcontroller.unlockContainer(id)
	}()

	select {
	case <-c:
		return resp, nil
	case <-ctxt.Done():
		//TODO cancel req.do ... (needed) ?
		<-c
		return nil, ctxt.Err()
	}
}

//GetVMFromName generates the docker image from peer information given the hashcode. This is needed to
//keep image name's unique in a single host, multi-peer environment (such as a development environment)
func GetVMFromName(name string) string {
	vmName := fmt.Sprintf("%s-%s-%s", viper.GetString("peer.networkId"), viper.GetString("peer.id"), name)
	return vmName
}

/*******************
 * OLD ... leavethis here as sample for "client.CreateExec" in case we need it at some point
func (vm *dockerVM) start(ctxt context.Context, id string, args []string, detach bool, instream io.Reader, outstream io.Writer) error {
	client, err := vm.newClient()
	if err != nil {
		fmt.Printf("start - cannot create client %s\n", err)
		return err
	}
	id = strings.Replace(id, ":", "_", -1)
	fmt.Printf("starting container %s\n", id)
	econfig := docker.CreateExecOptions{
		Container:    id,
		Cmd:          args,
		AttachStdout: true,
	}
	execObj, err := client.CreateExec(econfig)
	if err != nil {
		//perhaps container not started
		err = client.StartContainer(id, &docker.HostConfig{})
		if err != nil {
			fmt.Printf("start-could not start container %s\n", err)
			return err
		}
		execObj, err = client.CreateExec(econfig)
	}

	if err != nil {
		fmt.Printf("start-could not create exec %s\n", err)
		return err
	}
	sconfig := docker.StartExecOptions{
		Detach:       detach,
		InputStream:  instream,
		OutputStream: outstream,
	}
	err = client.StartExec(execObj.ID, sconfig)
	if err != nil {
		fmt.Printf("start-could not start exec %s\n", err)
		return err
	}
	fmt.Printf("start-started and execed container for %s\n", id)
	return nil
}
****************************/
<|endoftext|>


<commit_before>package service

import (
	"encoding/json"
	"fmt"
	"github.com/jinzhu/gorm"
	memcache "github.com/patrickmn/go-cache"
	"github.com/zwirec/TGChatScanner/TGBotApi"
	"github.com/zwirec/TGChatScanner/clarifaiApi"
	"github.com/zwirec/TGChatScanner/modelManager"
	"github.com/zwirec/TGChatScanner/requestHandler"
	"github.com/zwirec/TGChatScanner/requestHandler/appContext"
	"github.com/zwirec/TGChatScanner/requestHandler/deforkers"
	file "github.com/zwirec/TGChatScanner/requestHandler/filetypes"
	"github.com/zwirec/TGChatScanner/requestHandler/forkers"
	"github.com/zwirec/TGChatScanner/requestHandler/recognizers"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"net/url"
	"os"
	"os/signal"
	"os/user"
	"sync"
	"syscall"
	"time"
)

var (
	home      = os.Getenv("HOME")
	configURL = os.Getenv("TGCHATSCANNER_REMOTE_CONFIG")
)

const (
	DefaultWorkersNumber   = 5
	DefaultCacheExpiraiton = 5 * time.Minute
	DefaultCacheClean      = 10 * time.Minute
)

func init() {
	if home == "" {
		u, err := user.Current()
		if err != nil {
			log.Fatal(err)
		}
		home := u.HomeDir
		fmt.Fprint(ioutil.Discard, home)
	}
	if configURL == "" {

		configURL = home + "/.config/tgchatscanner/config.json"
	}
}

type Config map[string]map[string]interface{}

type Service struct {
	sock         net.Listener
	mux          *http.ServeMux
	srv          *http.Server
	reqHandler   *requestHandler.RequestHandler
	config       Config
	errLogger    *log.Logger
	accessLogger *log.Logger
	notifier     chan os.Signal
	poolsWG      sync.WaitGroup
	endpointWg   sync.WaitGroup
	poolsDone    chan struct{}
}

func NewService() *Service {
	accL, errL := createLoggers()
	return &Service{
		reqHandler:   requestHandler.NewRequestHandler(),
		mux:          http.NewServeMux(),
		notifier:     make(chan os.Signal),
		poolsDone:    make(chan struct{}),
		errLogger:    errL,
		accessLogger: accL,
	}
}

func (s *Service) Run() error {

	if err := s.parseConfig(configURL); err != nil {
		s.errLogger.Println(err)
		return err
	}

	s.signalProcessing()

	db, err := s.initModels()

	if err != nil {
		s.errLogger.Println(err)
		return err
	}

	hostname := s.getHostname()

	clAPI := s.initClarifaiAPI()

	botAPI := s.initBotApi()

	workersNumber := s.getWorkersNumber()

	cache := memcache.New(DefaultCacheExpiraiton, DefaultCacheClean)

	imgPath, err := s.createImgPath()
	if err != nil {
		s.errLogger.Println(err)
		return err
	}

	downloadRequests := s.initPools(workersNumber)

	context := appContext.AppContext{
		DB:               db,
		DownloadRequests: downloadRequests,
		BotAPI:           botAPI,
		CfAPI:            clAPI,
		Cache:            cache,
		ErrLogger:        s.errLogger,
		AccessLogger:     s.accessLogger,
		ImagesPath:       imgPath,
		Hostname:         hostname,
	}

	appContext.SetAppContext(&context)
	s.reqHandler.RegisterHandlers()

	s.srv = &http.Server{Handler: s.reqHandler}

	s.endpointWg.Add(1)

	go func() {
		defer s.endpointWg.Done()
		s.endpoint()
	}()
	s.endpointWg.Wait()
	return nil
}

func (s *Service) endpoint() (err error) {
	s.sock, err = net.Listen("unix", s.config["server"]["socket"].(string))
	if err != nil {
		s.errLogger.Println(err)
		os.Remove(s.config["server"]["socket"].(string))
		s.sock, _ = net.Listen("unix", s.config["server"]["socket"].(string))
	}
	if err := os.Chmod(s.config["server"]["socket"].(string), 0777); err != nil {
		s.errLogger.Println(err)
		s.notifier <- syscall.SIGINT
	}

	s.errLogger.Println("Socket opened")
	s.errLogger.Println("Server started")
	log.Println("Server started")
	if err := s.srv.Serve(s.sock); err != nil {
		s.errLogger.Println(err)
	}
	return nil
}

func (s *Service) parseConfig(URL string) error {
	var configRaw []byte

	_, err := url.Parse(URL)

	if err == nil {
		res, err := http.Get(URL)
		if err != nil {
			s.errLogger.Println(err)
			return err
		}

		configRaw, err = ioutil.ReadAll(res.Body)
		res.Body.Close()
		if err != nil {
			s.errLogger.Println(err)
			return err
		}

	} else {
		var err error
		configRaw, err = ioutil.ReadFile(URL)
		if err != nil {
			s.errLogger.Println(err)
			return err
		}
	}

	if err := json.Unmarshal(configRaw, &s.config); err != nil {
		s.errLogger.Println(err)
		return err
	}

	return nil
}

func (s *Service) signalProcessing() {
	signal.Notify(s.notifier, syscall.SIGINT)
	go s.handler(s.notifier)
}

func (s *Service) handler(c chan os.Signal) {
	for {
		<-c
		s.errLogger.Println("Gracefully stopping...")
		log.Println("Gracefully stopping...")
		close(appContext.DownloadRequests)
		close(s.poolsDone)
		s.poolsWG.Wait()
		if err := s.srv.Shutdown(nil); err != nil {
			s.errLogger.Println(err)
			return
		}
	}
}

func (s *Service) initPools(workersNumber int) chan *file.FileBasic {
	dr := make(chan *file.FileBasic, workersNumber*2)

	fp := &requestHandler.FilePreparationsPool{In: dr, Done: s.poolsDone, WorkersNumber: workersNumber}
	fpOut := fp.Run(workersNumber*2, &s.poolsWG)

	forker := &forkers.ForkersPool{
		In:             fpOut,
		Done:           s.poolsDone,
		WorkersNumber:  workersNumber,
		ForkToFileInfo: requestHandler.CastToFileInfo,
		ForkToFileLink: requestHandler.CastToFileLink,
	}

	fdIn, prIn := forker.Run(workersNumber, workersNumber, &s.poolsWG)

	fd := &requestHandler.FileDownloadersPool{In: fdIn, Done: s.poolsDone, WorkersNumber: workersNumber}
	fdOut := fd.Run(workersNumber, &s.poolsWG)

	pr := &recognizers.PhotoRecognizersPool{In: prIn, Done: s.poolsDone, WorkersNumber: workersNumber}
	prOut := pr.Run(workersNumber, &s.poolsWG)

	deforker := &deforkers.DeforkersPool{
		In1:              fdOut,
		In2:              prOut,
		WorkersNumber:    workersNumber,
		DeforkDownloaded: requestHandler.CastFromDownloadedFile,
		DeforkRecognized: requestHandler.CastFromRecognizedPhoto,
	}

	dbsIn := deforker.Run(workersNumber*2, &s.poolsWG)

	dbs := &requestHandler.DbStoragesPool{In: dbsIn, WorkersNumber: workersNumber}
	dbs.Run(&s.poolsWG)
	return dr
}

func (s *Service) initClarifaiAPI() *clarifaiAPI.ClarifaiAPI {
	key := s.config["clarifai"]["api_key"].(string)
	url := s.config["clarifai"]["url"].(string)
	clAPI := clarifaiAPI.NewClarifaiAPI(key, url)
	return clAPI
}

func (s *Service) initBotApi() *TGBotAPI.BotAPI {
	key := s.config["tg_bot_api"]["token"].(string)
	return TGBotAPI.NewBotAPI(key)
}

func (s *Service) getWorkersNumber() int {

	wn, ok := s.config["server"]["workers"].(int)

	if !ok {
		wn = DefaultWorkersNumber
	}
	return wn
}

func createLoggers() (accLog *log.Logger, errLog *log.Logger) {
	errorlog, err := os.OpenFile("error.log", os.O_CREATE|os.O_APPEND|os.O_WRONLY, os.ModePerm)
	if err != nil {
		errorlog = os.Stderr
	}
	accesslog, err := os.OpenFile("access.log", os.O_CREATE|os.O_APPEND|os.O_WRONLY, os.ModePerm)
	if err != nil {
		accesslog = os.Stdout
	}
	accLog = log.New(errorlog, "", log.LstdFlags|log.Llongfile)
	errLog = log.New(accesslog, "", log.LstdFlags)
	return accLog, errLog
}

func (s *Service) initModels() (*gorm.DB, error) {
	db, err := modelManager.ConnectToDB(s.config["db"])
	if err != nil {
		return nil, err
	}

	if err := modelManager.InitDB(db); err != nil {
		return nil, err
	}
	return db, err
}

func (s *Service) createImgPath() (string, error) {
	imgPath, ok := s.config["chatscanner"]["images_path"].(string)

	if !ok {
		wd, _ := os.Getwd()
		imgPath = wd + "/uploads/"
	}

	if err := os.MkdirAll(imgPath, os.ModePerm); err != nil {
		return "", err
	}
	return imgPath, nil
}

func (s *Service) getHostname() string {
	hostname, _ := s.config["chatscanner"]["host"].(string)

	_, err := url.Parse(hostname)
	if err != nil {
		hostname, err = os.Hostname()
		if err != nil {
			s.errLogger.Println(err)
			hostname = "localhost"
		}
	}
	return hostname
}
<commit_msg>logging fixed<commit_after>package service

import (
	"encoding/json"
	"fmt"
	"github.com/jinzhu/gorm"
	memcache "github.com/patrickmn/go-cache"
	"github.com/zwirec/TGChatScanner/TGBotApi"
	"github.com/zwirec/TGChatScanner/clarifaiApi"
	"github.com/zwirec/TGChatScanner/modelManager"
	"github.com/zwirec/TGChatScanner/requestHandler"
	"github.com/zwirec/TGChatScanner/requestHandler/appContext"
	"github.com/zwirec/TGChatScanner/requestHandler/deforkers"
	file "github.com/zwirec/TGChatScanner/requestHandler/filetypes"
	"github.com/zwirec/TGChatScanner/requestHandler/forkers"
	"github.com/zwirec/TGChatScanner/requestHandler/recognizers"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"net/url"
	"os"
	"os/signal"
	"os/user"
	"sync"
	"syscall"
	"time"
)

var (
	home      = os.Getenv("HOME")
	configURL = os.Getenv("TGCHATSCANNER_REMOTE_CONFIG")
)

const (
	DefaultWorkersNumber   = 5
	DefaultCacheExpiraiton = 5 * time.Minute
	DefaultCacheClean      = 10 * time.Minute
)

func init() {
	if home == "" {
		u, err := user.Current()
		if err != nil {
			log.Fatal(err)
		}
		home := u.HomeDir
		fmt.Fprint(ioutil.Discard, home)
	}
	if configURL == "" {

		configURL = home + "/.config/tgchatscanner/config.json"
	}
}

type Config map[string]map[string]interface{}

type Service struct {
	sock         net.Listener
	mux          *http.ServeMux
	srv          *http.Server
	reqHandler   *requestHandler.RequestHandler
	config       Config
	errLogger    *log.Logger
	accessLogger *log.Logger
	notifier     chan os.Signal
	poolsWG      sync.WaitGroup
	endpointWg   sync.WaitGroup
	poolsDone    chan struct{}
}

func NewService() *Service {
	accL, errL := createLoggers()
	return &Service{
		reqHandler:   requestHandler.NewRequestHandler(),
		mux:          http.NewServeMux(),
		notifier:     make(chan os.Signal),
		poolsDone:    make(chan struct{}),
		errLogger:    errL,
		accessLogger: accL,
	}
}

func (s *Service) Run() error {

	if err := s.parseConfig(configURL); err != nil {
		s.errLogger.Println(err)
		return err
	}

	s.signalProcessing()

	db, err := s.initModels()

	if err != nil {
		s.errLogger.Println(err)
		return err
	}

	hostname := s.getHostname()

	clAPI := s.initClarifaiAPI()

	botAPI := s.initBotApi()

	workersNumber := s.getWorkersNumber()

	cache := memcache.New(DefaultCacheExpiraiton, DefaultCacheClean)

	imgPath, err := s.createImgPath()
	if err != nil {
		s.errLogger.Println(err)
		return err
	}

	downloadRequests := s.initPools(workersNumber)

	context := appContext.AppContext{
		DB:               db,
		DownloadRequests: downloadRequests,
		BotAPI:           botAPI,
		CfAPI:            clAPI,
		Cache:            cache,
		ErrLogger:        s.errLogger,
		AccessLogger:     s.accessLogger,
		ImagesPath:       imgPath,
		Hostname:         hostname,
	}

	appContext.SetAppContext(&context)
	s.reqHandler.RegisterHandlers()

	s.srv = &http.Server{Handler: s.reqHandler}

	s.endpointWg.Add(1)

	go func() {
		defer s.endpointWg.Done()
		s.endpoint()
	}()
	s.endpointWg.Wait()
	return nil
}

func (s *Service) endpoint() (err error) {
	s.sock, err = net.Listen("unix", s.config["server"]["socket"].(string))
	if err != nil {
		s.errLogger.Println(err)
		os.Remove(s.config["server"]["socket"].(string))
		s.sock, _ = net.Listen("unix", s.config["server"]["socket"].(string))
	}
	if err := os.Chmod(s.config["server"]["socket"].(string), 0777); err != nil {
		s.errLogger.Println(err)
		s.notifier <- syscall.SIGINT
	}

	s.errLogger.Println("Socket opened")
	s.errLogger.Println("Server started")
	log.Println("Server started")
	if err := s.srv.Serve(s.sock); err != nil {
		s.errLogger.Println(err)
	}
	return nil
}

func (s *Service) parseConfig(URL string) error {
	var configRaw []byte

	_, err := url.Parse(URL)

	if err == nil {
		res, err := http.Get(URL)
		if err != nil {
			s.errLogger.Println(err)
			return err
		}

		configRaw, err = ioutil.ReadAll(res.Body)
		res.Body.Close()
		if err != nil {
			s.errLogger.Println(err)
			return err
		}

	} else {
		var err error
		configRaw, err = ioutil.ReadFile(URL)
		if err != nil {
			s.errLogger.Println(err)
			return err
		}
	}

	if err := json.Unmarshal(configRaw, &s.config); err != nil {
		s.errLogger.Println(err)
		return err
	}

	return nil
}

func (s *Service) signalProcessing() {
	signal.Notify(s.notifier, syscall.SIGINT)
	go s.handler(s.notifier)
}

func (s *Service) handler(c chan os.Signal) {
	for {
		<-c
		s.errLogger.Println("Gracefully stopping...")
		log.Println("Gracefully stopping...")
		close(appContext.DownloadRequests)
		close(s.poolsDone)
		s.poolsWG.Wait()
		if err := s.srv.Shutdown(nil); err != nil {
			s.errLogger.Println(err)
			return
		}
	}
}

func (s *Service) initPools(workersNumber int) chan *file.FileBasic {
	dr := make(chan *file.FileBasic, workersNumber*2)

	fp := &requestHandler.FilePreparationsPool{In: dr, Done: s.poolsDone, WorkersNumber: workersNumber}
	fpOut := fp.Run(workersNumber*2, &s.poolsWG)

	forker := &forkers.ForkersPool{
		In:             fpOut,
		Done:           s.poolsDone,
		WorkersNumber:  workersNumber,
		ForkToFileInfo: requestHandler.CastToFileInfo,
		ForkToFileLink: requestHandler.CastToFileLink,
	}

	fdIn, prIn := forker.Run(workersNumber, workersNumber, &s.poolsWG)

	fd := &requestHandler.FileDownloadersPool{In: fdIn, Done: s.poolsDone, WorkersNumber: workersNumber}
	fdOut := fd.Run(workersNumber, &s.poolsWG)

	pr := &recognizers.PhotoRecognizersPool{In: prIn, Done: s.poolsDone, WorkersNumber: workersNumber}
	prOut := pr.Run(workersNumber, &s.poolsWG)

	deforker := &deforkers.DeforkersPool{
		In1:              fdOut,
		In2:              prOut,
		WorkersNumber:    workersNumber,
		DeforkDownloaded: requestHandler.CastFromDownloadedFile,
		DeforkRecognized: requestHandler.CastFromRecognizedPhoto,
	}

	dbsIn := deforker.Run(workersNumber*2, &s.poolsWG)

	dbs := &requestHandler.DbStoragesPool{In: dbsIn, WorkersNumber: workersNumber}
	dbs.Run(&s.poolsWG)
	return dr
}

func (s *Service) initClarifaiAPI() *clarifaiAPI.ClarifaiAPI {
	key := s.config["clarifai"]["api_key"].(string)
	url := s.config["clarifai"]["url"].(string)
	clAPI := clarifaiAPI.NewClarifaiAPI(key, url)
	return clAPI
}

func (s *Service) initBotApi() *TGBotAPI.BotAPI {
	key := s.config["tg_bot_api"]["token"].(string)
	return TGBotAPI.NewBotAPI(key)
}

func (s *Service) getWorkersNumber() int {

	wn, ok := s.config["server"]["workers"].(int)

	if !ok {
		wn = DefaultWorkersNumber
	}
	return wn
}

func createLoggers() (accLog *log.Logger, errLog *log.Logger) {
	errorlog, err := os.OpenFile("error.log", os.O_CREATE|os.O_APPEND|os.O_WRONLY, os.ModePerm)
	if err != nil {
		errorlog = os.Stderr
	}
	accesslog, err := os.OpenFile("access.log", os.O_CREATE|os.O_APPEND|os.O_WRONLY, os.ModePerm)
	if err != nil {
		accesslog = os.Stdout
	}
	errLog = log.New(errorlog, "", log.LstdFlags|log.Llongfile)
	accLog = log.New(accesslog, "", log.LstdFlags)
	return accLog, errLog
}

func (s *Service) initModels() (*gorm.DB, error) {
	db, err := modelManager.ConnectToDB(s.config["db"])
	if err != nil {
		return nil, err
	}

	if err := modelManager.InitDB(db); err != nil {
		return nil, err
	}
	return db, err
}

func (s *Service) createImgPath() (string, error) {
	imgPath, ok := s.config["chatscanner"]["images_path"].(string)

	if !ok {
		wd, _ := os.Getwd()
		imgPath = wd + "/uploads/"
	}

	if err := os.MkdirAll(imgPath, os.ModePerm); err != nil {
		return "", err
	}
	return imgPath, nil
}

func (s *Service) getHostname() string {
	hostname, _ := s.config["chatscanner"]["host"].(string)

	_, err := url.Parse(hostname)
	if err != nil {
		hostname, err = os.Hostname()
		if err != nil {
			s.errLogger.Println(err)
			hostname = "localhost"
		}
	}
	return hostname
}
<|endoftext|>


<commit_before>package service
<commit_msg>Start service<commit_after>package service

import (
	"database/sql"
)

type Service struct {
	db *sql.DB
}

func NewService(db *sql.DB) *Service {
	return &Service{
		db: db,
	}
}
<|endoftext|>