[REV] merge branch 3.7 to master

This commit is contained in:
barnettZQG 2018-10-08 12:25:05 +08:00
commit 1dc22cc25c
78 changed files with 4097 additions and 150 deletions

View File

@ -1 +1 @@
53f4fc0a87a3c74370c4c2d51b28546628bcab308d25d8cebaa32ecb3b773a3a
003620d97ecf10a5d0b1542ea0e21a8db2c2ee38ad9691e99afbdecc5049269d

View File

@ -33,7 +33,7 @@ pkg:
run:build
ifeq ($(WHAT),api)
${BIN_PATH}/${BASE_NAME}-api --log-level=debug \
--mysql="root:admin@tcp(127.0.0.1:3306)/region" \
--mysql="root:@tcp(127.0.0.1:3306)/region" \
--kube-config="`PWD`/test/admin.kubeconfig" \
--api-ssl-enable=true \
--client-ca-file="`PWD`/test/ssl/ca.pem" \

View File

@ -143,6 +143,7 @@ type AppInterface interface {
ExportApp(w http.ResponseWriter, r *http.Request)
Download(w http.ResponseWriter, r *http.Request)
Upload(w http.ResponseWriter, r *http.Request)
NewUpload(w http.ResponseWriter, r *http.Request)
ImportID(w http.ResponseWriter, r *http.Request)
ImportApp(w http.ResponseWriter, r *http.Request)
}

View File

@ -236,7 +236,8 @@ func (v2 *V2) appRouter() chi.Router {
r.Get("/export/{eventId}", controller.GetManager().ExportApp)
r.Get("/download/{format}/{fileName}", controller.GetManager().Download)
r.Post("/upload", controller.GetManager().Upload)
r.Post("/upload/{event_id}", controller.GetManager().NewUpload)
r.Options("/upload/{event_id}", controller.GetManager().NewUpload)
r.Post("/import/ids/{eventId}", controller.GetManager().ImportID)
r.Get("/import/ids/{eventId}", controller.GetManager().ImportID)

View File

@ -47,6 +47,7 @@ func LogRoutes() chi.Router {
func AppRoutes() chi.Router {
r := chi.NewRouter()
r.Get("/download/{format}/{fileName}", controller.GetManager().Download)
r.Post("/upload", controller.GetManager().Upload)
r.Post("/upload/{event_id}", controller.GetManager().Upload)
r.Options("/upload/{event_id}", controller.GetManager().Upload)
return r
}

View File

@ -8,14 +8,17 @@ import (
"os"
"strings"
"io/ioutil"
"path/filepath"
"github.com/Sirupsen/logrus"
"github.com/go-chi/chi"
"github.com/goodrain/rainbond/api/handler"
"github.com/goodrain/rainbond/api/model"
"github.com/goodrain/rainbond/db"
httputil "github.com/goodrain/rainbond/util/http"
"io/ioutil"
"path/filepath"
"github.com/jinzhu/gorm"
"github.com/goodrain/rainbond/api/controller/upload"
)
type AppStruct struct{}
@ -52,13 +55,13 @@ func (a *AppStruct) ExportApp(w http.ResponseWriter, r *http.Request) {
case "GET":
eventId := strings.TrimSpace(chi.URLParam(r, "eventId"))
if eventId == "" {
httputil.ReturnError(r, w, 501, fmt.Sprintf("Arguments eventId is must defined."))
httputil.ReturnError(r, w, 400, fmt.Sprintf("Arguments eventId is must defined."))
return
}
res, err := db.GetManager().AppDao().GetByEventId(eventId)
if err != nil {
httputil.ReturnError(r, w, 502, fmt.Sprintf("Failed to query status of export app by event id %s: %v", eventId, err))
httputil.ReturnError(r, w, 404, fmt.Sprintf("Failed to query status of export app by event id %s: %v", eventId, err))
return
}
@ -72,9 +75,9 @@ func (a *AppStruct) Download(w http.ResponseWriter, r *http.Request) {
fileName := strings.TrimSpace(chi.URLParam(r, "fileName"))
tarFile := fmt.Sprintf("%s/%s/%s", handler.GetAppHandler().GetStaticDir(), format, fileName)
// return status code 502 if the file not exists.
// return status code 404 if the file not exists.
if _, err := os.Stat(tarFile); os.IsNotExist(err) {
httputil.ReturnError(r, w, 502, fmt.Sprintf("Not found export app tar file: %s", tarFile))
httputil.ReturnError(r, w, 404, fmt.Sprintf("Not found export app tar file: %s", tarFile))
return
}
@ -84,7 +87,7 @@ func (a *AppStruct) Download(w http.ResponseWriter, r *http.Request) {
func (a *AppStruct) ImportID(w http.ResponseWriter, r *http.Request) {
eventId := strings.TrimSpace(chi.URLParam(r, "eventId"))
if eventId == "" {
httputil.ReturnError(r, w, 501, "Failed to parse eventId.")
httputil.ReturnError(r, w, 400, "Failed to parse eventId.")
return
}
dirName := fmt.Sprintf("%s/import/%s", handler.GetAppHandler().GetStaticDir(), eventId)
@ -93,15 +96,25 @@ func (a *AppStruct) ImportID(w http.ResponseWriter, r *http.Request) {
case "POST":
err := os.MkdirAll(dirName, 0755)
if err != nil {
httputil.ReturnError(r, w, 502, "Failed to create directory by event id: " + err.Error())
httputil.ReturnError(r, w, 502, "Failed to create directory by event id: "+err.Error())
return
}
httputil.ReturnSuccess(r, w, map[string]string{"path": dirName})
case "GET":
_, err := os.Stat(dirName)
if err != nil {
if !os.IsExist(err) {
err := os.MkdirAll(dirName, 0755)
if err != nil {
httputil.ReturnError(r, w, 502, "Failed to create directory by event id: "+err.Error())
return
}
}
}
apps, err := ioutil.ReadDir(dirName)
if err != nil {
httputil.ReturnError(r, w, 502, "Failed to list import id in directory.")
httputil.ReturnSuccess(r, w, map[string][]string{"apps": []string{}})
return
}
@ -111,7 +124,7 @@ func (a *AppStruct) ImportID(w http.ResponseWriter, r *http.Request) {
continue
}
ex := filepath.Ext(dir.Name())
if ex != ".tar" {
if ex != ".zip" {
continue
}
appArr = append(appArr, dir.Name())
@ -121,47 +134,98 @@ func (a *AppStruct) ImportID(w http.ResponseWriter, r *http.Request) {
case "DELETE":
err := os.RemoveAll(dirName)
if err != nil {
httputil.ReturnError(r, w, 502, "Failed to delete directory by id: " + eventId)
httputil.ReturnError(r, w, 501, "Failed to delete directory by id: "+eventId)
return
}
res, err := db.GetManager().AppDao().GetByEventId(eventId)
if err != nil {
httputil.ReturnError(r, w, 404, fmt.Sprintf("Failed to query status of export app by event id %s: %v", eventId, err))
return
}
res.Status = "cleaned"
db.GetManager().AppDao().UpdateModel(res)
httputil.ReturnSuccess(r, w, "successful")
}
}
func (a *AppStruct) NewUpload(w http.ResponseWriter, r *http.Request) {
eventId := strings.TrimSpace(chi.URLParam(r, "event_id"))
switch r.Method {
case "OPTIONS":
origin := r.Header.Get("Origin")
w.Header().Add("Access-Control-Allow-Origin", origin)
w.Header().Add("Access-Control-Allow-Methods", "POST,OPTIONS")
w.Header().Add("Access-Control-Allow-Credentials", "true")
w.Header().Add("Access-Control-Allow-Headers", "x-requested-with,Content-Type,X-Custom-Header")
httputil.ReturnSuccess(r, w, nil)
case "POST":
if eventId == "" {
httputil.ReturnError(r, w, 500, "Failed to parse eventId.")
return
}
dirName := fmt.Sprintf("%s/import/%s", handler.GetAppHandler().GetStaticDir(), eventId)
st := upload.NewStorage(dirName)
st.UploadHandler(w, r)
}
}
func (a *AppStruct) Upload(w http.ResponseWriter, r *http.Request) {
eventId := r.FormValue("eventId")
if eventId == "" {
httputil.ReturnError(r, w, 500, "Failed to parse eventId.")
return
eventId := strings.TrimSpace(chi.URLParam(r, "event_id"))
switch r.Method {
case "POST":
if eventId == "" {
httputil.ReturnError(r, w, 400, "Failed to parse eventId.")
return
}
logrus.Debug("Start receive upload file: ", eventId)
reader, header, err := r.FormFile("appTarFile")
if err != nil {
logrus.Errorf("Failed to parse upload file:", err.Error())
httputil.ReturnError(r, w, 501, "Failed to parse upload file.")
return
}
defer reader.Close()
dirName := fmt.Sprintf("%s/import/%s", handler.GetAppHandler().GetStaticDir(), eventId)
os.MkdirAll(dirName, 0755)
fileName := fmt.Sprintf("%s/%s", dirName, header.Filename)
file, err := os.OpenFile(fileName, os.O_WRONLY|os.O_CREATE, 0644)
if err != nil {
logrus.Errorf("Failed to open file: ", err.Error())
httputil.ReturnError(r, w, 502, "Failed to open file: "+err.Error())
}
defer file.Close()
logrus.Debug("Start write file to: ", fileName)
if _, err := io.Copy(file, reader); err != nil {
logrus.Errorf("Failed to write file%s", err.Error())
httputil.ReturnError(r, w, 503, "Failed to write file: "+err.Error())
}
logrus.Debug("successful write file to: ", fileName)
origin := r.Header.Get("Origin")
w.Header().Add("Access-Control-Allow-Origin", origin)
w.Header().Add("Access-Control-Allow-Methods", "POST,OPTIONS")
w.Header().Add("Access-Control-Allow-Credentials", "true")
w.Header().Add("Access-Control-Allow-Headers", "x-requested-with,Content-Type,X-Custom-Header")
httputil.ReturnSuccess(r, w, nil)
case "OPTIONS":
origin := r.Header.Get("Origin")
w.Header().Add("Access-Control-Allow-Origin", origin)
w.Header().Add("Access-Control-Allow-Methods", "POST,OPTIONS")
w.Header().Add("Access-Control-Allow-Credentials", "true")
w.Header().Add("Access-Control-Allow-Headers", "x-requested-with,Content-Type,X-Custom-Header")
httputil.ReturnSuccess(r, w, nil)
}
logrus.Debug("Start receive upload file: ", eventId)
reader, header, err := r.FormFile("appTarFile")
if err != nil {
httputil.ReturnError(r, w, 501, "Failed to parse upload file.")
return
}
defer reader.Close()
dirName := fmt.Sprintf("%s/import/%s", handler.GetAppHandler().GetStaticDir(), eventId)
os.MkdirAll(dirName, 0755)
fileName := fmt.Sprintf("%s/%s", dirName, header.Filename)
file, err := os.OpenFile(fileName, os.O_WRONLY|os.O_CREATE, 0644)
if err != nil {
httputil.ReturnError(r, w, 502, "Failed to open file: "+err.Error())
}
defer file.Close()
logrus.Debug("Start write file to: ", fileName)
if _, err := io.Copy(file, reader); err != nil {
httputil.ReturnError(r, w, 503, "Failed to write file: "+err.Error())
}
logrus.Debug("successful write file to: ", fileName)
httputil.ReturnSuccess(r, w, "successful")
}
func (a *AppStruct) ImportApp(w http.ResponseWriter, r *http.Request) {
@ -197,13 +261,23 @@ func (a *AppStruct) ImportApp(w http.ResponseWriter, r *http.Request) {
case "GET":
eventId := strings.TrimSpace(chi.URLParam(r, "eventId"))
if eventId == "" {
httputil.ReturnError(r, w, 501, fmt.Sprintf("Arguments eventId is must defined."))
httputil.ReturnError(r, w, 400, fmt.Sprintf("Arguments eventId is must defined."))
return
}
res, err := db.GetManager().AppDao().GetByEventId(eventId)
if err != nil {
httputil.ReturnError(r, w, 502, fmt.Sprintf("Failed to query status of export app by event id %s: %v", eventId, err))
if err == gorm.ErrRecordNotFound {
res.Status = "uploading"
httputil.ReturnSuccess(r, w, res)
return
}
httputil.ReturnError(r, w, 500, fmt.Sprintf("Failed to query status of export app by event id %s: %v", eventId, err))
return
}
if res.Status == "cleaned" {
res.Metadata = ""
httputil.ReturnSuccess(r, w, res)
return
}
@ -223,20 +297,20 @@ func (a *AppStruct) ImportApp(w http.ResponseWriter, r *http.Request) {
case "DELETE":
eventId := strings.TrimSpace(chi.URLParam(r, "eventId"))
if eventId == "" {
httputil.ReturnError(r, w, 501, fmt.Sprintf("Arguments eventId is must defined."))
httputil.ReturnError(r, w, 400, fmt.Sprintf("Arguments eventId is must defined."))
return
}
res, err := db.GetManager().AppDao().GetByEventId(eventId)
if err != nil {
httputil.ReturnError(r, w, 502, fmt.Sprintf("Failed to query status of export app by event id %s: %v", eventId, err))
httputil.ReturnError(r, w, 404, fmt.Sprintf("Failed to query status of export app by event id %s: %v", eventId, err))
return
}
if err := db.GetManager().AppDao().DeleteModelByEventId(res.EventID);err!=nil{
if err := db.GetManager().AppDao().DeleteModelByEventId(res.EventID); err != nil {
httputil.ReturnError(r, w, 503, fmt.Sprintf("Deleting database records by event ID failed %s: %v", eventId, err))
return
}
if _, err := os.Stat(res.SourceDir); err == nil {
if err := os.RemoveAll(res.SourceDir);err != nil{
if err := os.RemoveAll(res.SourceDir); err != nil {
httputil.ReturnError(r, w, 504, fmt.Sprintf("Deleting uploading application directory failed %s : %v", res.SourceDir, err))
return
}

View File

@ -197,7 +197,6 @@ func (e *EventLogStruct) LogByAction(w http.ResponseWriter, r *http.Request) {
if !ok {
return
}
logrus.Info(elog.Body.Level)
dl, err := handler.GetEventHandler().GetLevelLog(elog.Body.EventID, elog.Body.Level)
if err != nil {
logrus.Errorf("get event log error, %v", err)

View File

@ -0,0 +1,70 @@
package upload
import (
"os"
)
// attachment contain info about directory, base mime type and all files saved.
type attachment struct {
originalFile *originalFile
Dir *dirManager
Versions map[string]fileManager
}
func create(storage string, ofile *originalFile, delChunk bool) (*attachment, error) {
dm, err := createDir(storage, ofile.BaseMime)
if err != nil {
return nil, err
}
at := &attachment{
originalFile: ofile,
Dir: dm,
Versions: make(map[string]fileManager),
}
makeVersion := func(a *attachment, version, convert string) error {
fm, err := at.createVersion(version)
if err != nil {
return err
}
at.Versions[version] = fm
return nil
}
if err := makeVersion(at, "original", ""); err != nil {
return nil, err
}
if delChunk {
return at, os.Remove(at.originalFile.Filepath)
}
return at, nil
}
// Directly save single version and return fileManager.
func (attachment *attachment) createVersion(version string) (fileManager, error) {
fm := newFileManager(attachment.Dir, version)
fm.SetFilename(attachment.originalFile)
if err := fm.convert(attachment.originalFile.Filepath); err != nil {
return nil, err
}
return fm, nil
}
func (attachment *attachment) ToJson() map[string]interface{} {
data := make(map[string]interface{})
data["type"] = attachment.originalFile.BaseMime
data["dir"] = attachment.Dir.Path
data["name"] = attachment.originalFile.Filename
versions := make(map[string]interface{})
for version, fm := range attachment.Versions {
versions[version] = fm.ToJson()
}
data["versions"] = versions
return data
}

View File

@ -0,0 +1,29 @@
package upload
import (
"io"
"mime/multipart"
"os"
)
// Upload body info.
type body struct {
XFile *os.File
body io.Reader
MR *multipart.Reader
Available bool
}
// Check exists body in xfile and return body.
func newBody(req_body io.Reader) (*body, error) {
return &body{body: req_body, Available: true}, nil
}
// Close filehandler of body if XFile exists.
func (body *body) Close() error {
if body.XFile != nil {
return body.XFile.Close()
}
return nil
}

View File

@ -0,0 +1,59 @@
package upload
import (
"math/rand"
"os"
"path/filepath"
"strconv"
"time"
)
// Directory mananger
type dirManager struct {
Root string
Path string
}
// Prepare dirManager given root, mime.
func createDir(root, mime string) (*dirManager, error) {
dm := newDirManager(root)
dm.CalcPath(mime)
if err := dm.create(); err != nil {
return nil, err
}
return dm, nil
}
// newDirManager returns a new dirManager given a root.
func newDirManager(root string) *dirManager {
return &dirManager{Root: root}
}
// Return absolute path for directory
func (dm *dirManager) Abs() string {
return filepath.Join(dm.Root, dm.Path)
}
// Create directory obtained by concatenating the root and path.
func (dm *dirManager) create() error {
return os.MkdirAll(dm.Root+dm.Path, 0755)
}
// Generate path given mime and date.
func (dm *dirManager) CalcPath(mime string) {
dm.Path = ""
}
func yearDay(t time.Time) string {
return strconv.FormatInt(int64(t.YearDay()), 36)
}
func containerName(t time.Time) string {
r := rand.New(rand.NewSource(time.Now().UnixNano())).Intn(1000)
seconds := t.Hour()*3600 + t.Minute()*60 + t.Second()
return strconv.FormatInt(int64(seconds*1000+r), 36)
}

View File

@ -0,0 +1,40 @@
package upload
import (
"os"
)
type fileDefaultManager struct {
*fileBaseManager
Size int64
}
func (fdm *fileDefaultManager) convert(src string) error {
return fdm.rawCopy(src)
}
func (fdm *fileDefaultManager) ToJson() map[string]interface{} {
return map[string]interface{}{
"url": fdm.Url(),
"filename": fdm.Filename,
"size": fdm.Size,
}
}
func (fdm *fileDefaultManager) rawCopy(src string) error {
if err := fdm.copyFile(src, fdm.Filepath()); err != nil {
return err
}
f, err := os.Open(fdm.Filepath())
if err != nil {
return err
}
fi, err := f.Stat()
if err != nil {
return err
}
fdm.Size = fi.Size()
return nil
}

View File

@ -0,0 +1,105 @@
package upload
import (
"fmt"
"io"
"os"
"path/filepath"
"time"
)
type fileManager interface {
convert(string) error
SetFilename(*originalFile)
ToJson() map[string]interface{}
}
type fileBaseManager struct {
Dir *dirManager
Version string
Filename string
}
// Return fileManager for given base mime and version.
func newFileManager(dm *dirManager, version string) fileManager {
fbm := &fileBaseManager{Dir: dm, Version: version}
fdm := &fileDefaultManager{fileBaseManager: fbm}
return fdm
}
func (fbm *fileBaseManager) SetFilename(file *originalFile) {
fbm.Filename = file.Filename
}
func (fbm *fileBaseManager) Filepath() string {
return filepath.Join(fbm.Dir.Abs(), fbm.Filename)
}
func (fbm *fileBaseManager) Url() string {
return filepath.Join(fbm.Dir.Path, fbm.Filename)
}
// copyFile copies a file from src to dst. If src and dst files exist, and are
// the same, then return success. Otherwise copy the file contents from src to dst.
func (fbm *fileBaseManager) copyFile(src, dst string) error {
sfi, err := os.Stat(src)
if err != nil {
return err
}
if !sfi.Mode().IsRegular() {
// cannot copy non-regular files (e.g., directories,
// symlinks, devices, etc.)
// FIXME
return fmt.Errorf("CopyFile: non-regular source file %s (%q)", sfi.Name(), sfi.Mode().String())
}
dfi, err := os.Stat(dst)
if err != nil {
if !os.IsNotExist(err) {
return err
}
} else {
if !(dfi.Mode().IsRegular()) {
return fmt.Errorf("CopyFile: non-regular destination file %s (%q)", dfi.Name(), dfi.Mode().String())
}
if os.SameFile(sfi, dfi) {
return err
}
}
if err := fbm.copyFileContents(src, dst); err != nil {
return err
}
return nil
}
// copyFileContents copies the contents of the file named src to the file named
// by dst. The file will be created if it does not already exist. If the
// destination file exists, all it's contents will be replaced by the contents
// of the source file.
func (fbm *fileBaseManager) copyFileContents(src, dst string) error {
var err error
in, err := os.Open(src)
if err != nil {
return err
}
defer in.Close()
out, err := os.Create(dst)
if err != nil {
return err
}
defer func() {
cerr := out.Close()
if err == nil {
err = cerr
}
}()
if _, err = io.Copy(out, in); err != nil {
return err
}
err = out.Sync()
return err
}
func seconds() int64 {
t := time.Now()
return int64(t.Hour()*3600 + t.Minute()*60 + t.Second())
}

View File

@ -0,0 +1,76 @@
package upload
import (
"errors"
"mime"
"net/http"
)
// Info about request headers
type meta struct {
MediaType string
Boundary string
Filename string
}
// Parse request headers and make Meta.
func parseMeta(req *http.Request) (*meta, error) {
m := &meta{}
if err := m.parseContentType(req.Header.Get("Content-Type")); err != nil {
return nil, err
}
if err := m.parseContentDisposition(req.Header.Get("Content-Disposition")); err != nil {
return nil, err
}
return m, nil
}
func (m *meta) parseContentType(ct string) error {
if ct == "" {
m.MediaType = "application/octet-stream"
return nil
}
mediatype, params, err := mime.ParseMediaType(ct)
if err != nil {
return err
}
if mediatype == "multipart/form-data" {
boundary, ok := params["boundary"]
if !ok {
return errors.New("meta: boundary not defined")
}
m.MediaType = mediatype
m.Boundary = boundary
} else {
m.MediaType = "application/octet-stream"
}
return nil
}
func (m *meta) parseContentDisposition(cd string) error {
if cd == "" {
return nil
}
_, params, err := mime.ParseMediaType(cd)
if err != nil {
return err
}
filename, ok := params["filename"]
if !ok {
return errors.New("meta: filename in Content-Disposition not defined")
}
m.Filename = filename
return nil
}

View File

@ -0,0 +1,209 @@
package upload
import (
"crypto/md5"
"encoding/hex"
"errors"
"io"
"io/ioutil"
"mime/multipart"
"net/http"
"os"
"path/filepath"
"strings"
)
// Error incomplete returned by uploader when loaded non-last chunk.
var incomplete = errors.New("incomplete")
// Structure describes the state of the original file.
type originalFile struct {
BaseMime string
Filepath string
Filename string
Size int64
}
func (ofile *originalFile) Ext() string {
return strings.ToLower(filepath.Ext(ofile.Filename))
}
func process(req *http.Request, storage string) ([]*originalFile, error) {
meta, err := parseMeta(req)
if err != nil {
return nil, err
}
body, err := newBody(req.Body)
if err != nil {
return nil, err
}
up := &uploader{Root: storage, Meta: meta, body: body}
files, err := up.SaveFiles()
if err == incomplete {
return files, err
}
if err != nil {
return nil, err
}
return files, nil
}
// Upload manager.
type uploader struct {
Root string
Meta *meta
body *body
}
// Function SaveFiles sequentially loads the original files or chunk's.
func (up *uploader) SaveFiles() ([]*originalFile, error) {
files := make([]*originalFile, 0)
for {
ofile, err := up.SaveFile()
if err == io.EOF {
break
}
if err != nil {
return nil, err
}
files = append(files, ofile)
}
return files, nil
}
// Function loads one or download the original file chunk.
// Asks for the starting position in the body of the request to read the next file.
// Asks for a temporary file.
// Writes data from the request body into a temporary file.
// Specifies the size of the resulting temporary file.
// If the query specified header Content-Range,
// and the size of the resulting file does not match, it returns an error incomplete.
// Otherwise, defines the basic mime type, and returns the original file.
func (up *uploader) SaveFile() (*originalFile, error) {
body, filename, err := up.Reader()
if err != nil {
return nil, err
}
temp_file, err := up.tempFile()
if err != nil {
return nil, err
}
defer temp_file.Close()
if err = up.Write(temp_file, body); err != nil {
return nil, err
}
fi, err := temp_file.Stat()
if err != nil {
return nil, err
}
ofile := &originalFile{Filename: filename, Filepath: temp_file.Name(), Size: fi.Size()}
ofile.BaseMime, err = identifyMime(ofile.Filepath)
if err != nil {
return nil, err
}
return ofile, nil
}
// Returns the reader to read the file or chunk of request body and the original file name.
// If the request header Content-Type is multipart/form-data, returns the next copy part.
// If all of part read the case of binary loading read the request body, an error is returned io.EOF.
func (up *uploader) Reader() (io.Reader, string, error) {
if up.Meta.MediaType == "multipart/form-data" {
if up.body.MR == nil {
up.body.MR = multipart.NewReader(up.body.body, up.Meta.Boundary)
}
for {
part, err := up.body.MR.NextPart()
if err != nil {
return nil, "", err
}
if part.FormName() == "files[]" {
return part, part.FileName(), nil
}
}
}
if !up.body.Available {
return nil, "", io.EOF
}
up.body.Available = false
return up.body.body, up.Meta.Filename, nil
}
// Returns a temporary file to download the file or resume chunk.
func (up *uploader) tempFile() (*os.File, error) {
return tempFile()
}
// Returns the newly created temporary file.
func tempFile() (*os.File, error) {
return ioutil.TempFile(os.TempDir(), "coquelicot")
}
// Returns a temporary file to download chunk.
// To calculate a unique file name used cookie named coquelicot and the original file name.
// File located in the directory chunks storage root directory.
// Before returning the file pointer is shifted by the value of offset,
// in a situation where the pieces are loaded from the second to the last.
func tempFileChunks(offset int64, storage, upload_sid, user_filename string) (*os.File, error) {
hasher := md5.New()
hasher.Write([]byte(upload_sid + user_filename))
filename := hex.EncodeToString(hasher.Sum(nil))
path := filepath.Join(storage, "chunks")
err := os.MkdirAll(path, 0755)
if err != nil {
return nil, err
}
file, err := os.OpenFile(filepath.Join(path, filename), os.O_CREATE|os.O_WRONLY, 0664)
if err != nil {
return nil, err
}
if _, err = file.Seek(offset, 0); err != nil {
return nil, err
}
return file, nil
}
// The function writes a temporary file value from reader.
func (up *uploader) Write(temp_file *os.File, body io.Reader) error {
var err error
_, err = io.Copy(temp_file, body)
return err
}
// identifyMine gets base mime type.
func identifyMime(file string) (string, error) {
f, err := os.Open(file)
if err != nil {
return "", err
}
defer f.Close()
// DetectContentType reads at most the first 512 bytes
buf := make([]byte, 512)
_, err = f.Read(buf)
if err != nil {
return "", err
}
mime := strings.Split(http.DetectContentType(buf), "/")[0]
return mime, nil
}

View File

@ -0,0 +1,48 @@
package upload
import (
"net/http"
httputil "github.com/goodrain/rainbond/util/http"
)
type Storage struct {
output string
verbosity int
}
func (s *Storage) StorageDir() string {
return s.output
}
func NewStorage(rootDir string) *Storage {
return &Storage{output: rootDir}
}
// UploadHandler is the endpoint for uploading and storing files.
func (s *Storage) UploadHandler(w http.ResponseWriter, r *http.Request) {
// Performs the processing of writing data into chunk files.
files, err := process(r, s.StorageDir())
if err == incomplete {
httputil.ReturnSuccess(r, w, nil)
return
}
if err != nil {
httputil.ReturnError(r, w, 500, err.Error())
return
}
data := make([]map[string]interface{}, 0)
for _, file := range files {
attachment, err := create(s.StorageDir(), file, true)
if err != nil {
httputil.ReturnError(r, w, 500, err.Error())
return
}
data = append(data, attachment.ToJson())
}
httputil.ReturnSuccess(r, w, data)
}

View File

@ -19,9 +19,9 @@
package handler
import (
"github.com/goodrain/rainbond/cmd/api/option"
"github.com/goodrain/rainbond/api/discover"
"github.com/goodrain/rainbond/api/proxy"
"github.com/goodrain/rainbond/cmd/api/option"
)
var nodeProxy proxy.Proxy
@ -47,7 +47,6 @@ func InitProxy(conf option.Config) {
monitorProxy = proxy.CreateProxy("monitor", "http", []string{"127.0.0.1:3329"})
discover.GetEndpointDiscover(conf.EtcdEndpoint).AddProject("monitor", monitorProxy)
}
}
//GetNodeProxy GetNodeProxy

View File

@ -20,7 +20,6 @@ package middleware
import (
"encoding/base64"
"fmt"
"io"
"net/http"
"os"
@ -44,7 +43,6 @@ func Token(next http.Handler) http.Handler {
}
auths := strings.SplitN(auth, " ", 2)
if len(auths) != 2 {
fmt.Println("error")
return
}
authMethod := auths[0]
@ -101,7 +99,6 @@ func FullToken(next http.Handler) http.Handler {
}
auths := strings.SplitN(auth, " ", 2)
if len(auths) != 2 {
fmt.Println("error")
return
}
authMethod := auths[0]

View File

@ -1407,7 +1407,7 @@ type MQBody struct {
func NewAppStatusFromExport(app *ExportAppStruct) *dbmodel.AppStatus {
fields := strings.Split(app.SourceDir, "/")
tarName := fields[len(fields)-1]
tarFileHref := fmt.Sprintf("/v2/app/download/%s/%s.tar", app.Body.Format, tarName)
tarFileHref := fmt.Sprintf("/v2/app/download/%s/%s.zip", app.Body.Format, tarName)
return &dbmodel.AppStatus{
Format: app.Body.Format,
EventID: app.Body.EventID,

View File

@ -21,7 +21,10 @@ package proxy
import (
"net/http"
"net/http/httputil"
"net/url"
"strings"
"github.com/Sirupsen/logrus"
)
//HTTPProxy HTTPProxy
@ -34,12 +37,16 @@ type HTTPProxy struct {
//Proxy 代理
func (h *HTTPProxy) Proxy(w http.ResponseWriter, r *http.Request) {
endpoint := h.lb.Select(r, h.endpoints)
director := func(req *http.Request) {
req = r
req.URL.Scheme = "http"
req.URL.Host = endpoint.String()
endURL, err := url.Parse(endpoint.GetHTTPAddr())
if err != nil {
logrus.Errorf("parse endpoint url error,%s", err.Error())
w.WriteHeader(502)
return
}
proxy := &httputil.ReverseProxy{Director: director}
if endURL.Scheme == "" {
endURL.Scheme = "http"
}
proxy := httputil.NewSingleHostReverseProxy(endURL)
proxy.ServeHTTP(w, r)
}
@ -64,6 +71,8 @@ func (h *HTTPProxy) Do(r *http.Request) (*http.Response, error) {
} else {
r.URL.Host = endpoint.String()
}
//default is http
r.URL.Scheme = "http"
return http.DefaultClient.Do(r)
}

View File

@ -41,6 +41,7 @@ func (e Endpoint) String() string {
return string(e)
}
//GetName get endpoint name
func (e Endpoint) GetName() string {
if kv := strings.Split(string(e), "=>"); len(kv) > 1 {
return kv[0]
@ -48,6 +49,7 @@ func (e Endpoint) GetName() string {
return string(e)
}
//GetAddr get addr
func (e Endpoint) GetAddr() string {
if kv := strings.Split(string(e), "=>"); len(kv) > 1 {
return kv[1]
@ -55,6 +57,21 @@ func (e Endpoint) GetAddr() string {
return string(e)
}
//GetHTTPAddr get http url
func (e Endpoint) GetHTTPAddr() string {
if kv := strings.Split(string(e), "=>"); len(kv) > 1 {
return withScheme(kv[1])
}
return withScheme(string(e))
}
func withScheme(s string) string {
if strings.HasPrefix(s, "http") {
return s
}
return "http://" + s
}
//EndpointList EndpointList
type EndpointList []Endpoint

View File

@ -18,9 +18,20 @@
package proxy
import "testing"
import (
"net/url"
"testing"
)
func TestNewSelectBalance(t *testing.T) {
sb := NewSelectBalance()
t.Log(sb.hostIDMap)
}
func TestURLParse(t *testing.T) {
endURL, err := url.Parse("127.0.0.1:8080")
if err != nil {
t.Fatal(err)
}
t.Log(endURL)
}

View File

@ -638,7 +638,7 @@ func (i *ExportApp) ErrorCallBack(err error) {
}
func (i *ExportApp) zip() error {
err := util.Zip(i.SourceDir, i.SourceDir+".tar")
err := util.Zip(i.SourceDir, i.SourceDir+".zip")
if err != nil {
i.Logger.Error("Export application failure:Zip failure", map[string]string{"step": "export-app", "status": "failure"})
logrus.Errorf("Failed to create tar file for group %s: %v", i.SourceDir, err)

View File

@ -24,13 +24,10 @@ import (
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"strings"
"time"
"bytes"
"github.com/Sirupsen/logrus"
"github.com/bitly/go-simplejson"
"github.com/docker/engine-api/client"
@ -48,15 +45,16 @@ func init() {
//ImportApp Export app to specified format(rainbond-app or dockercompose)
type ImportApp struct {
EventID string `json:"event_id"`
Format string `json:"format"`
SourceDir string `json:"source_dir"`
Apps []string `json:"apps"`
ServiceImage model.ServiceImage
ServiceSlug model.ServiceSlug
Logger event.Logger
DockerClient *client.Client
oldAPPPath map[string]string
EventID string `json:"event_id"`
Format string `json:"format"`
SourceDir string `json:"source_dir"`
Apps []string `json:"apps"`
ServiceImage model.ServiceImage
ServiceSlug model.ServiceSlug
Logger event.Logger
DockerClient *client.Client
oldAPPPath map[string]string
oldPluginPath map[string]string
}
//NewImportApp create
@ -82,15 +80,16 @@ func NewImportApp(in []byte, m *exectorManager) (TaskWorker, error) {
logger := event.GetManager().GetLogger(eventID)
return &ImportApp{
Format: gjson.GetBytes(in, "format").String(),
SourceDir: gjson.GetBytes(in, "source_dir").String(),
Apps: apps,
ServiceImage: serviceImage,
ServiceSlug: serviceSlug,
Logger: logger,
EventID: eventID,
DockerClient: m.DockerClient,
oldAPPPath: make(map[string]string),
Format: gjson.GetBytes(in, "format").String(),
SourceDir: gjson.GetBytes(in, "source_dir").String(),
Apps: apps,
ServiceImage: serviceImage,
ServiceSlug: serviceSlug,
Logger: logger,
EventID: eventID,
DockerClient: m.DockerClient,
oldAPPPath: make(map[string]string),
oldPluginPath: make(map[string]string),
}, nil
}
@ -111,7 +110,7 @@ func (i *ImportApp) GetLogger() event.Logger {
//ErrorCallBack if run error will callback
func (i *ImportApp) ErrorCallBack(err error) {
i.updateStatus("failed", "")
}
//Run Run
@ -119,18 +118,16 @@ func (i *ImportApp) Run(timeout time.Duration) error {
if i.Format == "rainbond-app" {
err := i.importApp()
if err != nil {
i.updateStatus("failed", "")
return err
}
return nil
} else {
return errors.New("Unsupported the format: " + i.Format)
}
return errors.New("Unsupported the format: " + i.Format)
}
// 组目录命名规则将组名中unicode转为中文并去掉空格"JAVA-ETCD\\u5206\\u4eab\\u7ec4" -> "JAVA-ETCD分享组"
// importApp import app
// support batch import
func (i *ImportApp) importApp() error {
oldSourceDir := i.SourceDir
var datas = "["
tmpDir := oldSourceDir + "/TmpUnzipDir"
@ -138,44 +135,29 @@ func (i *ImportApp) importApp() error {
if err := i.updateStatusForApp(app, "importing"); err != nil {
logrus.Errorf("Failed to update status to importing for app %s: %v", app, err)
}
appFile := filepath.Join(oldSourceDir, app)
os.MkdirAll(tmpDir, 0755)
cmd := exec.Command("sh", "-c", fmt.Sprintf("tar -xf %s -C %s/", appFile, tmpDir))
var out bytes.Buffer
cmd.Stdout = &out
cmd.Stderr = &out
err := cmd.Run()
err := util.Unzip(appFile, tmpDir)
if err != nil {
err := util.Unzip(appFile, tmpDir)
if err != nil {
logrus.Errorf("Failed to unzip tar %s: %v", appFile, out.String())
i.updateStatusForApp(app, "failed")
continue
}
logrus.Errorf("Failed to unzip app file %s : %s", appFile, err.Error())
i.updateStatusForApp(app, "failed")
continue
}
files, _ := ioutil.ReadDir(tmpDir)
if len(files) < 1 {
logrus.Errorf("Failed to read files in tmp dir %s: %v", appFile, err)
continue
}
i.SourceDir = fmt.Sprintf("%s/%s", oldSourceDir, files[0].Name())
if _, err := os.Stat(i.SourceDir); err == nil {
os.RemoveAll(i.SourceDir)
}
err = os.Rename(fmt.Sprintf("%s/%s", tmpDir, files[0].Name()), i.SourceDir)
if err != nil {
logrus.Errorf("Failed to mv source dir to %s: %v", i.SourceDir, err)
continue
}
os.RemoveAll(tmpDir)
// push image and slug file
// 修改json元数据中的镜像和源码包仓库地址为指定地址
@ -189,14 +171,12 @@ func (i *ImportApp) importApp() error {
i.updateStatusForApp(app, "failed")
continue
}
apps, err := meta.Get("apps").Array()
if err != nil {
logrus.Errorf("Failed to get apps from meta for load app %s: %v", appFile, err)
i.updateStatusForApp(app, "failed")
continue
}
for index := range apps {
app := meta.Get("apps").GetIndex(index)
if _, ok := app.CheckGet("service_image"); ok {
@ -242,7 +222,6 @@ func (i *ImportApp) importApp() error {
}
apps[index] = app
}
meta.Set("apps", apps)
data, err = meta.MarshalJSON()
if err != nil {
@ -250,44 +229,35 @@ func (i *ImportApp) importApp() error {
i.updateStatusForApp(app, "failed")
continue
}
// 修改完毕后写回文件中
err = ioutil.WriteFile(metaFile, data, 0644)
if err != nil {
logrus.Errorf("Failed to write metadata load app %s: %v", appFile, err)
i.updateStatusForApp(app, "failed")
continue
}
// 上传镜像和源码包到仓库中
// load all service version attachment in app
if err := i.loadApps(); err != nil {
logrus.Errorf("Failed to load app %s: %v", appFile, err)
i.updateStatusForApp(app, "failed")
continue
}
// 上传插件镜像到仓库中
// load all plugins
if err := i.importPlugins(); err != nil {
logrus.Errorf("Failed to load app plugin %s: %v", appFile, err)
i.updateStatusForApp(app, "failed")
continue
}
if datas == "[" {
datas += string(data)
} else {
datas += ", " + string(data)
}
if err := i.updateStatusForApp(app, "success"); err != nil {
logrus.Errorf("Failed to update status to success for app %s: %v", app, err)
continue
}
os.Rename(appFile, appFile+".success")
logrus.Debug("Successful import app: ", appFile)
}
datas += "]"
i.SourceDir = oldSourceDir
@ -358,7 +328,7 @@ func (i *ImportApp) importPlugins() error {
if _, ok := plugin.CheckGet("plugin_image"); ok {
plugin.Set("plugin_image", i.ServiceImage)
}
getAppImage := func() string {
getImageImage := func() string {
oldname, _ := plugin.Get("share_image").String()
oldImageName := sources.ImageNameWithNamespaceHandle(oldname)
var image string
@ -371,8 +341,8 @@ func (i *ImportApp) importPlugins() error {
}
if oldimage, ok := plugin.CheckGet("share_image"); ok {
appKey, _ := plugin.Get("service_key").String()
i.oldAPPPath[appKey], _ = oldimage.String()
plugin.Set("share_image", getAppImage())
i.oldPluginPath[appKey], _ = oldimage.String()
plugin.Set("share_image", getImageImage())
}
oldPlugins[index] = plugin
}
@ -418,10 +388,12 @@ func (i *ImportApp) importPlugins() error {
user := plugin.Get("plugin_image.hub_user").String()
pass := plugin.Get("plugin_image.hub_password").String()
// 上传之前先要根据新的仓库地址修改镜像名
image := i.oldAPPPath[plugin.Get("service_key").String()]
saveImageName := plugin.Get("share_image").String()
if err := sources.ImageTag(i.DockerClient, image, saveImageName, i.Logger, 2); err != nil {
return fmt.Errorf("change plugin image tag(%s => %s) error %s", saveImageName, image, err.Error())
image := i.oldPluginPath[plugin.Get("service_key").String()]
imageName := sources.ImageNameWithNamespaceHandle(image)
saveImageName := fmt.Sprintf("%s/%s:%s", "goodrain.me", imageName.Name, imageName.Tag)
newImageName := plugin.Get("share_image").String()
if err := sources.ImageTag(i.DockerClient, saveImageName, newImageName, i.Logger, 2); err != nil {
return fmt.Errorf("change plugin image tag(%s => %s) error %s", saveImageName, newImageName, err.Error())
}
// 开始上传
if err := sources.ImagePush(i.DockerClient, saveImageName, user, pass, i.Logger, 15); err != nil {
@ -470,7 +442,7 @@ func (i *ImportApp) loadApps() error {
pass := app.Get("service_image.hub_password").String()
// 上传之前先要根据新的仓库地址修改镜像名
image := app.Get("share_image").String()
if err := sources.ImageTag(i.DockerClient, fmt.Sprintf("%s/%s:%s", i.ServiceImage.HubUrl, oldImageName.Name, oldImageName.Tag), image, i.Logger, 15); err != nil {
if err := sources.ImageTag(i.DockerClient, fmt.Sprintf("%s/%s:%s", "goodrain.me", oldImageName.Name, oldImageName.Tag), image, i.Logger, 15); err != nil {
return fmt.Errorf("change image tag(%s => %s) error %s", fmt.Sprintf("%s/%s:%s", i.ServiceImage.HubUrl, oldImageName.Name, oldImageName.Tag), image, err.Error())
}
// 开始上传
@ -516,7 +488,7 @@ func (i *ImportApp) updateStatus(status, data string) error {
// 从数据库中获取该应用的状态信息
res, err := db.GetManager().AppDao().GetByEventId(i.EventID)
if err != nil {
err = fmt.Errorf("failed to get app %s from db: %v", i.EventID, err)
err = fmt.Errorf("failed to get app %s from db: %s", i.EventID, err.Error())
logrus.Error(err)
return err
}
@ -525,7 +497,7 @@ func (i *ImportApp) updateStatus(status, data string) error {
res.Status = status
if err := db.GetManager().AppDao().UpdateModel(res); err != nil {
err = fmt.Errorf("failed to update app %s: %v", i.EventID, err)
err = fmt.Errorf("failed to update app %s: %s", i.EventID, err.Error())
logrus.Error(err)
return err
}
@ -538,7 +510,7 @@ func (i *ImportApp) updateStatusForApp(app, status string) error {
// 从数据库中获取该应用的状态信息
res, err := db.GetManager().AppDao().GetByEventId(i.EventID)
if err != nil {
err = errors.New(fmt.Sprintf("Failed to get app %s from db: %v", i.EventID, err))
err = fmt.Errorf("Failed to get app %s from db: %s", i.EventID, err.Error())
logrus.Error(err)
return err
}
@ -549,7 +521,7 @@ func (i *ImportApp) updateStatusForApp(app, status string) error {
res.Apps = map2str(appsMap)
if err := db.GetManager().AppDao().UpdateModel(res); err != nil {
err = errors.New(fmt.Sprintf("Failed to update app %s: %v", i.EventID, err))
err = fmt.Errorf("Failed to update app %s: %s", i.EventID, err.Error())
logrus.Error(err)
return err
}

View File

@ -5,7 +5,7 @@ type AppStatus struct {
Format string `gorm:"column:format;size:32" json:"format"` // only rainbond-app/docker-compose
SourceDir string `gorm:"column:source_dir;size:255" json:"source_dir"`
Apps string `gorm:"column:apps;type:text" json:"apps"`
Status string `gorm:"column:status;size:32" json:"status"` // only exporting/importing/failed/success
Status string `gorm:"column:status;size:32" json:"status"` // only exporting/importing/failed/success/cleaned
TarFileHref string `gorm:"column:tar_file_href;size:255" json:"tar_file_href"`
Metadata string `gorm:"column:metadata;type:text" json:"metadata"`
}

View File

@ -104,7 +104,6 @@ func (m *EventFilePlugin) GetMessages(eventID, level string) (MessageDataList, e
flag := line[0]
if CheckLevel(string(flag), level) {
info := strings.SplitN(string(line), " ", 3)
fmt.Println(info)
if len(info) == 3 {
timeunix := info[1]
unix, _ := strconv.ParseInt(timeunix, 10, 64)

View File

@ -40,7 +40,7 @@ func InitClient(kubeconfig string) error {
// use the current context in kubeconfig
config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
if err != nil {
panic(err.Error())
return err
}
config.QPS = 50
config.Burst = 100

View File

@ -42,6 +42,7 @@ func GetCmds() []cli.Command {
cmds = append(cmds, NewCmdShow())
cmds = append(cmds, NewCmdAlerting())
cmds = append(cmds, NewCmdNotificationEvent())
cmds = append(cmds, NewCmdReset())
//task相关命令
//cmds = append(cmds, NewCmdTasks())

View File

@ -42,9 +42,9 @@ func NewCmdInit() cli.Command {
Name: "init",
Flags: []cli.Flag{
cli.StringFlag{
Name: "type",
Usage: "node type: manage or compute",
Value: "manage",
Name: "role",
Usage: "node role: master,worker",
Value: "master",
},
cli.StringFlag{
Name: "work_dir",
@ -160,7 +160,7 @@ func initCluster(c *cli.Context) {
// start setup script to install rainbond
fmt.Println("Begin init cluster first node,please don't exit,wait install")
cmd := exec.Command("bash", "-c", fmt.Sprintf("cd %s ; ./setup.sh %s %s %s", c.String("work_dir"), c.String("install-type"), c.String("eip"), c.String("domain")))
cmd := exec.Command("bash", "-c", fmt.Sprintf("cd %s ; ./setup.sh %s %s %s %s", c.String("work_dir"), c.String("role"), c.String("install-type"), c.String("eip"), c.String("domain")))
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Stdin = os.Stdin

View File

@ -448,7 +448,7 @@ func NewCmdNode() cli.Command {
},
cli.StringFlag{
Name: "role,r",
Usage: "The option is required, the allowed values are: [manage|compute|storage]",
Usage: "The option is required, the allowed values are: [master|worker]",
},
},
Action: func(c *cli.Context) error {
@ -470,7 +470,7 @@ func NewCmdNode() cli.Command {
// start add node script
fmt.Println("Begin add node, please don't exit")
line := fmt.Sprintf("cd /opt/rainbond/install/scripts; ./%s.sh %s %s %s %s %s", c.String("role"), c.String("hostname"),
line := fmt.Sprintf("cd /opt/rainbond/install/scripts; ./join.sh %s %s %s %s %s %s", c.String("role"), c.String("hostname"),
c.String("internal-ip"), model, c.String("root-pass"), c.String("private-key"))
cmd := exec.Command("bash", "-c", line)
cmd.Stdout = os.Stdout

View File

@ -13,8 +13,8 @@ import (
//NewCmdNode NewCmdNode
func NewCmdNotificationEvent() cli.Command {
c := cli.Command{
Name: "notification",
Usage: "应用异常通知事件。grctl notification",
Name: "msg",
Usage: "应用异常通知事件。grctl msg",
Subcommands: []cli.Command{
{
Name: "get",
@ -47,12 +47,12 @@ func NewCmdNotificationEvent() cli.Command {
val, err := clients.RegionClient.Notification().GetNotification(startTime, EndTme)
handleErr(err)
serviceTable := termtables.CreateTable()
serviceTable.AddHeaders("ServiceName(应用别名)", "TenantName(租户别名)", "Message(异常信息)", "Reason(异常原因)", "Count(出现次数)", "LastTime(最后一次异常时间)", "FirstTime(第一次异常时间)")
serviceTable.AddHeaders("TenantName(租户别名)/ServiceName(应用别名)", "Message(异常信息)", "Reason(异常原因)", "Count(出现次数)", "LastTime(最后一次异常时间)", "FirstTime(第一次异常时间)")
for _, v := range val {
if v.KindID == "" || v.ServiceName == "" || v.TenantName == "" {
continue
}
serviceTable.AddRow(v.ServiceName, v.TenantName, v.Message, v.Reason, v.Count, v.LastTime, v.FirstTime)
serviceTable.AddRow(v.TenantName+"/"+v.ServiceName, v.Message, v.Reason, v.Count, v.LastTime, v.FirstTime)
}
fmt.Println(serviceTable.Render())
return nil

67
grctl/cmd/reset.go Normal file
View File

@ -0,0 +1,67 @@
// RAINBOND, Application Management Platform
// Copyright (C) 2014-2017 Goodrain Co., Ltd.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. For any non-GPL usage of Rainbond,
// one or multiple Commercial Licenses authorized by Goodrain Co., Ltd.
// must be obtained first.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package cmd
import (
"fmt"
// "io/ioutil"
"os/exec"
//"github.com/goodrain/rainbond/event"
//"github.com/Sirupsen/logrus"
"github.com/urfave/cli"
"os"
//"github.com/goodrain/rainbond/builder/sources"
//"github.com/goodrain/rainbond/grctl/clients"
//"flag"
)
//NewCmdInit grctl reset
func NewCmdReset() cli.Command {
c := cli.Command{
Name: "reset",
Usage: "重置当前节点grctl reset",
Action: func(c *cli.Context) error {
resetCurrentNode(c)
return nil
},
}
return c
}
func resetCurrentNode(c *cli.Context) {
// stop rainbond services
fmt.Println("Start stop rainbond services")
cmd := exec.Command("grclis", "reset")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Stdin = os.Stdin
err := cmd.Run()
if err != nil {
println(err.Error())
return
}
return
}

View File

@ -303,7 +303,7 @@ func (n *Cluster) handleNodeStatus(v *client.HostNode) {
//var haveready bool
for _, condiction := range v.NodeStatus.Conditions {
if condiction.Status == "True" && (condiction.Type == "OutOfDisk" || condiction.Type == "MemoryPressure" || condiction.Type == "DiskPressure") {
if (condiction.Status == "True" || condiction.Status == "Unknown") && (condiction.Type == "OutOfDisk" || condiction.Type == "MemoryPressure" || condiction.Type == "DiskPressure") {
v.Status = status
v.NodeStatus.Status = status
@ -360,6 +360,7 @@ func (n *Cluster) handleNodeStatus(v *client.HostNode) {
Status: client.ConditionFalse,
LastHeartbeatTime: time.Now(),
LastTransitionTime: time.Now(),
Message: "K8s node status is NotReady",
}
v.UpdataCondition(r)
}

View File

@ -256,7 +256,9 @@ func (p *probeManager) WatchServiceHealthy(serviceName string) Watcher {
serviceName: serviceName,
}
if s, ok := p.watches[serviceName]; ok {
p.lock.Lock()
s[w.id] = w
p.lock.Unlock()
} else {
p.lock.Lock()
p.watches[serviceName] = map[string]*watcher{

9
vendor/github.com/google/uuid/.travis.yml generated vendored Normal file
View File

@ -0,0 +1,9 @@
language: go
go:
- 1.4.3
- 1.5.3
- tip
script:
- go test -v ./...

10
vendor/github.com/google/uuid/CONTRIBUTING.md generated vendored Normal file
View File

@ -0,0 +1,10 @@
# How to contribute
We definitely welcome patches and contribution to this project!
### Legal requirements
In order to protect both you and ourselves, you will need to sign the
[Contributor License Agreement](https://cla.developers.google.com/clas).
You may have already signed it for other Google projects.

9
vendor/github.com/google/uuid/CONTRIBUTORS generated vendored Normal file
View File

@ -0,0 +1,9 @@
Paul Borman <borman@google.com>
bmatsuo
shawnps
theory
jboverfelt
dsymonds
cd1
wallclockbuilder
dansouza

27
vendor/github.com/google/uuid/LICENSE generated vendored Normal file
View File

@ -0,0 +1,27 @@
Copyright (c) 2009,2014 Google Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* 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.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
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.

19
vendor/github.com/google/uuid/README.md generated vendored Normal file
View File

@ -0,0 +1,19 @@
# uuid ![build status](https://travis-ci.org/google/uuid.svg?branch=master)
The uuid package generates and inspects UUIDs based on
[RFC 4122](http://tools.ietf.org/html/rfc4122)
and DCE 1.1: Authentication and Security Services.
This package is based on the github.com/pborman/uuid package (previously named
code.google.com/p/go-uuid). It differs from these earlier packages in that
a UUID is a 16 byte array rather than a byte slice. One loss due to this
change is the ability to represent an invalid UUID (vs a NIL UUID).
###### Install
`go get github.com/google/uuid`
###### Documentation
[![GoDoc](https://godoc.org/github.com/google/uuid?status.svg)](http://godoc.org/github.com/google/uuid)
Full `go doc` style documentation for the package can be viewed online without
installing this package by using the GoDoc site here:
http://godoc.org/github.com/google/uuid

80
vendor/github.com/google/uuid/dce.go generated vendored Normal file
View File

@ -0,0 +1,80 @@
// Copyright 2016 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
"encoding/binary"
"fmt"
"os"
)
// A Domain represents a Version 2 domain
type Domain byte
// Domain constants for DCE Security (Version 2) UUIDs.
const (
Person = Domain(0)
Group = Domain(1)
Org = Domain(2)
)
// NewDCESecurity returns a DCE Security (Version 2) UUID.
//
// The domain should be one of Person, Group or Org.
// On a POSIX system the id should be the users UID for the Person
// domain and the users GID for the Group. The meaning of id for
// the domain Org or on non-POSIX systems is site defined.
//
// For a given domain/id pair the same token may be returned for up to
// 7 minutes and 10 seconds.
func NewDCESecurity(domain Domain, id uint32) (UUID, error) {
uuid, err := NewUUID()
if err == nil {
uuid[6] = (uuid[6] & 0x0f) | 0x20 // Version 2
uuid[9] = byte(domain)
binary.BigEndian.PutUint32(uuid[0:], id)
}
return uuid, err
}
// NewDCEPerson returns a DCE Security (Version 2) UUID in the person
// domain with the id returned by os.Getuid.
//
// NewDCESecurity(Person, uint32(os.Getuid()))
func NewDCEPerson() (UUID, error) {
return NewDCESecurity(Person, uint32(os.Getuid()))
}
// NewDCEGroup returns a DCE Security (Version 2) UUID in the group
// domain with the id returned by os.Getgid.
//
// NewDCESecurity(Group, uint32(os.Getgid()))
func NewDCEGroup() (UUID, error) {
return NewDCESecurity(Group, uint32(os.Getgid()))
}
// Domain returns the domain for a Version 2 UUID. Domains are only defined
// for Version 2 UUIDs.
func (uuid UUID) Domain() Domain {
return Domain(uuid[9])
}
// ID returns the id for a Version 2 UUID. IDs are only defined for Version 2
// UUIDs.
func (uuid UUID) ID() uint32 {
return binary.BigEndian.Uint32(uuid[0:4])
}
func (d Domain) String() string {
switch d {
case Person:
return "Person"
case Group:
return "Group"
case Org:
return "Org"
}
return fmt.Sprintf("Domain%d", int(d))
}

12
vendor/github.com/google/uuid/doc.go generated vendored Normal file
View File

@ -0,0 +1,12 @@
// Copyright 2016 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package uuid generates and inspects UUIDs.
//
// UUIDs are based on RFC 4122 and DCE 1.1: Authentication and Security
// Services.
//
// A UUID is a 16 byte (128 bit) array. UUIDs may be used as keys to
// maps or compared directly.
package uuid

1
vendor/github.com/google/uuid/go.mod generated vendored Normal file
View File

@ -0,0 +1 @@
module github.com/google/uuid

53
vendor/github.com/google/uuid/hash.go generated vendored Normal file
View File

@ -0,0 +1,53 @@
// Copyright 2016 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
"crypto/md5"
"crypto/sha1"
"hash"
)
// Well known namespace IDs and UUIDs
var (
NameSpaceDNS = Must(Parse("6ba7b810-9dad-11d1-80b4-00c04fd430c8"))
NameSpaceURL = Must(Parse("6ba7b811-9dad-11d1-80b4-00c04fd430c8"))
NameSpaceOID = Must(Parse("6ba7b812-9dad-11d1-80b4-00c04fd430c8"))
NameSpaceX500 = Must(Parse("6ba7b814-9dad-11d1-80b4-00c04fd430c8"))
Nil UUID // empty UUID, all zeros
)
// NewHash returns a new UUID derived from the hash of space concatenated with
// data generated by h. The hash should be at least 16 byte in length. The
// first 16 bytes of the hash are used to form the UUID. The version of the
// UUID will be the lower 4 bits of version. NewHash is used to implement
// NewMD5 and NewSHA1.
func NewHash(h hash.Hash, space UUID, data []byte, version int) UUID {
h.Reset()
h.Write(space[:])
h.Write(data)
s := h.Sum(nil)
var uuid UUID
copy(uuid[:], s)
uuid[6] = (uuid[6] & 0x0f) | uint8((version&0xf)<<4)
uuid[8] = (uuid[8] & 0x3f) | 0x80 // RFC 4122 variant
return uuid
}
// NewMD5 returns a new MD5 (Version 3) UUID based on the
// supplied name space and data. It is the same as calling:
//
// NewHash(md5.New(), space, data, 3)
func NewMD5(space UUID, data []byte) UUID {
return NewHash(md5.New(), space, data, 3)
}
// NewSHA1 returns a new SHA1 (Version 5) UUID based on the
// supplied name space and data. It is the same as calling:
//
// NewHash(sha1.New(), space, data, 5)
func NewSHA1(space UUID, data []byte) UUID {
return NewHash(sha1.New(), space, data, 5)
}

62
vendor/github.com/google/uuid/json_test.go generated vendored Normal file
View File

@ -0,0 +1,62 @@
// Copyright 2016 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
"encoding/json"
"reflect"
"testing"
)
var testUUID = Must(Parse("f47ac10b-58cc-0372-8567-0e02b2c3d479"))
func TestJSON(t *testing.T) {
type S struct {
ID1 UUID
ID2 UUID
}
s1 := S{ID1: testUUID}
data, err := json.Marshal(&s1)
if err != nil {
t.Fatal(err)
}
var s2 S
if err := json.Unmarshal(data, &s2); err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(&s1, &s2) {
t.Errorf("got %#v, want %#v", s2, s1)
}
}
func BenchmarkUUID_MarshalJSON(b *testing.B) {
x := &struct {
UUID UUID `json:"uuid"`
}{}
var err error
x.UUID, err = Parse("f47ac10b-58cc-0372-8567-0e02b2c3d479")
if err != nil {
b.Fatal(err)
}
for i := 0; i < b.N; i++ {
js, err := json.Marshal(x)
if err != nil {
b.Fatalf("marshal json: %#v (%v)", js, err)
}
}
}
func BenchmarkUUID_UnmarshalJSON(b *testing.B) {
js := []byte(`{"uuid":"f47ac10b-58cc-0372-8567-0e02b2c3d479"}`)
var x *struct {
UUID UUID `json:"uuid"`
}
for i := 0; i < b.N; i++ {
err := json.Unmarshal(js, &x)
if err != nil {
b.Fatalf("marshal json: %#v (%v)", js, err)
}
}
}

37
vendor/github.com/google/uuid/marshal.go generated vendored Normal file
View File

@ -0,0 +1,37 @@
// Copyright 2016 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import "fmt"
// MarshalText implements encoding.TextMarshaler.
func (uuid UUID) MarshalText() ([]byte, error) {
var js [36]byte
encodeHex(js[:], uuid)
return js[:], nil
}
// UnmarshalText implements encoding.TextUnmarshaler.
func (uuid *UUID) UnmarshalText(data []byte) error {
id, err := ParseBytes(data)
if err == nil {
*uuid = id
}
return err
}
// MarshalBinary implements encoding.BinaryMarshaler.
func (uuid UUID) MarshalBinary() ([]byte, error) {
return uuid[:], nil
}
// UnmarshalBinary implements encoding.BinaryUnmarshaler.
func (uuid *UUID) UnmarshalBinary(data []byte) error {
if len(data) != 16 {
return fmt.Errorf("invalid UUID (got %d bytes)", len(data))
}
copy(uuid[:], data)
return nil
}

89
vendor/github.com/google/uuid/node.go generated vendored Normal file
View File

@ -0,0 +1,89 @@
// Copyright 2016 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
"sync"
)
var (
nodeMu sync.Mutex
ifname string // name of interface being used
nodeID [6]byte // hardware for version 1 UUIDs
zeroID [6]byte // nodeID with only 0's
)
// NodeInterface returns the name of the interface from which the NodeID was
// derived. The interface "user" is returned if the NodeID was set by
// SetNodeID.
func NodeInterface() string {
defer nodeMu.Unlock()
nodeMu.Lock()
return ifname
}
// SetNodeInterface selects the hardware address to be used for Version 1 UUIDs.
// If name is "" then the first usable interface found will be used or a random
// Node ID will be generated. If a named interface cannot be found then false
// is returned.
//
// SetNodeInterface never fails when name is "".
func SetNodeInterface(name string) bool {
defer nodeMu.Unlock()
nodeMu.Lock()
return setNodeInterface(name)
}
func setNodeInterface(name string) bool {
iname, addr := getHardwareInterface(name) // null implementation for js
if iname != "" && addr != nil {
ifname = iname
copy(nodeID[:], addr)
return true
}
// We found no interfaces with a valid hardware address. If name
// does not specify a specific interface generate a random Node ID
// (section 4.1.6)
if name == "" {
randomBits(nodeID[:])
return true
}
return false
}
// NodeID returns a slice of a copy of the current Node ID, setting the Node ID
// if not already set.
func NodeID() []byte {
defer nodeMu.Unlock()
nodeMu.Lock()
if nodeID == zeroID {
setNodeInterface("")
}
nid := nodeID
return nid[:]
}
// SetNodeID sets the Node ID to be used for Version 1 UUIDs. The first 6 bytes
// of id are used. If id is less than 6 bytes then false is returned and the
// Node ID is not set.
func SetNodeID(id []byte) bool {
if len(id) < 6 {
return false
}
defer nodeMu.Unlock()
nodeMu.Lock()
copy(nodeID[:], id)
ifname = "user"
return true
}
// NodeID returns the 6 byte node id encoded in uuid. It returns nil if uuid is
// not valid. The NodeID is only well defined for version 1 and 2 UUIDs.
func (uuid UUID) NodeID() []byte {
var node [6]byte
copy(node[:], uuid[10:])
return node[:]
}

12
vendor/github.com/google/uuid/node_js.go generated vendored Normal file
View File

@ -0,0 +1,12 @@
// Copyright 2017 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build js
package uuid
// getHardwareInterface returns nil values for the JS version of the code.
// This remvoves the "net" dependency, because it is not used in the browser.
// Using the "net" library inflates the size of the transpiled JS code by 673k bytes.
func getHardwareInterface(name string) (string, []byte) { return "", nil }

33
vendor/github.com/google/uuid/node_net.go generated vendored Normal file
View File

@ -0,0 +1,33 @@
// Copyright 2017 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !js
package uuid
import "net"
var interfaces []net.Interface // cached list of interfaces
// getHardwareInterface returns the name and hardware address of interface name.
// If name is "" then the name and hardware address of one of the system's
// interfaces is returned. If no interfaces are found (name does not exist or
// there are no interfaces) then "", nil is returned.
//
// Only addresses of at least 6 bytes are returned.
func getHardwareInterface(name string) (string, []byte) {
if interfaces == nil {
var err error
interfaces, err = net.Interfaces()
if err != nil {
return "", nil
}
}
for _, ifs := range interfaces {
if len(ifs.HardwareAddr) >= 6 && (name == "" || name == ifs.Name) {
return ifs.Name, ifs.HardwareAddr
}
}
return "", nil
}

66
vendor/github.com/google/uuid/seq_test.go generated vendored Normal file
View File

@ -0,0 +1,66 @@
// Copyright 2016 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
"flag"
"runtime"
"testing"
"time"
)
// This test is only run when --regressions is passed on the go test line.
var regressions = flag.Bool("regressions", false, "run uuid regression tests")
// TestClockSeqRace tests for a particular race condition of returning two
// identical Version1 UUIDs. The duration of 1 minute was chosen as the race
// condition, before being fixed, nearly always occurred in under 30 seconds.
func TestClockSeqRace(t *testing.T) {
if !*regressions {
t.Skip("skipping regression tests")
}
duration := time.Minute
done := make(chan struct{})
defer close(done)
ch := make(chan UUID, 10000)
ncpu := runtime.NumCPU()
switch ncpu {
case 0, 1:
// We can't run the test effectively.
t.Skip("skipping race test, only one CPU detected")
return
default:
runtime.GOMAXPROCS(ncpu)
}
for i := 0; i < ncpu; i++ {
go func() {
for {
select {
case <-done:
return
case ch <- Must(NewUUID()):
}
}
}()
}
uuids := make(map[string]bool)
cnt := 0
start := time.Now()
for u := range ch {
s := u.String()
if uuids[s] {
t.Errorf("duplicate uuid after %d in %v: %s", cnt, time.Since(start), s)
return
}
uuids[s] = true
if time.Since(start) > duration {
return
}
cnt++
}
}

59
vendor/github.com/google/uuid/sql.go generated vendored Normal file
View File

@ -0,0 +1,59 @@
// Copyright 2016 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
"database/sql/driver"
"fmt"
)
// Scan implements sql.Scanner so UUIDs can be read from databases transparently
// Currently, database types that map to string and []byte are supported. Please
// consult database-specific driver documentation for matching types.
func (uuid *UUID) Scan(src interface{}) error {
switch src := src.(type) {
case nil:
return nil
case string:
// if an empty UUID comes from a table, we return a null UUID
if src == "" {
return nil
}
// see Parse for required string format
u, err := Parse(src)
if err != nil {
return fmt.Errorf("Scan: %v", err)
}
*uuid = u
case []byte:
// if an empty UUID comes from a table, we return a null UUID
if len(src) == 0 {
return nil
}
// assumes a simple slice of bytes if 16 bytes
// otherwise attempts to parse
if len(src) != 16 {
return uuid.Scan(string(src))
}
copy((*uuid)[:], src)
default:
return fmt.Errorf("Scan: unable to scan type %T into UUID", src)
}
return nil
}
// Value implements sql.Valuer so that UUIDs can be written to databases
// transparently. Currently, UUIDs map to strings. Please consult
// database-specific driver documentation for matching types.
func (uuid UUID) Value() (driver.Value, error) {
return uuid.String(), nil
}

113
vendor/github.com/google/uuid/sql_test.go generated vendored Normal file
View File

@ -0,0 +1,113 @@
// Copyright 2016 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
"strings"
"testing"
)
func TestScan(t *testing.T) {
stringTest := "f47ac10b-58cc-0372-8567-0e02b2c3d479"
badTypeTest := 6
invalidTest := "f47ac10b-58cc-0372-8567-0e02b2c3d4"
byteTest := make([]byte, 16)
byteTestUUID := Must(Parse(stringTest))
copy(byteTest, byteTestUUID[:])
// sunny day tests
var uuid UUID
err := (&uuid).Scan(stringTest)
if err != nil {
t.Fatal(err)
}
err = (&uuid).Scan([]byte(stringTest))
if err != nil {
t.Fatal(err)
}
err = (&uuid).Scan(byteTest)
if err != nil {
t.Fatal(err)
}
// bad type tests
err = (&uuid).Scan(badTypeTest)
if err == nil {
t.Error("int correctly parsed and shouldn't have")
}
if !strings.Contains(err.Error(), "unable to scan type") {
t.Error("attempting to parse an int returned an incorrect error message")
}
// invalid/incomplete uuids
err = (&uuid).Scan(invalidTest)
if err == nil {
t.Error("invalid uuid was parsed without error")
}
if !strings.Contains(err.Error(), "invalid UUID") {
t.Error("attempting to parse an invalid UUID returned an incorrect error message")
}
err = (&uuid).Scan(byteTest[:len(byteTest)-2])
if err == nil {
t.Error("invalid byte uuid was parsed without error")
}
if !strings.Contains(err.Error(), "invalid UUID") {
t.Error("attempting to parse an invalid byte UUID returned an incorrect error message")
}
// empty tests
uuid = UUID{}
var emptySlice []byte
err = (&uuid).Scan(emptySlice)
if err != nil {
t.Fatal(err)
}
for _, v := range uuid {
if v != 0 {
t.Error("UUID was not nil after scanning empty byte slice")
}
}
uuid = UUID{}
var emptyString string
err = (&uuid).Scan(emptyString)
if err != nil {
t.Fatal(err)
}
for _, v := range uuid {
if v != 0 {
t.Error("UUID was not nil after scanning empty byte slice")
}
}
uuid = UUID{}
err = (&uuid).Scan(nil)
if err != nil {
t.Fatal(err)
}
for _, v := range uuid {
if v != 0 {
t.Error("UUID was not nil after scanning nil")
}
}
}
func TestValue(t *testing.T) {
stringTest := "f47ac10b-58cc-0372-8567-0e02b2c3d479"
uuid := Must(Parse(stringTest))
val, _ := uuid.Value()
if val != stringTest {
t.Error("Value() did not return expected string")
}
}

123
vendor/github.com/google/uuid/time.go generated vendored Normal file
View File

@ -0,0 +1,123 @@
// Copyright 2016 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
"encoding/binary"
"sync"
"time"
)
// A Time represents a time as the number of 100's of nanoseconds since 15 Oct
// 1582.
type Time int64
const (
lillian = 2299160 // Julian day of 15 Oct 1582
unix = 2440587 // Julian day of 1 Jan 1970
epoch = unix - lillian // Days between epochs
g1582 = epoch * 86400 // seconds between epochs
g1582ns100 = g1582 * 10000000 // 100s of a nanoseconds between epochs
)
var (
timeMu sync.Mutex
lasttime uint64 // last time we returned
clockSeq uint16 // clock sequence for this run
timeNow = time.Now // for testing
)
// UnixTime converts t the number of seconds and nanoseconds using the Unix
// epoch of 1 Jan 1970.
func (t Time) UnixTime() (sec, nsec int64) {
sec = int64(t - g1582ns100)
nsec = (sec % 10000000) * 100
sec /= 10000000
return sec, nsec
}
// GetTime returns the current Time (100s of nanoseconds since 15 Oct 1582) and
// clock sequence as well as adjusting the clock sequence as needed. An error
// is returned if the current time cannot be determined.
func GetTime() (Time, uint16, error) {
defer timeMu.Unlock()
timeMu.Lock()
return getTime()
}
func getTime() (Time, uint16, error) {
t := timeNow()
// If we don't have a clock sequence already, set one.
if clockSeq == 0 {
setClockSequence(-1)
}
now := uint64(t.UnixNano()/100) + g1582ns100
// If time has gone backwards with this clock sequence then we
// increment the clock sequence
if now <= lasttime {
clockSeq = ((clockSeq + 1) & 0x3fff) | 0x8000
}
lasttime = now
return Time(now), clockSeq, nil
}
// ClockSequence returns the current clock sequence, generating one if not
// already set. The clock sequence is only used for Version 1 UUIDs.
//
// The uuid package does not use global static storage for the clock sequence or
// the last time a UUID was generated. Unless SetClockSequence is used, a new
// random clock sequence is generated the first time a clock sequence is
// requested by ClockSequence, GetTime, or NewUUID. (section 4.2.1.1)
func ClockSequence() int {
defer timeMu.Unlock()
timeMu.Lock()
return clockSequence()
}
func clockSequence() int {
if clockSeq == 0 {
setClockSequence(-1)
}
return int(clockSeq & 0x3fff)
}
// SetClockSequence sets the clock sequence to the lower 14 bits of seq. Setting to
// -1 causes a new sequence to be generated.
func SetClockSequence(seq int) {
defer timeMu.Unlock()
timeMu.Lock()
setClockSequence(seq)
}
func setClockSequence(seq int) {
if seq == -1 {
var b [2]byte
randomBits(b[:]) // clock sequence
seq = int(b[0])<<8 | int(b[1])
}
oldSeq := clockSeq
clockSeq = uint16(seq&0x3fff) | 0x8000 // Set our variant
if oldSeq != clockSeq {
lasttime = 0
}
}
// Time returns the time in 100s of nanoseconds since 15 Oct 1582 encoded in
// uuid. The time is only defined for version 1 and 2 UUIDs.
func (uuid UUID) Time() Time {
time := int64(binary.BigEndian.Uint32(uuid[0:4]))
time |= int64(binary.BigEndian.Uint16(uuid[4:6])) << 32
time |= int64(binary.BigEndian.Uint16(uuid[6:8])&0xfff) << 48
return Time(time)
}
// ClockSequence returns the clock sequence encoded in uuid.
// The clock sequence is only well defined for version 1 and 2 UUIDs.
func (uuid UUID) ClockSequence() int {
return int(binary.BigEndian.Uint16(uuid[8:10])) & 0x3fff
}

43
vendor/github.com/google/uuid/util.go generated vendored Normal file
View File

@ -0,0 +1,43 @@
// Copyright 2016 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
"io"
)
// randomBits completely fills slice b with random data.
func randomBits(b []byte) {
if _, err := io.ReadFull(rander, b); err != nil {
panic(err.Error()) // rand should never fail
}
}
// xvalues returns the value of a byte as a hexadecimal digit or 255.
var xvalues = [256]byte{
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255, 255,
255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
}
// xtob converts hex characters x1 and x2 into a byte.
func xtob(x1, x2 byte) (byte, bool) {
b1 := xvalues[x1]
b2 := xvalues[x2]
return (b1 << 4) | b2, b1 != 255 && b2 != 255
}

245
vendor/github.com/google/uuid/uuid.go generated vendored Normal file
View File

@ -0,0 +1,245 @@
// Copyright 2018 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
"bytes"
"crypto/rand"
"encoding/hex"
"errors"
"fmt"
"io"
"strings"
)
// A UUID is a 128 bit (16 byte) Universal Unique IDentifier as defined in RFC
// 4122.
type UUID [16]byte
// A Version represents a UUID's version.
type Version byte
// A Variant represents a UUID's variant.
type Variant byte
// Constants returned by Variant.
const (
Invalid = Variant(iota) // Invalid UUID
RFC4122 // The variant specified in RFC4122
Reserved // Reserved, NCS backward compatibility.
Microsoft // Reserved, Microsoft Corporation backward compatibility.
Future // Reserved for future definition.
)
var rander = rand.Reader // random function
// Parse decodes s into a UUID or returns an error. Both the standard UUID
// forms of xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx are decoded as well as the
// Microsoft encoding {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} and the raw hex
// encoding: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.
func Parse(s string) (UUID, error) {
var uuid UUID
switch len(s) {
// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
case 36:
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
case 36 + 9:
if strings.ToLower(s[:9]) != "urn:uuid:" {
return uuid, fmt.Errorf("invalid urn prefix: %q", s[:9])
}
s = s[9:]
// {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
case 36 + 2:
s = s[1:]
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
case 32:
var ok bool
for i := range uuid {
uuid[i], ok = xtob(s[i*2], s[i*2+1])
if !ok {
return uuid, errors.New("invalid UUID format")
}
}
return uuid, nil
default:
return uuid, fmt.Errorf("invalid UUID length: %d", len(s))
}
// s is now at least 36 bytes long
// it must be of the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' {
return uuid, errors.New("invalid UUID format")
}
for i, x := range [16]int{
0, 2, 4, 6,
9, 11,
14, 16,
19, 21,
24, 26, 28, 30, 32, 34} {
v, ok := xtob(s[x], s[x+1])
if !ok {
return uuid, errors.New("invalid UUID format")
}
uuid[i] = v
}
return uuid, nil
}
// ParseBytes is like Parse, except it parses a byte slice instead of a string.
func ParseBytes(b []byte) (UUID, error) {
var uuid UUID
switch len(b) {
case 36: // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
case 36 + 9: // urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
if !bytes.Equal(bytes.ToLower(b[:9]), []byte("urn:uuid:")) {
return uuid, fmt.Errorf("invalid urn prefix: %q", b[:9])
}
b = b[9:]
case 36 + 2: // {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
b = b[1:]
case 32: // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
var ok bool
for i := 0; i < 32; i += 2 {
uuid[i/2], ok = xtob(b[i], b[i+1])
if !ok {
return uuid, errors.New("invalid UUID format")
}
}
return uuid, nil
default:
return uuid, fmt.Errorf("invalid UUID length: %d", len(b))
}
// s is now at least 36 bytes long
// it must be of the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
if b[8] != '-' || b[13] != '-' || b[18] != '-' || b[23] != '-' {
return uuid, errors.New("invalid UUID format")
}
for i, x := range [16]int{
0, 2, 4, 6,
9, 11,
14, 16,
19, 21,
24, 26, 28, 30, 32, 34} {
v, ok := xtob(b[x], b[x+1])
if !ok {
return uuid, errors.New("invalid UUID format")
}
uuid[i] = v
}
return uuid, nil
}
// MustParse is like Parse but panics if the string cannot be parsed.
// It simplifies safe initialization of global variables holding compiled UUIDs.
func MustParse(s string) UUID {
uuid, err := Parse(s)
if err != nil {
panic(`uuid: Parse(` + s + `): ` + err.Error())
}
return uuid
}
// FromBytes creates a new UUID from a byte slice. Returns an error if the slice
// does not have a length of 16. The bytes are copied from the slice.
func FromBytes(b []byte) (uuid UUID, err error) {
err = uuid.UnmarshalBinary(b)
return uuid, err
}
// Must returns uuid if err is nil and panics otherwise.
func Must(uuid UUID, err error) UUID {
if err != nil {
panic(err)
}
return uuid
}
// String returns the string form of uuid, xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
// , or "" if uuid is invalid.
func (uuid UUID) String() string {
var buf [36]byte
encodeHex(buf[:], uuid)
return string(buf[:])
}
// URN returns the RFC 2141 URN form of uuid,
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, or "" if uuid is invalid.
func (uuid UUID) URN() string {
var buf [36 + 9]byte
copy(buf[:], "urn:uuid:")
encodeHex(buf[9:], uuid)
return string(buf[:])
}
func encodeHex(dst []byte, uuid UUID) {
hex.Encode(dst, uuid[:4])
dst[8] = '-'
hex.Encode(dst[9:13], uuid[4:6])
dst[13] = '-'
hex.Encode(dst[14:18], uuid[6:8])
dst[18] = '-'
hex.Encode(dst[19:23], uuid[8:10])
dst[23] = '-'
hex.Encode(dst[24:], uuid[10:])
}
// Variant returns the variant encoded in uuid.
func (uuid UUID) Variant() Variant {
switch {
case (uuid[8] & 0xc0) == 0x80:
return RFC4122
case (uuid[8] & 0xe0) == 0xc0:
return Microsoft
case (uuid[8] & 0xe0) == 0xe0:
return Future
default:
return Reserved
}
}
// Version returns the version of uuid.
func (uuid UUID) Version() Version {
return Version(uuid[6] >> 4)
}
func (v Version) String() string {
if v > 15 {
return fmt.Sprintf("BAD_VERSION_%d", v)
}
return fmt.Sprintf("VERSION_%d", v)
}
func (v Variant) String() string {
switch v {
case RFC4122:
return "RFC4122"
case Reserved:
return "Reserved"
case Microsoft:
return "Microsoft"
case Future:
return "Future"
case Invalid:
return "Invalid"
}
return fmt.Sprintf("BadVariant%d", int(v))
}
// SetRand sets the random number generator to r, which implements io.Reader.
// If r.Read returns an error when the package requests random data then
// a panic will be issued.
//
// Calling SetRand with nil sets the random number generator to the default
// generator.
func SetRand(r io.Reader) {
if r == nil {
rander = rand.Reader
return
}
rander = r
}

559
vendor/github.com/google/uuid/uuid_test.go generated vendored Normal file
View File

@ -0,0 +1,559 @@
// Copyright 2016 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
"bytes"
"fmt"
"os"
"runtime"
"strings"
"testing"
"time"
"unsafe"
)
type test struct {
in string
version Version
variant Variant
isuuid bool
}
var tests = []test{
{"f47ac10b-58cc-0372-8567-0e02b2c3d479", 0, RFC4122, true},
{"f47ac10b-58cc-1372-8567-0e02b2c3d479", 1, RFC4122, true},
{"f47ac10b-58cc-2372-8567-0e02b2c3d479", 2, RFC4122, true},
{"f47ac10b-58cc-3372-8567-0e02b2c3d479", 3, RFC4122, true},
{"f47ac10b-58cc-4372-8567-0e02b2c3d479", 4, RFC4122, true},
{"f47ac10b-58cc-5372-8567-0e02b2c3d479", 5, RFC4122, true},
{"f47ac10b-58cc-6372-8567-0e02b2c3d479", 6, RFC4122, true},
{"f47ac10b-58cc-7372-8567-0e02b2c3d479", 7, RFC4122, true},
{"f47ac10b-58cc-8372-8567-0e02b2c3d479", 8, RFC4122, true},
{"f47ac10b-58cc-9372-8567-0e02b2c3d479", 9, RFC4122, true},
{"f47ac10b-58cc-a372-8567-0e02b2c3d479", 10, RFC4122, true},
{"f47ac10b-58cc-b372-8567-0e02b2c3d479", 11, RFC4122, true},
{"f47ac10b-58cc-c372-8567-0e02b2c3d479", 12, RFC4122, true},
{"f47ac10b-58cc-d372-8567-0e02b2c3d479", 13, RFC4122, true},
{"f47ac10b-58cc-e372-8567-0e02b2c3d479", 14, RFC4122, true},
{"f47ac10b-58cc-f372-8567-0e02b2c3d479", 15, RFC4122, true},
{"urn:uuid:f47ac10b-58cc-4372-0567-0e02b2c3d479", 4, Reserved, true},
{"URN:UUID:f47ac10b-58cc-4372-0567-0e02b2c3d479", 4, Reserved, true},
{"f47ac10b-58cc-4372-0567-0e02b2c3d479", 4, Reserved, true},
{"f47ac10b-58cc-4372-1567-0e02b2c3d479", 4, Reserved, true},
{"f47ac10b-58cc-4372-2567-0e02b2c3d479", 4, Reserved, true},
{"f47ac10b-58cc-4372-3567-0e02b2c3d479", 4, Reserved, true},
{"f47ac10b-58cc-4372-4567-0e02b2c3d479", 4, Reserved, true},
{"f47ac10b-58cc-4372-5567-0e02b2c3d479", 4, Reserved, true},
{"f47ac10b-58cc-4372-6567-0e02b2c3d479", 4, Reserved, true},
{"f47ac10b-58cc-4372-7567-0e02b2c3d479", 4, Reserved, true},
{"f47ac10b-58cc-4372-8567-0e02b2c3d479", 4, RFC4122, true},
{"f47ac10b-58cc-4372-9567-0e02b2c3d479", 4, RFC4122, true},
{"f47ac10b-58cc-4372-a567-0e02b2c3d479", 4, RFC4122, true},
{"f47ac10b-58cc-4372-b567-0e02b2c3d479", 4, RFC4122, true},
{"f47ac10b-58cc-4372-c567-0e02b2c3d479", 4, Microsoft, true},
{"f47ac10b-58cc-4372-d567-0e02b2c3d479", 4, Microsoft, true},
{"f47ac10b-58cc-4372-e567-0e02b2c3d479", 4, Future, true},
{"f47ac10b-58cc-4372-f567-0e02b2c3d479", 4, Future, true},
{"f47ac10b158cc-5372-a567-0e02b2c3d479", 0, Invalid, false},
{"f47ac10b-58cc25372-a567-0e02b2c3d479", 0, Invalid, false},
{"f47ac10b-58cc-53723a567-0e02b2c3d479", 0, Invalid, false},
{"f47ac10b-58cc-5372-a56740e02b2c3d479", 0, Invalid, false},
{"f47ac10b-58cc-5372-a567-0e02-2c3d479", 0, Invalid, false},
{"g47ac10b-58cc-4372-a567-0e02b2c3d479", 0, Invalid, false},
{"{f47ac10b-58cc-0372-8567-0e02b2c3d479}", 0, RFC4122, true},
{"{f47ac10b-58cc-0372-8567-0e02b2c3d479", 0, Invalid, false},
{"f47ac10b-58cc-0372-8567-0e02b2c3d479}", 0, Invalid, false},
{"f47ac10b58cc037285670e02b2c3d479", 0, RFC4122, true},
{"f47ac10b58cc037285670e02b2c3d4790", 0, Invalid, false},
{"f47ac10b58cc037285670e02b2c3d47", 0, Invalid, false},
}
var constants = []struct {
c interface{}
name string
}{
{Person, "Person"},
{Group, "Group"},
{Org, "Org"},
{Invalid, "Invalid"},
{RFC4122, "RFC4122"},
{Reserved, "Reserved"},
{Microsoft, "Microsoft"},
{Future, "Future"},
{Domain(17), "Domain17"},
{Variant(42), "BadVariant42"},
}
func testTest(t *testing.T, in string, tt test) {
uuid, err := Parse(in)
if ok := (err == nil); ok != tt.isuuid {
t.Errorf("Parse(%s) got %v expected %v\b", in, ok, tt.isuuid)
}
if err != nil {
return
}
if v := uuid.Variant(); v != tt.variant {
t.Errorf("Variant(%s) got %d expected %d\b", in, v, tt.variant)
}
if v := uuid.Version(); v != tt.version {
t.Errorf("Version(%s) got %d expected %d\b", in, v, tt.version)
}
}
func testBytes(t *testing.T, in []byte, tt test) {
uuid, err := ParseBytes(in)
if ok := (err == nil); ok != tt.isuuid {
t.Errorf("ParseBytes(%s) got %v expected %v\b", in, ok, tt.isuuid)
}
if err != nil {
return
}
suuid, _ := Parse(string(in))
if uuid != suuid {
t.Errorf("ParseBytes(%s) got %v expected %v\b", in, uuid, suuid)
}
}
func TestUUID(t *testing.T) {
for _, tt := range tests {
testTest(t, tt.in, tt)
testTest(t, strings.ToUpper(tt.in), tt)
testBytes(t, []byte(tt.in), tt)
}
}
func TestFromBytes(t *testing.T) {
b := []byte{
0x7d, 0x44, 0x48, 0x40,
0x9d, 0xc0,
0x11, 0xd1,
0xb2, 0x45,
0x5f, 0xfd, 0xce, 0x74, 0xfa, 0xd2,
}
uuid, err := FromBytes(b)
if err != nil {
t.Fatalf("%s", err)
}
for i := 0; i < len(uuid); i++ {
if b[i] != uuid[i] {
t.Fatalf("FromBytes() got %v expected %v\b", uuid[:], b)
}
}
}
func TestConstants(t *testing.T) {
for x, tt := range constants {
v, ok := tt.c.(fmt.Stringer)
if !ok {
t.Errorf("%x: %v: not a stringer", x, v)
} else if s := v.String(); s != tt.name {
v, _ := tt.c.(int)
t.Errorf("%x: Constant %T:%d gives %q, expected %q", x, tt.c, v, s, tt.name)
}
}
}
func TestRandomUUID(t *testing.T) {
m := make(map[string]bool)
for x := 1; x < 32; x++ {
uuid := New()
s := uuid.String()
if m[s] {
t.Errorf("NewRandom returned duplicated UUID %s", s)
}
m[s] = true
if v := uuid.Version(); v != 4 {
t.Errorf("Random UUID of version %s", v)
}
if uuid.Variant() != RFC4122 {
t.Errorf("Random UUID is variant %d", uuid.Variant())
}
}
}
func TestNew(t *testing.T) {
m := make(map[UUID]bool)
for x := 1; x < 32; x++ {
s := New()
if m[s] {
t.Errorf("New returned duplicated UUID %s", s)
}
m[s] = true
uuid, err := Parse(s.String())
if err != nil {
t.Errorf("New.String() returned %q which does not decode", s)
continue
}
if v := uuid.Version(); v != 4 {
t.Errorf("Random UUID of version %s", v)
}
if uuid.Variant() != RFC4122 {
t.Errorf("Random UUID is variant %d", uuid.Variant())
}
}
}
func TestClockSeq(t *testing.T) {
// Fake time.Now for this test to return a monotonically advancing time; restore it at end.
defer func(orig func() time.Time) { timeNow = orig }(timeNow)
monTime := time.Now()
timeNow = func() time.Time {
monTime = monTime.Add(1 * time.Second)
return monTime
}
SetClockSequence(-1)
uuid1, err := NewUUID()
if err != nil {
t.Fatalf("could not create UUID: %v", err)
}
uuid2, err := NewUUID()
if err != nil {
t.Fatalf("could not create UUID: %v", err)
}
if s1, s2 := uuid1.ClockSequence(), uuid2.ClockSequence(); s1 != s2 {
t.Errorf("clock sequence %d != %d", s1, s2)
}
SetClockSequence(-1)
uuid2, err = NewUUID()
if err != nil {
t.Fatalf("could not create UUID: %v", err)
}
// Just on the very off chance we generated the same sequence
// two times we try again.
if uuid1.ClockSequence() == uuid2.ClockSequence() {
SetClockSequence(-1)
uuid2, err = NewUUID()
if err != nil {
t.Fatalf("could not create UUID: %v", err)
}
}
if s1, s2 := uuid1.ClockSequence(), uuid2.ClockSequence(); s1 == s2 {
t.Errorf("Duplicate clock sequence %d", s1)
}
SetClockSequence(0x1234)
uuid1, err = NewUUID()
if err != nil {
t.Fatalf("could not create UUID: %v", err)
}
if seq := uuid1.ClockSequence(); seq != 0x1234 {
t.Errorf("%s: expected seq 0x1234 got 0x%04x", uuid1, seq)
}
}
func TestCoding(t *testing.T) {
text := "7d444840-9dc0-11d1-b245-5ffdce74fad2"
urn := "urn:uuid:7d444840-9dc0-11d1-b245-5ffdce74fad2"
data := UUID{
0x7d, 0x44, 0x48, 0x40,
0x9d, 0xc0,
0x11, 0xd1,
0xb2, 0x45,
0x5f, 0xfd, 0xce, 0x74, 0xfa, 0xd2,
}
if v := data.String(); v != text {
t.Errorf("%x: encoded to %s, expected %s", data, v, text)
}
if v := data.URN(); v != urn {
t.Errorf("%x: urn is %s, expected %s", data, v, urn)
}
uuid, err := Parse(text)
if err != nil {
t.Errorf("Parse returned unexpected error %v", err)
}
if data != uuid {
t.Errorf("%s: decoded to %s, expected %s", text, uuid, data)
}
}
func TestVersion1(t *testing.T) {
uuid1, err := NewUUID()
if err != nil {
t.Fatalf("could not create UUID: %v", err)
}
uuid2, err := NewUUID()
if err != nil {
t.Fatalf("could not create UUID: %v", err)
}
if uuid1 == uuid2 {
t.Errorf("%s:duplicate uuid", uuid1)
}
if v := uuid1.Version(); v != 1 {
t.Errorf("%s: version %s expected 1", uuid1, v)
}
if v := uuid2.Version(); v != 1 {
t.Errorf("%s: version %s expected 1", uuid2, v)
}
n1 := uuid1.NodeID()
n2 := uuid2.NodeID()
if !bytes.Equal(n1, n2) {
t.Errorf("Different nodes %x != %x", n1, n2)
}
t1 := uuid1.Time()
t2 := uuid2.Time()
q1 := uuid1.ClockSequence()
q2 := uuid2.ClockSequence()
switch {
case t1 == t2 && q1 == q2:
t.Error("time stopped")
case t1 > t2 && q1 == q2:
t.Error("time reversed")
case t1 < t2 && q1 != q2:
t.Error("clock sequence changed unexpectedly")
}
}
func TestNode(t *testing.T) {
// This test is mostly to make sure we don't leave nodeMu locked.
ifname = ""
if ni := NodeInterface(); ni != "" {
t.Errorf("NodeInterface got %q, want %q", ni, "")
}
if SetNodeInterface("xyzzy") {
t.Error("SetNodeInterface succeeded on a bad interface name")
}
if !SetNodeInterface("") {
t.Error("SetNodeInterface failed")
}
if runtime.GOARCH != "js" {
if ni := NodeInterface(); ni == "" {
t.Error("NodeInterface returned an empty string")
}
}
ni := NodeID()
if len(ni) != 6 {
t.Errorf("ni got %d bytes, want 6", len(ni))
}
hasData := false
for _, b := range ni {
if b != 0 {
hasData = true
}
}
if !hasData {
t.Error("nodeid is all zeros")
}
id := []byte{1, 2, 3, 4, 5, 6, 7, 8}
SetNodeID(id)
ni = NodeID()
if !bytes.Equal(ni, id[:6]) {
t.Errorf("got nodeid %v, want %v", ni, id[:6])
}
if ni := NodeInterface(); ni != "user" {
t.Errorf("got interface %q, want %q", ni, "user")
}
}
func TestNodeAndTime(t *testing.T) {
// Time is February 5, 1998 12:30:23.136364800 AM GMT
uuid, err := Parse("7d444840-9dc0-11d1-b245-5ffdce74fad2")
if err != nil {
t.Fatalf("Parser returned unexpected error %v", err)
}
node := []byte{0x5f, 0xfd, 0xce, 0x74, 0xfa, 0xd2}
ts := uuid.Time()
c := time.Unix(ts.UnixTime())
want := time.Date(1998, 2, 5, 0, 30, 23, 136364800, time.UTC)
if !c.Equal(want) {
t.Errorf("Got time %v, want %v", c, want)
}
if !bytes.Equal(node, uuid.NodeID()) {
t.Errorf("Expected node %v got %v", node, uuid.NodeID())
}
}
func TestMD5(t *testing.T) {
uuid := NewMD5(NameSpaceDNS, []byte("python.org")).String()
want := "6fa459ea-ee8a-3ca4-894e-db77e160355e"
if uuid != want {
t.Errorf("MD5: got %q expected %q", uuid, want)
}
}
func TestSHA1(t *testing.T) {
uuid := NewSHA1(NameSpaceDNS, []byte("python.org")).String()
want := "886313e1-3b8a-5372-9b90-0c9aee199e5d"
if uuid != want {
t.Errorf("SHA1: got %q expected %q", uuid, want)
}
}
func TestNodeID(t *testing.T) {
nid := []byte{1, 2, 3, 4, 5, 6}
SetNodeInterface("")
s := NodeInterface()
if runtime.GOARCH != "js" {
if s == "" || s == "user" {
t.Errorf("NodeInterface %q after SetInterface", s)
}
}
node1 := NodeID()
if node1 == nil {
t.Error("NodeID nil after SetNodeInterface", s)
}
SetNodeID(nid)
s = NodeInterface()
if s != "user" {
t.Errorf("Expected NodeInterface %q got %q", "user", s)
}
node2 := NodeID()
if node2 == nil {
t.Error("NodeID nil after SetNodeID", s)
}
if bytes.Equal(node1, node2) {
t.Error("NodeID not changed after SetNodeID", s)
} else if !bytes.Equal(nid, node2) {
t.Errorf("NodeID is %x, expected %x", node2, nid)
}
}
func testDCE(t *testing.T, name string, uuid UUID, err error, domain Domain, id uint32) {
if err != nil {
t.Errorf("%s failed: %v", name, err)
return
}
if v := uuid.Version(); v != 2 {
t.Errorf("%s: %s: expected version 2, got %s", name, uuid, v)
return
}
if v := uuid.Domain(); v != domain {
t.Errorf("%s: %s: expected domain %d, got %d", name, uuid, domain, v)
}
if v := uuid.ID(); v != id {
t.Errorf("%s: %s: expected id %d, got %d", name, uuid, id, v)
}
}
func TestDCE(t *testing.T) {
uuid, err := NewDCESecurity(42, 12345678)
testDCE(t, "NewDCESecurity", uuid, err, 42, 12345678)
uuid, err = NewDCEPerson()
testDCE(t, "NewDCEPerson", uuid, err, Person, uint32(os.Getuid()))
uuid, err = NewDCEGroup()
testDCE(t, "NewDCEGroup", uuid, err, Group, uint32(os.Getgid()))
}
type badRand struct{}
func (r badRand) Read(buf []byte) (int, error) {
for i := range buf {
buf[i] = byte(i)
}
return len(buf), nil
}
func TestBadRand(t *testing.T) {
SetRand(badRand{})
uuid1 := New()
uuid2 := New()
if uuid1 != uuid2 {
t.Errorf("expected duplicates, got %q and %q", uuid1, uuid2)
}
SetRand(nil)
uuid1 = New()
uuid2 = New()
if uuid1 == uuid2 {
t.Errorf("unexpected duplicates, got %q", uuid1)
}
}
var asString = "f47ac10b-58cc-0372-8567-0e02b2c3d479"
var asBytes = []byte(asString)
func BenchmarkParse(b *testing.B) {
for i := 0; i < b.N; i++ {
_, err := Parse(asString)
if err != nil {
b.Fatal(err)
}
}
}
func BenchmarkParseBytes(b *testing.B) {
for i := 0; i < b.N; i++ {
_, err := ParseBytes(asBytes)
if err != nil {
b.Fatal(err)
}
}
}
// parseBytesUnsafe is to benchmark using unsafe.
func parseBytesUnsafe(b []byte) (UUID, error) {
return Parse(*(*string)(unsafe.Pointer(&b)))
}
func BenchmarkParseBytesUnsafe(b *testing.B) {
for i := 0; i < b.N; i++ {
_, err := parseBytesUnsafe(asBytes)
if err != nil {
b.Fatal(err)
}
}
}
// parseBytesCopy is to benchmark not using unsafe.
func parseBytesCopy(b []byte) (UUID, error) {
return Parse(string(b))
}
func BenchmarkParseBytesCopy(b *testing.B) {
for i := 0; i < b.N; i++ {
_, err := parseBytesCopy(asBytes)
if err != nil {
b.Fatal(err)
}
}
}
func BenchmarkNew(b *testing.B) {
for i := 0; i < b.N; i++ {
New()
}
}
func BenchmarkUUID_String(b *testing.B) {
uuid, err := Parse("f47ac10b-58cc-0372-8567-0e02b2c3d479")
if err != nil {
b.Fatal(err)
}
for i := 0; i < b.N; i++ {
if uuid.String() == "" {
b.Fatal("invalid uuid")
}
}
}
func BenchmarkUUID_URN(b *testing.B) {
uuid, err := Parse("f47ac10b-58cc-0372-8567-0e02b2c3d479")
if err != nil {
b.Fatal(err)
}
for i := 0; i < b.N; i++ {
if uuid.URN() == "" {
b.Fatal("invalid uuid")
}
}
}

44
vendor/github.com/google/uuid/version1.go generated vendored Normal file
View File

@ -0,0 +1,44 @@
// Copyright 2016 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
"encoding/binary"
)
// NewUUID returns a Version 1 UUID based on the current NodeID and clock
// sequence, and the current time. If the NodeID has not been set by SetNodeID
// or SetNodeInterface then it will be set automatically. If the NodeID cannot
// be set NewUUID returns nil. If clock sequence has not been set by
// SetClockSequence then it will be set automatically. If GetTime fails to
// return the current NewUUID returns nil and an error.
//
// In most cases, New should be used.
func NewUUID() (UUID, error) {
nodeMu.Lock()
if nodeID == zeroID {
setNodeInterface("")
}
nodeMu.Unlock()
var uuid UUID
now, seq, err := GetTime()
if err != nil {
return uuid, err
}
timeLow := uint32(now & 0xffffffff)
timeMid := uint16((now >> 32) & 0xffff)
timeHi := uint16((now >> 48) & 0x0fff)
timeHi |= 0x1000 // Version 1
binary.BigEndian.PutUint32(uuid[0:], timeLow)
binary.BigEndian.PutUint16(uuid[4:], timeMid)
binary.BigEndian.PutUint16(uuid[6:], timeHi)
binary.BigEndian.PutUint16(uuid[8:], seq)
copy(uuid[10:], nodeID[:])
return uuid, nil
}

38
vendor/github.com/google/uuid/version4.go generated vendored Normal file
View File

@ -0,0 +1,38 @@
// Copyright 2016 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import "io"
// New creates a new random UUID or panics. New is equivalent to
// the expression
//
// uuid.Must(uuid.NewRandom())
func New() UUID {
return Must(NewRandom())
}
// NewRandom returns a Random (Version 4) UUID.
//
// The strength of the UUIDs is based on the strength of the crypto/rand
// package.
//
// A note about uniqueness derived from the UUID Wikipedia entry:
//
// Randomly generated UUIDs have 122 random bits. One's annual risk of being
// hit by a meteorite is estimated to be one chance in 17 billion, that
// means the probability is about 0.00000000006 (6 × 1011),
// equivalent to the odds of creating a few tens of trillions of UUIDs in a
// year and having one duplicate.
func NewRandom() (UUID, error) {
var uuid UUID
_, err := io.ReadFull(rander, uuid[:])
if err != nil {
return Nil, err
}
uuid[6] = (uuid[6] & 0x0f) | 0x40 // Version 4
uuid[8] = (uuid[8] & 0x3f) | 0x80 // Variant is 10
return uuid, nil
}

10
vendor/github.com/pborman/uuid/.travis.yml generated vendored Normal file
View File

@ -0,0 +1,10 @@
language: go
go:
- "1.9"
- "1.10"
- "1.11"
- tip
script:
- go test -v ./...

10
vendor/github.com/pborman/uuid/CONTRIBUTING.md generated vendored Normal file
View File

@ -0,0 +1,10 @@
# How to contribute
We definitely welcome patches and contribution to this project!
### Legal requirements
In order to protect both you and ourselves, you will need to sign the
[Contributor License Agreement](https://cla.developers.google.com/clas).
You may have already signed it for other Google projects.

1
vendor/github.com/pborman/uuid/CONTRIBUTORS generated vendored Normal file
View File

@ -0,0 +1 @@
Paul Borman <borman@google.com>

27
vendor/github.com/pborman/uuid/LICENSE generated vendored Normal file
View File

@ -0,0 +1,27 @@
Copyright (c) 2009,2014 Google Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* 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.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
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.

15
vendor/github.com/pborman/uuid/README.md generated vendored Normal file
View File

@ -0,0 +1,15 @@
This project was automatically exported from code.google.com/p/go-uuid
# uuid ![build status](https://travis-ci.org/pborman/uuid.svg?branch=master)
The uuid package generates and inspects UUIDs based on [RFC 4122](http://tools.ietf.org/html/rfc4122) and DCE 1.1: Authentication and Security Services.
This package now leverages the github.com/google/uuid package (which is based off an earlier version of this package).
###### Install
`go get github.com/pborman/uuid`
###### Documentation
[![GoDoc](https://godoc.org/github.com/pborman/uuid?status.svg)](http://godoc.org/github.com/pborman/uuid)
Full `go doc` style documentation for the package can be viewed online without installing this package by using the GoDoc site here:
http://godoc.org/github.com/pborman/uuid

84
vendor/github.com/pborman/uuid/dce.go generated vendored Normal file
View File

@ -0,0 +1,84 @@
// Copyright 2011 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
"encoding/binary"
"fmt"
"os"
)
// A Domain represents a Version 2 domain
type Domain byte
// Domain constants for DCE Security (Version 2) UUIDs.
const (
Person = Domain(0)
Group = Domain(1)
Org = Domain(2)
)
// NewDCESecurity returns a DCE Security (Version 2) UUID.
//
// The domain should be one of Person, Group or Org.
// On a POSIX system the id should be the users UID for the Person
// domain and the users GID for the Group. The meaning of id for
// the domain Org or on non-POSIX systems is site defined.
//
// For a given domain/id pair the same token may be returned for up to
// 7 minutes and 10 seconds.
func NewDCESecurity(domain Domain, id uint32) UUID {
uuid := NewUUID()
if uuid != nil {
uuid[6] = (uuid[6] & 0x0f) | 0x20 // Version 2
uuid[9] = byte(domain)
binary.BigEndian.PutUint32(uuid[0:], id)
}
return uuid
}
// NewDCEPerson returns a DCE Security (Version 2) UUID in the person
// domain with the id returned by os.Getuid.
//
// NewDCEPerson(Person, uint32(os.Getuid()))
func NewDCEPerson() UUID {
return NewDCESecurity(Person, uint32(os.Getuid()))
}
// NewDCEGroup returns a DCE Security (Version 2) UUID in the group
// domain with the id returned by os.Getgid.
//
// NewDCEGroup(Group, uint32(os.Getgid()))
func NewDCEGroup() UUID {
return NewDCESecurity(Group, uint32(os.Getgid()))
}
// Domain returns the domain for a Version 2 UUID or false.
func (uuid UUID) Domain() (Domain, bool) {
if v, _ := uuid.Version(); v != 2 {
return 0, false
}
return Domain(uuid[9]), true
}
// Id returns the id for a Version 2 UUID or false.
func (uuid UUID) Id() (uint32, bool) {
if v, _ := uuid.Version(); v != 2 {
return 0, false
}
return binary.BigEndian.Uint32(uuid[0:4]), true
}
func (d Domain) String() string {
switch d {
case Person:
return "Person"
case Group:
return "Group"
case Org:
return "Org"
}
return fmt.Sprintf("Domain%d", int(d))
}

13
vendor/github.com/pborman/uuid/doc.go generated vendored Normal file
View File

@ -0,0 +1,13 @@
// Copyright 2011 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// The uuid package generates and inspects UUIDs.
//
// UUIDs are based on RFC 4122 and DCE 1.1: Authentication and Security
// Services.
//
// This package is a partial wrapper around the github.com/google/uuid package.
// This package represents a UUID as []byte while github.com/google/uuid
// represents a UUID as [16]byte.
package uuid

3
vendor/github.com/pborman/uuid/go.mod generated vendored Normal file
View File

@ -0,0 +1,3 @@
module github.com/pborman/uuid
require github.com/google/uuid v1.0.0

2
vendor/github.com/pborman/uuid/go.sum generated vendored Normal file
View File

@ -0,0 +1,2 @@
github.com/google/uuid v1.0.0 h1:b4Gk+7WdP/d3HZH8EJsZpvV7EtDOgaZLtnaNGIu1adA=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=

53
vendor/github.com/pborman/uuid/hash.go generated vendored Normal file
View File

@ -0,0 +1,53 @@
// Copyright 2011 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
"crypto/md5"
"crypto/sha1"
"hash"
)
// Well known Name Space IDs and UUIDs
var (
NameSpace_DNS = Parse("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
NameSpace_URL = Parse("6ba7b811-9dad-11d1-80b4-00c04fd430c8")
NameSpace_OID = Parse("6ba7b812-9dad-11d1-80b4-00c04fd430c8")
NameSpace_X500 = Parse("6ba7b814-9dad-11d1-80b4-00c04fd430c8")
NIL = Parse("00000000-0000-0000-0000-000000000000")
)
// NewHash returns a new UUID derived from the hash of space concatenated with
// data generated by h. The hash should be at least 16 byte in length. The
// first 16 bytes of the hash are used to form the UUID. The version of the
// UUID will be the lower 4 bits of version. NewHash is used to implement
// NewMD5 and NewSHA1.
func NewHash(h hash.Hash, space UUID, data []byte, version int) UUID {
h.Reset()
h.Write(space)
h.Write([]byte(data))
s := h.Sum(nil)
uuid := make([]byte, 16)
copy(uuid, s)
uuid[6] = (uuid[6] & 0x0f) | uint8((version&0xf)<<4)
uuid[8] = (uuid[8] & 0x3f) | 0x80 // RFC 4122 variant
return uuid
}
// NewMD5 returns a new MD5 (Version 3) UUID based on the
// supplied name space and data.
//
// NewHash(md5.New(), space, data, 3)
func NewMD5(space UUID, data []byte) UUID {
return NewHash(md5.New(), space, data, 3)
}
// NewSHA1 returns a new SHA1 (Version 5) UUID based on the
// supplied name space and data.
//
// NewHash(sha1.New(), space, data, 5)
func NewSHA1(space UUID, data []byte) UUID {
return NewHash(sha1.New(), space, data, 5)
}

85
vendor/github.com/pborman/uuid/marshal.go generated vendored Normal file
View File

@ -0,0 +1,85 @@
// Copyright 2016 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
"errors"
"fmt"
guuid "github.com/google/uuid"
)
// MarshalText implements encoding.TextMarshaler.
func (u UUID) MarshalText() ([]byte, error) {
if len(u) != 16 {
return nil, nil
}
var js [36]byte
encodeHex(js[:], u)
return js[:], nil
}
// UnmarshalText implements encoding.TextUnmarshaler.
func (u *UUID) UnmarshalText(data []byte) error {
if len(data) == 0 {
return nil
}
id := Parse(string(data))
if id == nil {
return errors.New("invalid UUID")
}
*u = id
return nil
}
// MarshalBinary implements encoding.BinaryMarshaler.
func (u UUID) MarshalBinary() ([]byte, error) {
return u[:], nil
}
// UnmarshalBinary implements encoding.BinaryUnmarshaler.
func (u *UUID) UnmarshalBinary(data []byte) error {
if len(data) == 0 {
return nil
}
if len(data) != 16 {
return fmt.Errorf("invalid UUID (got %d bytes)", len(data))
}
var id [16]byte
copy(id[:], data)
*u = id[:]
return nil
}
// MarshalText implements encoding.TextMarshaler.
func (u Array) MarshalText() ([]byte, error) {
var js [36]byte
encodeHex(js[:], u[:])
return js[:], nil
}
// UnmarshalText implements encoding.TextUnmarshaler.
func (u *Array) UnmarshalText(data []byte) error {
id, err := guuid.ParseBytes(data)
if err != nil {
return err
}
*u = Array(id)
return nil
}
// MarshalBinary implements encoding.BinaryMarshaler.
func (u Array) MarshalBinary() ([]byte, error) {
return u[:], nil
}
// UnmarshalBinary implements encoding.BinaryUnmarshaler.
func (u *Array) UnmarshalBinary(data []byte) error {
if len(data) != 16 {
return fmt.Errorf("invalid UUID (got %d bytes)", len(data))
}
copy(u[:], data)
return nil
}

124
vendor/github.com/pborman/uuid/marshal_test.go generated vendored Normal file
View File

@ -0,0 +1,124 @@
// Copyright 2014 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
"bytes"
"encoding/json"
"reflect"
"testing"
)
var testUUID = Parse("f47ac10b-58cc-0372-8567-0e02b2c3d479")
var testArray = testUUID.Array()
func TestJSON(t *testing.T) {
type S struct {
ID1 UUID
ID2 UUID
}
s1 := S{ID1: testUUID}
data, err := json.Marshal(&s1)
if err != nil {
t.Fatal(err)
}
var s2 S
if err := json.Unmarshal(data, &s2); err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(&s1, &s2) {
t.Errorf("got %#v, want %#v", s2, s1)
}
}
func TestJSONArray(t *testing.T) {
type S struct {
ID1 Array
ID2 Array
}
s1 := S{ID1: testArray}
data, err := json.Marshal(&s1)
if err != nil {
t.Fatal(err)
}
var s2 S
if err := json.Unmarshal(data, &s2); err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(&s1, &s2) {
t.Errorf("got %#v, want %#v", s2, s1)
}
}
func TestMarshal(t *testing.T) {
data, err := testUUID.MarshalBinary()
if err != nil {
t.Fatalf("MarhsalBinary returned unexpected error %v", err)
}
if !bytes.Equal(data, testUUID) {
t.Fatalf("MarhsalBinary returns %x, want %x", data, testUUID)
}
var u UUID
u.UnmarshalBinary(data)
if !Equal(data, u) {
t.Fatalf("UnmarhsalBinary returns %v, want %v", u, testUUID)
}
}
func TestMarshalArray(t *testing.T) {
data, err := testArray.MarshalBinary()
if err != nil {
t.Fatalf("MarhsalBinary returned unexpected error %v", err)
}
if !bytes.Equal(data, testUUID) {
t.Fatalf("MarhsalBinary returns %x, want %x", data, testUUID)
}
var a Array
a.UnmarshalBinary(data)
if a != testArray {
t.Fatalf("UnmarhsalBinary returns %v, want %v", a, testArray)
}
}
func TestMarshalTextArray(t *testing.T) {
data, err := testArray.MarshalText()
if err != nil {
t.Fatalf("MarhsalText returned unexpected error %v", err)
}
var a Array
a.UnmarshalText(data)
if a != testArray {
t.Fatalf("UnmarhsalText returns %v, want %v", a, testArray)
}
}
func BenchmarkUUID_MarshalJSON(b *testing.B) {
x := &struct {
UUID UUID `json:"uuid"`
}{}
x.UUID = Parse("f47ac10b-58cc-0372-8567-0e02b2c3d479")
if x.UUID == nil {
b.Fatal("invalid uuid")
}
for i := 0; i < b.N; i++ {
js, err := json.Marshal(x)
if err != nil {
b.Fatalf("marshal json: %#v (%v)", js, err)
}
}
}
func BenchmarkUUID_UnmarshalJSON(b *testing.B) {
js := []byte(`{"uuid":"f47ac10b-58cc-0372-8567-0e02b2c3d479"}`)
var x *struct {
UUID UUID `json:"uuid"`
}
for i := 0; i < b.N; i++ {
err := json.Unmarshal(js, &x)
if err != nil {
b.Fatalf("marshal json: %#v (%v)", js, err)
}
}
}

50
vendor/github.com/pborman/uuid/node.go generated vendored Normal file
View File

@ -0,0 +1,50 @@
// Copyright 2011 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
guuid "github.com/google/uuid"
)
// NodeInterface returns the name of the interface from which the NodeID was
// derived. The interface "user" is returned if the NodeID was set by
// SetNodeID.
func NodeInterface() string {
return guuid.NodeInterface()
}
// SetNodeInterface selects the hardware address to be used for Version 1 UUIDs.
// If name is "" then the first usable interface found will be used or a random
// Node ID will be generated. If a named interface cannot be found then false
// is returned.
//
// SetNodeInterface never fails when name is "".
func SetNodeInterface(name string) bool {
return guuid.SetNodeInterface(name)
}
// NodeID returns a slice of a copy of the current Node ID, setting the Node ID
// if not already set.
func NodeID() []byte {
return guuid.NodeID()
}
// SetNodeID sets the Node ID to be used for Version 1 UUIDs. The first 6 bytes
// of id are used. If id is less than 6 bytes then false is returned and the
// Node ID is not set.
func SetNodeID(id []byte) bool {
return guuid.SetNodeID(id)
}
// NodeID returns the 6 byte node id encoded in uuid. It returns nil if uuid is
// not valid. The NodeID is only well defined for version 1 and 2 UUIDs.
func (uuid UUID) NodeID() []byte {
if len(uuid) != 16 {
return nil
}
node := make([]byte, 6)
copy(node, uuid[10:])
return node
}

66
vendor/github.com/pborman/uuid/seq_test.go generated vendored Normal file
View File

@ -0,0 +1,66 @@
// Copyright 2014 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
"flag"
"runtime"
"testing"
"time"
)
// This test is only run when --regressions is passed on the go test line.
var regressions = flag.Bool("regressions", false, "run uuid regression tests")
// TestClockSeqRace tests for a particular race condition of returning two
// identical Version1 UUIDs. The duration of 1 minute was chosen as the race
// condition, before being fixed, nearly always occured in under 30 seconds.
func TestClockSeqRace(t *testing.T) {
if !*regressions {
t.Skip("skipping regression tests")
}
duration := time.Minute
done := make(chan struct{})
defer close(done)
ch := make(chan UUID, 10000)
ncpu := runtime.NumCPU()
switch ncpu {
case 0, 1:
// We can't run the test effectively.
t.Skip("skipping race test, only one CPU detected")
return
default:
runtime.GOMAXPROCS(ncpu)
}
for i := 0; i < ncpu; i++ {
go func() {
for {
select {
case <-done:
return
case ch <- NewUUID():
}
}
}()
}
uuids := make(map[string]bool)
cnt := 0
start := time.Now()
for u := range ch {
s := u.String()
if uuids[s] {
t.Errorf("duplicate uuid after %d in %v: %s", cnt, time.Since(start), s)
return
}
uuids[s] = true
if time.Since(start) > duration {
return
}
cnt++
}
}

68
vendor/github.com/pborman/uuid/sql.go generated vendored Normal file
View File

@ -0,0 +1,68 @@
// Copyright 2015 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
"database/sql/driver"
"errors"
"fmt"
)
// Scan implements sql.Scanner so UUIDs can be read from databases transparently
// Currently, database types that map to string and []byte are supported. Please
// consult database-specific driver documentation for matching types.
func (uuid *UUID) Scan(src interface{}) error {
switch src.(type) {
case string:
// if an empty UUID comes from a table, we return a null UUID
if src.(string) == "" {
return nil
}
// see uuid.Parse for required string format
parsed := Parse(src.(string))
if parsed == nil {
return errors.New("Scan: invalid UUID format")
}
*uuid = parsed
case []byte:
b := src.([]byte)
// if an empty UUID comes from a table, we return a null UUID
if len(b) == 0 {
return nil
}
// assumes a simple slice of bytes if 16 bytes
// otherwise attempts to parse
if len(b) == 16 {
parsed := make([]byte, 16)
copy(parsed, b)
*uuid = UUID(parsed)
} else {
u := Parse(string(b))
if u == nil {
return errors.New("Scan: invalid UUID format")
}
*uuid = u
}
default:
return fmt.Errorf("Scan: unable to scan type %T into UUID", src)
}
return nil
}
// Value implements sql.Valuer so that UUIDs can be written to databases
// transparently. Currently, UUIDs map to strings. Please consult
// database-specific driver documentation for matching types.
func (uuid UUID) Value() (driver.Value, error) {
return uuid.String(), nil
}

96
vendor/github.com/pborman/uuid/sql_test.go generated vendored Normal file
View File

@ -0,0 +1,96 @@
// Copyright 2015 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
"strings"
"testing"
)
func TestScan(t *testing.T) {
var stringTest string = "f47ac10b-58cc-0372-8567-0e02b2c3d479"
var byteTest []byte = Parse(stringTest)
var badTypeTest int = 6
var invalidTest string = "f47ac10b-58cc-0372-8567-0e02b2c3d4"
// sunny day tests
var uuid UUID
err := (&uuid).Scan(stringTest)
if err != nil {
t.Fatal(err)
}
err = (&uuid).Scan([]byte(stringTest))
if err != nil {
t.Fatal(err)
}
err = (&uuid).Scan(byteTest)
if err != nil {
t.Fatal(err)
}
// bad type tests
err = (&uuid).Scan(badTypeTest)
if err == nil {
t.Error("int correctly parsed and shouldn't have")
}
if !strings.Contains(err.Error(), "unable to scan type") {
t.Error("attempting to parse an int returned an incorrect error message")
}
// invalid/incomplete uuids
err = (&uuid).Scan(invalidTest)
if err == nil {
t.Error("invalid uuid was parsed without error")
}
if !strings.Contains(err.Error(), "invalid UUID") {
t.Error("attempting to parse an invalid UUID returned an incorrect error message")
}
err = (&uuid).Scan(byteTest[:len(byteTest)-2])
if err == nil {
t.Error("invalid byte uuid was parsed without error")
}
if !strings.Contains(err.Error(), "invalid UUID") {
t.Error("attempting to parse an invalid byte UUID returned an incorrect error message")
}
// empty tests
uuid = nil
var emptySlice []byte
err = (&uuid).Scan(emptySlice)
if err != nil {
t.Fatal(err)
}
if uuid != nil {
t.Error("UUID was not nil after scanning empty byte slice")
}
uuid = nil
var emptyString string
err = (&uuid).Scan(emptyString)
if err != nil {
t.Fatal(err)
}
if uuid != nil {
t.Error("UUID was not nil after scanning empty string")
}
}
func TestValue(t *testing.T) {
stringTest := "f47ac10b-58cc-0372-8567-0e02b2c3d479"
uuid := Parse(stringTest)
val, _ := uuid.Value()
if val != stringTest {
t.Error("Value() did not return expected string")
}
}

57
vendor/github.com/pborman/uuid/time.go generated vendored Normal file
View File

@ -0,0 +1,57 @@
// Copyright 2014 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
"encoding/binary"
guuid "github.com/google/uuid"
)
// A Time represents a time as the number of 100's of nanoseconds since 15 Oct
// 1582.
type Time = guuid.Time
// GetTime returns the current Time (100s of nanoseconds since 15 Oct 1582) and
// clock sequence as well as adjusting the clock sequence as needed. An error
// is returned if the current time cannot be determined.
func GetTime() (Time, uint16, error) { return guuid.GetTime() }
// ClockSequence returns the current clock sequence, generating one if not
// already set. The clock sequence is only used for Version 1 UUIDs.
//
// The uuid package does not use global static storage for the clock sequence or
// the last time a UUID was generated. Unless SetClockSequence a new random
// clock sequence is generated the first time a clock sequence is requested by
// ClockSequence, GetTime, or NewUUID. (section 4.2.1.1) sequence is generated
// for
func ClockSequence() int { return guuid.ClockSequence() }
// SetClockSeq sets the clock sequence to the lower 14 bits of seq. Setting to
// -1 causes a new sequence to be generated.
func SetClockSequence(seq int) { guuid.SetClockSequence(seq) }
// Time returns the time in 100s of nanoseconds since 15 Oct 1582 encoded in
// uuid. It returns false if uuid is not valid. The time is only well defined
// for version 1 and 2 UUIDs.
func (uuid UUID) Time() (Time, bool) {
if len(uuid) != 16 {
return 0, false
}
time := int64(binary.BigEndian.Uint32(uuid[0:4]))
time |= int64(binary.BigEndian.Uint16(uuid[4:6])) << 32
time |= int64(binary.BigEndian.Uint16(uuid[6:8])&0xfff) << 48
return Time(time), true
}
// ClockSequence returns the clock sequence encoded in uuid. It returns false
// if uuid is not valid. The clock sequence is only well defined for version 1
// and 2 UUIDs.
func (uuid UUID) ClockSequence() (int, bool) {
if len(uuid) != 16 {
return 0, false
}
return int(binary.BigEndian.Uint16(uuid[8:10])) & 0x3fff, true
}

32
vendor/github.com/pborman/uuid/util.go generated vendored Normal file
View File

@ -0,0 +1,32 @@
// Copyright 2011 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
// xvalues returns the value of a byte as a hexadecimal digit or 255.
var xvalues = [256]byte{
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255, 255,
255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
}
// xtob converts the the first two hex bytes of x into a byte.
func xtob(x string) (byte, bool) {
b1 := xvalues[x[0]]
b2 := xvalues[x[1]]
return (b1 << 4) | b2, b1 != 255 && b2 != 255
}

162
vendor/github.com/pborman/uuid/uuid.go generated vendored Normal file
View File

@ -0,0 +1,162 @@
// Copyright 2011 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
"bytes"
"crypto/rand"
"encoding/hex"
"io"
guuid "github.com/google/uuid"
)
// Array is a pass-by-value UUID that can be used as an effecient key in a map.
type Array [16]byte
// UUID converts uuid into a slice.
func (uuid Array) UUID() UUID {
return uuid[:]
}
// String returns the string representation of uuid,
// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.
func (uuid Array) String() string {
return guuid.UUID(uuid).String()
}
// A UUID is a 128 bit (16 byte) Universal Unique IDentifier as defined in RFC
// 4122.
type UUID []byte
// A Version represents a UUIDs version.
type Version = guuid.Version
// A Variant represents a UUIDs variant.
type Variant = guuid.Variant
// Constants returned by Variant.
const (
Invalid = guuid.Invalid // Invalid UUID
RFC4122 = guuid.RFC4122 // The variant specified in RFC4122
Reserved = guuid.Reserved // Reserved, NCS backward compatibility.
Microsoft = guuid.Microsoft // Reserved, Microsoft Corporation backward compatibility.
Future = guuid.Future // Reserved for future definition.
)
var rander = rand.Reader // random function
// New returns a new random (version 4) UUID as a string. It is a convenience
// function for NewRandom().String().
func New() string {
return NewRandom().String()
}
// Parse decodes s into a UUID or returns nil. See github.com/google/uuid for
// the formats parsed.
func Parse(s string) UUID {
gu, err := guuid.Parse(s)
if err == nil {
return gu[:]
}
return nil
}
// ParseBytes is like Parse, except it parses a byte slice instead of a string.
func ParseBytes(b []byte) (UUID, error) {
gu, err := guuid.ParseBytes(b)
if err == nil {
return gu[:], nil
}
return nil, err
}
// Equal returns true if uuid1 and uuid2 are equal.
func Equal(uuid1, uuid2 UUID) bool {
return bytes.Equal(uuid1, uuid2)
}
// Array returns an array representation of uuid that can be used as a map key.
// Array panics if uuid is not valid.
func (uuid UUID) Array() Array {
if len(uuid) != 16 {
panic("invalid uuid")
}
var a Array
copy(a[:], uuid)
return a
}
// String returns the string form of uuid, xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
// , or "" if uuid is invalid.
func (uuid UUID) String() string {
if len(uuid) != 16 {
return ""
}
var buf [36]byte
encodeHex(buf[:], uuid)
return string(buf[:])
}
// URN returns the RFC 2141 URN form of uuid,
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, or "" if uuid is invalid.
func (uuid UUID) URN() string {
if len(uuid) != 16 {
return ""
}
var buf [36 + 9]byte
copy(buf[:], "urn:uuid:")
encodeHex(buf[9:], uuid)
return string(buf[:])
}
func encodeHex(dst []byte, uuid UUID) {
hex.Encode(dst[:], uuid[:4])
dst[8] = '-'
hex.Encode(dst[9:13], uuid[4:6])
dst[13] = '-'
hex.Encode(dst[14:18], uuid[6:8])
dst[18] = '-'
hex.Encode(dst[19:23], uuid[8:10])
dst[23] = '-'
hex.Encode(dst[24:], uuid[10:])
}
// Variant returns the variant encoded in uuid. It returns Invalid if
// uuid is invalid.
func (uuid UUID) Variant() Variant {
if len(uuid) != 16 {
return Invalid
}
switch {
case (uuid[8] & 0xc0) == 0x80:
return RFC4122
case (uuid[8] & 0xe0) == 0xc0:
return Microsoft
case (uuid[8] & 0xe0) == 0xe0:
return Future
default:
return Reserved
}
}
// Version returns the version of uuid. It returns false if uuid is not
// valid.
func (uuid UUID) Version() (Version, bool) {
if len(uuid) != 16 {
return 0, false
}
return Version(uuid[6] >> 4), true
}
// SetRand sets the random number generator to r, which implements io.Reader.
// If r.Read returns an error when the package requests random data then
// a panic will be issued.
//
// Calling SetRand with nil sets the random number generator to the default
// generator.
func SetRand(r io.Reader) {
guuid.SetRand(r)
}

410
vendor/github.com/pborman/uuid/uuid_test.go generated vendored Normal file
View File

@ -0,0 +1,410 @@
// Copyright 2011 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
// Some of these tests can probably be removed as they are redundant with the
// tests in github.com/google/uuid.
import (
"bytes"
"fmt"
"os"
"strings"
"testing"
)
type test struct {
in string
version Version
variant Variant
isuuid bool
}
var tests = []test{
{"f47ac10b-58cc-0372-8567-0e02b2c3d479", 0, RFC4122, true},
{"f47ac10b-58cc-1372-8567-0e02b2c3d479", 1, RFC4122, true},
{"f47ac10b-58cc-2372-8567-0e02b2c3d479", 2, RFC4122, true},
{"f47ac10b-58cc-3372-8567-0e02b2c3d479", 3, RFC4122, true},
{"f47ac10b-58cc-4372-8567-0e02b2c3d479", 4, RFC4122, true},
{"f47ac10b-58cc-5372-8567-0e02b2c3d479", 5, RFC4122, true},
{"f47ac10b-58cc-6372-8567-0e02b2c3d479", 6, RFC4122, true},
{"f47ac10b-58cc-7372-8567-0e02b2c3d479", 7, RFC4122, true},
{"f47ac10b-58cc-8372-8567-0e02b2c3d479", 8, RFC4122, true},
{"f47ac10b-58cc-9372-8567-0e02b2c3d479", 9, RFC4122, true},
{"f47ac10b-58cc-a372-8567-0e02b2c3d479", 10, RFC4122, true},
{"f47ac10b-58cc-b372-8567-0e02b2c3d479", 11, RFC4122, true},
{"f47ac10b-58cc-c372-8567-0e02b2c3d479", 12, RFC4122, true},
{"f47ac10b-58cc-d372-8567-0e02b2c3d479", 13, RFC4122, true},
{"f47ac10b-58cc-e372-8567-0e02b2c3d479", 14, RFC4122, true},
{"f47ac10b-58cc-f372-8567-0e02b2c3d479", 15, RFC4122, true},
{"urn:uuid:f47ac10b-58cc-4372-0567-0e02b2c3d479", 4, Reserved, true},
{"URN:UUID:f47ac10b-58cc-4372-0567-0e02b2c3d479", 4, Reserved, true},
{"f47ac10b-58cc-4372-0567-0e02b2c3d479", 4, Reserved, true},
{"f47ac10b-58cc-4372-1567-0e02b2c3d479", 4, Reserved, true},
{"f47ac10b-58cc-4372-2567-0e02b2c3d479", 4, Reserved, true},
{"f47ac10b-58cc-4372-3567-0e02b2c3d479", 4, Reserved, true},
{"f47ac10b-58cc-4372-4567-0e02b2c3d479", 4, Reserved, true},
{"f47ac10b-58cc-4372-5567-0e02b2c3d479", 4, Reserved, true},
{"f47ac10b-58cc-4372-6567-0e02b2c3d479", 4, Reserved, true},
{"f47ac10b-58cc-4372-7567-0e02b2c3d479", 4, Reserved, true},
{"f47ac10b-58cc-4372-8567-0e02b2c3d479", 4, RFC4122, true},
{"f47ac10b-58cc-4372-9567-0e02b2c3d479", 4, RFC4122, true},
{"f47ac10b-58cc-4372-a567-0e02b2c3d479", 4, RFC4122, true},
{"f47ac10b-58cc-4372-b567-0e02b2c3d479", 4, RFC4122, true},
{"f47ac10b-58cc-4372-c567-0e02b2c3d479", 4, Microsoft, true},
{"f47ac10b-58cc-4372-d567-0e02b2c3d479", 4, Microsoft, true},
{"f47ac10b-58cc-4372-e567-0e02b2c3d479", 4, Future, true},
{"f47ac10b-58cc-4372-f567-0e02b2c3d479", 4, Future, true},
{"f47ac10b158cc-5372-a567-0e02b2c3d479", 0, Invalid, false},
{"f47ac10b-58cc25372-a567-0e02b2c3d479", 0, Invalid, false},
{"f47ac10b-58cc-53723a567-0e02b2c3d479", 0, Invalid, false},
{"f47ac10b-58cc-5372-a56740e02b2c3d479", 0, Invalid, false},
{"f47ac10b-58cc-5372-a567-0e02-2c3d479", 0, Invalid, false},
{"g47ac10b-58cc-4372-a567-0e02b2c3d479", 0, Invalid, false},
}
var constants = []struct {
c interface{}
name string
}{
{Person, "Person"},
{Group, "Group"},
{Org, "Org"},
{Invalid, "Invalid"},
{RFC4122, "RFC4122"},
{Reserved, "Reserved"},
{Microsoft, "Microsoft"},
{Future, "Future"},
{Domain(17), "Domain17"},
{Variant(42), "BadVariant42"},
}
func testTest(t *testing.T, in string, tt test) {
uuid := Parse(in)
if ok := (uuid != nil); ok != tt.isuuid {
t.Errorf("Parse(%s) got %v expected %v\b", in, ok, tt.isuuid)
}
if uuid == nil {
return
}
if v := uuid.Variant(); v != tt.variant {
t.Errorf("Variant(%s) got %d expected %d\b", in, v, tt.variant)
}
if v, _ := uuid.Version(); v != tt.version {
t.Errorf("Version(%s) got %d expected %d\b", in, v, tt.version)
}
}
func TestUUID(t *testing.T) {
for _, tt := range tests {
testTest(t, tt.in, tt)
testTest(t, strings.ToUpper(tt.in), tt)
}
}
func TestConstants(t *testing.T) {
for x, tt := range constants {
v, ok := tt.c.(fmt.Stringer)
if !ok {
t.Errorf("%x: %v: not a stringer", x, v)
} else if s := v.String(); s != tt.name {
v, _ := tt.c.(int)
t.Errorf("%x: Constant %T:%d gives %q, expected %q", x, tt.c, v, s, tt.name)
}
}
}
func TestRandomUUID(t *testing.T) {
m := make(map[string]bool)
for x := 1; x < 32; x++ {
uuid := NewRandom()
s := uuid.String()
if m[s] {
t.Errorf("NewRandom returned duplicated UUID %s", s)
}
m[s] = true
if v, _ := uuid.Version(); v != 4 {
t.Errorf("Random UUID of version %s", v)
}
if uuid.Variant() != RFC4122 {
t.Errorf("Random UUID is variant %d", uuid.Variant())
}
}
}
func TestNew(t *testing.T) {
m := make(map[string]bool)
for x := 1; x < 32; x++ {
s := New()
if m[s] {
t.Errorf("New returned duplicated UUID %s", s)
}
m[s] = true
uuid := Parse(s)
if uuid == nil {
t.Errorf("New returned %q which does not decode", s)
continue
}
if v, _ := uuid.Version(); v != 4 {
t.Errorf("Random UUID of version %s", v)
}
if uuid.Variant() != RFC4122 {
t.Errorf("Random UUID is variant %d", uuid.Variant())
}
}
}
func TestCoding(t *testing.T) {
text := "7d444840-9dc0-11d1-b245-5ffdce74fad2"
urn := "urn:uuid:7d444840-9dc0-11d1-b245-5ffdce74fad2"
data := UUID{
0x7d, 0x44, 0x48, 0x40,
0x9d, 0xc0,
0x11, 0xd1,
0xb2, 0x45,
0x5f, 0xfd, 0xce, 0x74, 0xfa, 0xd2,
}
if v := data.String(); v != text {
t.Errorf("%x: encoded to %s, expected %s", data, v, text)
}
if v := data.URN(); v != urn {
t.Errorf("%x: urn is %s, expected %s", data, v, urn)
}
uuid := Parse(text)
if !Equal(uuid, data) {
t.Errorf("%s: decoded to %s, expected %s", text, uuid, data)
}
}
func TestVersion1(t *testing.T) {
uuid1 := NewUUID()
uuid2 := NewUUID()
if Equal(uuid1, uuid2) {
t.Errorf("%s:duplicate uuid", uuid1)
}
if v, _ := uuid1.Version(); v != 1 {
t.Errorf("%s: version %s expected 1", uuid1, v)
}
if v, _ := uuid2.Version(); v != 1 {
t.Errorf("%s: version %s expected 1", uuid2, v)
}
n1 := uuid1.NodeID()
n2 := uuid2.NodeID()
if !bytes.Equal(n1, n2) {
t.Errorf("Different nodes %x != %x", n1, n2)
}
t1, ok := uuid1.Time()
if !ok {
t.Errorf("%s: invalid time", uuid1)
}
t2, ok := uuid2.Time()
if !ok {
t.Errorf("%s: invalid time", uuid2)
}
q1, ok := uuid1.ClockSequence()
if !ok {
t.Errorf("%s: invalid clock sequence", uuid1)
}
q2, ok := uuid2.ClockSequence()
if !ok {
t.Errorf("%s: invalid clock sequence", uuid2)
}
switch {
case t1 == t2 && q1 == q2:
t.Error("time stopped")
case t1 > t2 && q1 == q2:
t.Error("time reversed")
case t1 < t2 && q1 != q2:
t.Error("clock sequence chaned unexpectedly")
}
}
func TestMD5(t *testing.T) {
uuid := NewMD5(NameSpace_DNS, []byte("python.org")).String()
want := "6fa459ea-ee8a-3ca4-894e-db77e160355e"
if uuid != want {
t.Errorf("MD5: got %q expected %q", uuid, want)
}
}
func TestSHA1(t *testing.T) {
uuid := NewSHA1(NameSpace_DNS, []byte("python.org")).String()
want := "886313e1-3b8a-5372-9b90-0c9aee199e5d"
if uuid != want {
t.Errorf("SHA1: got %q expected %q", uuid, want)
}
}
func testDCE(t *testing.T, name string, uuid UUID, domain Domain, id uint32) {
if uuid == nil {
t.Errorf("%s failed", name)
return
}
if v, _ := uuid.Version(); v != 2 {
t.Errorf("%s: %s: expected version 2, got %s", name, uuid, v)
return
}
if v, ok := uuid.Domain(); !ok || v != domain {
if !ok {
t.Errorf("%s: %d: Domain failed", name, uuid)
} else {
t.Errorf("%s: %s: expected domain %d, got %d", name, uuid, domain, v)
}
}
if v, ok := uuid.Id(); !ok || v != id {
if !ok {
t.Errorf("%s: %d: Id failed", name, uuid)
} else {
t.Errorf("%s: %s: expected id %d, got %d", name, uuid, id, v)
}
}
}
func TestDCE(t *testing.T) {
testDCE(t, "NewDCESecurity", NewDCESecurity(42, 12345678), 42, 12345678)
testDCE(t, "NewDCEPerson", NewDCEPerson(), Person, uint32(os.Getuid()))
testDCE(t, "NewDCEGroup", NewDCEGroup(), Group, uint32(os.Getgid()))
}
type badRand struct{}
func (r badRand) Read(buf []byte) (int, error) {
for i, _ := range buf {
buf[i] = byte(i)
}
return len(buf), nil
}
func TestBadRand(t *testing.T) {
SetRand(badRand{})
uuid1 := New()
uuid2 := New()
if uuid1 != uuid2 {
t.Errorf("expected duplicates, got %q and %q", uuid1, uuid2)
}
SetRand(nil)
uuid1 = New()
uuid2 = New()
if uuid1 == uuid2 {
t.Errorf("unexpected duplicates, got %q", uuid1)
}
}
func TestUUID_Array(t *testing.T) {
expect := Array{
0xf4, 0x7a, 0xc1, 0x0b,
0x58, 0xcc,
0x03, 0x72,
0x85, 0x67,
0x0e, 0x02, 0xb2, 0xc3, 0xd4, 0x79,
}
uuid := Parse("f47ac10b-58cc-0372-8567-0e02b2c3d479")
if uuid == nil {
t.Fatal("invalid uuid")
}
if uuid.Array() != expect {
t.Fatal("invalid array")
}
}
func TestArray_UUID(t *testing.T) {
array := Array{
0xf4, 0x7a, 0xc1, 0x0b,
0x58, 0xcc,
0x03, 0x72,
0x85, 0x67,
0x0e, 0x02, 0xb2, 0xc3, 0xd4, 0x79,
}
expect := Parse("f47ac10b-58cc-0372-8567-0e02b2c3d479")
if expect == nil {
t.Fatal("invalid uuid")
}
if !bytes.Equal(array.UUID(), expect) {
t.Fatal("invalid uuid")
}
}
func BenchmarkParse(b *testing.B) {
for i := 0; i < b.N; i++ {
uuid := Parse("f47ac10b-58cc-0372-8567-0e02b2c3d479")
if uuid == nil {
b.Fatal("invalid uuid")
}
}
}
func BenchmarkNew(b *testing.B) {
for i := 0; i < b.N; i++ {
New()
}
}
func BenchmarkUUID_String(b *testing.B) {
uuid := Parse("f47ac10b-58cc-0372-8567-0e02b2c3d479")
if uuid == nil {
b.Fatal("invalid uuid")
}
for i := 0; i < b.N; i++ {
if uuid.String() == "" {
b.Fatal("invalid uuid")
}
}
}
func BenchmarkUUID_URN(b *testing.B) {
uuid := Parse("f47ac10b-58cc-0372-8567-0e02b2c3d479")
if uuid == nil {
b.Fatal("invalid uuid")
}
for i := 0; i < b.N; i++ {
if uuid.URN() == "" {
b.Fatal("invalid uuid")
}
}
}
func BenchmarkUUID_Array(b *testing.B) {
expect := Array{
0xf4, 0x7a, 0xc1, 0x0b,
0x58, 0xcc,
0x03, 0x72,
0x85, 0x67,
0x0e, 0x02, 0xb2, 0xc3, 0xd4, 0x79,
}
uuid := Parse("f47ac10b-58cc-0372-8567-0e02b2c3d479")
if uuid == nil {
b.Fatal("invalid uuid")
}
for i := 0; i < b.N; i++ {
if uuid.Array() != expect {
b.Fatal("invalid array")
}
}
}
func BenchmarkArray_UUID(b *testing.B) {
array := Array{
0xf4, 0x7a, 0xc1, 0x0b,
0x58, 0xcc,
0x03, 0x72,
0x85, 0x67,
0x0e, 0x02, 0xb2, 0xc3, 0xd4, 0x79,
}
expect := Parse("f47ac10b-58cc-0372-8567-0e02b2c3d479")
if expect == nil {
b.Fatal("invalid uuid")
}
for i := 0; i < b.N; i++ {
if !bytes.Equal(array.UUID(), expect) {
b.Fatal("invalid uuid")
}
}
}

23
vendor/github.com/pborman/uuid/version1.go generated vendored Normal file
View File

@ -0,0 +1,23 @@
// Copyright 2011 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
guuid "github.com/google/uuid"
)
// NewUUID returns a Version 1 UUID based on the current NodeID and clock
// sequence, and the current time. If the NodeID has not been set by SetNodeID
// or SetNodeInterface then it will be set automatically. If the NodeID cannot
// be set NewUUID returns nil. If clock sequence has not been set by
// SetClockSequence then it will be set automatically. If GetTime fails to
// return the current NewUUID returns nil.
func NewUUID() UUID {
gu, err := guuid.NewUUID()
if err == nil {
return UUID(gu[:])
}
return nil
}

26
vendor/github.com/pborman/uuid/version4.go generated vendored Normal file
View File

@ -0,0 +1,26 @@
// Copyright 2011 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import guuid "github.com/google/uuid"
// Random returns a Random (Version 4) UUID or panics.
//
// The strength of the UUIDs is based on the strength of the crypto/rand
// package.
//
// A note about uniqueness derived from the UUID Wikipedia entry:
//
// Randomly generated UUIDs have 122 random bits. One's annual risk of being
// hit by a meteorite is estimated to be one chance in 17 billion, that
// means the probability is about 0.00000000006 (6 × 1011),
// equivalent to the odds of creating a few tens of trillions of UUIDs in a
// year and having one duplicate.
func NewRandom() UUID {
if gu, err := guuid.NewRandom(); err == nil {
return UUID(gu[:])
}
return nil
}