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

package discovery

import (
	"errors"
	"fmt"
	"strings"
	"unicode/utf8"

	"v.io/v23/discovery"
)

const (
	maxAdvertisementSize = 512
	maxAttachmentSize    = 4096
	maxNumAttributes     = 32
	maxNumAttachments    = 32
)

// validateKey returns an error if the key is not suitable for advertising.
func validateKey(key string) error {
	if len(key) == 0 {
		return errors.New("empty key")
	}
	if strings.HasPrefix(key, "_") {
		return errors.New("key starts with '_'")
	}
	for _, c := range key {
		if c < 0x20 || c > 0x7e {
			return errors.New("key is not printable US-ASCII")
		}
		if c == '=' {
			return errors.New("key includes '='")
		}
	}
	return nil
}

// validateAttributes returns an error if the attributes are not suitable for advertising.
func validateAttributes(attributes discovery.Attributes) error {
	if len(attributes) > maxNumAttributes {
		return errors.New("too many")
	}
	for k, v := range attributes {
		if err := validateKey(k); err != nil {
			return err
		}
		if !utf8.ValidString(v) {
			return errors.New("value is not valid UTF-8 string")
		}
	}
	return nil
}

// validateAttachments returns an error if the attachments are not suitable for advertising.
func validateAttachments(attachments discovery.Attachments) error {
	if len(attachments) > maxNumAttachments {
		return errors.New("too many")
	}
	for k, v := range attachments {
		if err := validateKey(k); err != nil {
			return err
		}
		if len(v) > maxAttachmentSize {
			return errors.New("too large")
		}
	}
	return nil
}

// sizeOfAd returns the size of ad excluding id and attachments.
func sizeOfAd(ad *discovery.Advertisement) int {
	size := len(ad.InterfaceName)
	for _, a := range ad.Addresses {
		size += len(a)
	}
	for k, v := range ad.Attributes {
		size += len(k) + len(v)
	}
	return size
}

// validateAd returns an error if ad is not suitable for advertising.
func validateAd(ad *discovery.Advertisement) error {
	if !ad.Id.IsValid() {
		return errors.New("id not valid")
	}
	if len(ad.InterfaceName) == 0 {
		return errors.New("interface name not provided")
	}
	if len(ad.Addresses) == 0 {
		return errors.New("address not provided")
	}
	if err := validateAttributes(ad.Attributes); err != nil {
		return fmt.Errorf("attributes not valid: %v", err)
	}
	if err := validateAttachments(ad.Attachments); err != nil {
		return fmt.Errorf("attachments not valid: %v", err)
	}
	if sizeOfAd(ad) > maxAdvertisementSize {
		return errors.New("advertisement too large")
	}
	return nil
}
<commit_msg>discovery: make validation error messages more descriptive<commit_after>// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package discovery

import (
	"errors"
	"fmt"
	"strings"
	"unicode/utf8"

	"v.io/v23/discovery"
)

const (
	maxAdvertisementSize = 512
	maxAttachmentSize    = 4096
	maxNumAttributes     = 32
	maxNumAttachments    = 32
)

// validateKey returns an error if the key is not suitable for advertising.
func validateKey(key string) error {
	if len(key) == 0 {
		return errors.New("empty key")
	}
	if strings.HasPrefix(key, "_") {
		return fmt.Errorf("key starts with '_': %q", key)
	}
	for _, c := range key {
		if c < 0x20 || c > 0x7e {
			return fmt.Errorf("key is not printable US-ASCII: %q", key)
		}
		if c == '=' {
			return fmt.Errorf("key includes '=': %q", key)
		}
	}
	return nil
}

// validateAttributes returns an error if the attributes are not suitable for advertising.
func validateAttributes(attributes discovery.Attributes) error {
	if len(attributes) > maxNumAttributes {
		return fmt.Errorf("too many: %d > %d", len(attributes), maxNumAttributes)
	}
	for k, v := range attributes {
		if err := validateKey(k); err != nil {
			return err
		}
		if !utf8.ValidString(v) {
			return fmt.Errorf("value is not valid UTF-8 string: %q", v)
		}
	}
	return nil
}

// validateAttachments returns an error if the attachments are not suitable for advertising.
func validateAttachments(attachments discovery.Attachments) error {
	if len(attachments) > maxNumAttachments {
		return fmt.Errorf("too many: %d > %d", len(attachments), maxNumAttachments)
	}
	for k, v := range attachments {
		if err := validateKey(k); err != nil {
			return err
		}
		if len(v) > maxAttachmentSize {
			return fmt.Errorf("too large value for %q: %d > %d", k, len(v), maxAttachmentSize)
		}
	}
	return nil
}

// sizeOfAd returns the size of ad excluding id and attachments.
func sizeOfAd(ad *discovery.Advertisement) int {
	size := len(ad.InterfaceName)
	for _, a := range ad.Addresses {
		size += len(a)
	}
	for k, v := range ad.Attributes {
		size += len(k) + len(v)
	}
	return size
}

// validateAd returns an error if ad is not suitable for advertising.
func validateAd(ad *discovery.Advertisement) error {
	if !ad.Id.IsValid() {
		return errors.New("id not valid")
	}
	if len(ad.InterfaceName) == 0 {
		return errors.New("interface name not provided")
	}
	if len(ad.Addresses) == 0 {
		return errors.New("address not provided")
	}
	if err := validateAttributes(ad.Attributes); err != nil {
		return fmt.Errorf("attributes not valid: %v", err)
	}
	if err := validateAttachments(ad.Attachments); err != nil {
		return fmt.Errorf("attachments not valid: %v", err)
	}
	if sizeOfAd(ad) > maxAdvertisementSize {
		return fmt.Errorf("advertisement too large: %d > %d", sizeOfAd(ad), maxAdvertisementSize)
	}
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	// zmq "github.com/alecthomas/gozmq"
	trisclient "github.com/fvbock/tris/client"
	trisserver "github.com/fvbock/tris/server"
	"github.com/sbinet/liner"
	"io"
	"os"
	"path"
	"strconv"
	"strings"
)

// TODO: detect connection loss and handle reconnect + currentDB

var (
	term      *liner.State = nil
	dsnString              = flag.String("d", "tcp:localhost:6000", "dsn to connect to")
)

func init() {
	fmt.Printf("TriS cli %s\n", trisclient.VERSION)
	term = liner.NewLiner()

	fname := path.Join(os.Getenv("HOME"), ".tris.history")
	f, err := os.Open(fname)
	if err != nil {
		fmt.Printf("**warning: could not access history file [%s]\n", fname)
		return
	}
	defer f.Close()
	_, err = term.ReadHistory(f)
	if err != nil {
		fmt.Printf("**warning: could not read history file [%s]\n", fname)
		return
	}
}

func atexit() {
	fmt.Println("CLI atexit")
	fname := path.Join(os.Getenv("HOME"), ".tris.history")
	f, err := os.OpenFile(fname, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0666)
	if err != nil {
		fmt.Printf("**warning: could not access history file [%s]\n", fname)
		return
	}
	defer f.Close()
	_, err = term.WriteHistory(f)
	if err != nil {
		fmt.Printf("**warning: could not write history file [%s]\n", fname)
		return
	}

	err = term.Close()
	if err != nil {
		fmt.Printf("**warning: problem closing term: %v\n", err)
		return
	}
	fmt.Println("\n")
}

func main() {
	defer atexit()
	var ierr error = nil // previous interpreter error
	ps1 := "[not connected]> "
	// ps2 := "...  "
	prompt := &ps1
	command := ""

	// TRIS conn
	flag.Parse()
	dsnParts := strings.Split(*dsnString, ":")
	port, _ := strconv.ParseInt(dsnParts[2], 10, 32)
	dsn := &trisclient.DSN{
		Protocol: dsnParts[0],
		Host:     dsnParts[1],
		Port:     int(port),
	}
	fmt.Printf("Connecting to %s://%s:%v\n", dsn.Protocol, dsn.Host, dsn.Port)

	client, err := trisclient.NewClient(dsn)
	err = client.Dial()
	if err != nil {
		fmt.Println(command, ierr)
	} else {
		ps1 = fmt.Sprintf("%s:%v/[%s]> ", dsnParts[1], dsnParts[2], client.ActiveDb)
	}
	defer client.Close()

	// check conn
	// r, err := client.Send("PING")
	// if err != nil {
	// 	fmt.Println("Error:", err)
	// }
	response, err := client.Ping()
	// response := trisserver.Unserialize(r)
	if response.ReturnCode != trisserver.COMMAND_OK {
		fmt.Printf("Initial PING failed:\n%v\n", response)
	} else {
		for {
			ps1 = fmt.Sprintf("%s:%v/[%s]> ", dsnParts[1], dsnParts[2], client.ActiveDb)
			// fmt.Println(">>>", client.ActiveDb)
			line, err := term.Prompt(*prompt)
			if err != nil {
				if err != io.EOF {
					ierr = err
				} else {
					ierr = nil
				}
				break //os.Exit(0)
			}
			if line == "" || line == ";" {
				// no more input
				prompt = &ps1
			}

			command += line
			if command != "" {
				for _, ll := range strings.Split(command, "\n") {
					term.AppendHistory(ll)
				}
			} else {
				continue
			}

			// // nama
			// r, err := client.Send(command)
			// if err != nil {
			// 	fmt.Println("Error:", err)
			// }

			// response := trisserver.Unserialize(r)
			// // fmt.Println(response)
			// response.Print()

			// use lib
			var cmds []string
			var args [][]string
			msgs := strings.Split(strings.Trim(command, " "), "\n")
			fmt.Println("msgs", msgs)
			for n, msg := range msgs {
				parts := strings.Split(strings.Trim(msg, " "), " ")
				for i, p := range parts {
					if len(p) == 0 {
						continue
					}
					if i == 0 {
						cmds = append(cmds, strings.ToUpper(p))
						args = append(args, make([]string, 0))
					} else {
						args[n] = append(args[n], p)
					}
				}
			}
			fmt.Println("cmds, args", cmds, args)

		cmdexec:
			for i, cmdname := range cmds {
				var response *trisserver.Reply
				var err error
				switch cmdname {
				case "PING":
					response, err = client.Ping()
				case "SELECT":
					response, err = client.Select(args[i][0])
				case "DBINFO":
					response, err = client.DbInfo()
				case "INFO":
					response, err = client.Info()
				case "SAVE":
					response, err = client.Save()
				case "IMPORT":
					response, err = client.ImportDb(args[i][0], args[i][1])
				case "MERGE":
					response, err = client.MergeDb(args[i][0])
				case "CREATE":
					response, err = client.Create(args[i][0])
				case "ADD":
					response, err = client.Add(args[i][0])
				case "DEL":
					response, err = client.Del(args[i][0])
				case "HAS":
					response, err = client.Has(args[i][0])
				case "HASCOUNT":
					response, err = client.HasCount(args[i][0])
				case "HASPREFIX":
					response, err = client.HasPrefix(args[i][0])
				case "MEMBERS":
					response, err = client.Members()
				case "PREFIXMEMBERS":
					response, err = client.PrefixMembers(args[i][0])
				default:
					fmt.Println("Unknown command.")
					break cmdexec
				}
				if response.ReturnCode != trisserver.COMMAND_OK || err != nil {
					// TODO
				}
				response.Print()
			}

			// reset state
			command = ""
			ierr = nil
		}
	}
}
<commit_msg>add basic script file support<commit_after>package main

import (
	"flag"
	"fmt"
	// zmq "github.com/alecthomas/gozmq"
	trisclient "github.com/fvbock/tris/client"
	trisserver "github.com/fvbock/tris/server"
	"github.com/sbinet/liner"
	"io"
	"io/ioutil"
	"os"
	"path"
	"strconv"
	"strings"
)

// TODO: detect connection loss and handle reconnect + currentDB

var (
	term      *liner.State = nil
	dsnString              = flag.String("d", "tcp:localhost:6000", "dsn to connect to")
)

func init() {
	fmt.Printf("TriS cli %s\n", trisclient.VERSION)
	term = liner.NewLiner()

	fname := path.Join(os.Getenv("HOME"), ".tris.history")
	f, err := os.Open(fname)
	if err != nil {
		fmt.Printf("**warning: could not access history file [%s]\n", fname)
		return
	}
	defer f.Close()
	_, err = term.ReadHistory(f)
	if err != nil {
		fmt.Printf("**warning: could not read history file [%s]\n", fname)
		return
	}
}

func atexit() {
	fmt.Println("CLI atexit")
	fname := path.Join(os.Getenv("HOME"), ".tris.history")
	f, err := os.OpenFile(fname, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0666)
	if err != nil {
		fmt.Printf("**warning: could not access history file [%s]\n", fname)
		return
	}
	defer f.Close()
	_, err = term.WriteHistory(f)
	if err != nil {
		fmt.Printf("**warning: could not write history file [%s]\n", fname)
		return
	}

	err = term.Close()
	if err != nil {
		fmt.Printf("**warning: problem closing term: %v\n", err)
		return
	}
	fmt.Println("\n")
}

func main() {
	defer atexit()
	var ierr error = nil // previous interpreter error
	ps1 := "[not connected]> "
	// ps2 := "...  "
	prompt := &ps1
	command := ""

	// TRIS conn
	flag.Parse()
	dsnParts := strings.Split(*dsnString, ":")
	port, _ := strconv.ParseInt(dsnParts[2], 10, 32)
	dsn := &trisclient.DSN{
		Protocol: dsnParts[0],
		Host:     dsnParts[1],
		Port:     int(port),
	}
	fmt.Printf("Connecting to %s://%s:%v\n", dsn.Protocol, dsn.Host, dsn.Port)

	client, err := trisclient.NewClient(dsn)
	err = client.Dial()
	if err != nil {
		fmt.Println(command, ierr)
	} else {
		ps1 = fmt.Sprintf("%s:%v/[%s]> ", dsnParts[1], dsnParts[2], client.ActiveDb)
	}
	defer client.Close()

	// check conn
	// r, err := client.Send("PING")
	// if err != nil {
	// 	fmt.Println("Error:", err)
	// }
	response, err := client.Ping()
	// response := trisserver.Unserialize(r)
	if response.ReturnCode != trisserver.COMMAND_OK {
		fmt.Printf("Initial PING failed:\n%v\n", response)
	} else {
		for {
			ps1 = fmt.Sprintf("%s:%v/[%s]> ", dsnParts[1], dsnParts[2], client.ActiveDb)
			// fmt.Println(">>>", client.ActiveDb)
			line, err := term.Prompt(*prompt)
			if err != nil {
				if err != io.EOF {
					ierr = err
				} else {
					ierr = nil
				}
				break //os.Exit(0)
			}
			if line == "" || line == ";" {
				// no more input
				prompt = &ps1
			}

			command += line
			if command != "" {
				for _, ll := range strings.Split(command, "\n") {
					term.AppendHistory(ll)
				}
			} else {
				continue
			}

			// SOURCE cmd. read script file
			if strings.ToUpper(command[:6]) == "SOURCE" {
				fname := strings.Trim(command[6:], " \n")
				fmt.Println("OPEN source file:", fname)
				sourcedFile, err := ioutil.ReadFile(fname)
				if err != nil {
					fmt.Println("ERR opening source file:", err)
					continue
				}
				command = string(sourcedFile)
			}
			// // nama
			// r, err := client.Send(command)
			// if err != nil {
			// 	fmt.Println("Error:", err)
			// }

			// response := trisserver.Unserialize(r)
			// // fmt.Println(response)
			// response.Print()

			// use lib
			var cmds []string
			var args [][]string
			msgs := strings.Split(strings.Trim(command, " "), "\n")
			fmt.Println("msgs", msgs)
			for n, msg := range msgs {
				parts := strings.Split(strings.Trim(msg, " "), " ")
				for i, p := range parts {
					if len(p) == 0 {
						continue
					}
					if i == 0 {
						cmds = append(cmds, strings.ToUpper(p))
						args = append(args, make([]string, 0))
					} else {
						args[n] = append(args[n], p)
					}
				}
			}
			fmt.Println("cmds, args", cmds, args)

		cmdexec:
			for i, cmdname := range cmds {
				var response *trisserver.Reply
				var err error
				switch cmdname {
				case "PING":
					response, err = client.Ping()
				case "SELECT":
					response, err = client.Select(args[i][0])
				case "DBINFO":
					response, err = client.DbInfo()
				case "INFO":
					response, err = client.Info()
				case "SAVE":
					response, err = client.Save()
				case "IMPORT":
					response, err = client.ImportDb(args[i][0], args[i][1])
				case "MERGE":
					response, err = client.MergeDb(args[i][0])
				case "CREATE":
					response, err = client.Create(args[i][0])
				case "ADD":
					response, err = client.Add(args[i][0])
				case "DEL":
					response, err = client.Del(args[i][0])
				case "HAS":
					response, err = client.Has(args[i][0])
				case "HASCOUNT":
					response, err = client.HasCount(args[i][0])
				case "HASPREFIX":
					response, err = client.HasPrefix(args[i][0])
				case "MEMBERS":
					response, err = client.Members()
				case "PREFIXMEMBERS":
					response, err = client.PrefixMembers(args[i][0])
				default:
					fmt.Println("Unknown command.")
					break cmdexec
				}
				if response.ReturnCode != trisserver.COMMAND_OK || err != nil {
					// TODO
				}
				response.Print()
			}

			// reset state
			command = ""
			ierr = nil
		}
	}
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package main

import (
	"testing"

	"github.com/smartystreets/goconvey/convey"
)

func TestListUsers(t *testing.T) {
	convey.Convey("Given I get all users", t, func() {
		server := mockRequest("/api/users/", "GET", 200, `[]`)
		m := Manager{URL: server.URL}
		_, err := m.ListUsers("token")
		convey.Convey("Then It does not fail", func() {
			convey.So(err, convey.ShouldBeNil)
		})
	})
}

func TestCreateUser(t *testing.T) {
	t.Skip()
	convey.Convey("Given I create a client", t, func() {
		server := mockRequest("/api/groups/", "POST", 200, `{}`)
		m := Manager{URL: server.URL}
		err := m.CreateUser("name", "email", "user", "password", "adminuser", "adminpassword")
		convey.Convey("Then It does not fail", func() {
			convey.So(err, convey.ShouldBeNil)
		})
	})
}
<commit_msg>Fix CI<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package main

import (
	"testing"

	"github.com/smartystreets/goconvey/convey"
)

func TestListUsers(t *testing.T) {
	convey.Convey("Given I get all users", t, func() {
		server := mockRequest("/api/users/", "GET", 200, `[]`)
		m := Manager{URL: server.URL}
		_, err := m.ListUsers("token")
		convey.Convey("Then It does not fail", func() {
			convey.So(err, convey.ShouldBeNil)
		})
	})
}

func TestCreateUser(t *testing.T) {
	t.Skip()
	convey.Convey("Given I create a client", t, func() {
		server := mockRequest("/api/groups/", "POST", 200, `{}`)
		m := Manager{URL: server.URL}
		err := m.CreateUser("token", "name", "email", "user", "password")
		convey.Convey("Then It does not fail", func() {
			convey.So(err, convey.ShouldBeNil)
		})
	})
}
<|endoftext|>


<commit_before>/*

*/
package mandrake

import (
	"fmt"
	"log"
	"encoding/json"

	"golang.org/x/exp/inotify"
	"github.com/hosom/gomandrake/config"
	"github.com/hosom/gomandrake/filemeta"
	"github.com/hosom/gomandrake/plugin"
)

// Mandrake is a wrapper struct for the bulk of the application logic
type Mandrake struct {
	AnalysisPipeline	chan string
	MonitoredDirectory	string
	Analyzers			[]plugin.AnalyzerCaller
}

// NewMandrake creates and returns a Mandrake struct utilizing a passed
// parsed configuration file to create the correct fields.
func NewMandrake(c config.Config) Mandrake {
	log.Println(c.Analyzers)
	analyzers := []plugin.AnalyzerCaller{}
	for _, plug := range c.Analyzers {
		log.Println(plug)
		analyzer := plugin.NewAnalyzerCaller(plug)
		analyzers = append(analyzers, analyzer)
	}

	return Mandrake{make(chan string), c.MonitoredDirectory, analyzers}
}

// ListenAndServe starts the goroutines that perform all of the heavy lifting
// including Monitor() and DispatchAnalysis().
func (m Mandrake) ListenAndServe() {
	log.SetPrefix("[mandrake] ")
	fmt.Println("HELLO")
	log.Println(m.Analyzers[0])
	go m.DispatchAnalysis()
	m.Monitor()
}

// DispatchAnalysis intelligently sends a new file to registered plugins so
// that it can be analyzed.
func (m Mandrake) DispatchAnalysis() {
	for fpath := range m.AnalysisPipeline {
		fmeta, err := filemeta.NewFileMeta(fpath)
		if err != nil {
			log.Println(err)
		}

		fs, err := json.Marshal(fmeta)

		log.Println(string(fs))
		log.Printf("%s", fpath)
	}
}

// Monitor uses inotify to monitor the MonitoredDirectory for IN_CLOSE_WRITE
// events. Files written to the MonitoredDirectory will be sent to the
// analysis pipeline to be analyzed.
func (m Mandrake) Monitor() {
	log.Println("starting inotify watcher")
	watcher, err := inotify.NewWatcher()
	if err != nil {
		log.Fatal(err)
	}

	log.Printf("adding watcher to %s directory", m.MonitoredDirectory)
	err = watcher.AddWatch(m.MonitoredDirectory, inotify.IN_CLOSE_WRITE)
	if err != nil {
		log.Fatal(err)
	}

	for {
		select {
		case ev := <- watcher.Event:
			m.AnalysisPipeline <- ev.Name
		case err := <- watcher.Error:
			log.Printf("inotify error: %s", err)
		}
	}
}<commit_msg>add Analyze call for plugins<commit_after>/*

*/
package mandrake

import (
	"fmt"
	"log"
	"encoding/json"

	"golang.org/x/exp/inotify"
	"github.com/hosom/gomandrake/config"
	"github.com/hosom/gomandrake/filemeta"
	"github.com/hosom/gomandrake/plugin"
)

// Mandrake is a wrapper struct for the bulk of the application logic
type Mandrake struct {
	AnalysisPipeline	chan string
	MonitoredDirectory	string
	Analyzers			[]plugin.AnalyzerCaller
}

// NewMandrake creates and returns a Mandrake struct utilizing a passed
// parsed configuration file to create the correct fields.
func NewMandrake(c config.Config) Mandrake {
	analyzers := []plugin.AnalyzerCaller{}
	for _, plug := range c.Analyzers {
		analyzer := plugin.NewAnalyzerCaller(plug)
		analyzers = append(analyzers, analyzer)
	}

	return Mandrake{make(chan string), c.MonitoredDirectory, analyzers}
}

// ListenAndServe starts the goroutines that perform all of the heavy lifting
// including Monitor() and DispatchAnalysis().
func (m Mandrake) ListenAndServe() {
	log.SetPrefix("[mandrake] ")
	log.Println(m.Analyzers[0])
	go m.DispatchAnalysis()
	m.Monitor()
}

// DispatchAnalysis intelligently sends a new file to registered plugins so
// that it can be analyzed.
func (m Mandrake) DispatchAnalysis() {
	for fpath := range m.AnalysisPipeline {
		fmeta, err := filemeta.NewFileMeta(fpath)
		if err != nil {
			log.Println(err)
		}

		fs, err := json.Marshal(fmeta)

		for _, analyzer := range m.Analyzers {
			result, err := analyzer.Analyze(fmeta)
			log.Print(result)
		}

		log.Println(string(fs))
		log.Printf("%s", fpath)
	}
}

// Monitor uses inotify to monitor the MonitoredDirectory for IN_CLOSE_WRITE
// events. Files written to the MonitoredDirectory will be sent to the
// analysis pipeline to be analyzed.
func (m Mandrake) Monitor() {
	log.Println("starting inotify watcher")
	watcher, err := inotify.NewWatcher()
	if err != nil {
		log.Fatal(err)
	}

	log.Printf("adding watcher to %s directory", m.MonitoredDirectory)
	err = watcher.AddWatch(m.MonitoredDirectory, inotify.IN_CLOSE_WRITE)
	if err != nil {
		log.Fatal(err)
	}

	for {
		select {
		case ev := <- watcher.Event:
			m.AnalysisPipeline <- ev.Name
		case err := <- watcher.Error:
			log.Printf("inotify error: %s", err)
		}
	}
}<|endoftext|>


<commit_before>/*

*/
package mandrake

import (
	"log"
	"encoding/json"

	"golang.org/x/exp/inotify"
	"github.com/hosom/gomandrake/config"
	"github.com/hosom/gomandrake/filemeta"
	"github.com/hosom/gomandrake/plugin"
)

// Mandrake is a wrapper struct for the bulk of the application logic
type Mandrake struct {
	AnalysisPipeline	chan string
	MonitoredDirectory	string
	Analyzers			[]plugin.AnalyzerCaller
}

// NewMandrake creates and returns a Mandrake struct utilizing a passed
// parsed configuration file to create the correct fields.
func NewMandrake(c config.Config) Mandrake {
	analyzers := []plugin.AnalyzerCaller{}
	for _, plug := range c.Analyzers {
		analyzer := plugin.NewAnalyzerCaller(plug)
		analyzers = append(analyzers, analyzer)
	}

	return Mandrake{make(chan string), c.MonitoredDirectory, analyzers}
}

// ListenAndServe starts the goroutines that perform all of the heavy lifting
// including Monitor() and DispatchAnalysis().
func (m Mandrake) ListenAndServe() {
	log.SetPrefix("[mandrake] ")
	go m.DispatchAnalysis()
	m.Monitor()
}

// DispatchAnalysis intelligently sends a new file to registered plugins so
// that it can be analyzed.
func (m Mandrake) DispatchAnalysis() {
	for fpath := range m.AnalysisPipeline {
		fmeta, err := filemeta.NewFileMeta(fpath)
		if err != nil {
			log.Println(err)
		}

		fs, err := json.Marshal(fmeta)

		log.Println(string(fs))
		log.Printf("%s", fpath)
	}
}

// Monitor uses inotify to monitor the MonitoredDirectory for IN_CLOSE_WRITE
// events. Files written to the MonitoredDirectory will be sent to the
// analysis pipeline to be analyzed.
func (m Mandrake) Monitor() {
	log.Println("starting inotify watcher")
	watcher, err := inotify.NewWatcher()
	if err != nil {
		log.Fatal(err)
	}

	log.Printf("adding watcher to %s directory", m.MonitoredDirectory)
	err = watcher.AddWatch(m.MonitoredDirectory, inotify.IN_CLOSE_WRITE)
	if err != nil {
		log.Fatal(err)
	}

	for {
		select {
		case ev := <- watcher.Event:
			m.AnalysisPipeline <- ev.Name
		case err := <- watcher.Error:
			log.Printf("inotify error: %s", err)
		}
	}
}<commit_msg>updates<commit_after>/*

*/
package mandrake

import (
	"log"
	"encoding/json"

	"golang.org/x/exp/inotify"
	"github.com/hosom/gomandrake/config"
	"github.com/hosom/gomandrake/filemeta"
	"github.com/hosom/gomandrake/plugin"
)

// Mandrake is a wrapper struct for the bulk of the application logic
type Mandrake struct {
	AnalysisPipeline	chan string
	MonitoredDirectory	string
	Analyzers			[]plugin.AnalyzerCaller
}

// NewMandrake creates and returns a Mandrake struct utilizing a passed
// parsed configuration file to create the correct fields.
func NewMandrake(c config.Config) Mandrake {
	log.Println(c.Analyzers)
	analyzers := []plugin.AnalyzerCaller{}
	for _, plug := range c.Analyzers {
		log.Println(plug)
		analyzer := plugin.NewAnalyzerCaller(plug)
		analyzers = append(analyzers, analyzer)
	}

	return Mandrake{make(chan string), c.MonitoredDirectory, analyzers}
}

// ListenAndServe starts the goroutines that perform all of the heavy lifting
// including Monitor() and DispatchAnalysis().
func (m Mandrake) ListenAndServe() {
	log.SetPrefix("[mandrake] ")
	log.Println(m.Analyzers)
	go m.DispatchAnalysis()
	m.Monitor()
}

// DispatchAnalysis intelligently sends a new file to registered plugins so
// that it can be analyzed.
func (m Mandrake) DispatchAnalysis() {
	for fpath := range m.AnalysisPipeline {
		fmeta, err := filemeta.NewFileMeta(fpath)
		if err != nil {
			log.Println(err)
		}

		fs, err := json.Marshal(fmeta)

		log.Println(string(fs))
		log.Printf("%s", fpath)
	}
}

// Monitor uses inotify to monitor the MonitoredDirectory for IN_CLOSE_WRITE
// events. Files written to the MonitoredDirectory will be sent to the
// analysis pipeline to be analyzed.
func (m Mandrake) Monitor() {
	log.Println("starting inotify watcher")
	watcher, err := inotify.NewWatcher()
	if err != nil {
		log.Fatal(err)
	}

	log.Printf("adding watcher to %s directory", m.MonitoredDirectory)
	err = watcher.AddWatch(m.MonitoredDirectory, inotify.IN_CLOSE_WRITE)
	if err != nil {
		log.Fatal(err)
	}

	for {
		select {
		case ev := <- watcher.Event:
			m.AnalysisPipeline <- ev.Name
		case err := <- watcher.Error:
			log.Printf("inotify error: %s", err)
		}
	}
}<|endoftext|>


<commit_before>package manifest

import (
	"io/ioutil"
	"os"
	"path"
	"time"
)

type Manifest struct {
	Name    string               `json:"name"`
	Size    int64                `json:"size"`
	ModTime time.Time            `json:"lastModified"`
	Mode    os.FileMode          `json:"fileMode"`
	IsDir   bool                 `json:"isDir"`
	Files   map[string]*Manifest `json:"files,omitempty"`
}

func NewManifest(name string, size int64, modtime time.Time, mode os.FileMode, isDir bool) *Manifest {
	return &Manifest{name, size, modtime, mode, isDir, nil}
}

func GetManifest(dirPath string) (map[string]*Manifest, error) {
	if dirPath == "/" || dirPath == "../" || dirPath == ".." {
		dirPath = "."
	}
	list, err := ioutil.ReadDir(dirPath)
	if err != nil {
		return nil, err
	}
	manifest := make(map[string]*Manifest)
	for _, child := range list {
		childPath := path.Join(dirPath, child.Name())
		manifest[childPath] = NewManifest(childPath, child.Size(), child.ModTime(), child.Mode(), child.IsDir())
		if child.IsDir() == true {
			childContent, err := GetManifest(childPath)
			if err != nil {
				return nil, err
			}
			manifest[childPath].Files = childContent
		}
	}
	return manifest, nil
}
<commit_msg>Updated manifest/manifest.go to use ./ instead of "." when trying to specify current working directory<commit_after>package manifest

import (
	"io/ioutil"
	"os"
	"path"
	"time"
)

type Manifest struct {
	Name    string               `json:"name"`
	Size    int64                `json:"size"`
	ModTime time.Time            `json:"lastModified"`
	Mode    os.FileMode          `json:"fileMode"`
	IsDir   bool                 `json:"isDir"`
	Files   map[string]*Manifest `json:"files,omitempty"`
}

func NewManifest(name string, size int64, modtime time.Time, mode os.FileMode, isDir bool) *Manifest {
	return &Manifest{name, size, modtime, mode, isDir, nil}
}

func GetManifest(dirPath string) (map[string]*Manifest, error) {
	if dirPath == "/" || dirPath == "../" || dirPath == ".." {
		dirPath = "./"
	}
	list, err := ioutil.ReadDir(dirPath)
	if err != nil {
		return nil, err
	}
	manifest := make(map[string]*Manifest)
	for _, child := range list {
		childPath := path.Join(dirPath, child.Name())
		manifest[childPath] = NewManifest(childPath, child.Size(), child.ModTime(), child.Mode(), child.IsDir())
		if child.IsDir() == true {
			childContent, err := GetManifest(childPath)
			if err != nil {
				return nil, err
			}
			manifest[childPath].Files = childContent
		}
	}
	return manifest, nil
}
<|endoftext|>


<commit_before>// Copyright (c) Alex Ellis 2017. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

package commands

import (
	"fmt"
	"log"
	"os"
	"sync"

	"github.com/alexellis/faas-cli/builder"
	"github.com/alexellis/faas-cli/stack"
	"github.com/spf13/cobra"
)

// Flags that are to be added to commands.
var (
	nocache  bool
	squash   bool
	parallel int
)

func init() {
	// Setup flags that are used by multiple commands (variables defined in faas.go)
	buildCmd.Flags().StringVar(&image, "image", "", "Docker image name to build")
	buildCmd.Flags().StringVar(&handler, "handler", "", "Directory with handler for function, e.g. handler.js")
	buildCmd.Flags().StringVar(&functionName, "name", "", "Name of the deployed function")
	buildCmd.Flags().StringVar(&language, "lang", "node", "Programming language template")

	// Setup flags that are used only by this command (variables defined above)
	buildCmd.Flags().BoolVar(&nocache, "no-cache", false, "Do not use Docker's build cache")
	buildCmd.Flags().BoolVar(&squash, "squash", false, `Use Docker's squash flag for smaller images
						 [experimental] `)
	buildCmd.Flags().IntVar(&parallel, "parallel", 1, "Build in parallel to depth specified.")

	// Set bash-completion.
	_ = buildCmd.Flags().SetAnnotation("handler", cobra.BashCompSubdirsInDir, []string{})

	faasCmd.AddCommand(buildCmd)
}

// buildCmd allows the user to build an OpenFaaS function container
var buildCmd = &cobra.Command{
	Use: `build -f YAML_FILE [--no-cache] [--squash]
  faas-cli build --image IMAGE_NAME
                 --handler HANDLER_DIR
                 --name FUNCTION_NAME
                 [--lang <ruby|python|python3|node|csharp|Dockerfile>]
                 [--no-cache] [--squash]
                 [--regex "REGEX"]
				 [--filter "WILDCARD"]
				 [--parallel PARALLEL_DEPTH]`,
	Short: "Builds OpenFaaS function containers",
	Long: `Builds OpenFaaS function containers either via the supplied YAML config using
the "--yaml" flag (which may contain multiple function definitions), or directly
via flags.`,
	Example: `  faas-cli build -f https://domain/path/myfunctions.yml
  faas-cli build -f ./samples.yml --no-cache
  faas-cli build -f ./samples.yml --filter "*gif*"
  faas-cli build -f ./samples.yml --regex "fn[0-9]_.*"
  faas-cli build --image=my_image --lang=python --handler=/path/to/fn/
                 --name=my_fn --squash`,
	Run: runBuild,
}

func runBuild(cmd *cobra.Command, args []string) {

	var services stack.Services
	if len(yamlFile) > 0 {
		parsedServices, err := stack.ParseYAMLFile(yamlFile, regex, filter)
		if err != nil {
			log.Fatalln(err.Error())
			return
		}

		if parsedServices != nil {
			services = *parsedServices
		}
	}

	if pullErr := PullTemplates(""); pullErr != nil {
		log.Fatalln("Could not pull templates for OpenFaaS.", pullErr)
	}

	if len(services.Functions) > 0 {
		build(&services, parallel)
	} else {
		if len(image) == 0 {
			fmt.Println("Please provide a valid -image name for your Docker image.")
			return
		}
		if len(handler) == 0 {
			fmt.Println("Please provide the full path to your function's handler.")
			return
		}
		if len(functionName) == 0 {
			fmt.Println("Please provide the deployed -name of your function.")
			return
		}
		builder.BuildImage(image, handler, functionName, language, nocache, squash)
	}

}

// PullTemplates pulls templates from Github from the master zip download file.
func PullTemplates(templateUrl string) error {
	var err error
	exists, err := os.Stat("./template")
	if err != nil || exists == nil {
		log.Println("No templates found in current directory.")

		err = fetchTemplates(templateUrl)
		if err != nil {
			log.Println("Unable to download templates from Github.")
			return err
		}
	}
	return err
}

func build(services *stack.Services, queueDepth int) {
	wg := sync.WaitGroup{}

	workChannel := make(chan stack.Function)

	for i := 0; i < queueDepth; i++ {

		go func(index int) {
			wg.Add(1)
			for function := range workChannel {
				fmt.Printf("Building: %s.\n", function.Name)
				if len(function.Language) == 0 {
					fmt.Println("Please provide a valid -lang or 'Dockerfile' for your function.")

				} else {
					builder.BuildImage(function.Image, function.Handler, function.Name, function.Language, nocache, squash)
				}
			}
			fmt.Printf("worker done.\n")
			wg.Done()
		}(i)
	}

	for k, function := range services.Functions {
		if function.SkipBuild {
			fmt.Printf("Skipping build of: %s.\n", function.Name)
		} else {
			function.Name = k
			workChannel <- function
		}
	}
	close(workChannel)

	wg.Wait()

}
<commit_msg>Add builder number<commit_after>// Copyright (c) Alex Ellis 2017. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

package commands

import (
	"fmt"
	"log"
	"os"
	"sync"

	"github.com/alexellis/faas-cli/builder"
	"github.com/alexellis/faas-cli/stack"
	"github.com/spf13/cobra"
)

// Flags that are to be added to commands.
var (
	nocache  bool
	squash   bool
	parallel int
)

func init() {
	// Setup flags that are used by multiple commands (variables defined in faas.go)
	buildCmd.Flags().StringVar(&image, "image", "", "Docker image name to build")
	buildCmd.Flags().StringVar(&handler, "handler", "", "Directory with handler for function, e.g. handler.js")
	buildCmd.Flags().StringVar(&functionName, "name", "", "Name of the deployed function")
	buildCmd.Flags().StringVar(&language, "lang", "node", "Programming language template")

	// Setup flags that are used only by this command (variables defined above)
	buildCmd.Flags().BoolVar(&nocache, "no-cache", false, "Do not use Docker's build cache")
	buildCmd.Flags().BoolVar(&squash, "squash", false, `Use Docker's squash flag for smaller images
						 [experimental] `)
	buildCmd.Flags().IntVar(&parallel, "parallel", 1, "Build in parallel to depth specified.")

	// Set bash-completion.
	_ = buildCmd.Flags().SetAnnotation("handler", cobra.BashCompSubdirsInDir, []string{})

	faasCmd.AddCommand(buildCmd)
}

// buildCmd allows the user to build an OpenFaaS function container
var buildCmd = &cobra.Command{
	Use: `build -f YAML_FILE [--no-cache] [--squash]
  faas-cli build --image IMAGE_NAME
                 --handler HANDLER_DIR
                 --name FUNCTION_NAME
                 [--lang <ruby|python|python3|node|csharp|Dockerfile>]
                 [--no-cache] [--squash]
                 [--regex "REGEX"]
				 [--filter "WILDCARD"]
				 [--parallel PARALLEL_DEPTH]`,
	Short: "Builds OpenFaaS function containers",
	Long: `Builds OpenFaaS function containers either via the supplied YAML config using
the "--yaml" flag (which may contain multiple function definitions), or directly
via flags.`,
	Example: `  faas-cli build -f https://domain/path/myfunctions.yml
  faas-cli build -f ./samples.yml --no-cache
  faas-cli build -f ./samples.yml --filter "*gif*"
  faas-cli build -f ./samples.yml --regex "fn[0-9]_.*"
  faas-cli build --image=my_image --lang=python --handler=/path/to/fn/
                 --name=my_fn --squash`,
	Run: runBuild,
}

func runBuild(cmd *cobra.Command, args []string) {

	var services stack.Services
	if len(yamlFile) > 0 {
		parsedServices, err := stack.ParseYAMLFile(yamlFile, regex, filter)
		if err != nil {
			log.Fatalln(err.Error())
			return
		}

		if parsedServices != nil {
			services = *parsedServices
		}
	}

	if pullErr := PullTemplates(""); pullErr != nil {
		log.Fatalln("Could not pull templates for OpenFaaS.", pullErr)
	}

	if len(services.Functions) > 0 {
		build(&services, parallel)
	} else {
		if len(image) == 0 {
			fmt.Println("Please provide a valid -image name for your Docker image.")
			return
		}
		if len(handler) == 0 {
			fmt.Println("Please provide the full path to your function's handler.")
			return
		}
		if len(functionName) == 0 {
			fmt.Println("Please provide the deployed -name of your function.")
			return
		}
		builder.BuildImage(image, handler, functionName, language, nocache, squash)
	}

}

// PullTemplates pulls templates from Github from the master zip download file.
func PullTemplates(templateUrl string) error {
	var err error
	exists, err := os.Stat("./template")
	if err != nil || exists == nil {
		log.Println("No templates found in current directory.")

		err = fetchTemplates(templateUrl)
		if err != nil {
			log.Println("Unable to download templates from Github.")
			return err
		}
	}
	return err
}

func build(services *stack.Services, queueDepth int) {
	wg := sync.WaitGroup{}

	workChannel := make(chan stack.Function)

	for i := 0; i < queueDepth; i++ {

		go func(index int) {
			wg.Add(1)
			for function := range workChannel {
				fmt.Printf("[%d] > Building: %s.\n", index, function.Name)
				if len(function.Language) == 0 {
					fmt.Println("Please provide a valid -lang or 'Dockerfile' for your function.")

				} else {
					builder.BuildImage(function.Image, function.Handler, function.Name, function.Language, nocache, squash)
				}
			}

			fmt.Printf("[%d] < Builder done.\n", index)
			wg.Done()
		}(i)
	}

	for k, function := range services.Functions {
		if function.SkipBuild {
			fmt.Printf("Skipping build of: %s.\n", function.Name)
		} else {
			function.Name = k
			workChannel <- function
		}
	}
	close(workChannel)

	wg.Wait()

}
<|endoftext|>


<commit_before>package log

import (
	"DNA/config"
	"bytes"
	"errors"
	"fmt"
	"io"
	"log"
	"os"
	"path/filepath"
	"runtime"
	"strconv"
	"strings"
	"sync"
	"time"
)

const (
	Blue   = "0;34"
	Red    = "0;31"
	Green  = "0;32"
	Yellow = "0;33"
	Cyan   = "0;36"
	Pink   = "1;35"
)

func Color(code, msg string) string {
	return fmt.Sprintf("\033[%sm%s\033[m", code, msg)
}

const (
	traceLog = iota
	debugLog
	infoLog
	warnLog
	errorLog
	fatalLog
	printLog
	maxLevelLog
)

var (
	levels = map[int]string{
		traceLog: Color(Pink, "[TRACE]"),
		debugLog: Color(Green, "[DEBUG]"),
		infoLog:  Color(Green, "[INFO ]"),
		warnLog:  Color(Yellow, "[WARN ]"),
		errorLog: Color(Red, "[ERROR]"),
		fatalLog: Color(Red, "[FATAL]"),
		printLog: Color(Cyan, "[ForcePrint]"),
	}
)

const (
	namePrefix = "LEVEL"
	callDepth  = 2
)

func GetGID() uint64 {
	b := make([]byte, 64)
	b = b[:runtime.Stack(b, false)]
	b = bytes.TrimPrefix(b, []byte("goroutine "))
	b = b[:bytes.IndexByte(b, ' ')]
	n, _ := strconv.ParseUint(string(b), 10, 64)
	return n
}

var Log *Logger

func LevelName(level int) string {
	if name, ok := levels[level]; ok {
		return name
	}
	return namePrefix + strconv.Itoa(level)
}

func NameLevel(name string) int {
	for k, v := range levels {
		if v == name {
			return k
		}
	}
	var level int
	if strings.HasPrefix(name, namePrefix) {
		level, _ = strconv.Atoi(name[len(namePrefix):])
	}
	return level
}

type Logger struct {
	sync.Mutex
	level  int
	logger *log.Logger
}

func New(out io.Writer, prefix string, flag, level int) *Logger {
	return &Logger{
		level:  level,
		logger: log.New(out, prefix, flag),
	}
}

func (l *Logger) SetDebugLevel(level int) error {
	l.Lock()
	defer l.Unlock()
	if level >= maxLevelLog || level < 0 {
		return errors.New("Invalid Debug Level")
	}
	l.level = level
	return nil
}

func (l *Logger) output(level int, s string) error {
	// FIXME enable print GID for all log, should be disable as it effect performance
	if (level == 0) || (level == 1) || (level == 2) || (level == 3) || (level == 4) {
		gid := GetGID()
		gidStr := strconv.FormatUint(gid, 10)

		return l.logger.Output(callDepth, LevelName(level)+" "+"GID"+
			" "+gidStr+", "+s)
	} else {
		return l.logger.Output(callDepth, LevelName(level)+" "+s)
	}
}

func (l *Logger) Output(level int, a ...interface{}) error {
	if level >= l.level {
		return l.output(level, fmt.Sprintln(a...))
	}
	return nil
}

func (l *Logger) Trace(a ...interface{}) {
	l.Lock()
	defer l.Unlock()
	l.Output(traceLog, a...)
}

func (l *Logger) Print(a ...interface{}) {
	l.Lock()
	defer l.Unlock()
	l.Output(printLog, a...)
}

func (l *Logger) Debug(a ...interface{}) {
	l.Lock()
	defer l.Unlock()
	l.Output(debugLog, a...)
}

func (l *Logger) Info(a ...interface{}) {
	l.Lock()
	defer l.Unlock()
	l.Output(infoLog, a...)
}

func (l *Logger) Warn(a ...interface{}) {
	l.Lock()
	defer l.Unlock()
	l.Output(warnLog, a...)
}

func (l *Logger) Error(a ...interface{}) {
	l.Lock()
	defer l.Unlock()
	l.Output(errorLog, a...)
}

func (l *Logger) Fatal(a ...interface{}) {
	l.Lock()
	defer l.Unlock()
	l.Output(fatalLog, a...)
}

func Trace(a ...interface{}) {
	pc := make([]uintptr, 10)
	runtime.Callers(2, pc)
	f := runtime.FuncForPC(pc[0])
	file, line := f.FileLine(pc[0])
	fileName := filepath.Base(file)

	Log.Trace(fmt.Sprint(f.Name(), " ", fileName, ":", line))

}

func Debug(a ...interface{}) {
	Log.Debug(fmt.Sprint(a...))
}

func Info(a ...interface{}) {
	Log.Info(fmt.Sprint(a...))
}

func Warn(a ...interface{}) {
	Log.Warn(fmt.Sprint(a...))
}

func Error(a ...interface{}) {
	Log.Error(fmt.Sprint(a...))
}

func Fatal(a ...interface{}) {
	Log.Fatal(fmt.Sprint(a...))
}

func Print(a ...interface{}) {
	Log.Print(fmt.Sprint(a...))
}

func FileOpen(path string) (*os.File, error) {
	if fi, err := os.Stat(path); err == nil {
		if !fi.IsDir() {
			return nil, fmt.Errorf("open %s: not a directory", path)
		}
	} else if os.IsNotExist(err) {
		if err := os.MkdirAll(path, 0766); err != nil {
			return nil, err
		}
	} else {
		return nil, err
	}

	var currenttime string = time.Now().Format("2006-01-02")

	logfile, err := os.OpenFile(path+currenttime+"_LOG.log", os.O_RDWR|os.O_CREATE, 0666)
	if err != nil {
		fmt.Printf("%s\n", err.Error())
		//os.Exit(-1)
	}

	//defer logfile.Close()

	return logfile, nil
}

func CreatePrintLog(path string) {
	logfile, err := FileOpen(path)
	if err != nil {
		fmt.Printf("%s\n", err.Error)
	}
	var printlevel int = config.Parameters.PrintLevel
	writers := []io.Writer{
		logfile,
		os.Stdout,
	}
	fileAndStdoutWrite := io.MultiWriter(writers...)

	Log = New(fileAndStdoutWrite, "", log.Lmicroseconds, printlevel)
}

func ClosePrintLog() {
	//TODO
}
<commit_msg>Use log.trace instead of force print<commit_after>package log

import (
	"DNA/config"
	"bytes"
	"errors"
	"fmt"
	"io"
	"log"
	"os"
	"path/filepath"
	"runtime"
	"strconv"
	"strings"
	"sync"
	"time"
)

const (
	Blue   = "0;34"
	Red    = "0;31"
	Green  = "0;32"
	Yellow = "0;33"
	Cyan   = "0;36"
	Pink   = "1;35"
)

func Color(code, msg string) string {
	return fmt.Sprintf("\033[%sm%s\033[m", code, msg)
}

const (
	debugLog = iota
	infoLog
	warnLog
	errorLog
	fatalLog
	traceLog
	maxLevelLog
)

var (
	levels = map[int]string{
		traceLog: Color(Pink, "[TRACE]"),
		debugLog: Color(Green, "[DEBUG]"),
		infoLog:  Color(Green, "[INFO ]"),
		warnLog:  Color(Yellow, "[WARN ]"),
		errorLog: Color(Red, "[ERROR]"),
		fatalLog: Color(Red, "[FATAL]"),
	}
)

const (
	namePrefix = "LEVEL"
	callDepth  = 2
)

func GetGID() uint64 {
	b := make([]byte, 64)
	b = b[:runtime.Stack(b, false)]
	b = bytes.TrimPrefix(b, []byte("goroutine "))
	b = b[:bytes.IndexByte(b, ' ')]
	n, _ := strconv.ParseUint(string(b), 10, 64)
	return n
}

var Log *Logger

func LevelName(level int) string {
	if name, ok := levels[level]; ok {
		return name
	}
	return namePrefix + strconv.Itoa(level)
}

func NameLevel(name string) int {
	for k, v := range levels {
		if v == name {
			return k
		}
	}
	var level int
	if strings.HasPrefix(name, namePrefix) {
		level, _ = strconv.Atoi(name[len(namePrefix):])
	}
	return level
}

type Logger struct {
	sync.Mutex
	level  int
	logger *log.Logger
}

func New(out io.Writer, prefix string, flag, level int) *Logger {
	return &Logger{
		level:  level,
		logger: log.New(out, prefix, flag),
	}
}

func (l *Logger) SetDebugLevel(level int) error {
	l.Lock()
	defer l.Unlock()
	if level >= maxLevelLog || level < 0 {
		return errors.New("Invalid Debug Level")
	}
	l.level = level
	return nil
}

func (l *Logger) output(level int, s string) error {
	// FIXME enable print GID for all log, should be disable as it effect performance
	if (level == 0) || (level == 1) || (level == 2) || (level == 3) || (level == 4) {
		gid := GetGID()
		gidStr := strconv.FormatUint(gid, 10)

		return l.logger.Output(callDepth, LevelName(level)+" "+"GID"+
			" "+gidStr+", "+s)
	} else {
		return l.logger.Output(callDepth, LevelName(level)+" "+s)
	}
}

func (l *Logger) Output(level int, a ...interface{}) error {
	if level >= l.level {
		return l.output(level, fmt.Sprintln(a...))
	}
	return nil
}

func (l *Logger) Trace(a ...interface{}) {
	l.Lock()
	defer l.Unlock()
	l.Output(traceLog, a...)
}

func (l *Logger) Debug(a ...interface{}) {
	l.Lock()
	defer l.Unlock()
	l.Output(debugLog, a...)
}

func (l *Logger) Info(a ...interface{}) {
	l.Lock()
	defer l.Unlock()
	l.Output(infoLog, a...)
}

func (l *Logger) Warn(a ...interface{}) {
	l.Lock()
	defer l.Unlock()
	l.Output(warnLog, a...)
}

func (l *Logger) Error(a ...interface{}) {
	l.Lock()
	defer l.Unlock()
	l.Output(errorLog, a...)
}

func (l *Logger) Fatal(a ...interface{}) {
	l.Lock()
	defer l.Unlock()
	l.Output(fatalLog, a...)
}

func Trace(a ...interface{}) {
	pc := make([]uintptr, 10)
	runtime.Callers(2, pc)
	f := runtime.FuncForPC(pc[0])
	file, line := f.FileLine(pc[0])
	fileName := filepath.Base(file)
	Log.Trace(fmt.Sprint(f.Name(), " ", fileName, ":", line, " ", fmt.Sprint(a...)))

}

func Debug(a ...interface{}) {
	Log.Debug(fmt.Sprint(a...))
}

func Info(a ...interface{}) {
	Log.Info(fmt.Sprint(a...))
}

func Warn(a ...interface{}) {
	Log.Warn(fmt.Sprint(a...))
}

func Error(a ...interface{}) {
	Log.Error(fmt.Sprint(a...))
}

func Fatal(a ...interface{}) {
	Log.Fatal(fmt.Sprint(a...))
}

func FileOpen(path string) (*os.File, error) {
	if fi, err := os.Stat(path); err == nil {
		if !fi.IsDir() {
			return nil, fmt.Errorf("open %s: not a directory", path)
		}
	} else if os.IsNotExist(err) {
		if err := os.MkdirAll(path, 0766); err != nil {
			return nil, err
		}
	} else {
		return nil, err
	}

	var currenttime string = time.Now().Format("2006-01-02")

	logfile, err := os.OpenFile(path+currenttime+"_LOG.log", os.O_RDWR|os.O_CREATE, 0666)
	if err != nil {
		fmt.Printf("%s\n", err.Error())
		//os.Exit(-1)
	}

	//defer logfile.Close()

	return logfile, nil
}

func CreatePrintLog(path string) {
	logfile, err := FileOpen(path)
	if err != nil {
		fmt.Printf("%s\n", err.Error)
	}

	var printlevel int = config.Parameters.PrintLevel
	writers := []io.Writer{
		logfile,
		os.Stdout,
	}
	fileAndStdoutWrite := io.MultiWriter(writers...)

	Log = New(fileAndStdoutWrite, "", log.Lmicroseconds, printlevel)
}

func ClosePrintLog() {
	//TODO
}
<|endoftext|>


<commit_before>package log

import (
	"fmt"

	"github.com/v2ray/v2ray-core/common/serial"
)

const (
	DebugLevel   = LogLevel(0)
	InfoLevel    = LogLevel(1)
	WarningLevel = LogLevel(2)
	ErrorLevel   = LogLevel(3)
)

type errorLog struct {
	prefix string
	values []interface{}
}

func (this *errorLog) String() string {
	data := ""
	for _, value := range this.values {
		switch typedVal := value.(type) {
		case string:
			data += typedVal
		case *string:
			data += *typedVal
		case serial.String:
			data += typedVal.String()
		case error:
			data += typedVal.Error()
		default:
			data += fmt.Sprintf("%v", value)
		}
	}
	return this.prefix + data
}

var (
	noOpLoggerInstance   logWriter = &noOpLogWriter{}
	streamLoggerInstance logWriter = newStdOutLogWriter()

	debugLogger   = streamLoggerInstance
	infoLogger    = streamLoggerInstance
	warningLogger = streamLoggerInstance
	errorLogger   = streamLoggerInstance
)

type LogLevel int

func SetLogLevel(level LogLevel) {
	debugLogger = noOpLoggerInstance
	if level <= DebugLevel {
		debugLogger = streamLoggerInstance
	}

	infoLogger = noOpLoggerInstance
	if level <= InfoLevel {
		infoLogger = streamLoggerInstance
	}

	warningLogger = noOpLoggerInstance
	if level <= WarningLevel {
		warningLogger = streamLoggerInstance
	}

	errorLogger = noOpLoggerInstance
	if level <= ErrorLevel {
		errorLogger = streamLoggerInstance
	}
}

func InitErrorLogger(file string) error {
	logger, err := newFileLogWriter(file)
	if err != nil {
		Error("Failed to create error logger on file (", file, "): ", err)
		return err
	}
	streamLoggerInstance = logger
	return nil
}

// Debug outputs a debug log with given format and optional arguments.
func Debug(v ...interface{}) {
	debugLogger.Log(&errorLog{
		prefix: "[Debug]",
		values: v,
	})
}

// Info outputs an info log with given format and optional arguments.
func Info(v ...interface{}) {
	infoLogger.Log(&errorLog{
		prefix: "[Info]",
		values: v,
	})
}

// Warning outputs a warning log with given format and optional arguments.
func Warning(v ...interface{}) {
	warningLogger.Log(&errorLog{
		prefix: "[Warning]",
		values: v,
	})
}

// Error outputs an error log with given format and optional arguments.
func Error(v ...interface{}) {
	errorLogger.Log(&errorLog{
		prefix: "[Error]",
		values: v,
	})
}
<commit_msg>revert unintentional change<commit_after>package log

import (
	"fmt"

	"github.com/v2ray/v2ray-core/common/serial"
)

const (
	DebugLevel   = LogLevel(0)
	InfoLevel    = LogLevel(1)
	WarningLevel = LogLevel(2)
	ErrorLevel   = LogLevel(3)
)

type errorLog struct {
	prefix string
	values []interface{}
}

func (this *errorLog) String() string {
	data := ""
	for _, value := range this.values {
		switch typedVal := value.(type) {
		case string:
			data += typedVal
		case *string:
			data += *typedVal
		case serial.String:
			data += typedVal.String()
		case error:
			data += typedVal.Error()
		default:
			data += fmt.Sprintf("%v", value)
		}
	}
	return this.prefix + data
}

var (
	noOpLoggerInstance   logWriter = &noOpLogWriter{}
	streamLoggerInstance logWriter = newStdOutLogWriter()

	debugLogger   = noOpLoggerInstance
	infoLogger    = noOpLoggerInstance
	warningLogger = streamLoggerInstance
	errorLogger   = streamLoggerInstance
)

type LogLevel int

func SetLogLevel(level LogLevel) {
	debugLogger = noOpLoggerInstance
	if level <= DebugLevel {
		debugLogger = streamLoggerInstance
	}

	infoLogger = noOpLoggerInstance
	if level <= InfoLevel {
		infoLogger = streamLoggerInstance
	}

	warningLogger = noOpLoggerInstance
	if level <= WarningLevel {
		warningLogger = streamLoggerInstance
	}

	errorLogger = noOpLoggerInstance
	if level <= ErrorLevel {
		errorLogger = streamLoggerInstance
	}
}

func InitErrorLogger(file string) error {
	logger, err := newFileLogWriter(file)
	if err != nil {
		Error("Failed to create error logger on file (", file, "): ", err)
		return err
	}
	streamLoggerInstance = logger
	return nil
}

// Debug outputs a debug log with given format and optional arguments.
func Debug(v ...interface{}) {
	debugLogger.Log(&errorLog{
		prefix: "[Debug]",
		values: v,
	})
}

// Info outputs an info log with given format and optional arguments.
func Info(v ...interface{}) {
	infoLogger.Log(&errorLog{
		prefix: "[Info]",
		values: v,
	})
}

// Warning outputs a warning log with given format and optional arguments.
func Warning(v ...interface{}) {
	warningLogger.Log(&errorLog{
		prefix: "[Warning]",
		values: v,
	})
}

// Error outputs an error log with given format and optional arguments.
func Error(v ...interface{}) {
	errorLogger.Log(&errorLog{
		prefix: "[Error]",
		values: v,
	})
}
<|endoftext|>


<commit_before>package slack

import (
	"time"

	"github.com/danryan/hal"
	"github.com/nlopes/slack"
)

func (a *adapter) startConnection() {
	chReceiver := make(chan slack.SlackEvent)
	api := slack.New(a.token)
	// api.SetDebug(true)

	users, err := api.GetUsers()
	if err != nil {
		hal.Logger.Debugf("%s\n", err)
	}

	for _, user := range users {
		// retrieve the name and mention name of our bot from the server
		// if user.Id == api.Id {
		// 	a.name = user.Name
		// 	// skip adding the bot to the users map
		// 	continue
		// }
		// Initialize a newUser object in case we need it.
		newUser := hal.User{
			ID:   user.Id,
			Name: user.Name,
		}
		// Prepopulate our users map because we can easily do so.
		// If a user doesn't exist, set it.
		u, err := a.Robot.Users.Get(user.Id)
		if err != nil {
			a.Robot.Users.Set(user.Id, newUser)
		}

		// If the user doesn't match completely (say, if someone changes their name),
		// then adjust what we have stored.
		if u.Name != user.Name {
			a.Robot.Users.Set(user.Id, newUser)
		}
	}
	hal.Logger.Debugf("Stored users: %s\n", a.Robot.Users.All())

	a.wsAPI, err = api.StartRTM("", "http://"+a.team+".slack.com")
	if err != nil {
		hal.Logger.Debugf("%s\n", err)
	}

	go a.wsAPI.HandleIncomingEvents(chReceiver)
	go a.wsAPI.Keepalive(20 * time.Second)
	for {
		select {
		case msg := <-chReceiver:
			hal.Logger.Debug("Event Received: ")
			switch msg.Data.(type) {
			case slack.HelloEvent:
				// Ignore hello
			case *slack.MessageEvent:
				m := msg.Data.(*slack.MessageEvent)
				hal.Logger.Debugf("Message: %v\n", m)
				msg := a.newMessage(m)
				a.Receive(msg)
			case *slack.PresenceChangeEvent:
				m := msg.Data.(*slack.PresenceChangeEvent)
				hal.Logger.Debugf("Presence Change: %v\n", m)
			case slack.LatencyReport:
				m := msg.Data.(slack.LatencyReport)
				hal.Logger.Debugf("Current latency: %v\n", m.Value)
			default:
				hal.Logger.Debugf("Unexpected: %v\n", msg.Data)
			}
		}
	}
}

func (a *adapter) newMessage(msg *slack.MessageEvent) *hal.Message {
	user, _ := a.Robot.Users.Get(msg.UserId)
	return &hal.Message{
		User: user,
		Room: msg.ChannelId,
		Text: msg.Text,
	}
}
<commit_msg>Handle new member joining the team<commit_after>package slack

import (
	"time"

	"github.com/danryan/hal"
	"github.com/nlopes/slack"
)

func (a *adapter) startConnection() {
	chReceiver := make(chan slack.SlackEvent)
	api := slack.New(a.token)
	// api.SetDebug(true)

	users, err := api.GetUsers()
	if err != nil {
		hal.Logger.Debugf("%s\n", err)
	}

	for _, user := range users {
		// retrieve the name and mention name of our bot from the server
		// if user.Id == api.Id {
		// 	a.name = user.Name
		// 	// skip adding the bot to the users map
		// 	continue
		// }
		// Initialize a newUser object in case we need it.
		newUser := hal.User{
			ID:   user.Id,
			Name: user.Name,
		}
		// Prepopulate our users map because we can easily do so.
		// If a user doesn't exist, set it.
		u, err := a.Robot.Users.Get(user.Id)
		if err != nil {
			a.Robot.Users.Set(user.Id, newUser)
		}

		// If the user doesn't match completely (say, if someone changes their name),
		// then adjust what we have stored.
		if u.Name != user.Name {
			a.Robot.Users.Set(user.Id, newUser)
		}
	}
	hal.Logger.Debugf("Stored users: %s\n", a.Robot.Users.All())

	a.wsAPI, err = api.StartRTM("", "http://"+a.team+".slack.com")
	if err != nil {
		hal.Logger.Debugf("%s\n", err)
	}

	go a.wsAPI.HandleIncomingEvents(chReceiver)
	go a.wsAPI.Keepalive(20 * time.Second)
	for {
		select {
		case msg := <-chReceiver:
			hal.Logger.Debug("Event Received: ")
			switch msg.Data.(type) {
			case slack.HelloEvent:
				// Ignore hello
			case *slack.MessageEvent:
				m := msg.Data.(*slack.MessageEvent)
				hal.Logger.Debugf("Message: %v\n", m)
				msg := a.newMessage(m)
				a.Receive(msg)
			case *slack.PresenceChangeEvent:
				m := msg.Data.(*slack.PresenceChangeEvent)
				hal.Logger.Debugf("Presence Change: %v\n", m)
			case slack.LatencyReport:
				m := msg.Data.(slack.LatencyReport)
				hal.Logger.Debugf("Current latency: %v\n", m.Value)
			case slack.TeamJoinEvent:
				m := msg.Data.(slack.TeamJoinEvent)
				hal.Logger.Debugf("New member joined the team: %v\n", m.User)
				// Add the new member to the user list
				if _, err := a.Robot.Users.Get(m.User.Id); err != nil {
					a.Robot.Users.Set(m.User.Id, hal.User{ID: m.User.Id, Name: m.User.Name})
				}

			default:
				hal.Logger.Debugf("Unexpected: %v\n", msg.Data)
			}
		}
	}
}

func (a *adapter) newMessage(msg *slack.MessageEvent) *hal.Message {
	user, _ := a.Robot.Users.Get(msg.UserId)
	return &hal.Message{
		User: user,
		Room: msg.ChannelId,
		Text: msg.Text,
	}
}
<|endoftext|>


<commit_before>// Copyright (c) 2012 - Cloud Instruments Co., Ltd.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

package seelog

import (
	"fmt"
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"time"
)

var workingDir = "/"

func init() {
	wd, err := os.Getwd()
	if err == nil {
		workingDir = filepath.ToSlash(wd) + "/"
	}
}

// Represents runtime caller context.
type LogContextInterface interface {
	// Caller's function name.
	Func() string
	// Caller's line number.
	Line() int
	// Caller's file short path (in slashed form).
	ShortPath() string
	// Caller's file full path (in slashed form).
	FullPath() string
	// Caller's file name (without path).
	FileName() string
	// True if the context is correct and may be used.
	// If false, then an error in context evaluation occurred and
	// all its other data may be corrupted.
	IsValid() bool
	// Time when log function was called.
	CallTime() time.Time
}

// Returns context of the caller
func currentContext() (LogContextInterface, error) {
	return specifyContext(1)
}

func extractCallerInfo(skip int) (fullPath string, shortPath string, funcName string, line int, err error) {
	pc, fp, ln, ok := runtime.Caller(skip)
	if !ok {
		err = fmt.Errorf("error during runtime.Caller")
		return
	}
	line = ln
	fullPath = fp
	if strings.HasPrefix(fp, workingDir) {
		shortPath = fp[len(workingDir):]
	} else {
		shortPath = fp
	}
	funcName = runtime.FuncForPC(pc).Name()
	if strings.HasPrefix(funcName, workingDir) {
		funcName = funcName[len(workingDir):]
	}
	return
}

// Returns context of the function with placed "skip" stack frames of the caller
// If skip == 0 then behaves like currentContext
// Context is returned in any situation, even if error occurs. But, if an error
// occurs, the returned context is an error context, which contains no paths
// or names, but states that they can't be extracted.
func specifyContext(skip int) (ctx LogContextInterface, err error) {
	callTime := time.Now()
	if skip < 0 {
		err = fmt.Errorf("can not skip negative stack frames")
		ctx = &errorContext{callTime, err}
		return
	}
	var (
		fullPath, shortPath, funcName string
		line                          int
	)
	fullPath, shortPath, funcName, line, err = extractCallerInfo(skip + 2)
	if err != nil {
		ctx = &errorContext{callTime, err}
		return
	}
	_, fileName := filepath.Split(fullPath)
	ctx = &logContext{funcName, line, shortPath, fullPath, fileName, callTime}
	return
}

// Represents a normal runtime caller context.
type logContext struct {
	funcName  string
	line      int
	shortPath string
	fullPath  string
	fileName  string
	callTime  time.Time
}

func (context *logContext) IsValid() bool {
	return true
}

func (context *logContext) Func() string {
	return context.funcName
}

func (context *logContext) Line() int {
	return context.line
}

func (context *logContext) ShortPath() string {
	return context.shortPath
}

func (context *logContext) FullPath() string {
	return context.fullPath
}

func (context *logContext) FileName() string {
	return context.fileName
}

func (context *logContext) CallTime() time.Time {
	return context.callTime
}

const (
	errorContextFunc      = "Func() error: "
	errorContextShortPath = "ShortPath() error: "
	errorContextFullPath  = "FullPath() error: "
	errorContextFileName  = "FileName() error: "
)

// Represents an error context
type errorContext struct {
	errorTime time.Time
	err       error
}

func (errContext *errorContext) IsValid() bool {
	return false
}

func (errContext *errorContext) Line() int {
	return -1
}

func (errContext *errorContext) Func() string {
	return errorContextFunc + errContext.err.Error()
}

func (errContext *errorContext) ShortPath() string {
	return errorContextShortPath + errContext.err.Error()
}

func (errContext *errorContext) FullPath() string {
	return errorContextFullPath + errContext.err.Error()
}

func (errContext *errorContext) FileName() string {
	return errorContextFileName + errContext.err.Error()
}

func (errContext *errorContext) CallTime() time.Time {
	return errContext.errorTime
}
<commit_msg>Refactor specifyContext function<commit_after>// Copyright (c) 2012 - Cloud Instruments Co., Ltd.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

package seelog

import (
	"fmt"
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"time"
)

var workingDir = "/"

func init() {
	wd, err := os.Getwd()
	if err == nil {
		workingDir = filepath.ToSlash(wd) + "/"
	}
}

// Represents runtime caller context.
type LogContextInterface interface {
	// Caller's function name.
	Func() string
	// Caller's line number.
	Line() int
	// Caller's file short path (in slashed form).
	ShortPath() string
	// Caller's file full path (in slashed form).
	FullPath() string
	// Caller's file name (without path).
	FileName() string
	// True if the context is correct and may be used.
	// If false, then an error in context evaluation occurred and
	// all its other data may be corrupted.
	IsValid() bool
	// Time when log function was called.
	CallTime() time.Time
}

// Returns context of the caller
func currentContext() (LogContextInterface, error) {
	return specifyContext(1)
}

func extractCallerInfo(skip int) (fullPath string, shortPath string, funcName string, line int, err error) {
	pc, fp, ln, ok := runtime.Caller(skip)
	if !ok {
		err = fmt.Errorf("error during runtime.Caller")
		return
	}
	line = ln
	fullPath = fp
	if strings.HasPrefix(fp, workingDir) {
		shortPath = fp[len(workingDir):]
	} else {
		shortPath = fp
	}
	funcName = runtime.FuncForPC(pc).Name()
	if strings.HasPrefix(funcName, workingDir) {
		funcName = funcName[len(workingDir):]
	}
	return
}

// Returns context of the function with placed "skip" stack frames of the caller
// If skip == 0 then behaves like currentContext
// Context is returned in any situation, even if error occurs. But, if an error
// occurs, the returned context is an error context, which contains no paths
// or names, but states that they can't be extracted.
func specifyContext(skip int) (LogContextInterface, error) {
	callTime := time.Now()
	if skip < 0 {
		err := fmt.Errorf("can not skip negative stack frames")
		return &errorContext{callTime, err}, err
	}
	fullPath, shortPath, funcName, line, err := extractCallerInfo(skip + 2)
	if err != nil {
		return &errorContext{callTime, err}, err
	}
	_, fileName := filepath.Split(fullPath)
	return &logContext{funcName, line, shortPath, fullPath, fileName, callTime}, nil
}

// Represents a normal runtime caller context.
type logContext struct {
	funcName  string
	line      int
	shortPath string
	fullPath  string
	fileName  string
	callTime  time.Time
}

func (context *logContext) IsValid() bool {
	return true
}

func (context *logContext) Func() string {
	return context.funcName
}

func (context *logContext) Line() int {
	return context.line
}

func (context *logContext) ShortPath() string {
	return context.shortPath
}

func (context *logContext) FullPath() string {
	return context.fullPath
}

func (context *logContext) FileName() string {
	return context.fileName
}

func (context *logContext) CallTime() time.Time {
	return context.callTime
}

const (
	errorContextFunc      = "Func() error: "
	errorContextShortPath = "ShortPath() error: "
	errorContextFullPath  = "FullPath() error: "
	errorContextFileName  = "FileName() error: "
)

// Represents an error context
type errorContext struct {
	errorTime time.Time
	err       error
}

func (errContext *errorContext) IsValid() bool {
	return false
}

func (errContext *errorContext) Line() int {
	return -1
}

func (errContext *errorContext) Func() string {
	return errorContextFunc + errContext.err.Error()
}

func (errContext *errorContext) ShortPath() string {
	return errorContextShortPath + errContext.err.Error()
}

func (errContext *errorContext) FullPath() string {
	return errorContextFullPath + errContext.err.Error()
}

func (errContext *errorContext) FileName() string {
	return errorContextFileName + errContext.err.Error()
}

func (errContext *errorContext) CallTime() time.Time {
	return errContext.errorTime
}
<|endoftext|>


<commit_before>package daemon

import (
	"github.com/Clever/sphinx/config"
	"io/ioutil"
	"net/http"
	"testing"
)

func TestConfigReload(t *testing.T) {
	conf, err := config.New("../example.yaml")
	if err != nil {
		t.Fatal("Error loading config: " + err.Error())
	}
	d := daemon{}
	d.LoadConfig(conf)
	if d.handler == nil {
		t.Fatal("Didn't assign handler")
	}
}

func TestFailedReload(t *testing.T) {
	conf, err := config.New("../example.yaml")
	if err != nil {
		t.Fatal("Error loading config: " + err.Error())
	}
	daemon, err := New(conf)
	if err != nil {
		t.Fatal("Error creating new daemon: " + err.Error())
	}
	conf2 := config.Config{}
	err = daemon.LoadConfig(conf2)
	if err == nil {
		t.Fatal("Should have errored on empty configuration")
	}

	conf.Proxy.Listen = ":1000"
	err = daemon.LoadConfig(conf)
	if err == nil {
		t.Fatalf("Should have errored on changed listen port")
	}
}

var localServerPort = ":8081"
var localServerHost = "http://localhost" + localServerPort
var localProxyHost = "http://localhost:6634"
var healthCheckURL = "http://localhost:60002/health/check"

func setUpDaemonWithLocalServer() error {
	// Set up a local server that 404s everywhere except route '/healthyroute'.
	mux := http.NewServeMux()
	mux.HandleFunc("/healthyroute", func(rw http.ResponseWriter, req *http.Request) {
		rw.Write([]byte("healthy"))
	})
	mux.HandleFunc("/", func(rw http.ResponseWriter, req *http.Request) {
		rw.WriteHeader(http.StatusNotFound)
		rw.Write([]byte("404"))
	})
	go http.ListenAndServe(localServerPort, mux)

	// Set up the daemon to proxy to the local server.
	conf, err := config.New("../example.yaml")
	if err != nil {
		return err
	}
	conf.Proxy.Host = localServerHost

	daemon, err := New(conf)
	if err != nil {
		return err
	}

	go daemon.Start()
	return nil
}

// testProxyRequest calls the proxy server at the given path and verifies that
// the request returns the given HTTP status and body content.
func testProxyRequest(t *testing.T, url string, expectedStatus int, expectedBody string) {
	resp, err := http.Get(url)
	if err != nil {
		t.Fatalf("Proxy request failed: %s", err.Error())
	}

	if resp.StatusCode != expectedStatus {
		t.Fatalf("Response status with url %s does not match expected value.  Actual: %d.  Expected: %d.",
			url, resp.StatusCode, expectedStatus)
	}

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		t.Fatalf("Couldn't read response body: %s", err.Error())
	}

	bodyStr := string(body)
	if bodyStr != expectedBody {
		t.Fatalf("Response body does not match expected value. Actual: \"%s\" Expected: \"%s\"",
			bodyStr, expectedBody)
	}
}

func TestHealthCheck(t *testing.T) {
	err := setUpDaemonWithLocalServer()
	if err != nil {
		t.Fatalf("Test daemon setup failed: %s", err.Error())
	}

	// Test a route that should be proxied to 404.
	testProxyRequest(t, localProxyHost+"/helloworld", http.StatusNotFound, "404")

	// Test a route that should be proxied to a valid response.
	testProxyRequest(t, localProxyHost+"/healthyroute", http.StatusOK, "healthy")

	// Test the health check.
	testProxyRequest(t, healthCheckURL, http.StatusOK, "")
}
<commit_msg>daemon: Add daemon test for no health check.<commit_after>package daemon

import (
	"github.com/Clever/sphinx/config"
	"io/ioutil"
	"net/http"
	"testing"
	"time"
)

func TestConfigReload(t *testing.T) {
	conf, err := config.New("../example.yaml")
	if err != nil {
		t.Fatal("Error loading config: " + err.Error())
	}
	d := daemon{}
	d.LoadConfig(conf)
	if d.handler == nil {
		t.Fatal("Didn't assign handler")
	}
}

func TestFailedReload(t *testing.T) {
	conf, err := config.New("../example.yaml")
	if err != nil {
		t.Fatal("Error loading config: " + err.Error())
	}
	daemon, err := New(conf)
	if err != nil {
		t.Fatal("Error creating new daemon: " + err.Error())
	}
	conf2 := config.Config{}
	err = daemon.LoadConfig(conf2)
	if err == nil {
		t.Fatal("Should have errored on empty configuration")
	}

	conf.Proxy.Listen = ":1000"
	err = daemon.LoadConfig(conf)
	if err == nil {
		t.Fatalf("Should have errored on changed listen port")
	}
}

func setUpDaemonWithLocalServer(localServerPort, localProxyListen, healthCheckPort string) error {
	// Set up a local server that 404s everywhere except route '/healthyroute'.
	mux := http.NewServeMux()
	mux.HandleFunc("/healthyroute", func(rw http.ResponseWriter, req *http.Request) {
		rw.Write([]byte("healthy"))
	})
	mux.HandleFunc("/", func(rw http.ResponseWriter, req *http.Request) {
		rw.WriteHeader(http.StatusNotFound)
		rw.Write([]byte("404"))
	})
	go http.ListenAndServe(":"+localServerPort, mux)

	// Set up the daemon to proxy to the local server.
	conf, err := config.New("../example.yaml")
	if err != nil {
		return err
	}
	conf.Proxy.Host = "http://localhost:" + localServerPort
	conf.Proxy.Listen = localProxyListen
	conf.HealthCheck.Port = healthCheckPort

	daemon, err := New(conf)
	if err != nil {
		return err
	}

	go daemon.Start()
	return nil
}

// testProxyRequest calls the proxy server at the given path and verifies that
// the request returns the given HTTP status and body content.
func testProxyRequest(t *testing.T, url string, expectedStatus int, expectedBody string) {
	resp, err := http.Get(url)
	if err != nil {
		t.Fatalf("Proxy request failed: %s", err.Error())
	}

	if resp.StatusCode != expectedStatus {
		t.Fatalf("Response status with url %s does not match expected value.  Actual: %d.  Expected: %d.",
			url, resp.StatusCode, expectedStatus)
	}

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		t.Fatalf("Couldn't read response body: %s", err.Error())
	}

	bodyStr := string(body)
	if bodyStr != expectedBody {
		t.Fatalf("Response body does not match expected value. Actual: \"%s\" Expected: \"%s\"",
			bodyStr, expectedBody)
	}
}

func getHealthCheckURLFromPort(port string) string {
	if len(port) > 0 {
		return "http://localhost:" + port + "/health/check"
	}
	return "http://localhost/health/check"
}

func TestHealthCheck(t *testing.T) {
	localProxyListen := ":6634"
	healthCheckPort := "60002"

	err := setUpDaemonWithLocalServer("8000", localProxyListen, healthCheckPort)
	if err != nil {
		t.Fatalf("Test daemon setup failed: %s", err.Error())
	}

	localProxyURL := "http://localhost" + localProxyListen

	// Test a route that should be proxied to 404.
	testProxyRequest(t, localProxyURL+"/helloworld", http.StatusNotFound, "404")

	// Test a route that should be proxied to a valid response.
	testProxyRequest(t, localProxyURL+"/healthyroute", http.StatusOK, "healthy")

	// Test the health check.
	testProxyRequest(t, getHealthCheckURLFromPort(healthCheckPort), http.StatusOK, "")
}

func TestDaemonWithNoHealthCheck(t *testing.T) {
	localProxyListen := ":6635"
	healthCheckPort := ""

	err := setUpDaemonWithLocalServer("8001", localProxyListen, healthCheckPort)
	if err != nil {
		t.Fatalf("Test daemon setup failed: %s", err.Error())
	}

	// Because so many servers are starting,  sleep  for a second to make sure
	// they start.
	time.Sleep(time.Second)

	localProxyURL := "http://localhost" + localProxyListen

	// Test a route that should be proxied to 404.
	testProxyRequest(t, localProxyURL+"/helloworld", http.StatusNotFound, "404")

	// Test a route that should be proxied to a valid response.
	testProxyRequest(t, localProxyURL+"/healthyroute", http.StatusOK, "healthy")

	// Health check request should fail.
	if _, err := http.Get(getHealthCheckURLFromPort(healthCheckPort)); err == nil {
		t.Fatalf("Health check request should have failed, but it did not.")
	}

}
<|endoftext|>


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

package main

import (
	"errors"
	"io/ioutil"
	"os"
	"path/filepath"
	"time"

	"github.com/cilium/cilium/common"
	"github.com/cilium/cilium/common/addressing"
	"github.com/cilium/cilium/daemon/options"
	"github.com/cilium/cilium/pkg/apierror"
	"github.com/cilium/cilium/pkg/endpoint"
	"github.com/cilium/cilium/pkg/labels"
	"github.com/cilium/cilium/pkg/option"
	"github.com/cilium/cilium/pkg/policy"

	. "gopkg.in/check.v1"
)

var (
	lbls = labels.Labels{
		"foo":    labels.NewLabel("foo", "bar", common.CiliumLabelSource),
		"foo2":   labels.NewLabel("foo2", "=bar2", common.CiliumLabelSource),
		"key":    labels.NewLabel("key", "", common.CiliumLabelSource),
		"foo==":  labels.NewLabel("foo==", "==", common.CiliumLabelSource),
		`foo\\=`: labels.NewLabel(`foo\\=`, `\=`, common.CiliumLabelSource),
		`//=/`:   labels.NewLabel(`//=/`, "", common.CiliumLabelSource),
		`%`:      labels.NewLabel(`%`, `%ed`, common.CiliumLabelSource),
	}
	lbls2 = labels.Labels{
		"foo":  labels.NewLabel("foo", "bar", common.CiliumLabelSource),
		"foo2": labels.NewLabel("foo2", "=bar2", common.CiliumLabelSource),
	}
	wantSecCtxLbls = policy.Identity{
		ID: 123,
		Endpoints: map[string]time.Time{
			"cc08ff400e355f736dce1c291a6a4007ab9f2d56d42e1f3630ba87b861d45307": time.Now(),
		},
		Labels: lbls,
	}
	nilAPIError *apierror.APIError
)

func (ds *DaemonSuite) SetUpTest(c *C) {
	time.Local = time.UTC
	tempRunDir, err := ioutil.TempDir("", "cilium-test-run")
	c.Assert(err, IsNil)
	err = os.Mkdir(filepath.Join(tempRunDir, "globals"), 0777)
	c.Assert(err, IsNil)

	nodeAddress, err := addressing.NewNodeAddress("beef:beef:beef:beef:aaaa:aaaa:1111:0", "10.1.0.1", "")
	c.Assert(err, IsNil)

	daemonConf := &Config{
		DryMode: true,
		Opts:    option.NewBoolOptions(&options.Library),
	}
	daemonConf.RunDir = tempRunDir
	daemonConf.StateDir = tempRunDir
	daemonConf.LXCMap = nil
	daemonConf.NodeAddress = nodeAddress
	daemonConf.DockerEndpoint = "tcp://127.0.0.1"
	daemonConf.K8sEndpoint = "tcp://127.0.0.1"
	daemonConf.ValidLabelPrefixes = nil
	daemonConf.Opts.Set(endpoint.OptionDropNotify, true)
	daemonConf.Device = "undefined"

	err = daemonConf.SetKVBackend()
	c.Assert(err, IsNil)

	d, err := NewDaemon(daemonConf)
	c.Assert(err, IsNil)
	ds.d = d
	d.kvClient.DeleteTree(common.OperationalPath)
	// Needs to be less than 1 second otherwise GetCachedMaxLabelID might
	// not work properly
	d.EnableKVStoreWatcher(time.Nanosecond)
}

func (ds *DaemonSuite) TearDownTest(c *C) {
	os.RemoveAll(ds.d.conf.RunDir)
}

func (ds *DaemonSuite) TestLabels(c *C) {
	//Set up last free ID with zero
	id, err := ds.d.GetMaxLabelID()
	c.Assert(err, IsNil)
	c.Assert(id, Equals, policy.MinimalNumericIdentity)

	secCtxLbl, new, err := ds.d.CreateOrUpdateIdentity(lbls, "containerLabel1-1")
	c.Assert(err, IsNil)
	c.Assert(secCtxLbl.ID, Equals, policy.MinimalNumericIdentity)
	c.Assert(secCtxLbl.RefCount(), Equals, 1)
	c.Assert(new, Equals, true)

	secCtxLbl, new, err = ds.d.CreateOrUpdateIdentity(lbls, "containerLabel1-2")
	c.Assert(err, IsNil)
	c.Assert(secCtxLbl.ID, Equals, policy.MinimalNumericIdentity)
	c.Assert(secCtxLbl.RefCount(), Equals, 2)
	c.Assert(new, Equals, false)

	secCtxLbl, new, err = ds.d.CreateOrUpdateIdentity(lbls2, "containerLabel2-1")
	c.Assert(err, IsNil)
	c.Assert(secCtxLbl.ID, Equals, policy.MinimalNumericIdentity+1)
	c.Assert(secCtxLbl.RefCount(), Equals, 1)
	c.Assert(new, Equals, true)

	secCtxLbl, new, err = ds.d.CreateOrUpdateIdentity(lbls2, "containerLabel2-2")
	c.Assert(err, IsNil)
	c.Assert(secCtxLbl.ID, Equals, policy.MinimalNumericIdentity+1)
	c.Assert(secCtxLbl.RefCount(), Equals, 2)
	c.Assert(new, Equals, false)

	secCtxLbl, new, err = ds.d.CreateOrUpdateIdentity(lbls, "containerLabel1-3")
	c.Assert(err, IsNil)
	c.Assert(secCtxLbl.ID, Equals, policy.MinimalNumericIdentity)
	c.Assert(secCtxLbl.RefCount(), Equals, 3)
	c.Assert(new, Equals, false)

	//Get labels from ID
	gotSecCtxLbl, err := ds.d.LookupIdentity(policy.MinimalNumericIdentity)
	c.Assert(err, IsNil)
	wantSecCtxLbls.ID = policy.MinimalNumericIdentity
	wantSecCtxLbls.Labels = lbls
	c.Assert(gotSecCtxLbl.ID, Equals, wantSecCtxLbls.ID)
	c.Assert(gotSecCtxLbl.Labels, DeepEquals, wantSecCtxLbls.Labels)
	c.Assert(gotSecCtxLbl.RefCount(), Equals, 3)

	err = ds.d.DeleteIdentity(policy.MinimalNumericIdentity, "containerLabel1-1")
	c.Assert(err, IsNil)
	gotSecCtxLbl, err = ds.d.LookupIdentity(policy.MinimalNumericIdentity)
	c.Assert(err, IsNil)
	wantSecCtxLbls.ID = policy.MinimalNumericIdentity
	wantSecCtxLbls.Labels = lbls
	c.Assert(gotSecCtxLbl.ID, Equals, wantSecCtxLbls.ID)
	c.Assert(gotSecCtxLbl.Labels, DeepEquals, wantSecCtxLbls.Labels)
	c.Assert(gotSecCtxLbl.RefCount(), Equals, 2)

	gotSecCtxLbl, err = ds.d.LookupIdentity(policy.MinimalNumericIdentity + 1)
	c.Assert(err, IsNil)
	wantSecCtxLbls.ID = policy.MinimalNumericIdentity + 1
	wantSecCtxLbls.Labels = lbls2
	c.Assert(gotSecCtxLbl.ID, Equals, wantSecCtxLbls.ID)
	c.Assert(gotSecCtxLbl.Labels, DeepEquals, wantSecCtxLbls.Labels)
	c.Assert(gotSecCtxLbl.RefCount(), Equals, 2)

	err = ds.d.DeleteIdentity(policy.MinimalNumericIdentity, "containerLabel1-2")
	c.Assert(err, IsNil)
	gotSecCtxLbl, err = ds.d.LookupIdentity(policy.MinimalNumericIdentity)
	wantSecCtxLbls.ID = policy.MinimalNumericIdentity
	wantSecCtxLbls.Labels = lbls
	c.Assert(gotSecCtxLbl.ID, Equals, wantSecCtxLbls.ID)
	c.Assert(gotSecCtxLbl.Labels, DeepEquals, wantSecCtxLbls.Labels)
	c.Assert(gotSecCtxLbl.RefCount(), Equals, 1)

	err = ds.d.DeleteIdentity(policy.MinimalNumericIdentity, "containerLabel1-3")
	c.Assert(err, IsNil)
	gotSecCtxLbl, err = ds.d.LookupIdentity(policy.MinimalNumericIdentity)
	c.Assert(err, IsNil)
	var emptySecCtxLblPtr *policy.Identity
	c.Assert(gotSecCtxLbl, Equals, emptySecCtxLblPtr)

	err = ds.d.kvClient.SetMaxID(common.LastFreeLabelIDKeyPath, policy.MinimalNumericIdentity.Uint32(), policy.MinimalNumericIdentity.Uint32())
	c.Assert(err, IsNil)

	err = ds.d.DeleteIdentity(policy.MinimalNumericIdentity, "containerLabel1-non-existent")
	c.Assert(err, DeepEquals, errors.New("identity not found"))
	gotSecCtxLbl, err = ds.d.LookupIdentity(policy.MinimalNumericIdentity)
	c.Assert(err, IsNil)
	c.Assert(gotSecCtxLbl, Equals, emptySecCtxLblPtr)

	secCtxLbl, new, err = ds.d.CreateOrUpdateIdentity(lbls2, "containerLabel2-3")
	c.Assert(err, IsNil)
	c.Assert(secCtxLbl.ID, Equals, policy.MinimalNumericIdentity+1)
	c.Assert(secCtxLbl.RefCount(), Equals, 3)
	c.Assert(new, Equals, false)

	sha256sum := lbls2.SHA256Sum()
	gotSecCtxLbl, err = ds.d.LookupIdentityBySHA256(sha256sum)
	c.Assert(err, IsNil)
	c.Assert(gotSecCtxLbl, DeepEquals, secCtxLbl)

	err = ds.d.DeleteIdentityBySHA256(sha256sum, "containerLabel2-1")
	c.Assert(err, IsNil)
	err = ds.d.DeleteIdentity(policy.MinimalNumericIdentity+1, "containerLabel2-2")
	c.Assert(err, IsNil)
	err = ds.d.DeleteIdentity(policy.MinimalNumericIdentity+1, "containerLabel2-3")
	c.Assert(err, IsNil)

	secCtxLbl, new, err = ds.d.CreateOrUpdateIdentity(lbls2, "containerLabel2-3")
	c.Assert(err, IsNil)
	c.Assert(secCtxLbl.ID, Equals, policy.MinimalNumericIdentity)
	c.Assert(secCtxLbl.RefCount(), Equals, 1)
	c.Assert(new, Equals, true)

	secCtxLbl, new, err = ds.d.CreateOrUpdateIdentity(lbls, "containerLabel2-3")
	c.Assert(err, IsNil)
	c.Assert(secCtxLbl.ID, Equals, policy.MinimalNumericIdentity+1)
	c.Assert(secCtxLbl.RefCount(), Equals, 1)
	c.Assert(new, Equals, true)
}

func (ds *DaemonSuite) TestGetMaxID(c *C) {
	lastID := policy.NumericIdentity(common.MaxSetOfLabels - 1)
	err := ds.d.kvClient.SetValue(common.LastFreeLabelIDKeyPath, lastID)
	c.Assert(err, IsNil)

	id, err := ds.d.GetMaxLabelID()
	c.Assert(err, IsNil)
	c.Assert(id, Equals, lastID)
}
<commit_msg>ineffassign: check unused error<commit_after>// Copyright 2016-2017 Authors of Cilium
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"errors"
	"io/ioutil"
	"os"
	"path/filepath"
	"time"

	"github.com/cilium/cilium/common"
	"github.com/cilium/cilium/common/addressing"
	"github.com/cilium/cilium/daemon/options"
	"github.com/cilium/cilium/pkg/apierror"
	"github.com/cilium/cilium/pkg/endpoint"
	"github.com/cilium/cilium/pkg/labels"
	"github.com/cilium/cilium/pkg/option"
	"github.com/cilium/cilium/pkg/policy"

	. "gopkg.in/check.v1"
)

var (
	lbls = labels.Labels{
		"foo":    labels.NewLabel("foo", "bar", common.CiliumLabelSource),
		"foo2":   labels.NewLabel("foo2", "=bar2", common.CiliumLabelSource),
		"key":    labels.NewLabel("key", "", common.CiliumLabelSource),
		"foo==":  labels.NewLabel("foo==", "==", common.CiliumLabelSource),
		`foo\\=`: labels.NewLabel(`foo\\=`, `\=`, common.CiliumLabelSource),
		`//=/`:   labels.NewLabel(`//=/`, "", common.CiliumLabelSource),
		`%`:      labels.NewLabel(`%`, `%ed`, common.CiliumLabelSource),
	}
	lbls2 = labels.Labels{
		"foo":  labels.NewLabel("foo", "bar", common.CiliumLabelSource),
		"foo2": labels.NewLabel("foo2", "=bar2", common.CiliumLabelSource),
	}
	wantSecCtxLbls = policy.Identity{
		ID: 123,
		Endpoints: map[string]time.Time{
			"cc08ff400e355f736dce1c291a6a4007ab9f2d56d42e1f3630ba87b861d45307": time.Now(),
		},
		Labels: lbls,
	}
	nilAPIError *apierror.APIError
)

func (ds *DaemonSuite) SetUpTest(c *C) {
	time.Local = time.UTC
	tempRunDir, err := ioutil.TempDir("", "cilium-test-run")
	c.Assert(err, IsNil)
	err = os.Mkdir(filepath.Join(tempRunDir, "globals"), 0777)
	c.Assert(err, IsNil)

	nodeAddress, err := addressing.NewNodeAddress("beef:beef:beef:beef:aaaa:aaaa:1111:0", "10.1.0.1", "")
	c.Assert(err, IsNil)

	daemonConf := &Config{
		DryMode: true,
		Opts:    option.NewBoolOptions(&options.Library),
	}
	daemonConf.RunDir = tempRunDir
	daemonConf.StateDir = tempRunDir
	daemonConf.LXCMap = nil
	daemonConf.NodeAddress = nodeAddress
	daemonConf.DockerEndpoint = "tcp://127.0.0.1"
	daemonConf.K8sEndpoint = "tcp://127.0.0.1"
	daemonConf.ValidLabelPrefixes = nil
	daemonConf.Opts.Set(endpoint.OptionDropNotify, true)
	daemonConf.Device = "undefined"

	err = daemonConf.SetKVBackend()
	c.Assert(err, IsNil)

	d, err := NewDaemon(daemonConf)
	c.Assert(err, IsNil)
	ds.d = d
	d.kvClient.DeleteTree(common.OperationalPath)
	// Needs to be less than 1 second otherwise GetCachedMaxLabelID might
	// not work properly
	d.EnableKVStoreWatcher(time.Nanosecond)
}

func (ds *DaemonSuite) TearDownTest(c *C) {
	os.RemoveAll(ds.d.conf.RunDir)
}

func (ds *DaemonSuite) TestLabels(c *C) {
	//Set up last free ID with zero
	id, err := ds.d.GetMaxLabelID()
	c.Assert(err, IsNil)
	c.Assert(id, Equals, policy.MinimalNumericIdentity)

	secCtxLbl, new, err := ds.d.CreateOrUpdateIdentity(lbls, "containerLabel1-1")
	c.Assert(err, IsNil)
	c.Assert(secCtxLbl.ID, Equals, policy.MinimalNumericIdentity)
	c.Assert(secCtxLbl.RefCount(), Equals, 1)
	c.Assert(new, Equals, true)

	secCtxLbl, new, err = ds.d.CreateOrUpdateIdentity(lbls, "containerLabel1-2")
	c.Assert(err, IsNil)
	c.Assert(secCtxLbl.ID, Equals, policy.MinimalNumericIdentity)
	c.Assert(secCtxLbl.RefCount(), Equals, 2)
	c.Assert(new, Equals, false)

	secCtxLbl, new, err = ds.d.CreateOrUpdateIdentity(lbls2, "containerLabel2-1")
	c.Assert(err, IsNil)
	c.Assert(secCtxLbl.ID, Equals, policy.MinimalNumericIdentity+1)
	c.Assert(secCtxLbl.RefCount(), Equals, 1)
	c.Assert(new, Equals, true)

	secCtxLbl, new, err = ds.d.CreateOrUpdateIdentity(lbls2, "containerLabel2-2")
	c.Assert(err, IsNil)
	c.Assert(secCtxLbl.ID, Equals, policy.MinimalNumericIdentity+1)
	c.Assert(secCtxLbl.RefCount(), Equals, 2)
	c.Assert(new, Equals, false)

	secCtxLbl, new, err = ds.d.CreateOrUpdateIdentity(lbls, "containerLabel1-3")
	c.Assert(err, IsNil)
	c.Assert(secCtxLbl.ID, Equals, policy.MinimalNumericIdentity)
	c.Assert(secCtxLbl.RefCount(), Equals, 3)
	c.Assert(new, Equals, false)

	//Get labels from ID
	gotSecCtxLbl, err := ds.d.LookupIdentity(policy.MinimalNumericIdentity)
	c.Assert(err, IsNil)
	wantSecCtxLbls.ID = policy.MinimalNumericIdentity
	wantSecCtxLbls.Labels = lbls
	c.Assert(gotSecCtxLbl.ID, Equals, wantSecCtxLbls.ID)
	c.Assert(gotSecCtxLbl.Labels, DeepEquals, wantSecCtxLbls.Labels)
	c.Assert(gotSecCtxLbl.RefCount(), Equals, 3)

	err = ds.d.DeleteIdentity(policy.MinimalNumericIdentity, "containerLabel1-1")
	c.Assert(err, IsNil)
	gotSecCtxLbl, err = ds.d.LookupIdentity(policy.MinimalNumericIdentity)
	c.Assert(err, IsNil)
	wantSecCtxLbls.ID = policy.MinimalNumericIdentity
	wantSecCtxLbls.Labels = lbls
	c.Assert(gotSecCtxLbl.ID, Equals, wantSecCtxLbls.ID)
	c.Assert(gotSecCtxLbl.Labels, DeepEquals, wantSecCtxLbls.Labels)
	c.Assert(gotSecCtxLbl.RefCount(), Equals, 2)

	gotSecCtxLbl, err = ds.d.LookupIdentity(policy.MinimalNumericIdentity + 1)
	c.Assert(err, IsNil)
	wantSecCtxLbls.ID = policy.MinimalNumericIdentity + 1
	wantSecCtxLbls.Labels = lbls2
	c.Assert(gotSecCtxLbl.ID, Equals, wantSecCtxLbls.ID)
	c.Assert(gotSecCtxLbl.Labels, DeepEquals, wantSecCtxLbls.Labels)
	c.Assert(gotSecCtxLbl.RefCount(), Equals, 2)

	err = ds.d.DeleteIdentity(policy.MinimalNumericIdentity, "containerLabel1-2")
	c.Assert(err, IsNil)
	gotSecCtxLbl, err = ds.d.LookupIdentity(policy.MinimalNumericIdentity)
	c.Assert(err, IsNil)
	wantSecCtxLbls.ID = policy.MinimalNumericIdentity
	wantSecCtxLbls.Labels = lbls
	c.Assert(gotSecCtxLbl.ID, Equals, wantSecCtxLbls.ID)
	c.Assert(gotSecCtxLbl.Labels, DeepEquals, wantSecCtxLbls.Labels)
	c.Assert(gotSecCtxLbl.RefCount(), Equals, 1)

	err = ds.d.DeleteIdentity(policy.MinimalNumericIdentity, "containerLabel1-3")
	c.Assert(err, IsNil)
	gotSecCtxLbl, err = ds.d.LookupIdentity(policy.MinimalNumericIdentity)
	c.Assert(err, IsNil)
	var emptySecCtxLblPtr *policy.Identity
	c.Assert(gotSecCtxLbl, Equals, emptySecCtxLblPtr)

	err = ds.d.kvClient.SetMaxID(common.LastFreeLabelIDKeyPath, policy.MinimalNumericIdentity.Uint32(), policy.MinimalNumericIdentity.Uint32())
	c.Assert(err, IsNil)

	err = ds.d.DeleteIdentity(policy.MinimalNumericIdentity, "containerLabel1-non-existent")
	c.Assert(err, DeepEquals, errors.New("identity not found"))
	gotSecCtxLbl, err = ds.d.LookupIdentity(policy.MinimalNumericIdentity)
	c.Assert(err, IsNil)
	c.Assert(gotSecCtxLbl, Equals, emptySecCtxLblPtr)

	secCtxLbl, new, err = ds.d.CreateOrUpdateIdentity(lbls2, "containerLabel2-3")
	c.Assert(err, IsNil)
	c.Assert(secCtxLbl.ID, Equals, policy.MinimalNumericIdentity+1)
	c.Assert(secCtxLbl.RefCount(), Equals, 3)
	c.Assert(new, Equals, false)

	sha256sum := lbls2.SHA256Sum()
	gotSecCtxLbl, err = ds.d.LookupIdentityBySHA256(sha256sum)
	c.Assert(err, IsNil)
	c.Assert(gotSecCtxLbl, DeepEquals, secCtxLbl)

	err = ds.d.DeleteIdentityBySHA256(sha256sum, "containerLabel2-1")
	c.Assert(err, IsNil)
	err = ds.d.DeleteIdentity(policy.MinimalNumericIdentity+1, "containerLabel2-2")
	c.Assert(err, IsNil)
	err = ds.d.DeleteIdentity(policy.MinimalNumericIdentity+1, "containerLabel2-3")
	c.Assert(err, IsNil)

	secCtxLbl, new, err = ds.d.CreateOrUpdateIdentity(lbls2, "containerLabel2-3")
	c.Assert(err, IsNil)
	c.Assert(secCtxLbl.ID, Equals, policy.MinimalNumericIdentity)
	c.Assert(secCtxLbl.RefCount(), Equals, 1)
	c.Assert(new, Equals, true)

	secCtxLbl, new, err = ds.d.CreateOrUpdateIdentity(lbls, "containerLabel2-3")
	c.Assert(err, IsNil)
	c.Assert(secCtxLbl.ID, Equals, policy.MinimalNumericIdentity+1)
	c.Assert(secCtxLbl.RefCount(), Equals, 1)
	c.Assert(new, Equals, true)
}

func (ds *DaemonSuite) TestGetMaxID(c *C) {
	lastID := policy.NumericIdentity(common.MaxSetOfLabels - 1)
	err := ds.d.kvClient.SetValue(common.LastFreeLabelIDKeyPath, lastID)
	c.Assert(err, IsNil)

	id, err := ds.d.GetMaxLabelID()
	c.Assert(err, IsNil)
	c.Assert(id, Equals, lastID)
}
<|endoftext|>