fix: set config, set remote

This commit is contained in:
Markus Pesch 2018-11-19 22:36:21 +01:00
parent 54dd2191d6
commit dd7ea3156e
Signed by: volker.raschek
GPG Key ID: 852BCC170D81A982
24 changed files with 1338 additions and 58 deletions

9
Gopkg.lock generated
View File

@ -17,6 +17,14 @@
revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75" revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75"
version = "v1.0" version = "v1.0"
[[projects]]
digest = "1:274f67cb6fed9588ea2521ecdac05a6d62a8c51c074c1fccc6a49a40ba80e925"
name = "github.com/satori/go.uuid"
packages = ["."]
pruneopts = "UT"
revision = "f58768cc1a7a7e77a3bd49e98cdd21419399b6a3"
version = "v1.2.0"
[[projects]] [[projects]]
digest = "1:645cabccbb4fa8aab25a956cbcbdf6a6845ca736b2c64e197ca7cbb9d210b939" digest = "1:645cabccbb4fa8aab25a956cbcbdf6a6845ca736b2c64e197ca7cbb9d210b939"
name = "github.com/spf13/cobra" name = "github.com/spf13/cobra"
@ -38,6 +46,7 @@
analyzer-version = 1 analyzer-version = 1
input-imports = [ input-imports = [
"git.cryptic.systems/fh-trier/go-flucky-server/pkg/types", "git.cryptic.systems/fh-trier/go-flucky-server/pkg/types",
"github.com/satori/go.uuid",
"github.com/spf13/cobra", "github.com/spf13/cobra",
] ]
solver-name = "gps-cdcl" solver-name = "gps-cdcl"

View File

@ -25,6 +25,14 @@
# unused-packages = true # unused-packages = true
[[constraint]]
branch = "master"
name = "git.cryptic.systems/fh-trier/go-flucky-server"
[[constraint]]
name = "github.com/satori/go.uuid"
version = "1.2.0"
[[constraint]] [[constraint]]
name = "github.com/spf13/cobra" name = "github.com/spf13/cobra"
version = "0.0.3" version = "0.0.3"

View File

@ -1,11 +1,11 @@
VERSION ?= "$(shell git rev-parse --short HEAD)-git" VERSION ?= "$(shell git rev-parse --short HEAD)-git"
go-build-arm7:
GOOS=linux GOARCH=arm GOARM=7 go build -o flucky -ldflags "-X main.version=${VERSION}"
go-build-amd: go-build-amd:
go build -o flucky -ldflags "-X main.version=${VERSION}" go build -o flucky -ldflags "-X main.version=${VERSION}"
go-build-arm7:
GOOS=linux GOARCH=arm GOARM=7 go build -o flucky -ldflags "-X main.version=${VERSION}"
pi-copy: go-build-arm7 pi-copy: go-build-arm7
scp flucky hades:/usr/local/bin scp flucky hades:/usr/local/bin
ssh hades 'chmod +x /usr/local/bin/flucky' ssh hades 'chmod +x /usr/local/bin/flucky'

View File

@ -1,10 +1,13 @@
package cmd package cmd
import ( import (
"git.cryptic.systems/fh-trier/go-flucky/cmd/temperature" "git.cryptic.systems/fh-trier/go-flucky/cmd/config"
"git.cryptic.systems/fh-trier/go-flucky/cmd/remote"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
var configDir string
var rootCmd = &cobra.Command{ var rootCmd = &cobra.Command{
Use: "flucky", Use: "flucky",
Short: "Read from sensors", Short: "Read from sensors",
@ -14,7 +17,11 @@ var rootCmd = &cobra.Command{
func Execute(version string) { func Execute(version string) {
rootCmd.Version = version rootCmd.Version = version
temperature.InitCmd(rootCmd) rootCmd.PersistentFlags().StringVarP(&configDir, "config", "c", "/etc/flucky", "The base directory for all configuration files.")
config.InitCmd(rootCmd, configDir)
remote.InitCmd(rootCmd, configDir)
//temperature.InitCmd(rootCmd)
rootCmd.Execute() rootCmd.Execute()
} }

19
cmd/config/config.go Normal file
View File

@ -0,0 +1,19 @@
package config
import (
"github.com/spf13/cobra"
)
var configDir string
var configCmd = &cobra.Command{
Use: "config",
Short: "config",
}
func InitCmd(cmd *cobra.Command, c string) {
configDir = c
cmd.AddCommand(configCmd)
}

26
cmd/config/create.go Normal file
View File

@ -0,0 +1,26 @@
package config
import (
"log"
"git.cryptic.systems/fh-trier/go-flucky/pkg/config"
"github.com/spf13/cobra"
)
var force bool
var createConfigCmd = &cobra.Command{
Use: "create",
Short: "create",
Run: func(cmd *cobra.Command, args []string) {
if err := config.Create(configDir, force); err != nil {
log.Fatal(err)
}
},
}
func init() {
configCmd.AddCommand(createConfigCmd)
createConfigCmd.Flags().BoolVarP(&force, "force", "f", false, "Force the creation of a new configuration")
}

30
cmd/remote/add.go Normal file
View File

@ -0,0 +1,30 @@
package remote
import (
"log"
"git.cryptic.systems/fh-trier/go-flucky/pkg/remote"
"git.cryptic.systems/fh-trier/go-flucky/pkg/types"
"github.com/spf13/cobra"
)
var addRemoteCmd = &cobra.Command{
Use: "add",
Short: "add",
Args: cobra.ExactArgs(2),
Run: func(cmd *cobra.Command, args []string) {
remoteObject := types.Remote{
Name: args[0],
Address: args[1],
}
if err := remote.Add(&remoteObject, configDir); err != nil {
log.Fatal(err)
}
},
}
func init() {
remoteCmd.AddCommand(addRemoteCmd)
}

24
cmd/remote/list.go Normal file
View File

@ -0,0 +1,24 @@
package remote
import (
"log"
"os"
"git.cryptic.systems/fh-trier/go-flucky/pkg/remote"
"github.com/spf13/cobra"
)
var listRemoteCmd = &cobra.Command{
Use: "list",
Short: "list",
Run: func(cmd *cobra.Command, args []string) {
if err := remote.List(os.Stdout, configDir); err != nil {
log.Fatal(err)
}
},
}
func init() {
remoteCmd.AddCommand(listRemoteCmd)
}

23
cmd/remote/register.go Normal file
View File

@ -0,0 +1,23 @@
package remote
import (
"log"
"git.cryptic.systems/fh-trier/go-flucky/pkg/remote"
"github.com/spf13/cobra"
)
var registerRemoteCmd = &cobra.Command{
Use: "register",
Short: "register on remote servers",
Run: func(cmd *cobra.Command, args []string) {
if err := remote.SendDevice(configDir); err != nil {
log.Fatal(err)
}
},
}
func init() {
remoteCmd.AddCommand(registerRemoteCmd)
}

18
cmd/remote/remote.go Normal file
View File

@ -0,0 +1,18 @@
package remote
import (
"github.com/spf13/cobra"
)
var configDir string
var remoteCmd = &cobra.Command{
Use: "remote",
Short: "remote",
}
func InitCmd(cmd *cobra.Command, c string) {
configDir = c
cmd.AddCommand(remoteCmd)
}

33
cmd/remote/remove.go Normal file
View File

@ -0,0 +1,33 @@
package remote
import (
"log"
"git.cryptic.systems/fh-trier/go-flucky/pkg/remote"
"github.com/spf13/cobra"
)
var all bool
var removeRemoteCmd = &cobra.Command{
Use: "remove",
Short: "remove",
Args: cobra.RangeArgs(0, 1),
Run: func(cmd *cobra.Command, args []string) {
if all {
if err := remote.RemoveAll(configDir); err != nil {
log.Fatal(err)
}
} else {
if err := remote.Remove(args[0], configDir); err != nil {
log.Fatal(err)
}
}
},
}
func init() {
remoteCmd.AddCommand(removeRemoteCmd)
removeRemoteCmd.Flags().BoolVarP(&all, "all", "a", false, "Select all remote connections")
}

25
cmd/temperature/get.go Normal file
View File

@ -0,0 +1,25 @@
package remote
import (
"log"
"os"
"git.cryptic.systems/fh-trier/go-flucky/pkg/temperature"
"github.com/spf13/cobra"
)
var getTemperatureCmd = &cobra.Command{
Use: "get",
Short: "get temperature from sensor",
// Args: cobra.ExactArgs(2),
Run: func(cmd *cobra.Command, args []string) {
if err := temperature.Get(os.Stdout); err != nil {
log.Fatal(err)
}
},
}
func init() {
temperatureCmd.AddCommand(getTemperatureCmd)
}

View File

@ -1,24 +1,16 @@
package temperature package remote
import ( import (
"log"
"os"
"git.cryptic.systems/fh-trier/go-flucky/pkg/temperature"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
var temperatureCmd = &cobra.Command{ var temperatureCmd = &cobra.Command{
Use: "temperature", Use: "temperature",
Short: "temperature", Short: "Read temperature from sensor",
Run: func(cmd *cobra.Command, args []string) {
if err := temperature.Print(os.Stdout); err != nil {
log.Fatal(err)
}
},
} }
func InitCmd(cmd *cobra.Command) { // Execute a
func Init(cmd *cobra.Command) {
cmd.AddCommand(temperatureCmd) cmd.AddCommand(temperatureCmd)

99
pkg/config/config.go Normal file
View File

@ -0,0 +1,99 @@
package config
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"github.com/satori/go.uuid"
"git.cryptic.systems/fh-trier/go-flucky/pkg/types"
)
var configFilename = "config.json"
func Create(configDir string, force bool) error {
configPath := filepath.Join(configDir, configFilename)
config := &types.Config{
DeviceID: uuid.NewV4().String(),
}
// If no config file exists, create a new one on the location
if !force {
if _, err := os.Stat(configPath); !os.IsNotExist(err) {
return fmt.Errorf("%v already exists. Use -f to overwrite", configPath)
}
}
if _, err := os.Stat(configPath); os.IsNotExist(err) {
err := os.MkdirAll(configDir, os.ModePerm)
if err != nil {
return fmt.Errorf("Can not create directory: %v", err)
}
}
f, err := os.Create(configPath)
if err != nil {
return fmt.Errorf("Can not create config: %v", err)
}
defer f.Close()
config.JSONWriter(f)
return nil
}
func Read(configDir string) (*types.Config, error) {
configPath := filepath.Join(configDir, configFilename)
var config types.Config
// If no config file exists, create a new one on the location
if _, err := os.Stat(configPath); os.IsNotExist(err) {
return nil, fmt.Errorf("Can not find config %v: %v", configPath, err)
}
// open config file
jsonFile, err := os.Open(configPath)
if err != nil {
return nil, fmt.Errorf("Can not open file %v: %v", configPath, err)
}
defer jsonFile.Close()
jsonParser := json.NewDecoder(jsonFile)
if err := jsonParser.Decode(&config); err != nil {
return nil, err
}
return &config, nil
}
func Write(config *types.Config, configDir string) error {
configPath := filepath.Join(configDir, configFilename)
// If no config file exists, create a new one on the location
if _, err := os.Stat(configPath); os.IsNotExist(err) {
return fmt.Errorf("Can not find config %v: %v", configPath, err)
}
// open config file
jsonFile, err := os.Create(configPath)
if err != nil {
return fmt.Errorf("Can not open file %v: %v", configPath, err)
}
defer jsonFile.Close()
err = config.JSONWriter(jsonFile)
if err != nil {
return err
}
return nil
}

167
pkg/remote/remote.go Normal file
View File

@ -0,0 +1,167 @@
package remote
import (
"bytes"
"fmt"
"io"
"net/http"
"text/tabwriter"
stypes "git.cryptic.systems/fh-trier/go-flucky-server/pkg/types"
"git.cryptic.systems/fh-trier/go-flucky/pkg/config"
"git.cryptic.systems/fh-trier/go-flucky/pkg/types"
)
func Add(remote *types.Remote, configDir string) error {
configuration, err := config.Read(configDir)
if err != nil {
return err
}
// search after duplicate remote_names
for _, r := range configuration.Remotes {
if r.Name == remote.Name {
return fmt.Errorf("Remote-Name %v already exists", remote.Name)
}
}
configuration.Remotes = append(configuration.Remotes, remote)
if err := config.Write(configuration, configDir); err != nil {
return err
}
return nil
}
func List(w io.Writer, configDir string) error {
configuration, err := config.Read(configDir)
if err != nil {
return err
}
tw := tabwriter.NewWriter(w, 0, 0, 5, ' ', 0)
fmt.Fprint(tw, "name\taddress\n")
for _, remote := range configuration.Remotes {
fmt.Fprintf(tw, "%v\t%v\n", remote.Name, remote.Address)
}
tw.Flush()
return nil
}
func Remove(name string, configDir string) error {
con, err := config.Read(configDir)
if err != nil {
return err
}
var j int
for _, remote := range con.Remotes {
if remote.Name == name {
con.Remotes = append(con.Remotes[:j], con.Remotes[j+1:]...)
if j > 0 {
j = j - 1
}
continue
}
j++
}
if err := config.Write(con, configDir); err != nil {
return err
}
return nil
}
func RemoveAll(configDir string) error {
con, err := config.Read(configDir)
if err != nil {
return err
}
con.Remotes = nil
if err := config.Write(con, configDir); err != nil {
return err
}
return nil
}
func SendTemperature(temperature *stypes.Temperature, configDir string) error {
con, err := config.Read(configDir)
if err != nil {
return err
}
var buffer bytes.Buffer
temperature.EncodeToJSON(&buffer)
for _, remote := range con.Remotes {
requestURL := fmt.Sprintf("%s%s", remote.Address, "/temperatures")
req, err := http.NewRequest("POST", requestURL, &buffer)
if err != nil {
return err
}
client := http.Client{}
resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode < 200 || resp.StatusCode > 299 {
return fmt.Errorf("Invalid HTTP-Statuscode - expected 200, got %d", resp.StatusCode)
}
}
return nil
}
// SendDevice ..
func SendDevice(configDir string) error {
con, err := config.Read(configDir)
if err != nil {
return err
}
device := new(stypes.Device)
device.DeviceID = con.DeviceID
var buffer bytes.Buffer
device.EncodeToJSON(&buffer)
for _, remote := range con.Remotes {
requestURL := fmt.Sprintf("%s%s", remote.Address, "/devices")
req, err := http.NewRequest("POST", requestURL, &buffer)
if err != nil {
return err
}
client := http.Client{}
resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode < 200 || resp.StatusCode > 299 {
return fmt.Errorf("Invalid HTTP-Statuscode - expected 200, got %d", resp.StatusCode)
}
}
return nil
}

View File

@ -1,50 +1,10 @@
package temperature package temperature
import ( import (
"bytes"
"fmt"
"io" "io"
"net/http"
"git.cryptic.systems/fh-trier/go-flucky-server/pkg/types"
) )
func Print(w io.Writer) error { func Get(w io.Writer) error {
t := types.Temperature{
TemperatureID: "1",
TemperatureValue: "22.5",
TemperatureDate: "2018-10-15T23:31:28.132417Z",
DeviceID: "510abdfb-3d0d-4248-b0e5-94ee962c2532",
}
err := postTemperature(&t)
if err != nil {
return err
}
return nil
}
func postTemperature(temperature *types.Temperature) error {
var buffer bytes.Buffer
temperature.EncodeToJSON(&buffer)
requestURL := fmt.Sprintf("%s://%s%s", "https", "flucky.cryptic.systems", "/temperatures")
req, err := http.NewRequest("POST", requestURL, &buffer)
if err != nil {
return err
}
client := http.Client{}
resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode < 200 || resp.StatusCode > 299 {
return fmt.Errorf("Invalid HTTP-Statuscode - expected 200, got %d", resp.StatusCode)
}
return nil return nil
} }

48
pkg/types/types.go Normal file
View File

@ -0,0 +1,48 @@
package types
import (
"bytes"
"encoding/json"
"fmt"
"io"
)
type Config struct {
DeviceID string `json:"device_id"`
Remotes []*Remote `json:"remotes"`
}
func (c *Config) ToJSON() (string, error) {
var b bytes.Buffer
err := c.JSONWriter(&b)
if err != nil {
return "", err
}
return b.String(), nil
}
// JSONWriter needs a writer to write the struct into json string
func (c *Config) JSONWriter(w io.Writer) error {
encoder := json.NewEncoder(w)
encoder.SetIndent("", " ")
err := encoder.Encode(&c)
if err != nil {
return fmt.Errorf("Error in encoding struct to json: %v", err)
}
return nil
}
// JSONDecoder decode a json string from a reader into a struct
func (c *Config) JSONDecoder(r io.Reader) error {
jsonDecoder := json.NewDecoder(r)
if err := jsonDecoder.Decode(&c); err != nil {
return fmt.Errorf("Can not unmarshal JSON: %v", err)
}
return nil
}
type Remote struct {
Name string `json:"remote_name"`
Address string `json:"remote_address"`
}

23
vendor/github.com/satori/go.uuid/.travis.yml generated vendored Normal file
View File

@ -0,0 +1,23 @@
language: go
sudo: false
go:
- 1.2
- 1.3
- 1.4
- 1.5
- 1.6
- 1.7
- 1.8
- 1.9
- tip
matrix:
allow_failures:
- go: tip
fast_finish: true
before_install:
- go get github.com/mattn/goveralls
- go get golang.org/x/tools/cmd/cover
script:
- $HOME/gopath/bin/goveralls -service=travis-ci
notifications:
email: false

20
vendor/github.com/satori/go.uuid/LICENSE generated vendored Normal file
View File

@ -0,0 +1,20 @@
Copyright (C) 2013-2018 by Maxim Bublis <b@codemonkey.ru>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

65
vendor/github.com/satori/go.uuid/README.md generated vendored Normal file
View File

@ -0,0 +1,65 @@
# UUID package for Go language
[![Build Status](https://travis-ci.org/satori/go.uuid.png?branch=master)](https://travis-ci.org/satori/go.uuid)
[![Coverage Status](https://coveralls.io/repos/github/satori/go.uuid/badge.svg?branch=master)](https://coveralls.io/github/satori/go.uuid)
[![GoDoc](http://godoc.org/github.com/satori/go.uuid?status.png)](http://godoc.org/github.com/satori/go.uuid)
This package provides pure Go implementation of Universally Unique Identifier (UUID). Supported both creation and parsing of UUIDs.
With 100% test coverage and benchmarks out of box.
Supported versions:
* Version 1, based on timestamp and MAC address (RFC 4122)
* Version 2, based on timestamp, MAC address and POSIX UID/GID (DCE 1.1)
* Version 3, based on MD5 hashing (RFC 4122)
* Version 4, based on random numbers (RFC 4122)
* Version 5, based on SHA-1 hashing (RFC 4122)
## Installation
Use the `go` command:
$ go get github.com/satori/go.uuid
## Requirements
UUID package requires Go >= 1.2.
## Example
```go
package main
import (
"fmt"
"github.com/satori/go.uuid"
)
func main() {
// Creating UUID Version 4
u1 := uuid.NewV4()
fmt.Printf("UUIDv4: %s\n", u1)
// Parsing UUID from string input
u2, err := uuid.FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
if err != nil {
fmt.Printf("Something gone wrong: %s", err)
}
fmt.Printf("Successfully parsed: %s", u2)
}
```
## Documentation
[Documentation](http://godoc.org/github.com/satori/go.uuid) is hosted at GoDoc project.
## Links
* [RFC 4122](http://tools.ietf.org/html/rfc4122)
* [DCE 1.1: Authentication and Security Services](http://pubs.opengroup.org/onlinepubs/9696989899/chap5.htm#tagcjh_08_02_01_01)
## Copyright
Copyright (C) 2013-2018 by Maxim Bublis <b@codemonkey.ru>.
UUID package released under MIT License.
See [LICENSE](https://github.com/satori/go.uuid/blob/master/LICENSE) for details.

206
vendor/github.com/satori/go.uuid/codec.go generated vendored Normal file
View File

@ -0,0 +1,206 @@
// Copyright (C) 2013-2018 by Maxim Bublis <b@codemonkey.ru>
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package uuid
import (
"bytes"
"encoding/hex"
"fmt"
)
// FromBytes returns UUID converted from raw byte slice input.
// It will return error if the slice isn't 16 bytes long.
func FromBytes(input []byte) (u UUID, err error) {
err = u.UnmarshalBinary(input)
return
}
// FromBytesOrNil returns UUID converted from raw byte slice input.
// Same behavior as FromBytes, but returns a Nil UUID on error.
func FromBytesOrNil(input []byte) UUID {
uuid, err := FromBytes(input)
if err != nil {
return Nil
}
return uuid
}
// FromString returns UUID parsed from string input.
// Input is expected in a form accepted by UnmarshalText.
func FromString(input string) (u UUID, err error) {
err = u.UnmarshalText([]byte(input))
return
}
// FromStringOrNil returns UUID parsed from string input.
// Same behavior as FromString, but returns a Nil UUID on error.
func FromStringOrNil(input string) UUID {
uuid, err := FromString(input)
if err != nil {
return Nil
}
return uuid
}
// MarshalText implements the encoding.TextMarshaler interface.
// The encoding is the same as returned by String.
func (u UUID) MarshalText() (text []byte, err error) {
text = []byte(u.String())
return
}
// UnmarshalText implements the encoding.TextUnmarshaler interface.
// Following formats are supported:
// "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
// "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}",
// "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8"
// "6ba7b8109dad11d180b400c04fd430c8"
// ABNF for supported UUID text representation follows:
// uuid := canonical | hashlike | braced | urn
// plain := canonical | hashlike
// canonical := 4hexoct '-' 2hexoct '-' 2hexoct '-' 6hexoct
// hashlike := 12hexoct
// braced := '{' plain '}'
// urn := URN ':' UUID-NID ':' plain
// URN := 'urn'
// UUID-NID := 'uuid'
// 12hexoct := 6hexoct 6hexoct
// 6hexoct := 4hexoct 2hexoct
// 4hexoct := 2hexoct 2hexoct
// 2hexoct := hexoct hexoct
// hexoct := hexdig hexdig
// hexdig := '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' |
// 'a' | 'b' | 'c' | 'd' | 'e' | 'f' |
// 'A' | 'B' | 'C' | 'D' | 'E' | 'F'
func (u *UUID) UnmarshalText(text []byte) (err error) {
switch len(text) {
case 32:
return u.decodeHashLike(text)
case 36:
return u.decodeCanonical(text)
case 38:
return u.decodeBraced(text)
case 41:
fallthrough
case 45:
return u.decodeURN(text)
default:
return fmt.Errorf("uuid: incorrect UUID length: %s", text)
}
}
// decodeCanonical decodes UUID string in format
// "6ba7b810-9dad-11d1-80b4-00c04fd430c8".
func (u *UUID) decodeCanonical(t []byte) (err error) {
if t[8] != '-' || t[13] != '-' || t[18] != '-' || t[23] != '-' {
return fmt.Errorf("uuid: incorrect UUID format %s", t)
}
src := t[:]
dst := u[:]
for i, byteGroup := range byteGroups {
if i > 0 {
src = src[1:] // skip dash
}
_, err = hex.Decode(dst[:byteGroup/2], src[:byteGroup])
if err != nil {
return
}
src = src[byteGroup:]
dst = dst[byteGroup/2:]
}
return
}
// decodeHashLike decodes UUID string in format
// "6ba7b8109dad11d180b400c04fd430c8".
func (u *UUID) decodeHashLike(t []byte) (err error) {
src := t[:]
dst := u[:]
if _, err = hex.Decode(dst, src); err != nil {
return err
}
return
}
// decodeBraced decodes UUID string in format
// "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}" or in format
// "{6ba7b8109dad11d180b400c04fd430c8}".
func (u *UUID) decodeBraced(t []byte) (err error) {
l := len(t)
if t[0] != '{' || t[l-1] != '}' {
return fmt.Errorf("uuid: incorrect UUID format %s", t)
}
return u.decodePlain(t[1 : l-1])
}
// decodeURN decodes UUID string in format
// "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8" or in format
// "urn:uuid:6ba7b8109dad11d180b400c04fd430c8".
func (u *UUID) decodeURN(t []byte) (err error) {
total := len(t)
urn_uuid_prefix := t[:9]
if !bytes.Equal(urn_uuid_prefix, urnPrefix) {
return fmt.Errorf("uuid: incorrect UUID format: %s", t)
}
return u.decodePlain(t[9:total])
}
// decodePlain decodes UUID string in canonical format
// "6ba7b810-9dad-11d1-80b4-00c04fd430c8" or in hash-like format
// "6ba7b8109dad11d180b400c04fd430c8".
func (u *UUID) decodePlain(t []byte) (err error) {
switch len(t) {
case 32:
return u.decodeHashLike(t)
case 36:
return u.decodeCanonical(t)
default:
return fmt.Errorf("uuid: incorrrect UUID length: %s", t)
}
}
// MarshalBinary implements the encoding.BinaryMarshaler interface.
func (u UUID) MarshalBinary() (data []byte, err error) {
data = u.Bytes()
return
}
// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface.
// It will return error if the slice isn't 16 bytes long.
func (u *UUID) UnmarshalBinary(data []byte) (err error) {
if len(data) != Size {
err = fmt.Errorf("uuid: UUID must be exactly 16 bytes long, got %d bytes", len(data))
return
}
copy(u[:], data)
return
}

239
vendor/github.com/satori/go.uuid/generator.go generated vendored Normal file
View File

@ -0,0 +1,239 @@
// Copyright (C) 2013-2018 by Maxim Bublis <b@codemonkey.ru>
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package uuid
import (
"crypto/md5"
"crypto/rand"
"crypto/sha1"
"encoding/binary"
"hash"
"net"
"os"
"sync"
"time"
)
// Difference in 100-nanosecond intervals between
// UUID epoch (October 15, 1582) and Unix epoch (January 1, 1970).
const epochStart = 122192928000000000
var (
global = newDefaultGenerator()
epochFunc = unixTimeFunc
posixUID = uint32(os.Getuid())
posixGID = uint32(os.Getgid())
)
// NewV1 returns UUID based on current timestamp and MAC address.
func NewV1() UUID {
return global.NewV1()
}
// NewV2 returns DCE Security UUID based on POSIX UID/GID.
func NewV2(domain byte) UUID {
return global.NewV2(domain)
}
// NewV3 returns UUID based on MD5 hash of namespace UUID and name.
func NewV3(ns UUID, name string) UUID {
return global.NewV3(ns, name)
}
// NewV4 returns random generated UUID.
func NewV4() UUID {
return global.NewV4()
}
// NewV5 returns UUID based on SHA-1 hash of namespace UUID and name.
func NewV5(ns UUID, name string) UUID {
return global.NewV5(ns, name)
}
// Generator provides interface for generating UUIDs.
type Generator interface {
NewV1() UUID
NewV2(domain byte) UUID
NewV3(ns UUID, name string) UUID
NewV4() UUID
NewV5(ns UUID, name string) UUID
}
// Default generator implementation.
type generator struct {
storageOnce sync.Once
storageMutex sync.Mutex
lastTime uint64
clockSequence uint16
hardwareAddr [6]byte
}
func newDefaultGenerator() Generator {
return &generator{}
}
// NewV1 returns UUID based on current timestamp and MAC address.
func (g *generator) NewV1() UUID {
u := UUID{}
timeNow, clockSeq, hardwareAddr := g.getStorage()
binary.BigEndian.PutUint32(u[0:], uint32(timeNow))
binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32))
binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48))
binary.BigEndian.PutUint16(u[8:], clockSeq)
copy(u[10:], hardwareAddr)
u.SetVersion(V1)
u.SetVariant(VariantRFC4122)
return u
}
// NewV2 returns DCE Security UUID based on POSIX UID/GID.
func (g *generator) NewV2(domain byte) UUID {
u := UUID{}
timeNow, clockSeq, hardwareAddr := g.getStorage()
switch domain {
case DomainPerson:
binary.BigEndian.PutUint32(u[0:], posixUID)
case DomainGroup:
binary.BigEndian.PutUint32(u[0:], posixGID)
}
binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32))
binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48))
binary.BigEndian.PutUint16(u[8:], clockSeq)
u[9] = domain
copy(u[10:], hardwareAddr)
u.SetVersion(V2)
u.SetVariant(VariantRFC4122)
return u
}
// NewV3 returns UUID based on MD5 hash of namespace UUID and name.
func (g *generator) NewV3(ns UUID, name string) UUID {
u := newFromHash(md5.New(), ns, name)
u.SetVersion(V3)
u.SetVariant(VariantRFC4122)
return u
}
// NewV4 returns random generated UUID.
func (g *generator) NewV4() UUID {
u := UUID{}
g.safeRandom(u[:])
u.SetVersion(V4)
u.SetVariant(VariantRFC4122)
return u
}
// NewV5 returns UUID based on SHA-1 hash of namespace UUID and name.
func (g *generator) NewV5(ns UUID, name string) UUID {
u := newFromHash(sha1.New(), ns, name)
u.SetVersion(V5)
u.SetVariant(VariantRFC4122)
return u
}
func (g *generator) initStorage() {
g.initClockSequence()
g.initHardwareAddr()
}
func (g *generator) initClockSequence() {
buf := make([]byte, 2)
g.safeRandom(buf)
g.clockSequence = binary.BigEndian.Uint16(buf)
}
func (g *generator) initHardwareAddr() {
interfaces, err := net.Interfaces()
if err == nil {
for _, iface := range interfaces {
if len(iface.HardwareAddr) >= 6 {
copy(g.hardwareAddr[:], iface.HardwareAddr)
return
}
}
}
// Initialize hardwareAddr randomly in case
// of real network interfaces absence
g.safeRandom(g.hardwareAddr[:])
// Set multicast bit as recommended in RFC 4122
g.hardwareAddr[0] |= 0x01
}
func (g *generator) safeRandom(dest []byte) {
if _, err := rand.Read(dest); err != nil {
panic(err)
}
}
// Returns UUID v1/v2 storage state.
// Returns epoch timestamp, clock sequence, and hardware address.
func (g *generator) getStorage() (uint64, uint16, []byte) {
g.storageOnce.Do(g.initStorage)
g.storageMutex.Lock()
defer g.storageMutex.Unlock()
timeNow := epochFunc()
// Clock changed backwards since last UUID generation.
// Should increase clock sequence.
if timeNow <= g.lastTime {
g.clockSequence++
}
g.lastTime = timeNow
return timeNow, g.clockSequence, g.hardwareAddr[:]
}
// Returns difference in 100-nanosecond intervals between
// UUID epoch (October 15, 1582) and current time.
// This is default epoch calculation function.
func unixTimeFunc() uint64 {
return epochStart + uint64(time.Now().UnixNano()/100)
}
// Returns UUID based on hashing of namespace UUID and name.
func newFromHash(h hash.Hash, ns UUID, name string) UUID {
u := UUID{}
h.Write(ns[:])
h.Write([]byte(name))
copy(u[:], h.Sum(nil))
return u
}

78
vendor/github.com/satori/go.uuid/sql.go generated vendored Normal file
View File

@ -0,0 +1,78 @@
// Copyright (C) 2013-2018 by Maxim Bublis <b@codemonkey.ru>
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package uuid
import (
"database/sql/driver"
"fmt"
)
// Value implements the driver.Valuer interface.
func (u UUID) Value() (driver.Value, error) {
return u.String(), nil
}
// Scan implements the sql.Scanner interface.
// A 16-byte slice is handled by UnmarshalBinary, while
// a longer byte slice or a string is handled by UnmarshalText.
func (u *UUID) Scan(src interface{}) error {
switch src := src.(type) {
case []byte:
if len(src) == Size {
return u.UnmarshalBinary(src)
}
return u.UnmarshalText(src)
case string:
return u.UnmarshalText([]byte(src))
}
return fmt.Errorf("uuid: cannot convert %T to UUID", src)
}
// NullUUID can be used with the standard sql package to represent a
// UUID value that can be NULL in the database
type NullUUID struct {
UUID UUID
Valid bool
}
// Value implements the driver.Valuer interface.
func (u NullUUID) Value() (driver.Value, error) {
if !u.Valid {
return nil, nil
}
// Delegate to UUID Value function
return u.UUID.Value()
}
// Scan implements the sql.Scanner interface.
func (u *NullUUID) Scan(src interface{}) error {
if src == nil {
u.UUID, u.Valid = Nil, false
return nil
}
// Delegate to UUID Scan function
u.Valid = true
return u.UUID.Scan(src)
}

161
vendor/github.com/satori/go.uuid/uuid.go generated vendored Normal file
View File

@ -0,0 +1,161 @@
// Copyright (C) 2013-2018 by Maxim Bublis <b@codemonkey.ru>
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// Package uuid provides implementation of Universally Unique Identifier (UUID).
// Supported versions are 1, 3, 4 and 5 (as specified in RFC 4122) and
// version 2 (as specified in DCE 1.1).
package uuid
import (
"bytes"
"encoding/hex"
)
// Size of a UUID in bytes.
const Size = 16
// UUID representation compliant with specification
// described in RFC 4122.
type UUID [Size]byte
// UUID versions
const (
_ byte = iota
V1
V2
V3
V4
V5
)
// UUID layout variants.
const (
VariantNCS byte = iota
VariantRFC4122
VariantMicrosoft
VariantFuture
)
// UUID DCE domains.
const (
DomainPerson = iota
DomainGroup
DomainOrg
)
// String parse helpers.
var (
urnPrefix = []byte("urn:uuid:")
byteGroups = []int{8, 4, 4, 4, 12}
)
// Nil is special form of UUID that is specified to have all
// 128 bits set to zero.
var Nil = UUID{}
// Predefined namespace UUIDs.
var (
NamespaceDNS = Must(FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8"))
NamespaceURL = Must(FromString("6ba7b811-9dad-11d1-80b4-00c04fd430c8"))
NamespaceOID = Must(FromString("6ba7b812-9dad-11d1-80b4-00c04fd430c8"))
NamespaceX500 = Must(FromString("6ba7b814-9dad-11d1-80b4-00c04fd430c8"))
)
// Equal returns true if u1 and u2 equals, otherwise returns false.
func Equal(u1 UUID, u2 UUID) bool {
return bytes.Equal(u1[:], u2[:])
}
// Version returns algorithm version used to generate UUID.
func (u UUID) Version() byte {
return u[6] >> 4
}
// Variant returns UUID layout variant.
func (u UUID) Variant() byte {
switch {
case (u[8] >> 7) == 0x00:
return VariantNCS
case (u[8] >> 6) == 0x02:
return VariantRFC4122
case (u[8] >> 5) == 0x06:
return VariantMicrosoft
case (u[8] >> 5) == 0x07:
fallthrough
default:
return VariantFuture
}
}
// Bytes returns bytes slice representation of UUID.
func (u UUID) Bytes() []byte {
return u[:]
}
// Returns canonical string representation of UUID:
// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.
func (u UUID) String() string {
buf := make([]byte, 36)
hex.Encode(buf[0:8], u[0:4])
buf[8] = '-'
hex.Encode(buf[9:13], u[4:6])
buf[13] = '-'
hex.Encode(buf[14:18], u[6:8])
buf[18] = '-'
hex.Encode(buf[19:23], u[8:10])
buf[23] = '-'
hex.Encode(buf[24:], u[10:])
return string(buf)
}
// SetVersion sets version bits.
func (u *UUID) SetVersion(v byte) {
u[6] = (u[6] & 0x0f) | (v << 4)
}
// SetVariant sets variant bits.
func (u *UUID) SetVariant(v byte) {
switch v {
case VariantNCS:
u[8] = (u[8]&(0xff>>1) | (0x00 << 7))
case VariantRFC4122:
u[8] = (u[8]&(0xff>>2) | (0x02 << 6))
case VariantMicrosoft:
u[8] = (u[8]&(0xff>>3) | (0x06 << 5))
case VariantFuture:
fallthrough
default:
u[8] = (u[8]&(0xff>>3) | (0x07 << 5))
}
}
// Must is a helper that wraps a call to a function returning (UUID, error)
// and panics if the error is non-nil. It is intended for use in variable
// initializations such as
// var packageUUID = uuid.Must(uuid.FromString("123e4567-e89b-12d3-a456-426655440000"));
func Must(u UUID, err error) UUID {
if err != nil {
panic(err)
}
return u
}