mirror of
https://github.com/Luzifer/vault-patch.git
synced 2024-11-09 09:50:04 +00:00
Remove old vendoring
Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
parent
a83d6a069a
commit
95400370d5
421 changed files with 0 additions and 170309 deletions
149
Godeps/Godeps.json
generated
149
Godeps/Godeps.json
generated
|
@ -1,149 +0,0 @@
|
||||||
{
|
|
||||||
"ImportPath": "github.com/Luzifer/vault-patch",
|
|
||||||
"GoVersion": "go1.8",
|
|
||||||
"GodepVersion": "v79",
|
|
||||||
"Deps": [
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/Luzifer/rconfig",
|
|
||||||
"Comment": "v1.1.0",
|
|
||||||
"Rev": "c27bd3a64b5b19556914d9fec69922cf3852d585"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/Sirupsen/logrus",
|
|
||||||
"Comment": "v0.10.0-38-g3ec0642",
|
|
||||||
"Rev": "3ec0642a7fb6488f65b06f9040adc67e3990296a"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/fatih/structs",
|
|
||||||
"Rev": "3fe2facc32a7fbde4b29c0f85604dc1dd22836d2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/hashicorp/errwrap",
|
|
||||||
"Rev": "7554cd9344cec97297fa6649b055a8c98c2a1e55"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/hashicorp/go-cleanhttp",
|
|
||||||
"Rev": "ad28ea4487f05916463e2423a55166280e8254b5"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/hashicorp/go-multierror",
|
|
||||||
"Rev": "d30f09973e19c1dfcd120b2d9c4f168e68d6b5d5"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/hashicorp/go-rootcerts",
|
|
||||||
"Rev": "6bb64b370b90e7ef1fa532be9e591a81c3493e00"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/hashicorp/hcl",
|
|
||||||
"Rev": "ef8133da8cda503718a74741312bf50821e6de79"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/hashicorp/hcl/hcl/ast",
|
|
||||||
"Rev": "ef8133da8cda503718a74741312bf50821e6de79"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/hashicorp/hcl/hcl/parser",
|
|
||||||
"Rev": "ef8133da8cda503718a74741312bf50821e6de79"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/hashicorp/hcl/hcl/scanner",
|
|
||||||
"Rev": "ef8133da8cda503718a74741312bf50821e6de79"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/hashicorp/hcl/hcl/strconv",
|
|
||||||
"Rev": "ef8133da8cda503718a74741312bf50821e6de79"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/hashicorp/hcl/hcl/token",
|
|
||||||
"Rev": "ef8133da8cda503718a74741312bf50821e6de79"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/hashicorp/hcl/json/parser",
|
|
||||||
"Rev": "ef8133da8cda503718a74741312bf50821e6de79"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/hashicorp/hcl/json/scanner",
|
|
||||||
"Rev": "ef8133da8cda503718a74741312bf50821e6de79"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/hashicorp/hcl/json/token",
|
|
||||||
"Rev": "ef8133da8cda503718a74741312bf50821e6de79"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/hashicorp/vault/api",
|
|
||||||
"Comment": "v0.7.0-190-g4490e93",
|
|
||||||
"Rev": "4490e93395fb70c3a25ade1fe88f363561a7d584"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/hashicorp/vault/helper/compressutil",
|
|
||||||
"Comment": "v0.7.0-190-g4490e93",
|
|
||||||
"Rev": "4490e93395fb70c3a25ade1fe88f363561a7d584"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/hashicorp/vault/helper/jsonutil",
|
|
||||||
"Comment": "v0.7.0-190-g4490e93",
|
|
||||||
"Rev": "4490e93395fb70c3a25ade1fe88f363561a7d584"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/hashicorp/vault/helper/kv-builder",
|
|
||||||
"Comment": "v0.7.0-190-g4490e93",
|
|
||||||
"Rev": "4490e93395fb70c3a25ade1fe88f363561a7d584"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/mitchellh/go-homedir",
|
|
||||||
"Rev": "981ab348d865cf048eb7d17e78ac7192632d8415"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/mitchellh/mapstructure",
|
|
||||||
"Rev": "ca63d7c062ee3c9f34db231e352b60012b4fd0c1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/sethgrid/pester",
|
|
||||||
"Rev": "4f4c0a67b6496764028e1ab9fd8dfb630282ed2f"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/spf13/pflag",
|
|
||||||
"Rev": "c7e63cf4530bcd3ba943729cee0efeff2ebea63f"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "golang.org/x/net/http2",
|
|
||||||
"Rev": "dfe83d419c9403b40b19d08cdba2afec27b002f7"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "golang.org/x/net/http2/hpack",
|
|
||||||
"Rev": "dfe83d419c9403b40b19d08cdba2afec27b002f7"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "golang.org/x/net/idna",
|
|
||||||
"Rev": "dfe83d419c9403b40b19d08cdba2afec27b002f7"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "golang.org/x/net/lex/httplex",
|
|
||||||
"Rev": "dfe83d419c9403b40b19d08cdba2afec27b002f7"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "golang.org/x/sys/unix",
|
|
||||||
"Rev": "8f0908ab3b2457e2e15403d3697c9ef5cb4b57a9"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "golang.org/x/text/secure/bidirule",
|
|
||||||
"Rev": "3491b61b9edc56653ad4333e605e2908e46a036b"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "golang.org/x/text/transform",
|
|
||||||
"Rev": "3491b61b9edc56653ad4333e605e2908e46a036b"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "golang.org/x/text/unicode/bidi",
|
|
||||||
"Rev": "3491b61b9edc56653ad4333e605e2908e46a036b"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "golang.org/x/text/unicode/norm",
|
|
||||||
"Rev": "3491b61b9edc56653ad4333e605e2908e46a036b"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "gopkg.in/yaml.v2",
|
|
||||||
"Rev": "31c299268d302dd0aa9a0dcf765a3d58971ac83f"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
5
Godeps/Readme
generated
5
Godeps/Readme
generated
|
@ -1,5 +0,0 @@
|
||||||
This directory tree is generated automatically by godep.
|
|
||||||
|
|
||||||
Please do not edit.
|
|
||||||
|
|
||||||
See https://github.com/tools/godep for more information.
|
|
8
vendor/github.com/Luzifer/rconfig/.travis.yml
generated
vendored
8
vendor/github.com/Luzifer/rconfig/.travis.yml
generated
vendored
|
@ -1,8 +0,0 @@
|
||||||
language: go
|
|
||||||
|
|
||||||
go:
|
|
||||||
- 1.4
|
|
||||||
- 1.5
|
|
||||||
- tip
|
|
||||||
|
|
||||||
script: go test -v -race -cover ./...
|
|
5
vendor/github.com/Luzifer/rconfig/History.md
generated
vendored
5
vendor/github.com/Luzifer/rconfig/History.md
generated
vendored
|
@ -1,5 +0,0 @@
|
||||||
# 1.1.0 / 2016-06-28
|
|
||||||
|
|
||||||
* Support time.Duration config parameters
|
|
||||||
* Added goreportcard badge
|
|
||||||
* Added testcase for using bool with ENV and default
|
|
13
vendor/github.com/Luzifer/rconfig/LICENSE
generated
vendored
13
vendor/github.com/Luzifer/rconfig/LICENSE
generated
vendored
|
@ -1,13 +0,0 @@
|
||||||
Copyright 2015 Knut Ahlers <knut@ahlers.me>
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
94
vendor/github.com/Luzifer/rconfig/README.md
generated
vendored
94
vendor/github.com/Luzifer/rconfig/README.md
generated
vendored
|
@ -1,94 +0,0 @@
|
||||||
[![Build Status](https://travis-ci.org/Luzifer/rconfig.svg?branch=master)](https://travis-ci.org/Luzifer/rconfig)
|
|
||||||
[![License: Apache v2.0](https://badge.luzifer.io/v1/badge?color=5d79b5&title=license&text=Apache+v2.0)](http://www.apache.org/licenses/LICENSE-2.0)
|
|
||||||
[![Documentation](https://badge.luzifer.io/v1/badge?title=godoc&text=reference)](https://godoc.org/github.com/Luzifer/rconfig)
|
|
||||||
[![Go Report](http://goreportcard.com/badge/Luzifer/rconfig)](http://goreportcard.com/report/Luzifer/rconfig)
|
|
||||||
|
|
||||||
## Description
|
|
||||||
|
|
||||||
> Package rconfig implements a CLI configuration reader with struct-embedded defaults, environment variables and posix compatible flag parsing using the [pflag](https://github.com/spf13/pflag) library.
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
Install by running:
|
|
||||||
|
|
||||||
```
|
|
||||||
go get -u github.com/Luzifer/rconfig
|
|
||||||
```
|
|
||||||
|
|
||||||
OR fetch a specific version:
|
|
||||||
|
|
||||||
```
|
|
||||||
go get -u gopkg.in/luzifer/rconfig.v1
|
|
||||||
```
|
|
||||||
|
|
||||||
Run tests by running:
|
|
||||||
|
|
||||||
```
|
|
||||||
go test -v -race -cover github.com/Luzifer/rconfig
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
As a first step define a struct holding your configuration:
|
|
||||||
|
|
||||||
```go
|
|
||||||
type config struct {
|
|
||||||
Username string `default:"unknown" flag:"user" description:"Your name"`
|
|
||||||
Details struct {
|
|
||||||
Age int `default:"25" flag:"age" env:"age" description:"Your age"`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Next create an instance of that struct and let `rconfig` fill that config:
|
|
||||||
|
|
||||||
```go
|
|
||||||
var cfg config
|
|
||||||
func init() {
|
|
||||||
cfg = config{}
|
|
||||||
rconfig.Parse(&cfg)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
You're ready to access your configuration:
|
|
||||||
|
|
||||||
```go
|
|
||||||
func main() {
|
|
||||||
fmt.Printf("Hello %s, happy birthday for your %dth birthday.",
|
|
||||||
cfg.Username,
|
|
||||||
cfg.Details.Age)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Provide variable defaults by using a file
|
|
||||||
|
|
||||||
Given you have a file `~/.myapp.yml` containing some secrets or usernames (for the example below username is assumed to be "luzifer") as a default configuration for your application you can use this source code to load the defaults from that file using the `vardefault` tag in your configuration struct.
|
|
||||||
|
|
||||||
The order of the directives (lower number = higher precedence):
|
|
||||||
|
|
||||||
1. Flags provided in command line
|
|
||||||
1. Environment variables
|
|
||||||
1. Variable defaults (`vardefault` tag in the struct)
|
|
||||||
1. `default` tag in the struct
|
|
||||||
|
|
||||||
```go
|
|
||||||
type config struct {
|
|
||||||
Username string `vardefault:"username" flag:"username" description:"Your username"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var cfg = config{}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
rconfig.SetVariableDefaults(rconfig.VarDefaultsFromYAMLFile("~/.myapp.yml"))
|
|
||||||
rconfig.Parse(&cfg)
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
fmt.Printf("Username = %s", cfg.Username)
|
|
||||||
// Output: Username = luzifer
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## More info
|
|
||||||
|
|
||||||
You can see the full reference documentation of the rconfig package [at godoc.org](https://godoc.org/github.com/Luzifer/rconfig), or through go's standard documentation system by running `godoc -http=:6060` and browsing to [http://localhost:6060/pkg/github.com/Luzifer/rconfig](http://localhost:6060/pkg/github.com/Luzifer/rconfig) after installation.
|
|
338
vendor/github.com/Luzifer/rconfig/config.go
generated
vendored
338
vendor/github.com/Luzifer/rconfig/config.go
generated
vendored
|
@ -1,338 +0,0 @@
|
||||||
// Package rconfig implements a CLI configuration reader with struct-embedded
|
|
||||||
// defaults, environment variables and posix compatible flag parsing using
|
|
||||||
// the pflag library.
|
|
||||||
package rconfig
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"reflect"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/spf13/pflag"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
fs *pflag.FlagSet
|
|
||||||
variableDefaults map[string]string
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
variableDefaults = make(map[string]string)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse takes the pointer to a struct filled with variables which should be read
|
|
||||||
// from ENV, default or flag. The precedence in this is flag > ENV > default. So
|
|
||||||
// if a flag is specified on the CLI it will overwrite the ENV and otherwise ENV
|
|
||||||
// overwrites the default specified.
|
|
||||||
//
|
|
||||||
// For your configuration struct you can use the following struct-tags to control
|
|
||||||
// the behavior of rconfig:
|
|
||||||
//
|
|
||||||
// default: Set a default value
|
|
||||||
// vardefault: Read the default value from the variable defaults
|
|
||||||
// env: Read the value from this environment variable
|
|
||||||
// flag: Flag to read in format "long,short" (for example "listen,l")
|
|
||||||
// description: A help text for Usage output to guide your users
|
|
||||||
//
|
|
||||||
// The format you need to specify those values you can see in the example to this
|
|
||||||
// function.
|
|
||||||
//
|
|
||||||
func Parse(config interface{}) error {
|
|
||||||
return parse(config, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Args returns the non-flag command-line arguments.
|
|
||||||
func Args() []string {
|
|
||||||
return fs.Args()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Usage prints a basic usage with the corresponding defaults for the flags to
|
|
||||||
// os.Stdout. The defaults are derived from the `default` struct-tag and the ENV.
|
|
||||||
func Usage() {
|
|
||||||
if fs != nil && fs.Parsed() {
|
|
||||||
fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
|
|
||||||
fs.PrintDefaults()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetVariableDefaults presets the parser with a map of default values to be used
|
|
||||||
// when specifying the vardefault tag
|
|
||||||
func SetVariableDefaults(defaults map[string]string) {
|
|
||||||
variableDefaults = defaults
|
|
||||||
}
|
|
||||||
|
|
||||||
func parse(in interface{}, args []string) error {
|
|
||||||
if args == nil {
|
|
||||||
args = os.Args
|
|
||||||
}
|
|
||||||
|
|
||||||
fs = pflag.NewFlagSet(os.Args[0], pflag.ExitOnError)
|
|
||||||
if err := execTags(in, fs); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return fs.Parse(args)
|
|
||||||
}
|
|
||||||
|
|
||||||
func execTags(in interface{}, fs *pflag.FlagSet) error {
|
|
||||||
if reflect.TypeOf(in).Kind() != reflect.Ptr {
|
|
||||||
return errors.New("Calling parser with non-pointer")
|
|
||||||
}
|
|
||||||
|
|
||||||
if reflect.ValueOf(in).Elem().Kind() != reflect.Struct {
|
|
||||||
return errors.New("Calling parser with pointer to non-struct")
|
|
||||||
}
|
|
||||||
|
|
||||||
st := reflect.ValueOf(in).Elem()
|
|
||||||
for i := 0; i < st.NumField(); i++ {
|
|
||||||
valField := st.Field(i)
|
|
||||||
typeField := st.Type().Field(i)
|
|
||||||
|
|
||||||
if typeField.Tag.Get("default") == "" && typeField.Tag.Get("env") == "" && typeField.Tag.Get("flag") == "" && typeField.Type.Kind() != reflect.Struct {
|
|
||||||
// None of our supported tags is present and it's not a sub-struct
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
value := varDefault(typeField.Tag.Get("vardefault"), typeField.Tag.Get("default"))
|
|
||||||
value = envDefault(typeField.Tag.Get("env"), value)
|
|
||||||
parts := strings.Split(typeField.Tag.Get("flag"), ",")
|
|
||||||
|
|
||||||
switch typeField.Type {
|
|
||||||
case reflect.TypeOf(time.Duration(0)):
|
|
||||||
v, err := time.ParseDuration(value)
|
|
||||||
if err != nil {
|
|
||||||
if value == "" {
|
|
||||||
v = time.Duration(0)
|
|
||||||
} else {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if typeField.Tag.Get("flag") != "" {
|
|
||||||
if len(parts) == 1 {
|
|
||||||
fs.DurationVar(valField.Addr().Interface().(*time.Duration), parts[0], v, typeField.Tag.Get("description"))
|
|
||||||
} else {
|
|
||||||
fs.DurationVarP(valField.Addr().Interface().(*time.Duration), parts[0], parts[1], v, typeField.Tag.Get("description"))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
valField.Set(reflect.ValueOf(v))
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
switch typeField.Type.Kind() {
|
|
||||||
case reflect.String:
|
|
||||||
if typeField.Tag.Get("flag") != "" {
|
|
||||||
if len(parts) == 1 {
|
|
||||||
fs.StringVar(valField.Addr().Interface().(*string), parts[0], value, typeField.Tag.Get("description"))
|
|
||||||
} else {
|
|
||||||
fs.StringVarP(valField.Addr().Interface().(*string), parts[0], parts[1], value, typeField.Tag.Get("description"))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
valField.SetString(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Bool:
|
|
||||||
v := value == "true"
|
|
||||||
if typeField.Tag.Get("flag") != "" {
|
|
||||||
if len(parts) == 1 {
|
|
||||||
fs.BoolVar(valField.Addr().Interface().(*bool), parts[0], v, typeField.Tag.Get("description"))
|
|
||||||
} else {
|
|
||||||
fs.BoolVarP(valField.Addr().Interface().(*bool), parts[0], parts[1], v, typeField.Tag.Get("description"))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
valField.SetBool(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Int, reflect.Int8, reflect.Int32, reflect.Int64:
|
|
||||||
vt, err := strconv.ParseInt(value, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
if value == "" {
|
|
||||||
vt = 0
|
|
||||||
} else {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if typeField.Tag.Get("flag") != "" {
|
|
||||||
registerFlagInt(typeField.Type.Kind(), fs, valField.Addr().Interface(), parts, vt, typeField.Tag.Get("description"))
|
|
||||||
} else {
|
|
||||||
valField.SetInt(vt)
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
|
||||||
vt, err := strconv.ParseUint(value, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
if value == "" {
|
|
||||||
vt = 0
|
|
||||||
} else {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if typeField.Tag.Get("flag") != "" {
|
|
||||||
registerFlagUint(typeField.Type.Kind(), fs, valField.Addr().Interface(), parts, vt, typeField.Tag.Get("description"))
|
|
||||||
} else {
|
|
||||||
valField.SetUint(vt)
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Float32, reflect.Float64:
|
|
||||||
vt, err := strconv.ParseFloat(value, 64)
|
|
||||||
if err != nil {
|
|
||||||
if value == "" {
|
|
||||||
vt = 0.0
|
|
||||||
} else {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if typeField.Tag.Get("flag") != "" {
|
|
||||||
registerFlagFloat(typeField.Type.Kind(), fs, valField.Addr().Interface(), parts, vt, typeField.Tag.Get("description"))
|
|
||||||
} else {
|
|
||||||
valField.SetFloat(vt)
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Struct:
|
|
||||||
if err := execTags(valField.Addr().Interface(), fs); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Slice:
|
|
||||||
switch typeField.Type.Elem().Kind() {
|
|
||||||
case reflect.Int:
|
|
||||||
def := []int{}
|
|
||||||
for _, v := range strings.Split(value, ",") {
|
|
||||||
it, err := strconv.ParseInt(strings.TrimSpace(v), 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
def = append(def, int(it))
|
|
||||||
}
|
|
||||||
if len(parts) == 1 {
|
|
||||||
fs.IntSliceVar(valField.Addr().Interface().(*[]int), parts[0], def, typeField.Tag.Get("description"))
|
|
||||||
} else {
|
|
||||||
fs.IntSliceVarP(valField.Addr().Interface().(*[]int), parts[0], parts[1], def, typeField.Tag.Get("description"))
|
|
||||||
}
|
|
||||||
case reflect.String:
|
|
||||||
del := typeField.Tag.Get("delimiter")
|
|
||||||
if len(del) == 0 {
|
|
||||||
del = ","
|
|
||||||
}
|
|
||||||
def := strings.Split(value, del)
|
|
||||||
if len(parts) == 1 {
|
|
||||||
fs.StringSliceVar(valField.Addr().Interface().(*[]string), parts[0], def, typeField.Tag.Get("description"))
|
|
||||||
} else {
|
|
||||||
fs.StringSliceVarP(valField.Addr().Interface().(*[]string), parts[0], parts[1], def, typeField.Tag.Get("description"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func registerFlagFloat(t reflect.Kind, fs *pflag.FlagSet, field interface{}, parts []string, vt float64, desc string) {
|
|
||||||
switch t {
|
|
||||||
case reflect.Float32:
|
|
||||||
if len(parts) == 1 {
|
|
||||||
fs.Float32Var(field.(*float32), parts[0], float32(vt), desc)
|
|
||||||
} else {
|
|
||||||
fs.Float32VarP(field.(*float32), parts[0], parts[1], float32(vt), desc)
|
|
||||||
}
|
|
||||||
case reflect.Float64:
|
|
||||||
if len(parts) == 1 {
|
|
||||||
fs.Float64Var(field.(*float64), parts[0], float64(vt), desc)
|
|
||||||
} else {
|
|
||||||
fs.Float64VarP(field.(*float64), parts[0], parts[1], float64(vt), desc)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func registerFlagInt(t reflect.Kind, fs *pflag.FlagSet, field interface{}, parts []string, vt int64, desc string) {
|
|
||||||
switch t {
|
|
||||||
case reflect.Int:
|
|
||||||
if len(parts) == 1 {
|
|
||||||
fs.IntVar(field.(*int), parts[0], int(vt), desc)
|
|
||||||
} else {
|
|
||||||
fs.IntVarP(field.(*int), parts[0], parts[1], int(vt), desc)
|
|
||||||
}
|
|
||||||
case reflect.Int8:
|
|
||||||
if len(parts) == 1 {
|
|
||||||
fs.Int8Var(field.(*int8), parts[0], int8(vt), desc)
|
|
||||||
} else {
|
|
||||||
fs.Int8VarP(field.(*int8), parts[0], parts[1], int8(vt), desc)
|
|
||||||
}
|
|
||||||
case reflect.Int32:
|
|
||||||
if len(parts) == 1 {
|
|
||||||
fs.Int32Var(field.(*int32), parts[0], int32(vt), desc)
|
|
||||||
} else {
|
|
||||||
fs.Int32VarP(field.(*int32), parts[0], parts[1], int32(vt), desc)
|
|
||||||
}
|
|
||||||
case reflect.Int64:
|
|
||||||
if len(parts) == 1 {
|
|
||||||
fs.Int64Var(field.(*int64), parts[0], int64(vt), desc)
|
|
||||||
} else {
|
|
||||||
fs.Int64VarP(field.(*int64), parts[0], parts[1], int64(vt), desc)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func registerFlagUint(t reflect.Kind, fs *pflag.FlagSet, field interface{}, parts []string, vt uint64, desc string) {
|
|
||||||
switch t {
|
|
||||||
case reflect.Uint:
|
|
||||||
if len(parts) == 1 {
|
|
||||||
fs.UintVar(field.(*uint), parts[0], uint(vt), desc)
|
|
||||||
} else {
|
|
||||||
fs.UintVarP(field.(*uint), parts[0], parts[1], uint(vt), desc)
|
|
||||||
}
|
|
||||||
case reflect.Uint8:
|
|
||||||
if len(parts) == 1 {
|
|
||||||
fs.Uint8Var(field.(*uint8), parts[0], uint8(vt), desc)
|
|
||||||
} else {
|
|
||||||
fs.Uint8VarP(field.(*uint8), parts[0], parts[1], uint8(vt), desc)
|
|
||||||
}
|
|
||||||
case reflect.Uint16:
|
|
||||||
if len(parts) == 1 {
|
|
||||||
fs.Uint16Var(field.(*uint16), parts[0], uint16(vt), desc)
|
|
||||||
} else {
|
|
||||||
fs.Uint16VarP(field.(*uint16), parts[0], parts[1], uint16(vt), desc)
|
|
||||||
}
|
|
||||||
case reflect.Uint32:
|
|
||||||
if len(parts) == 1 {
|
|
||||||
fs.Uint32Var(field.(*uint32), parts[0], uint32(vt), desc)
|
|
||||||
} else {
|
|
||||||
fs.Uint32VarP(field.(*uint32), parts[0], parts[1], uint32(vt), desc)
|
|
||||||
}
|
|
||||||
case reflect.Uint64:
|
|
||||||
if len(parts) == 1 {
|
|
||||||
fs.Uint64Var(field.(*uint64), parts[0], uint64(vt), desc)
|
|
||||||
} else {
|
|
||||||
fs.Uint64VarP(field.(*uint64), parts[0], parts[1], uint64(vt), desc)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func envDefault(env, def string) string {
|
|
||||||
value := def
|
|
||||||
|
|
||||||
if env != "" {
|
|
||||||
if e := os.Getenv(env); e != "" {
|
|
||||||
value = e
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
|
|
||||||
func varDefault(name, def string) string {
|
|
||||||
value := def
|
|
||||||
|
|
||||||
if name != "" {
|
|
||||||
if v, ok := variableDefaults[name]; ok {
|
|
||||||
value = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return value
|
|
||||||
}
|
|
27
vendor/github.com/Luzifer/rconfig/vardefault_providers.go
generated
vendored
27
vendor/github.com/Luzifer/rconfig/vardefault_providers.go
generated
vendored
|
@ -1,27 +0,0 @@
|
||||||
package rconfig
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io/ioutil"
|
|
||||||
|
|
||||||
"gopkg.in/yaml.v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
// VarDefaultsFromYAMLFile reads contents of a file and calls VarDefaultsFromYAML
|
|
||||||
func VarDefaultsFromYAMLFile(filename string) map[string]string {
|
|
||||||
data, err := ioutil.ReadFile(filename)
|
|
||||||
if err != nil {
|
|
||||||
return make(map[string]string)
|
|
||||||
}
|
|
||||||
|
|
||||||
return VarDefaultsFromYAML(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
// VarDefaultsFromYAML creates a vardefaults map from YAML raw data
|
|
||||||
func VarDefaultsFromYAML(in []byte) map[string]string {
|
|
||||||
out := make(map[string]string)
|
|
||||||
err := yaml.Unmarshal(in, &out)
|
|
||||||
if err != nil {
|
|
||||||
return make(map[string]string)
|
|
||||||
}
|
|
||||||
return out
|
|
||||||
}
|
|
1
vendor/github.com/Sirupsen/logrus/.gitignore
generated
vendored
1
vendor/github.com/Sirupsen/logrus/.gitignore
generated
vendored
|
@ -1 +0,0 @@
|
||||||
logrus
|
|
10
vendor/github.com/Sirupsen/logrus/.travis.yml
generated
vendored
10
vendor/github.com/Sirupsen/logrus/.travis.yml
generated
vendored
|
@ -1,10 +0,0 @@
|
||||||
language: go
|
|
||||||
go:
|
|
||||||
- 1.3
|
|
||||||
- 1.4
|
|
||||||
- 1.5
|
|
||||||
- 1.6
|
|
||||||
- tip
|
|
||||||
install:
|
|
||||||
- go get -t ./...
|
|
||||||
script: GOMAXPROCS=4 GORACE="halt_on_error=1" go test -race -v ./...
|
|
66
vendor/github.com/Sirupsen/logrus/CHANGELOG.md
generated
vendored
66
vendor/github.com/Sirupsen/logrus/CHANGELOG.md
generated
vendored
|
@ -1,66 +0,0 @@
|
||||||
# 0.10.0
|
|
||||||
|
|
||||||
* feature: Add a test hook (#180)
|
|
||||||
* feature: `ParseLevel` is now case-insensitive (#326)
|
|
||||||
* feature: `FieldLogger` interface that generalizes `Logger` and `Entry` (#308)
|
|
||||||
* performance: avoid re-allocations on `WithFields` (#335)
|
|
||||||
|
|
||||||
# 0.9.0
|
|
||||||
|
|
||||||
* logrus/text_formatter: don't emit empty msg
|
|
||||||
* logrus/hooks/airbrake: move out of main repository
|
|
||||||
* logrus/hooks/sentry: move out of main repository
|
|
||||||
* logrus/hooks/papertrail: move out of main repository
|
|
||||||
* logrus/hooks/bugsnag: move out of main repository
|
|
||||||
* logrus/core: run tests with `-race`
|
|
||||||
* logrus/core: detect TTY based on `stderr`
|
|
||||||
* logrus/core: support `WithError` on logger
|
|
||||||
* logrus/core: Solaris support
|
|
||||||
|
|
||||||
# 0.8.7
|
|
||||||
|
|
||||||
* logrus/core: fix possible race (#216)
|
|
||||||
* logrus/doc: small typo fixes and doc improvements
|
|
||||||
|
|
||||||
|
|
||||||
# 0.8.6
|
|
||||||
|
|
||||||
* hooks/raven: allow passing an initialized client
|
|
||||||
|
|
||||||
# 0.8.5
|
|
||||||
|
|
||||||
* logrus/core: revert #208
|
|
||||||
|
|
||||||
# 0.8.4
|
|
||||||
|
|
||||||
* formatter/text: fix data race (#218)
|
|
||||||
|
|
||||||
# 0.8.3
|
|
||||||
|
|
||||||
* logrus/core: fix entry log level (#208)
|
|
||||||
* logrus/core: improve performance of text formatter by 40%
|
|
||||||
* logrus/core: expose `LevelHooks` type
|
|
||||||
* logrus/core: add support for DragonflyBSD and NetBSD
|
|
||||||
* formatter/text: print structs more verbosely
|
|
||||||
|
|
||||||
# 0.8.2
|
|
||||||
|
|
||||||
* logrus: fix more Fatal family functions
|
|
||||||
|
|
||||||
# 0.8.1
|
|
||||||
|
|
||||||
* logrus: fix not exiting on `Fatalf` and `Fatalln`
|
|
||||||
|
|
||||||
# 0.8.0
|
|
||||||
|
|
||||||
* logrus: defaults to stderr instead of stdout
|
|
||||||
* hooks/sentry: add special field for `*http.Request`
|
|
||||||
* formatter/text: ignore Windows for colors
|
|
||||||
|
|
||||||
# 0.7.3
|
|
||||||
|
|
||||||
* formatter/\*: allow configuration of timestamp layout
|
|
||||||
|
|
||||||
# 0.7.2
|
|
||||||
|
|
||||||
* formatter/text: Add configuration option for time format (#158)
|
|
21
vendor/github.com/Sirupsen/logrus/LICENSE
generated
vendored
21
vendor/github.com/Sirupsen/logrus/LICENSE
generated
vendored
|
@ -1,21 +0,0 @@
|
||||||
The MIT License (MIT)
|
|
||||||
|
|
||||||
Copyright (c) 2014 Simon Eskildsen
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
THE SOFTWARE.
|
|
421
vendor/github.com/Sirupsen/logrus/README.md
generated
vendored
421
vendor/github.com/Sirupsen/logrus/README.md
generated
vendored
|
@ -1,421 +0,0 @@
|
||||||
# Logrus <img src="http://i.imgur.com/hTeVwmJ.png" width="40" height="40" alt=":walrus:" class="emoji" title=":walrus:"/> [![Build Status](https://travis-ci.org/Sirupsen/logrus.svg?branch=master)](https://travis-ci.org/Sirupsen/logrus) [![GoDoc](https://godoc.org/github.com/Sirupsen/logrus?status.svg)](https://godoc.org/github.com/Sirupsen/logrus)
|
|
||||||
|
|
||||||
Logrus is a structured logger for Go (golang), completely API compatible with
|
|
||||||
the standard library logger. [Godoc][godoc]. **Please note the Logrus API is not
|
|
||||||
yet stable (pre 1.0). Logrus itself is completely stable and has been used in
|
|
||||||
many large deployments. The core API is unlikely to change much but please
|
|
||||||
version control your Logrus to make sure you aren't fetching latest `master` on
|
|
||||||
every build.**
|
|
||||||
|
|
||||||
Nicely color-coded in development (when a TTY is attached, otherwise just
|
|
||||||
plain text):
|
|
||||||
|
|
||||||
![Colored](http://i.imgur.com/PY7qMwd.png)
|
|
||||||
|
|
||||||
With `log.SetFormatter(&log.JSONFormatter{})`, for easy parsing by logstash
|
|
||||||
or Splunk:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{"animal":"walrus","level":"info","msg":"A group of walrus emerges from the
|
|
||||||
ocean","size":10,"time":"2014-03-10 19:57:38.562264131 -0400 EDT"}
|
|
||||||
|
|
||||||
{"level":"warning","msg":"The group's number increased tremendously!",
|
|
||||||
"number":122,"omg":true,"time":"2014-03-10 19:57:38.562471297 -0400 EDT"}
|
|
||||||
|
|
||||||
{"animal":"walrus","level":"info","msg":"A giant walrus appears!",
|
|
||||||
"size":10,"time":"2014-03-10 19:57:38.562500591 -0400 EDT"}
|
|
||||||
|
|
||||||
{"animal":"walrus","level":"info","msg":"Tremendously sized cow enters the ocean.",
|
|
||||||
"size":9,"time":"2014-03-10 19:57:38.562527896 -0400 EDT"}
|
|
||||||
|
|
||||||
{"level":"fatal","msg":"The ice breaks!","number":100,"omg":true,
|
|
||||||
"time":"2014-03-10 19:57:38.562543128 -0400 EDT"}
|
|
||||||
```
|
|
||||||
|
|
||||||
With the default `log.SetFormatter(&log.TextFormatter{})` when a TTY is not
|
|
||||||
attached, the output is compatible with the
|
|
||||||
[logfmt](http://godoc.org/github.com/kr/logfmt) format:
|
|
||||||
|
|
||||||
```text
|
|
||||||
time="2015-03-26T01:27:38-04:00" level=debug msg="Started observing beach" animal=walrus number=8
|
|
||||||
time="2015-03-26T01:27:38-04:00" level=info msg="A group of walrus emerges from the ocean" animal=walrus size=10
|
|
||||||
time="2015-03-26T01:27:38-04:00" level=warning msg="The group's number increased tremendously!" number=122 omg=true
|
|
||||||
time="2015-03-26T01:27:38-04:00" level=debug msg="Temperature changes" temperature=-4
|
|
||||||
time="2015-03-26T01:27:38-04:00" level=panic msg="It's over 9000!" animal=orca size=9009
|
|
||||||
time="2015-03-26T01:27:38-04:00" level=fatal msg="The ice breaks!" err=&{0x2082280c0 map[animal:orca size:9009] 2015-03-26 01:27:38.441574009 -0400 EDT panic It's over 9000!} number=100 omg=true
|
|
||||||
exit status 1
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Example
|
|
||||||
|
|
||||||
The simplest way to use Logrus is simply the package-level exported logger:
|
|
||||||
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
log "github.com/Sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"animal": "walrus",
|
|
||||||
}).Info("A walrus appears")
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Note that it's completely api-compatible with the stdlib logger, so you can
|
|
||||||
replace your `log` imports everywhere with `log "github.com/Sirupsen/logrus"`
|
|
||||||
and you'll now have the flexibility of Logrus. You can customize it all you
|
|
||||||
want:
|
|
||||||
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
log "github.com/Sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
// Log as JSON instead of the default ASCII formatter.
|
|
||||||
log.SetFormatter(&log.JSONFormatter{})
|
|
||||||
|
|
||||||
// Output to stderr instead of stdout, could also be a file.
|
|
||||||
log.SetOutput(os.Stderr)
|
|
||||||
|
|
||||||
// Only log the warning severity or above.
|
|
||||||
log.SetLevel(log.WarnLevel)
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"animal": "walrus",
|
|
||||||
"size": 10,
|
|
||||||
}).Info("A group of walrus emerges from the ocean")
|
|
||||||
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"omg": true,
|
|
||||||
"number": 122,
|
|
||||||
}).Warn("The group's number increased tremendously!")
|
|
||||||
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"omg": true,
|
|
||||||
"number": 100,
|
|
||||||
}).Fatal("The ice breaks!")
|
|
||||||
|
|
||||||
// A common pattern is to re-use fields between logging statements by re-using
|
|
||||||
// the logrus.Entry returned from WithFields()
|
|
||||||
contextLogger := log.WithFields(log.Fields{
|
|
||||||
"common": "this is a common field",
|
|
||||||
"other": "I also should be logged always",
|
|
||||||
})
|
|
||||||
|
|
||||||
contextLogger.Info("I'll be logged with common and other field")
|
|
||||||
contextLogger.Info("Me too")
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
For more advanced usage such as logging to multiple locations from the same
|
|
||||||
application, you can also create an instance of the `logrus` Logger:
|
|
||||||
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/Sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Create a new instance of the logger. You can have any number of instances.
|
|
||||||
var log = logrus.New()
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
// The API for setting attributes is a little different than the package level
|
|
||||||
// exported logger. See Godoc.
|
|
||||||
log.Out = os.Stderr
|
|
||||||
|
|
||||||
log.WithFields(logrus.Fields{
|
|
||||||
"animal": "walrus",
|
|
||||||
"size": 10,
|
|
||||||
}).Info("A group of walrus emerges from the ocean")
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Fields
|
|
||||||
|
|
||||||
Logrus encourages careful, structured logging though logging fields instead of
|
|
||||||
long, unparseable error messages. For example, instead of: `log.Fatalf("Failed
|
|
||||||
to send event %s to topic %s with key %d")`, you should log the much more
|
|
||||||
discoverable:
|
|
||||||
|
|
||||||
```go
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"event": event,
|
|
||||||
"topic": topic,
|
|
||||||
"key": key,
|
|
||||||
}).Fatal("Failed to send event")
|
|
||||||
```
|
|
||||||
|
|
||||||
We've found this API forces you to think about logging in a way that produces
|
|
||||||
much more useful logging messages. We've been in countless situations where just
|
|
||||||
a single added field to a log statement that was already there would've saved us
|
|
||||||
hours. The `WithFields` call is optional.
|
|
||||||
|
|
||||||
In general, with Logrus using any of the `printf`-family functions should be
|
|
||||||
seen as a hint you should add a field, however, you can still use the
|
|
||||||
`printf`-family functions with Logrus.
|
|
||||||
|
|
||||||
#### Hooks
|
|
||||||
|
|
||||||
You can add hooks for logging levels. For example to send errors to an exception
|
|
||||||
tracking service on `Error`, `Fatal` and `Panic`, info to StatsD or log to
|
|
||||||
multiple places simultaneously, e.g. syslog.
|
|
||||||
|
|
||||||
Logrus comes with [built-in hooks](hooks/). Add those, or your custom hook, in
|
|
||||||
`init`:
|
|
||||||
|
|
||||||
```go
|
|
||||||
import (
|
|
||||||
log "github.com/Sirupsen/logrus"
|
|
||||||
"gopkg.in/gemnasium/logrus-airbrake-hook.v2" // the package is named "aibrake"
|
|
||||||
logrus_syslog "github.com/Sirupsen/logrus/hooks/syslog"
|
|
||||||
"log/syslog"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
|
|
||||||
// Use the Airbrake hook to report errors that have Error severity or above to
|
|
||||||
// an exception tracker. You can create custom hooks, see the Hooks section.
|
|
||||||
log.AddHook(airbrake.NewHook(123, "xyz", "production"))
|
|
||||||
|
|
||||||
hook, err := logrus_syslog.NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, "")
|
|
||||||
if err != nil {
|
|
||||||
log.Error("Unable to connect to local syslog daemon")
|
|
||||||
} else {
|
|
||||||
log.AddHook(hook)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
Note: Syslog hook also support connecting to local syslog (Ex. "/dev/log" or "/var/run/syslog" or "/var/run/log"). For the detail, please check the [syslog hook README](hooks/syslog/README.md).
|
|
||||||
|
|
||||||
| Hook | Description |
|
|
||||||
| ----- | ----------- |
|
|
||||||
| [Airbrake](https://github.com/gemnasium/logrus-airbrake-hook) | Send errors to the Airbrake API V3. Uses the official [`gobrake`](https://github.com/airbrake/gobrake) behind the scenes. |
|
|
||||||
| [Airbrake "legacy"](https://github.com/gemnasium/logrus-airbrake-legacy-hook) | Send errors to an exception tracking service compatible with the Airbrake API V2. Uses [`airbrake-go`](https://github.com/tobi/airbrake-go) behind the scenes. |
|
|
||||||
| [Papertrail](https://github.com/polds/logrus-papertrail-hook) | Send errors to the [Papertrail](https://papertrailapp.com) hosted logging service via UDP. |
|
|
||||||
| [Syslog](https://github.com/Sirupsen/logrus/blob/master/hooks/syslog/syslog.go) | Send errors to remote syslog server. Uses standard library `log/syslog` behind the scenes. |
|
|
||||||
| [Bugsnag](https://github.com/Shopify/logrus-bugsnag/blob/master/bugsnag.go) | Send errors to the Bugsnag exception tracking service. |
|
|
||||||
| [Sentry](https://github.com/evalphobia/logrus_sentry) | Send errors to the Sentry error logging and aggregation service. |
|
|
||||||
| [Hiprus](https://github.com/nubo/hiprus) | Send errors to a channel in hipchat. |
|
|
||||||
| [Logrusly](https://github.com/sebest/logrusly) | Send logs to [Loggly](https://www.loggly.com/) |
|
|
||||||
| [Slackrus](https://github.com/johntdyer/slackrus) | Hook for Slack chat. |
|
|
||||||
| [Journalhook](https://github.com/wercker/journalhook) | Hook for logging to `systemd-journald` |
|
|
||||||
| [Graylog](https://github.com/gemnasium/logrus-graylog-hook) | Hook for logging to [Graylog](http://graylog2.org/) |
|
|
||||||
| [Raygun](https://github.com/squirkle/logrus-raygun-hook) | Hook for logging to [Raygun.io](http://raygun.io/) |
|
|
||||||
| [LFShook](https://github.com/rifflock/lfshook) | Hook for logging to the local filesystem |
|
|
||||||
| [Honeybadger](https://github.com/agonzalezro/logrus_honeybadger) | Hook for sending exceptions to Honeybadger |
|
|
||||||
| [Mail](https://github.com/zbindenren/logrus_mail) | Hook for sending exceptions via mail |
|
|
||||||
| [Rollrus](https://github.com/heroku/rollrus) | Hook for sending errors to rollbar |
|
|
||||||
| [Fluentd](https://github.com/evalphobia/logrus_fluent) | Hook for logging to fluentd |
|
|
||||||
| [Mongodb](https://github.com/weekface/mgorus) | Hook for logging to mongodb |
|
|
||||||
| [Influxus] (http://github.com/vlad-doru/influxus) | Hook for concurrently logging to [InfluxDB] (http://influxdata.com/) |
|
|
||||||
| [InfluxDB](https://github.com/Abramovic/logrus_influxdb) | Hook for logging to influxdb |
|
|
||||||
| [Octokit](https://github.com/dorajistyle/logrus-octokit-hook) | Hook for logging to github via octokit |
|
|
||||||
| [DeferPanic](https://github.com/deferpanic/dp-logrus) | Hook for logging to DeferPanic |
|
|
||||||
| [Redis-Hook](https://github.com/rogierlommers/logrus-redis-hook) | Hook for logging to a ELK stack (through Redis) |
|
|
||||||
| [Amqp-Hook](https://github.com/vladoatanasov/logrus_amqp) | Hook for logging to Amqp broker (Like RabbitMQ) |
|
|
||||||
| [KafkaLogrus](https://github.com/goibibo/KafkaLogrus) | Hook for logging to kafka |
|
|
||||||
| [Typetalk](https://github.com/dragon3/logrus-typetalk-hook) | Hook for logging to [Typetalk](https://www.typetalk.in/) |
|
|
||||||
| [ElasticSearch](https://github.com/sohlich/elogrus) | Hook for logging to ElasticSearch|
|
|
||||||
| [Sumorus](https://github.com/doublefree/sumorus) | Hook for logging to [SumoLogic](https://www.sumologic.com/)|
|
|
||||||
| [Logstash](https://github.com/bshuster-repo/logrus-logstash-hook) | Hook for logging to [Logstash](https://www.elastic.co/products/logstash) |
|
|
||||||
| [Logmatic.io](https://github.com/logmatic/logmatic-go) | Hook for logging to [Logmatic.io](http://logmatic.io/) |
|
|
||||||
|
|
||||||
|
|
||||||
#### Level logging
|
|
||||||
|
|
||||||
Logrus has six logging levels: Debug, Info, Warning, Error, Fatal and Panic.
|
|
||||||
|
|
||||||
```go
|
|
||||||
log.Debug("Useful debugging information.")
|
|
||||||
log.Info("Something noteworthy happened!")
|
|
||||||
log.Warn("You should probably take a look at this.")
|
|
||||||
log.Error("Something failed but I'm not quitting.")
|
|
||||||
// Calls os.Exit(1) after logging
|
|
||||||
log.Fatal("Bye.")
|
|
||||||
// Calls panic() after logging
|
|
||||||
log.Panic("I'm bailing.")
|
|
||||||
```
|
|
||||||
|
|
||||||
You can set the logging level on a `Logger`, then it will only log entries with
|
|
||||||
that severity or anything above it:
|
|
||||||
|
|
||||||
```go
|
|
||||||
// Will log anything that is info or above (warn, error, fatal, panic). Default.
|
|
||||||
log.SetLevel(log.InfoLevel)
|
|
||||||
```
|
|
||||||
|
|
||||||
It may be useful to set `log.Level = logrus.DebugLevel` in a debug or verbose
|
|
||||||
environment if your application has that.
|
|
||||||
|
|
||||||
#### Entries
|
|
||||||
|
|
||||||
Besides the fields added with `WithField` or `WithFields` some fields are
|
|
||||||
automatically added to all logging events:
|
|
||||||
|
|
||||||
1. `time`. The timestamp when the entry was created.
|
|
||||||
2. `msg`. The logging message passed to `{Info,Warn,Error,Fatal,Panic}` after
|
|
||||||
the `AddFields` call. E.g. `Failed to send event.`
|
|
||||||
3. `level`. The logging level. E.g. `info`.
|
|
||||||
|
|
||||||
#### Environments
|
|
||||||
|
|
||||||
Logrus has no notion of environment.
|
|
||||||
|
|
||||||
If you wish for hooks and formatters to only be used in specific environments,
|
|
||||||
you should handle that yourself. For example, if your application has a global
|
|
||||||
variable `Environment`, which is a string representation of the environment you
|
|
||||||
could do:
|
|
||||||
|
|
||||||
```go
|
|
||||||
import (
|
|
||||||
log "github.com/Sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
init() {
|
|
||||||
// do something here to set environment depending on an environment variable
|
|
||||||
// or command-line flag
|
|
||||||
if Environment == "production" {
|
|
||||||
log.SetFormatter(&log.JSONFormatter{})
|
|
||||||
} else {
|
|
||||||
// The TextFormatter is default, you don't actually have to do this.
|
|
||||||
log.SetFormatter(&log.TextFormatter{})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
This configuration is how `logrus` was intended to be used, but JSON in
|
|
||||||
production is mostly only useful if you do log aggregation with tools like
|
|
||||||
Splunk or Logstash.
|
|
||||||
|
|
||||||
#### Formatters
|
|
||||||
|
|
||||||
The built-in logging formatters are:
|
|
||||||
|
|
||||||
* `logrus.TextFormatter`. Logs the event in colors if stdout is a tty, otherwise
|
|
||||||
without colors.
|
|
||||||
* *Note:* to force colored output when there is no TTY, set the `ForceColors`
|
|
||||||
field to `true`. To force no colored output even if there is a TTY set the
|
|
||||||
`DisableColors` field to `true`
|
|
||||||
* `logrus.JSONFormatter`. Logs fields as JSON.
|
|
||||||
|
|
||||||
Third party logging formatters:
|
|
||||||
|
|
||||||
* [`logstash`](https://github.com/bshuster-repo/logrus-logstash-hook). Logs fields as [Logstash](http://logstash.net) Events.
|
|
||||||
* [`prefixed`](https://github.com/x-cray/logrus-prefixed-formatter). Displays log entry source along with alternative layout.
|
|
||||||
* [`zalgo`](https://github.com/aybabtme/logzalgo). Invoking the P͉̫o̳̼̊w̖͈̰͎e̬͔̭͂r͚̼̹̲ ̫͓͉̳͈ō̠͕͖̚f̝͍̠ ͕̲̞͖͑Z̖̫̤̫ͪa͉̬͈̗l͖͎g̳̥o̰̥̅!̣͔̲̻͊̄ ̙̘̦̹̦.
|
|
||||||
|
|
||||||
You can define your formatter by implementing the `Formatter` interface,
|
|
||||||
requiring a `Format` method. `Format` takes an `*Entry`. `entry.Data` is a
|
|
||||||
`Fields` type (`map[string]interface{}`) with all your fields as well as the
|
|
||||||
default ones (see Entries section above):
|
|
||||||
|
|
||||||
```go
|
|
||||||
type MyJSONFormatter struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
log.SetFormatter(new(MyJSONFormatter))
|
|
||||||
|
|
||||||
func (f *MyJSONFormatter) Format(entry *Entry) ([]byte, error) {
|
|
||||||
// Note this doesn't include Time, Level and Message which are available on
|
|
||||||
// the Entry. Consult `godoc` on information about those fields or read the
|
|
||||||
// source of the official loggers.
|
|
||||||
serialized, err := json.Marshal(entry.Data)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err)
|
|
||||||
}
|
|
||||||
return append(serialized, '\n'), nil
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Logger as an `io.Writer`
|
|
||||||
|
|
||||||
Logrus can be transformed into an `io.Writer`. That writer is the end of an `io.Pipe` and it is your responsibility to close it.
|
|
||||||
|
|
||||||
```go
|
|
||||||
w := logger.Writer()
|
|
||||||
defer w.Close()
|
|
||||||
|
|
||||||
srv := http.Server{
|
|
||||||
// create a stdlib log.Logger that writes to
|
|
||||||
// logrus.Logger.
|
|
||||||
ErrorLog: log.New(w, "", 0),
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Each line written to that writer will be printed the usual way, using formatters
|
|
||||||
and hooks. The level for those entries is `info`.
|
|
||||||
|
|
||||||
#### Rotation
|
|
||||||
|
|
||||||
Log rotation is not provided with Logrus. Log rotation should be done by an
|
|
||||||
external program (like `logrotate(8)`) that can compress and delete old log
|
|
||||||
entries. It should not be a feature of the application-level logger.
|
|
||||||
|
|
||||||
#### Tools
|
|
||||||
|
|
||||||
| Tool | Description |
|
|
||||||
| ---- | ----------- |
|
|
||||||
|[Logrus Mate](https://github.com/gogap/logrus_mate)|Logrus mate is a tool for Logrus to manage loggers, you can initial logger's level, hook and formatter by config file, the logger will generated with different config at different environment.|
|
|
||||||
|
|
||||||
#### Testing
|
|
||||||
|
|
||||||
Logrus has a built in facility for asserting the presence of log messages. This is implemented through the `test` hook and provides:
|
|
||||||
|
|
||||||
* decorators for existing logger (`test.NewLocal` and `test.NewGlobal`) which basically just add the `test` hook
|
|
||||||
* a test logger (`test.NewNullLogger`) that just records log messages (and does not output any):
|
|
||||||
|
|
||||||
```go
|
|
||||||
logger, hook := NewNullLogger()
|
|
||||||
logger.Error("Hello error")
|
|
||||||
|
|
||||||
assert.Equal(1, len(hook.Entries))
|
|
||||||
assert.Equal(logrus.ErrorLevel, hook.LastEntry().Level)
|
|
||||||
assert.Equal("Hello error", hook.LastEntry().Message)
|
|
||||||
|
|
||||||
hook.Reset()
|
|
||||||
assert.Nil(hook.LastEntry())
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Fatal handlers
|
|
||||||
|
|
||||||
Logrus can register one or more functions that will be called when any `fatal`
|
|
||||||
level message is logged. The registered handlers will be executed before
|
|
||||||
logrus performs a `os.Exit(1)`. This behavior may be helpful if callers need
|
|
||||||
to gracefully shutdown. Unlike a `panic("Something went wrong...")` call which can be intercepted with a deferred `recover` a call to `os.Exit(1)` can not be intercepted.
|
|
||||||
|
|
||||||
```
|
|
||||||
...
|
|
||||||
handler := func() {
|
|
||||||
// gracefully shutdown something...
|
|
||||||
}
|
|
||||||
logrus.RegisterExitHandler(handler)
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Thread safty
|
|
||||||
|
|
||||||
By default Logger is protected by mutex for concurrent writes, this mutex is invoked when calling hooks and writing logs.
|
|
||||||
If you are sure such locking is not needed, you can call logger.SetNoLock() to disable the locking.
|
|
||||||
|
|
||||||
Situation when locking is not needed includes:
|
|
||||||
|
|
||||||
* You have no hooks registered, or hooks calling is already thread-safe.
|
|
||||||
|
|
||||||
* Writing to logger.Out is already thread-safe, for example:
|
|
||||||
|
|
||||||
1) logger.Out is protected by locks.
|
|
||||||
|
|
||||||
2) logger.Out is a os.File handler opened with `O_APPEND` flag, and every write is smaller than 4k. (This allow multi-thread/multi-process writing)
|
|
||||||
|
|
||||||
(Refer to http://www.notthewizard.com/2014/06/17/are-files-appends-really-atomic/)
|
|
64
vendor/github.com/Sirupsen/logrus/alt_exit.go
generated
vendored
64
vendor/github.com/Sirupsen/logrus/alt_exit.go
generated
vendored
|
@ -1,64 +0,0 @@
|
||||||
package logrus
|
|
||||||
|
|
||||||
// The following code was sourced and modified from the
|
|
||||||
// https://bitbucket.org/tebeka/atexit package governed by the following license:
|
|
||||||
//
|
|
||||||
// Copyright (c) 2012 Miki Tebeka <miki.tebeka@gmail.com>.
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
||||||
// this software and associated documentation files (the "Software"), to deal in
|
|
||||||
// the Software without restriction, including without limitation the rights to
|
|
||||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
||||||
// the Software, and to permit persons to whom the Software is furnished to do so,
|
|
||||||
// subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in all
|
|
||||||
// copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
||||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
||||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
||||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
var handlers = []func(){}
|
|
||||||
|
|
||||||
func runHandler(handler func()) {
|
|
||||||
defer func() {
|
|
||||||
if err := recover(); err != nil {
|
|
||||||
fmt.Fprintln(os.Stderr, "Error: Logrus exit handler error:", err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
handler()
|
|
||||||
}
|
|
||||||
|
|
||||||
func runHandlers() {
|
|
||||||
for _, handler := range handlers {
|
|
||||||
runHandler(handler)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Exit runs all the Logrus atexit handlers and then terminates the program using os.Exit(code)
|
|
||||||
func Exit(code int) {
|
|
||||||
runHandlers()
|
|
||||||
os.Exit(code)
|
|
||||||
}
|
|
||||||
|
|
||||||
// RegisterExitHandler adds a Logrus Exit handler, call logrus.Exit to invoke
|
|
||||||
// all handlers. The handlers will also be invoked when any Fatal log entry is
|
|
||||||
// made.
|
|
||||||
//
|
|
||||||
// This method is useful when a caller wishes to use logrus to log a fatal
|
|
||||||
// message but also needs to gracefully shutdown. An example usecase could be
|
|
||||||
// closing database connections, or sending a alert that the application is
|
|
||||||
// closing.
|
|
||||||
func RegisterExitHandler(handler func()) {
|
|
||||||
handlers = append(handlers, handler)
|
|
||||||
}
|
|
26
vendor/github.com/Sirupsen/logrus/doc.go
generated
vendored
26
vendor/github.com/Sirupsen/logrus/doc.go
generated
vendored
|
@ -1,26 +0,0 @@
|
||||||
/*
|
|
||||||
Package logrus is a structured logger for Go, completely API compatible with the standard library logger.
|
|
||||||
|
|
||||||
|
|
||||||
The simplest way to use Logrus is simply the package-level exported logger:
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
log "github.com/Sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"animal": "walrus",
|
|
||||||
"number": 1,
|
|
||||||
"size": 10,
|
|
||||||
}).Info("A walrus appears")
|
|
||||||
}
|
|
||||||
|
|
||||||
Output:
|
|
||||||
time="2015-09-07T08:48:33Z" level=info msg="A walrus appears" animal=walrus number=1 size=10
|
|
||||||
|
|
||||||
For a full guide visit https://github.com/Sirupsen/logrus
|
|
||||||
*/
|
|
||||||
package logrus
|
|
275
vendor/github.com/Sirupsen/logrus/entry.go
generated
vendored
275
vendor/github.com/Sirupsen/logrus/entry.go
generated
vendored
|
@ -1,275 +0,0 @@
|
||||||
package logrus
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
var bufferPool *sync.Pool
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
bufferPool = &sync.Pool{
|
|
||||||
New: func() interface{} {
|
|
||||||
return new(bytes.Buffer)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Defines the key when adding errors using WithError.
|
|
||||||
var ErrorKey = "error"
|
|
||||||
|
|
||||||
// An entry is the final or intermediate Logrus logging entry. It contains all
|
|
||||||
// the fields passed with WithField{,s}. It's finally logged when Debug, Info,
|
|
||||||
// Warn, Error, Fatal or Panic is called on it. These objects can be reused and
|
|
||||||
// passed around as much as you wish to avoid field duplication.
|
|
||||||
type Entry struct {
|
|
||||||
Logger *Logger
|
|
||||||
|
|
||||||
// Contains all the fields set by the user.
|
|
||||||
Data Fields
|
|
||||||
|
|
||||||
// Time at which the log entry was created
|
|
||||||
Time time.Time
|
|
||||||
|
|
||||||
// Level the log entry was logged at: Debug, Info, Warn, Error, Fatal or Panic
|
|
||||||
Level Level
|
|
||||||
|
|
||||||
// Message passed to Debug, Info, Warn, Error, Fatal or Panic
|
|
||||||
Message string
|
|
||||||
|
|
||||||
// When formatter is called in entry.log(), an Buffer may be set to entry
|
|
||||||
Buffer *bytes.Buffer
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewEntry(logger *Logger) *Entry {
|
|
||||||
return &Entry{
|
|
||||||
Logger: logger,
|
|
||||||
// Default is three fields, give a little extra room
|
|
||||||
Data: make(Fields, 5),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the string representation from the reader and ultimately the
|
|
||||||
// formatter.
|
|
||||||
func (entry *Entry) String() (string, error) {
|
|
||||||
serialized, err := entry.Logger.Formatter.Format(entry)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
str := string(serialized)
|
|
||||||
return str, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add an error as single field (using the key defined in ErrorKey) to the Entry.
|
|
||||||
func (entry *Entry) WithError(err error) *Entry {
|
|
||||||
return entry.WithField(ErrorKey, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add a single field to the Entry.
|
|
||||||
func (entry *Entry) WithField(key string, value interface{}) *Entry {
|
|
||||||
return entry.WithFields(Fields{key: value})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add a map of fields to the Entry.
|
|
||||||
func (entry *Entry) WithFields(fields Fields) *Entry {
|
|
||||||
data := make(Fields, len(entry.Data)+len(fields))
|
|
||||||
for k, v := range entry.Data {
|
|
||||||
data[k] = v
|
|
||||||
}
|
|
||||||
for k, v := range fields {
|
|
||||||
data[k] = v
|
|
||||||
}
|
|
||||||
return &Entry{Logger: entry.Logger, Data: data}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This function is not declared with a pointer value because otherwise
|
|
||||||
// race conditions will occur when using multiple goroutines
|
|
||||||
func (entry Entry) log(level Level, msg string) {
|
|
||||||
var buffer *bytes.Buffer
|
|
||||||
entry.Time = time.Now()
|
|
||||||
entry.Level = level
|
|
||||||
entry.Message = msg
|
|
||||||
|
|
||||||
if err := entry.Logger.Hooks.Fire(level, &entry); err != nil {
|
|
||||||
entry.Logger.mu.Lock()
|
|
||||||
fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err)
|
|
||||||
entry.Logger.mu.Unlock()
|
|
||||||
}
|
|
||||||
buffer = bufferPool.Get().(*bytes.Buffer)
|
|
||||||
buffer.Reset()
|
|
||||||
defer bufferPool.Put(buffer)
|
|
||||||
entry.Buffer = buffer
|
|
||||||
serialized, err := entry.Logger.Formatter.Format(&entry)
|
|
||||||
entry.Buffer = nil
|
|
||||||
if err != nil {
|
|
||||||
entry.Logger.mu.Lock()
|
|
||||||
fmt.Fprintf(os.Stderr, "Failed to obtain reader, %v\n", err)
|
|
||||||
entry.Logger.mu.Unlock()
|
|
||||||
} else {
|
|
||||||
entry.Logger.mu.Lock()
|
|
||||||
_, err = entry.Logger.Out.Write(serialized)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err)
|
|
||||||
}
|
|
||||||
entry.Logger.mu.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
// To avoid Entry#log() returning a value that only would make sense for
|
|
||||||
// panic() to use in Entry#Panic(), we avoid the allocation by checking
|
|
||||||
// directly here.
|
|
||||||
if level <= PanicLevel {
|
|
||||||
panic(&entry)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) Debug(args ...interface{}) {
|
|
||||||
if entry.Logger.Level >= DebugLevel {
|
|
||||||
entry.log(DebugLevel, fmt.Sprint(args...))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) Print(args ...interface{}) {
|
|
||||||
entry.Info(args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) Info(args ...interface{}) {
|
|
||||||
if entry.Logger.Level >= InfoLevel {
|
|
||||||
entry.log(InfoLevel, fmt.Sprint(args...))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) Warn(args ...interface{}) {
|
|
||||||
if entry.Logger.Level >= WarnLevel {
|
|
||||||
entry.log(WarnLevel, fmt.Sprint(args...))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) Warning(args ...interface{}) {
|
|
||||||
entry.Warn(args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) Error(args ...interface{}) {
|
|
||||||
if entry.Logger.Level >= ErrorLevel {
|
|
||||||
entry.log(ErrorLevel, fmt.Sprint(args...))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) Fatal(args ...interface{}) {
|
|
||||||
if entry.Logger.Level >= FatalLevel {
|
|
||||||
entry.log(FatalLevel, fmt.Sprint(args...))
|
|
||||||
}
|
|
||||||
Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) Panic(args ...interface{}) {
|
|
||||||
if entry.Logger.Level >= PanicLevel {
|
|
||||||
entry.log(PanicLevel, fmt.Sprint(args...))
|
|
||||||
}
|
|
||||||
panic(fmt.Sprint(args...))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Entry Printf family functions
|
|
||||||
|
|
||||||
func (entry *Entry) Debugf(format string, args ...interface{}) {
|
|
||||||
if entry.Logger.Level >= DebugLevel {
|
|
||||||
entry.Debug(fmt.Sprintf(format, args...))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) Infof(format string, args ...interface{}) {
|
|
||||||
if entry.Logger.Level >= InfoLevel {
|
|
||||||
entry.Info(fmt.Sprintf(format, args...))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) Printf(format string, args ...interface{}) {
|
|
||||||
entry.Infof(format, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) Warnf(format string, args ...interface{}) {
|
|
||||||
if entry.Logger.Level >= WarnLevel {
|
|
||||||
entry.Warn(fmt.Sprintf(format, args...))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) Warningf(format string, args ...interface{}) {
|
|
||||||
entry.Warnf(format, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) Errorf(format string, args ...interface{}) {
|
|
||||||
if entry.Logger.Level >= ErrorLevel {
|
|
||||||
entry.Error(fmt.Sprintf(format, args...))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) Fatalf(format string, args ...interface{}) {
|
|
||||||
if entry.Logger.Level >= FatalLevel {
|
|
||||||
entry.Fatal(fmt.Sprintf(format, args...))
|
|
||||||
}
|
|
||||||
Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) Panicf(format string, args ...interface{}) {
|
|
||||||
if entry.Logger.Level >= PanicLevel {
|
|
||||||
entry.Panic(fmt.Sprintf(format, args...))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Entry Println family functions
|
|
||||||
|
|
||||||
func (entry *Entry) Debugln(args ...interface{}) {
|
|
||||||
if entry.Logger.Level >= DebugLevel {
|
|
||||||
entry.Debug(entry.sprintlnn(args...))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) Infoln(args ...interface{}) {
|
|
||||||
if entry.Logger.Level >= InfoLevel {
|
|
||||||
entry.Info(entry.sprintlnn(args...))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) Println(args ...interface{}) {
|
|
||||||
entry.Infoln(args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) Warnln(args ...interface{}) {
|
|
||||||
if entry.Logger.Level >= WarnLevel {
|
|
||||||
entry.Warn(entry.sprintlnn(args...))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) Warningln(args ...interface{}) {
|
|
||||||
entry.Warnln(args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) Errorln(args ...interface{}) {
|
|
||||||
if entry.Logger.Level >= ErrorLevel {
|
|
||||||
entry.Error(entry.sprintlnn(args...))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) Fatalln(args ...interface{}) {
|
|
||||||
if entry.Logger.Level >= FatalLevel {
|
|
||||||
entry.Fatal(entry.sprintlnn(args...))
|
|
||||||
}
|
|
||||||
Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) Panicln(args ...interface{}) {
|
|
||||||
if entry.Logger.Level >= PanicLevel {
|
|
||||||
entry.Panic(entry.sprintlnn(args...))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sprintlnn => Sprint no newline. This is to get the behavior of how
|
|
||||||
// fmt.Sprintln where spaces are always added between operands, regardless of
|
|
||||||
// their type. Instead of vendoring the Sprintln implementation to spare a
|
|
||||||
// string allocation, we do the simplest thing.
|
|
||||||
func (entry *Entry) sprintlnn(args ...interface{}) string {
|
|
||||||
msg := fmt.Sprintln(args...)
|
|
||||||
return msg[:len(msg)-1]
|
|
||||||
}
|
|
193
vendor/github.com/Sirupsen/logrus/exported.go
generated
vendored
193
vendor/github.com/Sirupsen/logrus/exported.go
generated
vendored
|
@ -1,193 +0,0 @@
|
||||||
package logrus
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// std is the name of the standard logger in stdlib `log`
|
|
||||||
std = New()
|
|
||||||
)
|
|
||||||
|
|
||||||
func StandardLogger() *Logger {
|
|
||||||
return std
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetOutput sets the standard logger output.
|
|
||||||
func SetOutput(out io.Writer) {
|
|
||||||
std.mu.Lock()
|
|
||||||
defer std.mu.Unlock()
|
|
||||||
std.Out = out
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetFormatter sets the standard logger formatter.
|
|
||||||
func SetFormatter(formatter Formatter) {
|
|
||||||
std.mu.Lock()
|
|
||||||
defer std.mu.Unlock()
|
|
||||||
std.Formatter = formatter
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetLevel sets the standard logger level.
|
|
||||||
func SetLevel(level Level) {
|
|
||||||
std.mu.Lock()
|
|
||||||
defer std.mu.Unlock()
|
|
||||||
std.Level = level
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetLevel returns the standard logger level.
|
|
||||||
func GetLevel() Level {
|
|
||||||
std.mu.Lock()
|
|
||||||
defer std.mu.Unlock()
|
|
||||||
return std.Level
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddHook adds a hook to the standard logger hooks.
|
|
||||||
func AddHook(hook Hook) {
|
|
||||||
std.mu.Lock()
|
|
||||||
defer std.mu.Unlock()
|
|
||||||
std.Hooks.Add(hook)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithError creates an entry from the standard logger and adds an error to it, using the value defined in ErrorKey as key.
|
|
||||||
func WithError(err error) *Entry {
|
|
||||||
return std.WithField(ErrorKey, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithField creates an entry from the standard logger and adds a field to
|
|
||||||
// it. If you want multiple fields, use `WithFields`.
|
|
||||||
//
|
|
||||||
// Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal
|
|
||||||
// or Panic on the Entry it returns.
|
|
||||||
func WithField(key string, value interface{}) *Entry {
|
|
||||||
return std.WithField(key, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithFields creates an entry from the standard logger and adds multiple
|
|
||||||
// fields to it. This is simply a helper for `WithField`, invoking it
|
|
||||||
// once for each field.
|
|
||||||
//
|
|
||||||
// Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal
|
|
||||||
// or Panic on the Entry it returns.
|
|
||||||
func WithFields(fields Fields) *Entry {
|
|
||||||
return std.WithFields(fields)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Debug logs a message at level Debug on the standard logger.
|
|
||||||
func Debug(args ...interface{}) {
|
|
||||||
std.Debug(args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Print logs a message at level Info on the standard logger.
|
|
||||||
func Print(args ...interface{}) {
|
|
||||||
std.Print(args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Info logs a message at level Info on the standard logger.
|
|
||||||
func Info(args ...interface{}) {
|
|
||||||
std.Info(args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Warn logs a message at level Warn on the standard logger.
|
|
||||||
func Warn(args ...interface{}) {
|
|
||||||
std.Warn(args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Warning logs a message at level Warn on the standard logger.
|
|
||||||
func Warning(args ...interface{}) {
|
|
||||||
std.Warning(args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error logs a message at level Error on the standard logger.
|
|
||||||
func Error(args ...interface{}) {
|
|
||||||
std.Error(args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Panic logs a message at level Panic on the standard logger.
|
|
||||||
func Panic(args ...interface{}) {
|
|
||||||
std.Panic(args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fatal logs a message at level Fatal on the standard logger.
|
|
||||||
func Fatal(args ...interface{}) {
|
|
||||||
std.Fatal(args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Debugf logs a message at level Debug on the standard logger.
|
|
||||||
func Debugf(format string, args ...interface{}) {
|
|
||||||
std.Debugf(format, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Printf logs a message at level Info on the standard logger.
|
|
||||||
func Printf(format string, args ...interface{}) {
|
|
||||||
std.Printf(format, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Infof logs a message at level Info on the standard logger.
|
|
||||||
func Infof(format string, args ...interface{}) {
|
|
||||||
std.Infof(format, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Warnf logs a message at level Warn on the standard logger.
|
|
||||||
func Warnf(format string, args ...interface{}) {
|
|
||||||
std.Warnf(format, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Warningf logs a message at level Warn on the standard logger.
|
|
||||||
func Warningf(format string, args ...interface{}) {
|
|
||||||
std.Warningf(format, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Errorf logs a message at level Error on the standard logger.
|
|
||||||
func Errorf(format string, args ...interface{}) {
|
|
||||||
std.Errorf(format, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Panicf logs a message at level Panic on the standard logger.
|
|
||||||
func Panicf(format string, args ...interface{}) {
|
|
||||||
std.Panicf(format, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fatalf logs a message at level Fatal on the standard logger.
|
|
||||||
func Fatalf(format string, args ...interface{}) {
|
|
||||||
std.Fatalf(format, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Debugln logs a message at level Debug on the standard logger.
|
|
||||||
func Debugln(args ...interface{}) {
|
|
||||||
std.Debugln(args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Println logs a message at level Info on the standard logger.
|
|
||||||
func Println(args ...interface{}) {
|
|
||||||
std.Println(args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Infoln logs a message at level Info on the standard logger.
|
|
||||||
func Infoln(args ...interface{}) {
|
|
||||||
std.Infoln(args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Warnln logs a message at level Warn on the standard logger.
|
|
||||||
func Warnln(args ...interface{}) {
|
|
||||||
std.Warnln(args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Warningln logs a message at level Warn on the standard logger.
|
|
||||||
func Warningln(args ...interface{}) {
|
|
||||||
std.Warningln(args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Errorln logs a message at level Error on the standard logger.
|
|
||||||
func Errorln(args ...interface{}) {
|
|
||||||
std.Errorln(args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Panicln logs a message at level Panic on the standard logger.
|
|
||||||
func Panicln(args ...interface{}) {
|
|
||||||
std.Panicln(args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fatalln logs a message at level Fatal on the standard logger.
|
|
||||||
func Fatalln(args ...interface{}) {
|
|
||||||
std.Fatalln(args...)
|
|
||||||
}
|
|
45
vendor/github.com/Sirupsen/logrus/formatter.go
generated
vendored
45
vendor/github.com/Sirupsen/logrus/formatter.go
generated
vendored
|
@ -1,45 +0,0 @@
|
||||||
package logrus
|
|
||||||
|
|
||||||
import "time"
|
|
||||||
|
|
||||||
const DefaultTimestampFormat = time.RFC3339
|
|
||||||
|
|
||||||
// The Formatter interface is used to implement a custom Formatter. It takes an
|
|
||||||
// `Entry`. It exposes all the fields, including the default ones:
|
|
||||||
//
|
|
||||||
// * `entry.Data["msg"]`. The message passed from Info, Warn, Error ..
|
|
||||||
// * `entry.Data["time"]`. The timestamp.
|
|
||||||
// * `entry.Data["level"]. The level the entry was logged at.
|
|
||||||
//
|
|
||||||
// Any additional fields added with `WithField` or `WithFields` are also in
|
|
||||||
// `entry.Data`. Format is expected to return an array of bytes which are then
|
|
||||||
// logged to `logger.Out`.
|
|
||||||
type Formatter interface {
|
|
||||||
Format(*Entry) ([]byte, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is to not silently overwrite `time`, `msg` and `level` fields when
|
|
||||||
// dumping it. If this code wasn't there doing:
|
|
||||||
//
|
|
||||||
// logrus.WithField("level", 1).Info("hello")
|
|
||||||
//
|
|
||||||
// Would just silently drop the user provided level. Instead with this code
|
|
||||||
// it'll logged as:
|
|
||||||
//
|
|
||||||
// {"level": "info", "fields.level": 1, "msg": "hello", "time": "..."}
|
|
||||||
//
|
|
||||||
// It's not exported because it's still using Data in an opinionated way. It's to
|
|
||||||
// avoid code duplication between the two default formatters.
|
|
||||||
func prefixFieldClashes(data Fields) {
|
|
||||||
if t, ok := data["time"]; ok {
|
|
||||||
data["fields.time"] = t
|
|
||||||
}
|
|
||||||
|
|
||||||
if m, ok := data["msg"]; ok {
|
|
||||||
data["fields.msg"] = m
|
|
||||||
}
|
|
||||||
|
|
||||||
if l, ok := data["level"]; ok {
|
|
||||||
data["fields.level"] = l
|
|
||||||
}
|
|
||||||
}
|
|
34
vendor/github.com/Sirupsen/logrus/hooks.go
generated
vendored
34
vendor/github.com/Sirupsen/logrus/hooks.go
generated
vendored
|
@ -1,34 +0,0 @@
|
||||||
package logrus
|
|
||||||
|
|
||||||
// A hook to be fired when logging on the logging levels returned from
|
|
||||||
// `Levels()` on your implementation of the interface. Note that this is not
|
|
||||||
// fired in a goroutine or a channel with workers, you should handle such
|
|
||||||
// functionality yourself if your call is non-blocking and you don't wish for
|
|
||||||
// the logging calls for levels returned from `Levels()` to block.
|
|
||||||
type Hook interface {
|
|
||||||
Levels() []Level
|
|
||||||
Fire(*Entry) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Internal type for storing the hooks on a logger instance.
|
|
||||||
type LevelHooks map[Level][]Hook
|
|
||||||
|
|
||||||
// Add a hook to an instance of logger. This is called with
|
|
||||||
// `log.Hooks.Add(new(MyHook))` where `MyHook` implements the `Hook` interface.
|
|
||||||
func (hooks LevelHooks) Add(hook Hook) {
|
|
||||||
for _, level := range hook.Levels() {
|
|
||||||
hooks[level] = append(hooks[level], hook)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fire all the hooks for the passed level. Used by `entry.log` to fire
|
|
||||||
// appropriate hooks for a log entry.
|
|
||||||
func (hooks LevelHooks) Fire(level Level, entry *Entry) error {
|
|
||||||
for _, hook := range hooks[level] {
|
|
||||||
if err := hook.Fire(entry); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
41
vendor/github.com/Sirupsen/logrus/json_formatter.go
generated
vendored
41
vendor/github.com/Sirupsen/logrus/json_formatter.go
generated
vendored
|
@ -1,41 +0,0 @@
|
||||||
package logrus
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
type JSONFormatter struct {
|
|
||||||
// TimestampFormat sets the format used for marshaling timestamps.
|
|
||||||
TimestampFormat string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
|
|
||||||
data := make(Fields, len(entry.Data)+3)
|
|
||||||
for k, v := range entry.Data {
|
|
||||||
switch v := v.(type) {
|
|
||||||
case error:
|
|
||||||
// Otherwise errors are ignored by `encoding/json`
|
|
||||||
// https://github.com/Sirupsen/logrus/issues/137
|
|
||||||
data[k] = v.Error()
|
|
||||||
default:
|
|
||||||
data[k] = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
prefixFieldClashes(data)
|
|
||||||
|
|
||||||
timestampFormat := f.TimestampFormat
|
|
||||||
if timestampFormat == "" {
|
|
||||||
timestampFormat = DefaultTimestampFormat
|
|
||||||
}
|
|
||||||
|
|
||||||
data["time"] = entry.Time.Format(timestampFormat)
|
|
||||||
data["msg"] = entry.Message
|
|
||||||
data["level"] = entry.Level.String()
|
|
||||||
|
|
||||||
serialized, err := json.Marshal(data)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err)
|
|
||||||
}
|
|
||||||
return append(serialized, '\n'), nil
|
|
||||||
}
|
|
308
vendor/github.com/Sirupsen/logrus/logger.go
generated
vendored
308
vendor/github.com/Sirupsen/logrus/logger.go
generated
vendored
|
@ -1,308 +0,0 @@
|
||||||
package logrus
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Logger struct {
|
|
||||||
// The logs are `io.Copy`'d to this in a mutex. It's common to set this to a
|
|
||||||
// file, or leave it default which is `os.Stderr`. You can also set this to
|
|
||||||
// something more adventorous, such as logging to Kafka.
|
|
||||||
Out io.Writer
|
|
||||||
// Hooks for the logger instance. These allow firing events based on logging
|
|
||||||
// levels and log entries. For example, to send errors to an error tracking
|
|
||||||
// service, log to StatsD or dump the core on fatal errors.
|
|
||||||
Hooks LevelHooks
|
|
||||||
// All log entries pass through the formatter before logged to Out. The
|
|
||||||
// included formatters are `TextFormatter` and `JSONFormatter` for which
|
|
||||||
// TextFormatter is the default. In development (when a TTY is attached) it
|
|
||||||
// logs with colors, but to a file it wouldn't. You can easily implement your
|
|
||||||
// own that implements the `Formatter` interface, see the `README` or included
|
|
||||||
// formatters for examples.
|
|
||||||
Formatter Formatter
|
|
||||||
// The logging level the logger should log at. This is typically (and defaults
|
|
||||||
// to) `logrus.Info`, which allows Info(), Warn(), Error() and Fatal() to be
|
|
||||||
// logged. `logrus.Debug` is useful in
|
|
||||||
Level Level
|
|
||||||
// Used to sync writing to the log. Locking is enabled by Default
|
|
||||||
mu MutexWrap
|
|
||||||
// Reusable empty entry
|
|
||||||
entryPool sync.Pool
|
|
||||||
}
|
|
||||||
|
|
||||||
type MutexWrap struct {
|
|
||||||
lock sync.Mutex
|
|
||||||
disabled bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mw *MutexWrap) Lock() {
|
|
||||||
if !mw.disabled {
|
|
||||||
mw.lock.Lock()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mw *MutexWrap) Unlock() {
|
|
||||||
if !mw.disabled {
|
|
||||||
mw.lock.Unlock()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mw *MutexWrap) Disable() {
|
|
||||||
mw.disabled = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Creates a new logger. Configuration should be set by changing `Formatter`,
|
|
||||||
// `Out` and `Hooks` directly on the default logger instance. You can also just
|
|
||||||
// instantiate your own:
|
|
||||||
//
|
|
||||||
// var log = &Logger{
|
|
||||||
// Out: os.Stderr,
|
|
||||||
// Formatter: new(JSONFormatter),
|
|
||||||
// Hooks: make(LevelHooks),
|
|
||||||
// Level: logrus.DebugLevel,
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// It's recommended to make this a global instance called `log`.
|
|
||||||
func New() *Logger {
|
|
||||||
return &Logger{
|
|
||||||
Out: os.Stderr,
|
|
||||||
Formatter: new(TextFormatter),
|
|
||||||
Hooks: make(LevelHooks),
|
|
||||||
Level: InfoLevel,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) newEntry() *Entry {
|
|
||||||
entry, ok := logger.entryPool.Get().(*Entry)
|
|
||||||
if ok {
|
|
||||||
return entry
|
|
||||||
}
|
|
||||||
return NewEntry(logger)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) releaseEntry(entry *Entry) {
|
|
||||||
logger.entryPool.Put(entry)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adds a field to the log entry, note that it doesn't log until you call
|
|
||||||
// Debug, Print, Info, Warn, Fatal or Panic. It only creates a log entry.
|
|
||||||
// If you want multiple fields, use `WithFields`.
|
|
||||||
func (logger *Logger) WithField(key string, value interface{}) *Entry {
|
|
||||||
entry := logger.newEntry()
|
|
||||||
defer logger.releaseEntry(entry)
|
|
||||||
return entry.WithField(key, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adds a struct of fields to the log entry. All it does is call `WithField` for
|
|
||||||
// each `Field`.
|
|
||||||
func (logger *Logger) WithFields(fields Fields) *Entry {
|
|
||||||
entry := logger.newEntry()
|
|
||||||
defer logger.releaseEntry(entry)
|
|
||||||
return entry.WithFields(fields)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add an error as single field to the log entry. All it does is call
|
|
||||||
// `WithError` for the given `error`.
|
|
||||||
func (logger *Logger) WithError(err error) *Entry {
|
|
||||||
entry := logger.newEntry()
|
|
||||||
defer logger.releaseEntry(entry)
|
|
||||||
return entry.WithError(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Debugf(format string, args ...interface{}) {
|
|
||||||
if logger.Level >= DebugLevel {
|
|
||||||
entry := logger.newEntry()
|
|
||||||
entry.Debugf(format, args...)
|
|
||||||
logger.releaseEntry(entry)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Infof(format string, args ...interface{}) {
|
|
||||||
if logger.Level >= InfoLevel {
|
|
||||||
entry := logger.newEntry()
|
|
||||||
entry.Infof(format, args...)
|
|
||||||
logger.releaseEntry(entry)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Printf(format string, args ...interface{}) {
|
|
||||||
entry := logger.newEntry()
|
|
||||||
entry.Printf(format, args...)
|
|
||||||
logger.releaseEntry(entry)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Warnf(format string, args ...interface{}) {
|
|
||||||
if logger.Level >= WarnLevel {
|
|
||||||
entry := logger.newEntry()
|
|
||||||
entry.Warnf(format, args...)
|
|
||||||
logger.releaseEntry(entry)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Warningf(format string, args ...interface{}) {
|
|
||||||
if logger.Level >= WarnLevel {
|
|
||||||
entry := logger.newEntry()
|
|
||||||
entry.Warnf(format, args...)
|
|
||||||
logger.releaseEntry(entry)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Errorf(format string, args ...interface{}) {
|
|
||||||
if logger.Level >= ErrorLevel {
|
|
||||||
entry := logger.newEntry()
|
|
||||||
entry.Errorf(format, args...)
|
|
||||||
logger.releaseEntry(entry)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Fatalf(format string, args ...interface{}) {
|
|
||||||
if logger.Level >= FatalLevel {
|
|
||||||
entry := logger.newEntry()
|
|
||||||
entry.Fatalf(format, args...)
|
|
||||||
logger.releaseEntry(entry)
|
|
||||||
}
|
|
||||||
Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Panicf(format string, args ...interface{}) {
|
|
||||||
if logger.Level >= PanicLevel {
|
|
||||||
entry := logger.newEntry()
|
|
||||||
entry.Panicf(format, args...)
|
|
||||||
logger.releaseEntry(entry)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Debug(args ...interface{}) {
|
|
||||||
if logger.Level >= DebugLevel {
|
|
||||||
entry := logger.newEntry()
|
|
||||||
entry.Debug(args...)
|
|
||||||
logger.releaseEntry(entry)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Info(args ...interface{}) {
|
|
||||||
if logger.Level >= InfoLevel {
|
|
||||||
entry := logger.newEntry()
|
|
||||||
entry.Info(args...)
|
|
||||||
logger.releaseEntry(entry)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Print(args ...interface{}) {
|
|
||||||
entry := logger.newEntry()
|
|
||||||
entry.Info(args...)
|
|
||||||
logger.releaseEntry(entry)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Warn(args ...interface{}) {
|
|
||||||
if logger.Level >= WarnLevel {
|
|
||||||
entry := logger.newEntry()
|
|
||||||
entry.Warn(args...)
|
|
||||||
logger.releaseEntry(entry)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Warning(args ...interface{}) {
|
|
||||||
if logger.Level >= WarnLevel {
|
|
||||||
entry := logger.newEntry()
|
|
||||||
entry.Warn(args...)
|
|
||||||
logger.releaseEntry(entry)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Error(args ...interface{}) {
|
|
||||||
if logger.Level >= ErrorLevel {
|
|
||||||
entry := logger.newEntry()
|
|
||||||
entry.Error(args...)
|
|
||||||
logger.releaseEntry(entry)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Fatal(args ...interface{}) {
|
|
||||||
if logger.Level >= FatalLevel {
|
|
||||||
entry := logger.newEntry()
|
|
||||||
entry.Fatal(args...)
|
|
||||||
logger.releaseEntry(entry)
|
|
||||||
}
|
|
||||||
Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Panic(args ...interface{}) {
|
|
||||||
if logger.Level >= PanicLevel {
|
|
||||||
entry := logger.newEntry()
|
|
||||||
entry.Panic(args...)
|
|
||||||
logger.releaseEntry(entry)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Debugln(args ...interface{}) {
|
|
||||||
if logger.Level >= DebugLevel {
|
|
||||||
entry := logger.newEntry()
|
|
||||||
entry.Debugln(args...)
|
|
||||||
logger.releaseEntry(entry)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Infoln(args ...interface{}) {
|
|
||||||
if logger.Level >= InfoLevel {
|
|
||||||
entry := logger.newEntry()
|
|
||||||
entry.Infoln(args...)
|
|
||||||
logger.releaseEntry(entry)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Println(args ...interface{}) {
|
|
||||||
entry := logger.newEntry()
|
|
||||||
entry.Println(args...)
|
|
||||||
logger.releaseEntry(entry)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Warnln(args ...interface{}) {
|
|
||||||
if logger.Level >= WarnLevel {
|
|
||||||
entry := logger.newEntry()
|
|
||||||
entry.Warnln(args...)
|
|
||||||
logger.releaseEntry(entry)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Warningln(args ...interface{}) {
|
|
||||||
if logger.Level >= WarnLevel {
|
|
||||||
entry := logger.newEntry()
|
|
||||||
entry.Warnln(args...)
|
|
||||||
logger.releaseEntry(entry)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Errorln(args ...interface{}) {
|
|
||||||
if logger.Level >= ErrorLevel {
|
|
||||||
entry := logger.newEntry()
|
|
||||||
entry.Errorln(args...)
|
|
||||||
logger.releaseEntry(entry)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Fatalln(args ...interface{}) {
|
|
||||||
if logger.Level >= FatalLevel {
|
|
||||||
entry := logger.newEntry()
|
|
||||||
entry.Fatalln(args...)
|
|
||||||
logger.releaseEntry(entry)
|
|
||||||
}
|
|
||||||
Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Panicln(args ...interface{}) {
|
|
||||||
if logger.Level >= PanicLevel {
|
|
||||||
entry := logger.newEntry()
|
|
||||||
entry.Panicln(args...)
|
|
||||||
logger.releaseEntry(entry)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//When file is opened with appending mode, it's safe to
|
|
||||||
//write concurrently to a file (within 4k message on Linux).
|
|
||||||
//In these cases user can choose to disable the lock.
|
|
||||||
func (logger *Logger) SetNoLock() {
|
|
||||||
logger.mu.Disable()
|
|
||||||
}
|
|
143
vendor/github.com/Sirupsen/logrus/logrus.go
generated
vendored
143
vendor/github.com/Sirupsen/logrus/logrus.go
generated
vendored
|
@ -1,143 +0,0 @@
|
||||||
package logrus
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Fields type, used to pass to `WithFields`.
|
|
||||||
type Fields map[string]interface{}
|
|
||||||
|
|
||||||
// Level type
|
|
||||||
type Level uint8
|
|
||||||
|
|
||||||
// Convert the Level to a string. E.g. PanicLevel becomes "panic".
|
|
||||||
func (level Level) String() string {
|
|
||||||
switch level {
|
|
||||||
case DebugLevel:
|
|
||||||
return "debug"
|
|
||||||
case InfoLevel:
|
|
||||||
return "info"
|
|
||||||
case WarnLevel:
|
|
||||||
return "warning"
|
|
||||||
case ErrorLevel:
|
|
||||||
return "error"
|
|
||||||
case FatalLevel:
|
|
||||||
return "fatal"
|
|
||||||
case PanicLevel:
|
|
||||||
return "panic"
|
|
||||||
}
|
|
||||||
|
|
||||||
return "unknown"
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseLevel takes a string level and returns the Logrus log level constant.
|
|
||||||
func ParseLevel(lvl string) (Level, error) {
|
|
||||||
switch strings.ToLower(lvl) {
|
|
||||||
case "panic":
|
|
||||||
return PanicLevel, nil
|
|
||||||
case "fatal":
|
|
||||||
return FatalLevel, nil
|
|
||||||
case "error":
|
|
||||||
return ErrorLevel, nil
|
|
||||||
case "warn", "warning":
|
|
||||||
return WarnLevel, nil
|
|
||||||
case "info":
|
|
||||||
return InfoLevel, nil
|
|
||||||
case "debug":
|
|
||||||
return DebugLevel, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var l Level
|
|
||||||
return l, fmt.Errorf("not a valid logrus Level: %q", lvl)
|
|
||||||
}
|
|
||||||
|
|
||||||
// A constant exposing all logging levels
|
|
||||||
var AllLevels = []Level{
|
|
||||||
PanicLevel,
|
|
||||||
FatalLevel,
|
|
||||||
ErrorLevel,
|
|
||||||
WarnLevel,
|
|
||||||
InfoLevel,
|
|
||||||
DebugLevel,
|
|
||||||
}
|
|
||||||
|
|
||||||
// These are the different logging levels. You can set the logging level to log
|
|
||||||
// on your instance of logger, obtained with `logrus.New()`.
|
|
||||||
const (
|
|
||||||
// PanicLevel level, highest level of severity. Logs and then calls panic with the
|
|
||||||
// message passed to Debug, Info, ...
|
|
||||||
PanicLevel Level = iota
|
|
||||||
// FatalLevel level. Logs and then calls `os.Exit(1)`. It will exit even if the
|
|
||||||
// logging level is set to Panic.
|
|
||||||
FatalLevel
|
|
||||||
// ErrorLevel level. Logs. Used for errors that should definitely be noted.
|
|
||||||
// Commonly used for hooks to send errors to an error tracking service.
|
|
||||||
ErrorLevel
|
|
||||||
// WarnLevel level. Non-critical entries that deserve eyes.
|
|
||||||
WarnLevel
|
|
||||||
// InfoLevel level. General operational entries about what's going on inside the
|
|
||||||
// application.
|
|
||||||
InfoLevel
|
|
||||||
// DebugLevel level. Usually only enabled when debugging. Very verbose logging.
|
|
||||||
DebugLevel
|
|
||||||
)
|
|
||||||
|
|
||||||
// Won't compile if StdLogger can't be realized by a log.Logger
|
|
||||||
var (
|
|
||||||
_ StdLogger = &log.Logger{}
|
|
||||||
_ StdLogger = &Entry{}
|
|
||||||
_ StdLogger = &Logger{}
|
|
||||||
)
|
|
||||||
|
|
||||||
// StdLogger is what your logrus-enabled library should take, that way
|
|
||||||
// it'll accept a stdlib logger and a logrus logger. There's no standard
|
|
||||||
// interface, this is the closest we get, unfortunately.
|
|
||||||
type StdLogger interface {
|
|
||||||
Print(...interface{})
|
|
||||||
Printf(string, ...interface{})
|
|
||||||
Println(...interface{})
|
|
||||||
|
|
||||||
Fatal(...interface{})
|
|
||||||
Fatalf(string, ...interface{})
|
|
||||||
Fatalln(...interface{})
|
|
||||||
|
|
||||||
Panic(...interface{})
|
|
||||||
Panicf(string, ...interface{})
|
|
||||||
Panicln(...interface{})
|
|
||||||
}
|
|
||||||
|
|
||||||
// The FieldLogger interface generalizes the Entry and Logger types
|
|
||||||
type FieldLogger interface {
|
|
||||||
WithField(key string, value interface{}) *Entry
|
|
||||||
WithFields(fields Fields) *Entry
|
|
||||||
WithError(err error) *Entry
|
|
||||||
|
|
||||||
Debugf(format string, args ...interface{})
|
|
||||||
Infof(format string, args ...interface{})
|
|
||||||
Printf(format string, args ...interface{})
|
|
||||||
Warnf(format string, args ...interface{})
|
|
||||||
Warningf(format string, args ...interface{})
|
|
||||||
Errorf(format string, args ...interface{})
|
|
||||||
Fatalf(format string, args ...interface{})
|
|
||||||
Panicf(format string, args ...interface{})
|
|
||||||
|
|
||||||
Debug(args ...interface{})
|
|
||||||
Info(args ...interface{})
|
|
||||||
Print(args ...interface{})
|
|
||||||
Warn(args ...interface{})
|
|
||||||
Warning(args ...interface{})
|
|
||||||
Error(args ...interface{})
|
|
||||||
Fatal(args ...interface{})
|
|
||||||
Panic(args ...interface{})
|
|
||||||
|
|
||||||
Debugln(args ...interface{})
|
|
||||||
Infoln(args ...interface{})
|
|
||||||
Println(args ...interface{})
|
|
||||||
Warnln(args ...interface{})
|
|
||||||
Warningln(args ...interface{})
|
|
||||||
Errorln(args ...interface{})
|
|
||||||
Fatalln(args ...interface{})
|
|
||||||
Panicln(args ...interface{})
|
|
||||||
}
|
|
8
vendor/github.com/Sirupsen/logrus/terminal_appengine.go
generated
vendored
8
vendor/github.com/Sirupsen/logrus/terminal_appengine.go
generated
vendored
|
@ -1,8 +0,0 @@
|
||||||
// +build appengine
|
|
||||||
|
|
||||||
package logrus
|
|
||||||
|
|
||||||
// IsTerminal returns true if stderr's file descriptor is a terminal.
|
|
||||||
func IsTerminal() bool {
|
|
||||||
return true
|
|
||||||
}
|
|
10
vendor/github.com/Sirupsen/logrus/terminal_bsd.go
generated
vendored
10
vendor/github.com/Sirupsen/logrus/terminal_bsd.go
generated
vendored
|
@ -1,10 +0,0 @@
|
||||||
// +build darwin freebsd openbsd netbsd dragonfly
|
|
||||||
// +build !appengine
|
|
||||||
|
|
||||||
package logrus
|
|
||||||
|
|
||||||
import "syscall"
|
|
||||||
|
|
||||||
const ioctlReadTermios = syscall.TIOCGETA
|
|
||||||
|
|
||||||
type Termios syscall.Termios
|
|
14
vendor/github.com/Sirupsen/logrus/terminal_linux.go
generated
vendored
14
vendor/github.com/Sirupsen/logrus/terminal_linux.go
generated
vendored
|
@ -1,14 +0,0 @@
|
||||||
// Based on ssh/terminal:
|
|
||||||
// Copyright 2013 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build !appengine
|
|
||||||
|
|
||||||
package logrus
|
|
||||||
|
|
||||||
import "syscall"
|
|
||||||
|
|
||||||
const ioctlReadTermios = syscall.TCGETS
|
|
||||||
|
|
||||||
type Termios syscall.Termios
|
|
22
vendor/github.com/Sirupsen/logrus/terminal_notwindows.go
generated
vendored
22
vendor/github.com/Sirupsen/logrus/terminal_notwindows.go
generated
vendored
|
@ -1,22 +0,0 @@
|
||||||
// Based on ssh/terminal:
|
|
||||||
// Copyright 2011 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build linux darwin freebsd openbsd netbsd dragonfly
|
|
||||||
// +build !appengine
|
|
||||||
|
|
||||||
package logrus
|
|
||||||
|
|
||||||
import (
|
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
// IsTerminal returns true if stderr's file descriptor is a terminal.
|
|
||||||
func IsTerminal() bool {
|
|
||||||
fd := syscall.Stderr
|
|
||||||
var termios Termios
|
|
||||||
_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
|
|
||||||
return err == 0
|
|
||||||
}
|
|
15
vendor/github.com/Sirupsen/logrus/terminal_solaris.go
generated
vendored
15
vendor/github.com/Sirupsen/logrus/terminal_solaris.go
generated
vendored
|
@ -1,15 +0,0 @@
|
||||||
// +build solaris,!appengine
|
|
||||||
|
|
||||||
package logrus
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"golang.org/x/sys/unix"
|
|
||||||
)
|
|
||||||
|
|
||||||
// IsTerminal returns true if the given file descriptor is a terminal.
|
|
||||||
func IsTerminal() bool {
|
|
||||||
_, err := unix.IoctlGetTermios(int(os.Stdout.Fd()), unix.TCGETA)
|
|
||||||
return err == nil
|
|
||||||
}
|
|
27
vendor/github.com/Sirupsen/logrus/terminal_windows.go
generated
vendored
27
vendor/github.com/Sirupsen/logrus/terminal_windows.go
generated
vendored
|
@ -1,27 +0,0 @@
|
||||||
// Based on ssh/terminal:
|
|
||||||
// Copyright 2011 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build windows,!appengine
|
|
||||||
|
|
||||||
package logrus
|
|
||||||
|
|
||||||
import (
|
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
var kernel32 = syscall.NewLazyDLL("kernel32.dll")
|
|
||||||
|
|
||||||
var (
|
|
||||||
procGetConsoleMode = kernel32.NewProc("GetConsoleMode")
|
|
||||||
)
|
|
||||||
|
|
||||||
// IsTerminal returns true if stderr's file descriptor is a terminal.
|
|
||||||
func IsTerminal() bool {
|
|
||||||
fd := syscall.Stderr
|
|
||||||
var st uint32
|
|
||||||
r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0)
|
|
||||||
return r != 0 && e == 0
|
|
||||||
}
|
|
165
vendor/github.com/Sirupsen/logrus/text_formatter.go
generated
vendored
165
vendor/github.com/Sirupsen/logrus/text_formatter.go
generated
vendored
|
@ -1,165 +0,0 @@
|
||||||
package logrus
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"runtime"
|
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
nocolor = 0
|
|
||||||
red = 31
|
|
||||||
green = 32
|
|
||||||
yellow = 33
|
|
||||||
blue = 34
|
|
||||||
gray = 37
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
baseTimestamp time.Time
|
|
||||||
isTerminal bool
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
baseTimestamp = time.Now()
|
|
||||||
isTerminal = IsTerminal()
|
|
||||||
}
|
|
||||||
|
|
||||||
func miniTS() int {
|
|
||||||
return int(time.Since(baseTimestamp) / time.Second)
|
|
||||||
}
|
|
||||||
|
|
||||||
type TextFormatter struct {
|
|
||||||
// Set to true to bypass checking for a TTY before outputting colors.
|
|
||||||
ForceColors bool
|
|
||||||
|
|
||||||
// Force disabling colors.
|
|
||||||
DisableColors bool
|
|
||||||
|
|
||||||
// Disable timestamp logging. useful when output is redirected to logging
|
|
||||||
// system that already adds timestamps.
|
|
||||||
DisableTimestamp bool
|
|
||||||
|
|
||||||
// Enable logging the full timestamp when a TTY is attached instead of just
|
|
||||||
// the time passed since beginning of execution.
|
|
||||||
FullTimestamp bool
|
|
||||||
|
|
||||||
// TimestampFormat to use for display when a full timestamp is printed
|
|
||||||
TimestampFormat string
|
|
||||||
|
|
||||||
// The fields are sorted by default for a consistent output. For applications
|
|
||||||
// that log extremely frequently and don't use the JSON formatter this may not
|
|
||||||
// be desired.
|
|
||||||
DisableSorting bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
|
|
||||||
var b *bytes.Buffer
|
|
||||||
var keys []string = make([]string, 0, len(entry.Data))
|
|
||||||
for k := range entry.Data {
|
|
||||||
keys = append(keys, k)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !f.DisableSorting {
|
|
||||||
sort.Strings(keys)
|
|
||||||
}
|
|
||||||
if entry.Buffer != nil {
|
|
||||||
b = entry.Buffer
|
|
||||||
} else {
|
|
||||||
b = &bytes.Buffer{}
|
|
||||||
}
|
|
||||||
|
|
||||||
prefixFieldClashes(entry.Data)
|
|
||||||
|
|
||||||
isColorTerminal := isTerminal && (runtime.GOOS != "windows")
|
|
||||||
isColored := (f.ForceColors || isColorTerminal) && !f.DisableColors
|
|
||||||
|
|
||||||
timestampFormat := f.TimestampFormat
|
|
||||||
if timestampFormat == "" {
|
|
||||||
timestampFormat = DefaultTimestampFormat
|
|
||||||
}
|
|
||||||
if isColored {
|
|
||||||
f.printColored(b, entry, keys, timestampFormat)
|
|
||||||
} else {
|
|
||||||
if !f.DisableTimestamp {
|
|
||||||
f.appendKeyValue(b, "time", entry.Time.Format(timestampFormat))
|
|
||||||
}
|
|
||||||
f.appendKeyValue(b, "level", entry.Level.String())
|
|
||||||
if entry.Message != "" {
|
|
||||||
f.appendKeyValue(b, "msg", entry.Message)
|
|
||||||
}
|
|
||||||
for _, key := range keys {
|
|
||||||
f.appendKeyValue(b, key, entry.Data[key])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
b.WriteByte('\n')
|
|
||||||
return b.Bytes(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []string, timestampFormat string) {
|
|
||||||
var levelColor int
|
|
||||||
switch entry.Level {
|
|
||||||
case DebugLevel:
|
|
||||||
levelColor = gray
|
|
||||||
case WarnLevel:
|
|
||||||
levelColor = yellow
|
|
||||||
case ErrorLevel, FatalLevel, PanicLevel:
|
|
||||||
levelColor = red
|
|
||||||
default:
|
|
||||||
levelColor = blue
|
|
||||||
}
|
|
||||||
|
|
||||||
levelText := strings.ToUpper(entry.Level.String())[0:4]
|
|
||||||
|
|
||||||
if !f.FullTimestamp {
|
|
||||||
fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%04d] %-44s ", levelColor, levelText, miniTS(), entry.Message)
|
|
||||||
} else {
|
|
||||||
fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%s] %-44s ", levelColor, levelText, entry.Time.Format(timestampFormat), entry.Message)
|
|
||||||
}
|
|
||||||
for _, k := range keys {
|
|
||||||
v := entry.Data[k]
|
|
||||||
fmt.Fprintf(b, " \x1b[%dm%s\x1b[0m=%+v", levelColor, k, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func needsQuoting(text string) bool {
|
|
||||||
for _, ch := range text {
|
|
||||||
if !((ch >= 'a' && ch <= 'z') ||
|
|
||||||
(ch >= 'A' && ch <= 'Z') ||
|
|
||||||
(ch >= '0' && ch <= '9') ||
|
|
||||||
ch == '-' || ch == '.') {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *TextFormatter) appendKeyValue(b *bytes.Buffer, key string, value interface{}) {
|
|
||||||
|
|
||||||
b.WriteString(key)
|
|
||||||
b.WriteByte('=')
|
|
||||||
|
|
||||||
switch value := value.(type) {
|
|
||||||
case string:
|
|
||||||
if !needsQuoting(value) {
|
|
||||||
b.WriteString(value)
|
|
||||||
} else {
|
|
||||||
fmt.Fprintf(b, "%q", value)
|
|
||||||
}
|
|
||||||
case error:
|
|
||||||
errmsg := value.Error()
|
|
||||||
if !needsQuoting(errmsg) {
|
|
||||||
b.WriteString(errmsg)
|
|
||||||
} else {
|
|
||||||
fmt.Fprintf(b, "%q", value)
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
fmt.Fprint(b, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
b.WriteByte(' ')
|
|
||||||
}
|
|
53
vendor/github.com/Sirupsen/logrus/writer.go
generated
vendored
53
vendor/github.com/Sirupsen/logrus/writer.go
generated
vendored
|
@ -1,53 +0,0 @@
|
||||||
package logrus
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"io"
|
|
||||||
"runtime"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (logger *Logger) Writer() *io.PipeWriter {
|
|
||||||
return logger.WriterLevel(InfoLevel)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) WriterLevel(level Level) *io.PipeWriter {
|
|
||||||
reader, writer := io.Pipe()
|
|
||||||
|
|
||||||
var printFunc func(args ...interface{})
|
|
||||||
switch level {
|
|
||||||
case DebugLevel:
|
|
||||||
printFunc = logger.Debug
|
|
||||||
case InfoLevel:
|
|
||||||
printFunc = logger.Info
|
|
||||||
case WarnLevel:
|
|
||||||
printFunc = logger.Warn
|
|
||||||
case ErrorLevel:
|
|
||||||
printFunc = logger.Error
|
|
||||||
case FatalLevel:
|
|
||||||
printFunc = logger.Fatal
|
|
||||||
case PanicLevel:
|
|
||||||
printFunc = logger.Panic
|
|
||||||
default:
|
|
||||||
printFunc = logger.Print
|
|
||||||
}
|
|
||||||
|
|
||||||
go logger.writerScanner(reader, printFunc)
|
|
||||||
runtime.SetFinalizer(writer, writerFinalizer)
|
|
||||||
|
|
||||||
return writer
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) writerScanner(reader *io.PipeReader, printFunc func(args ...interface{})) {
|
|
||||||
scanner := bufio.NewScanner(reader)
|
|
||||||
for scanner.Scan() {
|
|
||||||
printFunc(scanner.Text())
|
|
||||||
}
|
|
||||||
if err := scanner.Err(); err != nil {
|
|
||||||
logger.Errorf("Error while reading from Writer: %s", err)
|
|
||||||
}
|
|
||||||
reader.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func writerFinalizer(writer *io.PipeWriter) {
|
|
||||||
writer.Close()
|
|
||||||
}
|
|
23
vendor/github.com/fatih/structs/.gitignore
generated
vendored
23
vendor/github.com/fatih/structs/.gitignore
generated
vendored
|
@ -1,23 +0,0 @@
|
||||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
|
||||||
*.o
|
|
||||||
*.a
|
|
||||||
*.so
|
|
||||||
|
|
||||||
# Folders
|
|
||||||
_obj
|
|
||||||
_test
|
|
||||||
|
|
||||||
# Architecture specific extensions/prefixes
|
|
||||||
*.[568vq]
|
|
||||||
[568vq].out
|
|
||||||
|
|
||||||
*.cgo1.go
|
|
||||||
*.cgo2.c
|
|
||||||
_cgo_defun.c
|
|
||||||
_cgo_gotypes.go
|
|
||||||
_cgo_export.*
|
|
||||||
|
|
||||||
_testmain.go
|
|
||||||
|
|
||||||
*.exe
|
|
||||||
*.test
|
|
11
vendor/github.com/fatih/structs/.travis.yml
generated
vendored
11
vendor/github.com/fatih/structs/.travis.yml
generated
vendored
|
@ -1,11 +0,0 @@
|
||||||
language: go
|
|
||||||
go:
|
|
||||||
- 1.6
|
|
||||||
- tip
|
|
||||||
sudo: false
|
|
||||||
before_install:
|
|
||||||
- go get github.com/axw/gocov/gocov
|
|
||||||
- go get github.com/mattn/goveralls
|
|
||||||
- if ! go get github.com/golang/tools/cmd/cover; then go get golang.org/x/tools/cmd/cover; fi
|
|
||||||
script:
|
|
||||||
- $HOME/gopath/bin/goveralls -service=travis-ci
|
|
21
vendor/github.com/fatih/structs/LICENSE
generated
vendored
21
vendor/github.com/fatih/structs/LICENSE
generated
vendored
|
@ -1,21 +0,0 @@
|
||||||
The MIT License (MIT)
|
|
||||||
|
|
||||||
Copyright (c) 2014 Fatih Arslan
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
163
vendor/github.com/fatih/structs/README.md
generated
vendored
163
vendor/github.com/fatih/structs/README.md
generated
vendored
|
@ -1,163 +0,0 @@
|
||||||
# Structs [![GoDoc](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)](http://godoc.org/github.com/fatih/structs) [![Build Status](http://img.shields.io/travis/fatih/structs.svg?style=flat-square)](https://travis-ci.org/fatih/structs) [![Coverage Status](http://img.shields.io/coveralls/fatih/structs.svg?style=flat-square)](https://coveralls.io/r/fatih/structs)
|
|
||||||
|
|
||||||
Structs contains various utilities to work with Go (Golang) structs. It was
|
|
||||||
initially used by me to convert a struct into a `map[string]interface{}`. With
|
|
||||||
time I've added other utilities for structs. It's basically a high level
|
|
||||||
package based on primitives from the reflect package. Feel free to add new
|
|
||||||
functions or improve the existing code.
|
|
||||||
|
|
||||||
## Install
|
|
||||||
|
|
||||||
```bash
|
|
||||||
go get github.com/fatih/structs
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage and Examples
|
|
||||||
|
|
||||||
Just like the standard lib `strings`, `bytes` and co packages, `structs` has
|
|
||||||
many global functions to manipulate or organize your struct data. Lets define
|
|
||||||
and declare a struct:
|
|
||||||
|
|
||||||
```go
|
|
||||||
type Server struct {
|
|
||||||
Name string `json:"name,omitempty"`
|
|
||||||
ID int
|
|
||||||
Enabled bool
|
|
||||||
users []string // not exported
|
|
||||||
http.Server // embedded
|
|
||||||
}
|
|
||||||
|
|
||||||
server := &Server{
|
|
||||||
Name: "gopher",
|
|
||||||
ID: 123456,
|
|
||||||
Enabled: true,
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```go
|
|
||||||
// Convert a struct to a map[string]interface{}
|
|
||||||
// => {"Name":"gopher", "ID":123456, "Enabled":true}
|
|
||||||
m := structs.Map(server)
|
|
||||||
|
|
||||||
// Convert the values of a struct to a []interface{}
|
|
||||||
// => ["gopher", 123456, true]
|
|
||||||
v := structs.Values(server)
|
|
||||||
|
|
||||||
// Convert the names of a struct to a []string
|
|
||||||
// (see "Names methods" for more info about fields)
|
|
||||||
n := structs.Names(server)
|
|
||||||
|
|
||||||
// Convert the values of a struct to a []*Field
|
|
||||||
// (see "Field methods" for more info about fields)
|
|
||||||
f := structs.Fields(server)
|
|
||||||
|
|
||||||
// Return the struct name => "Server"
|
|
||||||
n := structs.Name(server)
|
|
||||||
|
|
||||||
// Check if any field of a struct is initialized or not.
|
|
||||||
h := structs.HasZero(server)
|
|
||||||
|
|
||||||
// Check if all fields of a struct is initialized or not.
|
|
||||||
z := structs.IsZero(server)
|
|
||||||
|
|
||||||
// Check if server is a struct or a pointer to struct
|
|
||||||
i := structs.IsStruct(server)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Struct methods
|
|
||||||
|
|
||||||
The structs functions can be also used as independent methods by creating a new
|
|
||||||
`*structs.Struct`. This is handy if you want to have more control over the
|
|
||||||
structs (such as retrieving a single Field).
|
|
||||||
|
|
||||||
```go
|
|
||||||
// Create a new struct type:
|
|
||||||
s := structs.New(server)
|
|
||||||
|
|
||||||
m := s.Map() // Get a map[string]interface{}
|
|
||||||
v := s.Values() // Get a []interface{}
|
|
||||||
f := s.Fields() // Get a []*Field
|
|
||||||
n := s.Names() // Get a []string
|
|
||||||
f := s.Field(name) // Get a *Field based on the given field name
|
|
||||||
f, ok := s.FieldOk(name) // Get a *Field based on the given field name
|
|
||||||
n := s.Name() // Get the struct name
|
|
||||||
h := s.HasZero() // Check if any field is initialized
|
|
||||||
z := s.IsZero() // Check if all fields are initialized
|
|
||||||
```
|
|
||||||
|
|
||||||
### Field methods
|
|
||||||
|
|
||||||
We can easily examine a single Field for more detail. Below you can see how we
|
|
||||||
get and interact with various field methods:
|
|
||||||
|
|
||||||
|
|
||||||
```go
|
|
||||||
s := structs.New(server)
|
|
||||||
|
|
||||||
// Get the Field struct for the "Name" field
|
|
||||||
name := s.Field("Name")
|
|
||||||
|
|
||||||
// Get the underlying value, value => "gopher"
|
|
||||||
value := name.Value().(string)
|
|
||||||
|
|
||||||
// Set the field's value
|
|
||||||
name.Set("another gopher")
|
|
||||||
|
|
||||||
// Get the field's kind, kind => "string"
|
|
||||||
name.Kind()
|
|
||||||
|
|
||||||
// Check if the field is exported or not
|
|
||||||
if name.IsExported() {
|
|
||||||
fmt.Println("Name field is exported")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the value is a zero value, such as "" for string, 0 for int
|
|
||||||
if !name.IsZero() {
|
|
||||||
fmt.Println("Name is initialized")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the field is an anonymous (embedded) field
|
|
||||||
if !name.IsEmbedded() {
|
|
||||||
fmt.Println("Name is not an embedded field")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the Field's tag value for tag name "json", tag value => "name,omitempty"
|
|
||||||
tagValue := name.Tag("json")
|
|
||||||
```
|
|
||||||
|
|
||||||
Nested structs are supported too:
|
|
||||||
|
|
||||||
```go
|
|
||||||
addrField := s.Field("Server").Field("Addr")
|
|
||||||
|
|
||||||
// Get the value for addr
|
|
||||||
a := addrField.Value().(string)
|
|
||||||
|
|
||||||
// Or get all fields
|
|
||||||
httpServer := s.Field("Server").Fields()
|
|
||||||
```
|
|
||||||
|
|
||||||
We can also get a slice of Fields from the Struct type to iterate over all
|
|
||||||
fields. This is handy if you wish to examine all fields:
|
|
||||||
|
|
||||||
```go
|
|
||||||
s := structs.New(server)
|
|
||||||
|
|
||||||
for _, f := range s.Fields() {
|
|
||||||
fmt.Printf("field name: %+v\n", f.Name())
|
|
||||||
|
|
||||||
if f.IsExported() {
|
|
||||||
fmt.Printf("value : %+v\n", f.Value())
|
|
||||||
fmt.Printf("is zero : %+v\n", f.IsZero())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Credits
|
|
||||||
|
|
||||||
* [Fatih Arslan](https://github.com/fatih)
|
|
||||||
* [Cihangir Savas](https://github.com/cihangir)
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
The MIT License (MIT) - see LICENSE.md for more details
|
|
132
vendor/github.com/fatih/structs/field.go
generated
vendored
132
vendor/github.com/fatih/structs/field.go
generated
vendored
|
@ -1,132 +0,0 @@
|
||||||
package structs
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"reflect"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
errNotExported = errors.New("field is not exported")
|
|
||||||
errNotSettable = errors.New("field is not settable")
|
|
||||||
)
|
|
||||||
|
|
||||||
// Field represents a single struct field that encapsulates high level
|
|
||||||
// functions around the field.
|
|
||||||
type Field struct {
|
|
||||||
value reflect.Value
|
|
||||||
field reflect.StructField
|
|
||||||
defaultTag string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tag returns the value associated with key in the tag string. If there is no
|
|
||||||
// such key in the tag, Tag returns the empty string.
|
|
||||||
func (f *Field) Tag(key string) string {
|
|
||||||
return f.field.Tag.Get(key)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Value returns the underlying value of the field. It panics if the field
|
|
||||||
// is not exported.
|
|
||||||
func (f *Field) Value() interface{} {
|
|
||||||
return f.value.Interface()
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsEmbedded returns true if the given field is an anonymous field (embedded)
|
|
||||||
func (f *Field) IsEmbedded() bool {
|
|
||||||
return f.field.Anonymous
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsExported returns true if the given field is exported.
|
|
||||||
func (f *Field) IsExported() bool {
|
|
||||||
return f.field.PkgPath == ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsZero returns true if the given field is not initialized (has a zero value).
|
|
||||||
// It panics if the field is not exported.
|
|
||||||
func (f *Field) IsZero() bool {
|
|
||||||
zero := reflect.Zero(f.value.Type()).Interface()
|
|
||||||
current := f.Value()
|
|
||||||
|
|
||||||
return reflect.DeepEqual(current, zero)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Name returns the name of the given field
|
|
||||||
func (f *Field) Name() string {
|
|
||||||
return f.field.Name
|
|
||||||
}
|
|
||||||
|
|
||||||
// Kind returns the fields kind, such as "string", "map", "bool", etc ..
|
|
||||||
func (f *Field) Kind() reflect.Kind {
|
|
||||||
return f.value.Kind()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set sets the field to given value v. It returns an error if the field is not
|
|
||||||
// settable (not addressable or not exported) or if the given value's type
|
|
||||||
// doesn't match the fields type.
|
|
||||||
func (f *Field) Set(val interface{}) error {
|
|
||||||
// we can't set unexported fields, so be sure this field is exported
|
|
||||||
if !f.IsExported() {
|
|
||||||
return errNotExported
|
|
||||||
}
|
|
||||||
|
|
||||||
// do we get here? not sure...
|
|
||||||
if !f.value.CanSet() {
|
|
||||||
return errNotSettable
|
|
||||||
}
|
|
||||||
|
|
||||||
given := reflect.ValueOf(val)
|
|
||||||
|
|
||||||
if f.value.Kind() != given.Kind() {
|
|
||||||
return fmt.Errorf("wrong kind. got: %s want: %s", given.Kind(), f.value.Kind())
|
|
||||||
}
|
|
||||||
|
|
||||||
f.value.Set(given)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Zero sets the field to its zero value. It returns an error if the field is not
|
|
||||||
// settable (not addressable or not exported).
|
|
||||||
func (f *Field) Zero() error {
|
|
||||||
zero := reflect.Zero(f.value.Type()).Interface()
|
|
||||||
return f.Set(zero)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fields returns a slice of Fields. This is particular handy to get the fields
|
|
||||||
// of a nested struct . A struct tag with the content of "-" ignores the
|
|
||||||
// checking of that particular field. Example:
|
|
||||||
//
|
|
||||||
// // Field is ignored by this package.
|
|
||||||
// Field *http.Request `structs:"-"`
|
|
||||||
//
|
|
||||||
// It panics if field is not exported or if field's kind is not struct
|
|
||||||
func (f *Field) Fields() []*Field {
|
|
||||||
return getFields(f.value, f.defaultTag)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Field returns the field from a nested struct. It panics if the nested struct
|
|
||||||
// is not exported or if the field was not found.
|
|
||||||
func (f *Field) Field(name string) *Field {
|
|
||||||
field, ok := f.FieldOk(name)
|
|
||||||
if !ok {
|
|
||||||
panic("field not found")
|
|
||||||
}
|
|
||||||
|
|
||||||
return field
|
|
||||||
}
|
|
||||||
|
|
||||||
// FieldOk returns the field from a nested struct. The boolean returns whether
|
|
||||||
// the field was found (true) or not (false).
|
|
||||||
func (f *Field) FieldOk(name string) (*Field, bool) {
|
|
||||||
v := strctVal(f.value.Interface())
|
|
||||||
t := v.Type()
|
|
||||||
|
|
||||||
field, ok := t.FieldByName(name)
|
|
||||||
if !ok {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
return &Field{
|
|
||||||
field: field,
|
|
||||||
value: v.FieldByName(name),
|
|
||||||
}, true
|
|
||||||
}
|
|
507
vendor/github.com/fatih/structs/structs.go
generated
vendored
507
vendor/github.com/fatih/structs/structs.go
generated
vendored
|
@ -1,507 +0,0 @@
|
||||||
// Package structs contains various utilities functions to work with structs.
|
|
||||||
package structs
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"reflect"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// DefaultTagName is the default tag name for struct fields which provides
|
|
||||||
// a more granular to tweak certain structs. Lookup the necessary functions
|
|
||||||
// for more info.
|
|
||||||
DefaultTagName = "structs" // struct's field default tag name
|
|
||||||
)
|
|
||||||
|
|
||||||
// Struct encapsulates a struct type to provide several high level functions
|
|
||||||
// around the struct.
|
|
||||||
type Struct struct {
|
|
||||||
raw interface{}
|
|
||||||
value reflect.Value
|
|
||||||
TagName string
|
|
||||||
}
|
|
||||||
|
|
||||||
// New returns a new *Struct with the struct s. It panics if the s's kind is
|
|
||||||
// not struct.
|
|
||||||
func New(s interface{}) *Struct {
|
|
||||||
return &Struct{
|
|
||||||
raw: s,
|
|
||||||
value: strctVal(s),
|
|
||||||
TagName: DefaultTagName,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Map converts the given struct to a map[string]interface{}, where the keys
|
|
||||||
// of the map are the field names and the values of the map the associated
|
|
||||||
// values of the fields. The default key string is the struct field name but
|
|
||||||
// can be changed in the struct field's tag value. The "structs" key in the
|
|
||||||
// struct's field tag value is the key name. Example:
|
|
||||||
//
|
|
||||||
// // Field appears in map as key "myName".
|
|
||||||
// Name string `structs:"myName"`
|
|
||||||
//
|
|
||||||
// A tag value with the content of "-" ignores that particular field. Example:
|
|
||||||
//
|
|
||||||
// // Field is ignored by this package.
|
|
||||||
// Field bool `structs:"-"`
|
|
||||||
//
|
|
||||||
// A tag value with the content of "string" uses the stringer to get the value. Example:
|
|
||||||
//
|
|
||||||
// // The value will be output of Animal's String() func.
|
|
||||||
// // Map will panic if Animal does not implement String().
|
|
||||||
// Field *Animal `structs:"field,string"`
|
|
||||||
//
|
|
||||||
// A tag value with the option of "flatten" used in a struct field is to flatten its fields
|
|
||||||
// in the output map. Example:
|
|
||||||
//
|
|
||||||
// // The FieldStruct's fields will be flattened into the output map.
|
|
||||||
// FieldStruct time.Time `structs:"flatten"`
|
|
||||||
//
|
|
||||||
// A tag value with the option of "omitnested" stops iterating further if the type
|
|
||||||
// is a struct. Example:
|
|
||||||
//
|
|
||||||
// // Field is not processed further by this package.
|
|
||||||
// Field time.Time `structs:"myName,omitnested"`
|
|
||||||
// Field *http.Request `structs:",omitnested"`
|
|
||||||
//
|
|
||||||
// A tag value with the option of "omitempty" ignores that particular field if
|
|
||||||
// the field value is empty. Example:
|
|
||||||
//
|
|
||||||
// // Field appears in map as key "myName", but the field is
|
|
||||||
// // skipped if empty.
|
|
||||||
// Field string `structs:"myName,omitempty"`
|
|
||||||
//
|
|
||||||
// // Field appears in map as key "Field" (the default), but
|
|
||||||
// // the field is skipped if empty.
|
|
||||||
// Field string `structs:",omitempty"`
|
|
||||||
//
|
|
||||||
// Note that only exported fields of a struct can be accessed, non exported
|
|
||||||
// fields will be neglected.
|
|
||||||
func (s *Struct) Map() map[string]interface{} {
|
|
||||||
out := make(map[string]interface{})
|
|
||||||
s.FillMap(out)
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
// FillMap is the same as Map. Instead of returning the output, it fills the
|
|
||||||
// given map.
|
|
||||||
func (s *Struct) FillMap(out map[string]interface{}) {
|
|
||||||
if out == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
fields := s.structFields()
|
|
||||||
|
|
||||||
for _, field := range fields {
|
|
||||||
name := field.Name
|
|
||||||
val := s.value.FieldByName(name)
|
|
||||||
isSubStruct := false
|
|
||||||
var finalVal interface{}
|
|
||||||
|
|
||||||
tagName, tagOpts := parseTag(field.Tag.Get(s.TagName))
|
|
||||||
if tagName != "" {
|
|
||||||
name = tagName
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the value is a zero value and the field is marked as omitempty do
|
|
||||||
// not include
|
|
||||||
if tagOpts.Has("omitempty") {
|
|
||||||
zero := reflect.Zero(val.Type()).Interface()
|
|
||||||
current := val.Interface()
|
|
||||||
|
|
||||||
if reflect.DeepEqual(current, zero) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if IsStruct(val.Interface()) && !tagOpts.Has("omitnested") {
|
|
||||||
// look out for embedded structs, and convert them to a
|
|
||||||
// map[string]interface{} too
|
|
||||||
n := New(val.Interface())
|
|
||||||
n.TagName = s.TagName
|
|
||||||
m := n.Map()
|
|
||||||
isSubStruct = true
|
|
||||||
if len(m) == 0 {
|
|
||||||
finalVal = val.Interface()
|
|
||||||
} else {
|
|
||||||
finalVal = m
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
finalVal = val.Interface()
|
|
||||||
}
|
|
||||||
|
|
||||||
if tagOpts.Has("string") {
|
|
||||||
s, ok := val.Interface().(fmt.Stringer)
|
|
||||||
if ok {
|
|
||||||
out[name] = s.String()
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if isSubStruct && (tagOpts.Has("flatten")) {
|
|
||||||
for k := range finalVal.(map[string]interface{}) {
|
|
||||||
out[k] = finalVal.(map[string]interface{})[k]
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
out[name] = finalVal
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Values converts the given s struct's field values to a []interface{}. A
|
|
||||||
// struct tag with the content of "-" ignores the that particular field.
|
|
||||||
// Example:
|
|
||||||
//
|
|
||||||
// // Field is ignored by this package.
|
|
||||||
// Field int `structs:"-"`
|
|
||||||
//
|
|
||||||
// A value with the option of "omitnested" stops iterating further if the type
|
|
||||||
// is a struct. Example:
|
|
||||||
//
|
|
||||||
// // Fields is not processed further by this package.
|
|
||||||
// Field time.Time `structs:",omitnested"`
|
|
||||||
// Field *http.Request `structs:",omitnested"`
|
|
||||||
//
|
|
||||||
// A tag value with the option of "omitempty" ignores that particular field and
|
|
||||||
// is not added to the values if the field value is empty. Example:
|
|
||||||
//
|
|
||||||
// // Field is skipped if empty
|
|
||||||
// Field string `structs:",omitempty"`
|
|
||||||
//
|
|
||||||
// Note that only exported fields of a struct can be accessed, non exported
|
|
||||||
// fields will be neglected.
|
|
||||||
func (s *Struct) Values() []interface{} {
|
|
||||||
fields := s.structFields()
|
|
||||||
|
|
||||||
var t []interface{}
|
|
||||||
|
|
||||||
for _, field := range fields {
|
|
||||||
val := s.value.FieldByName(field.Name)
|
|
||||||
|
|
||||||
_, tagOpts := parseTag(field.Tag.Get(s.TagName))
|
|
||||||
|
|
||||||
// if the value is a zero value and the field is marked as omitempty do
|
|
||||||
// not include
|
|
||||||
if tagOpts.Has("omitempty") {
|
|
||||||
zero := reflect.Zero(val.Type()).Interface()
|
|
||||||
current := val.Interface()
|
|
||||||
|
|
||||||
if reflect.DeepEqual(current, zero) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if tagOpts.Has("string") {
|
|
||||||
s, ok := val.Interface().(fmt.Stringer)
|
|
||||||
if ok {
|
|
||||||
t = append(t, s.String())
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if IsStruct(val.Interface()) && !tagOpts.Has("omitnested") {
|
|
||||||
// look out for embedded structs, and convert them to a
|
|
||||||
// []interface{} to be added to the final values slice
|
|
||||||
for _, embeddedVal := range Values(val.Interface()) {
|
|
||||||
t = append(t, embeddedVal)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
t = append(t, val.Interface())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return t
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fields returns a slice of Fields. A struct tag with the content of "-"
|
|
||||||
// ignores the checking of that particular field. Example:
|
|
||||||
//
|
|
||||||
// // Field is ignored by this package.
|
|
||||||
// Field bool `structs:"-"`
|
|
||||||
//
|
|
||||||
// It panics if s's kind is not struct.
|
|
||||||
func (s *Struct) Fields() []*Field {
|
|
||||||
return getFields(s.value, s.TagName)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Names returns a slice of field names. A struct tag with the content of "-"
|
|
||||||
// ignores the checking of that particular field. Example:
|
|
||||||
//
|
|
||||||
// // Field is ignored by this package.
|
|
||||||
// Field bool `structs:"-"`
|
|
||||||
//
|
|
||||||
// It panics if s's kind is not struct.
|
|
||||||
func (s *Struct) Names() []string {
|
|
||||||
fields := getFields(s.value, s.TagName)
|
|
||||||
|
|
||||||
names := make([]string, len(fields))
|
|
||||||
|
|
||||||
for i, field := range fields {
|
|
||||||
names[i] = field.Name()
|
|
||||||
}
|
|
||||||
|
|
||||||
return names
|
|
||||||
}
|
|
||||||
|
|
||||||
func getFields(v reflect.Value, tagName string) []*Field {
|
|
||||||
if v.Kind() == reflect.Ptr {
|
|
||||||
v = v.Elem()
|
|
||||||
}
|
|
||||||
|
|
||||||
t := v.Type()
|
|
||||||
|
|
||||||
var fields []*Field
|
|
||||||
|
|
||||||
for i := 0; i < t.NumField(); i++ {
|
|
||||||
field := t.Field(i)
|
|
||||||
|
|
||||||
if tag := field.Tag.Get(tagName); tag == "-" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
f := &Field{
|
|
||||||
field: field,
|
|
||||||
value: v.FieldByName(field.Name),
|
|
||||||
}
|
|
||||||
|
|
||||||
fields = append(fields, f)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return fields
|
|
||||||
}
|
|
||||||
|
|
||||||
// Field returns a new Field struct that provides several high level functions
|
|
||||||
// around a single struct field entity. It panics if the field is not found.
|
|
||||||
func (s *Struct) Field(name string) *Field {
|
|
||||||
f, ok := s.FieldOk(name)
|
|
||||||
if !ok {
|
|
||||||
panic("field not found")
|
|
||||||
}
|
|
||||||
|
|
||||||
return f
|
|
||||||
}
|
|
||||||
|
|
||||||
// FieldOk returns a new Field struct that provides several high level functions
|
|
||||||
// around a single struct field entity. The boolean returns true if the field
|
|
||||||
// was found.
|
|
||||||
func (s *Struct) FieldOk(name string) (*Field, bool) {
|
|
||||||
t := s.value.Type()
|
|
||||||
|
|
||||||
field, ok := t.FieldByName(name)
|
|
||||||
if !ok {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
return &Field{
|
|
||||||
field: field,
|
|
||||||
value: s.value.FieldByName(name),
|
|
||||||
defaultTag: s.TagName,
|
|
||||||
}, true
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsZero returns true if all fields in a struct is a zero value (not
|
|
||||||
// initialized) A struct tag with the content of "-" ignores the checking of
|
|
||||||
// that particular field. Example:
|
|
||||||
//
|
|
||||||
// // Field is ignored by this package.
|
|
||||||
// Field bool `structs:"-"`
|
|
||||||
//
|
|
||||||
// A value with the option of "omitnested" stops iterating further if the type
|
|
||||||
// is a struct. Example:
|
|
||||||
//
|
|
||||||
// // Field is not processed further by this package.
|
|
||||||
// Field time.Time `structs:"myName,omitnested"`
|
|
||||||
// Field *http.Request `structs:",omitnested"`
|
|
||||||
//
|
|
||||||
// Note that only exported fields of a struct can be accessed, non exported
|
|
||||||
// fields will be neglected. It panics if s's kind is not struct.
|
|
||||||
func (s *Struct) IsZero() bool {
|
|
||||||
fields := s.structFields()
|
|
||||||
|
|
||||||
for _, field := range fields {
|
|
||||||
val := s.value.FieldByName(field.Name)
|
|
||||||
|
|
||||||
_, tagOpts := parseTag(field.Tag.Get(s.TagName))
|
|
||||||
|
|
||||||
if IsStruct(val.Interface()) && !tagOpts.Has("omitnested") {
|
|
||||||
ok := IsZero(val.Interface())
|
|
||||||
if !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// zero value of the given field, such as "" for string, 0 for int
|
|
||||||
zero := reflect.Zero(val.Type()).Interface()
|
|
||||||
|
|
||||||
// current value of the given field
|
|
||||||
current := val.Interface()
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(current, zero) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// HasZero returns true if a field in a struct is not initialized (zero value).
|
|
||||||
// A struct tag with the content of "-" ignores the checking of that particular
|
|
||||||
// field. Example:
|
|
||||||
//
|
|
||||||
// // Field is ignored by this package.
|
|
||||||
// Field bool `structs:"-"`
|
|
||||||
//
|
|
||||||
// A value with the option of "omitnested" stops iterating further if the type
|
|
||||||
// is a struct. Example:
|
|
||||||
//
|
|
||||||
// // Field is not processed further by this package.
|
|
||||||
// Field time.Time `structs:"myName,omitnested"`
|
|
||||||
// Field *http.Request `structs:",omitnested"`
|
|
||||||
//
|
|
||||||
// Note that only exported fields of a struct can be accessed, non exported
|
|
||||||
// fields will be neglected. It panics if s's kind is not struct.
|
|
||||||
func (s *Struct) HasZero() bool {
|
|
||||||
fields := s.structFields()
|
|
||||||
|
|
||||||
for _, field := range fields {
|
|
||||||
val := s.value.FieldByName(field.Name)
|
|
||||||
|
|
||||||
_, tagOpts := parseTag(field.Tag.Get(s.TagName))
|
|
||||||
|
|
||||||
if IsStruct(val.Interface()) && !tagOpts.Has("omitnested") {
|
|
||||||
ok := HasZero(val.Interface())
|
|
||||||
if ok {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// zero value of the given field, such as "" for string, 0 for int
|
|
||||||
zero := reflect.Zero(val.Type()).Interface()
|
|
||||||
|
|
||||||
// current value of the given field
|
|
||||||
current := val.Interface()
|
|
||||||
|
|
||||||
if reflect.DeepEqual(current, zero) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Name returns the structs's type name within its package. For more info refer
|
|
||||||
// to Name() function.
|
|
||||||
func (s *Struct) Name() string {
|
|
||||||
return s.value.Type().Name()
|
|
||||||
}
|
|
||||||
|
|
||||||
// structFields returns the exported struct fields for a given s struct. This
|
|
||||||
// is a convenient helper method to avoid duplicate code in some of the
|
|
||||||
// functions.
|
|
||||||
func (s *Struct) structFields() []reflect.StructField {
|
|
||||||
t := s.value.Type()
|
|
||||||
|
|
||||||
var f []reflect.StructField
|
|
||||||
|
|
||||||
for i := 0; i < t.NumField(); i++ {
|
|
||||||
field := t.Field(i)
|
|
||||||
// we can't access the value of unexported fields
|
|
||||||
if field.PkgPath != "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// don't check if it's omitted
|
|
||||||
if tag := field.Tag.Get(s.TagName); tag == "-" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
f = append(f, field)
|
|
||||||
}
|
|
||||||
|
|
||||||
return f
|
|
||||||
}
|
|
||||||
|
|
||||||
func strctVal(s interface{}) reflect.Value {
|
|
||||||
v := reflect.ValueOf(s)
|
|
||||||
|
|
||||||
// if pointer get the underlying element≤
|
|
||||||
if v.Kind() == reflect.Ptr {
|
|
||||||
v = v.Elem()
|
|
||||||
}
|
|
||||||
|
|
||||||
if v.Kind() != reflect.Struct {
|
|
||||||
panic("not struct")
|
|
||||||
}
|
|
||||||
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
// Map converts the given struct to a map[string]interface{}. For more info
|
|
||||||
// refer to Struct types Map() method. It panics if s's kind is not struct.
|
|
||||||
func Map(s interface{}) map[string]interface{} {
|
|
||||||
return New(s).Map()
|
|
||||||
}
|
|
||||||
|
|
||||||
// FillMap is the same as Map. Instead of returning the output, it fills the
|
|
||||||
// given map.
|
|
||||||
func FillMap(s interface{}, out map[string]interface{}) {
|
|
||||||
New(s).FillMap(out)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Values converts the given struct to a []interface{}. For more info refer to
|
|
||||||
// Struct types Values() method. It panics if s's kind is not struct.
|
|
||||||
func Values(s interface{}) []interface{} {
|
|
||||||
return New(s).Values()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fields returns a slice of *Field. For more info refer to Struct types
|
|
||||||
// Fields() method. It panics if s's kind is not struct.
|
|
||||||
func Fields(s interface{}) []*Field {
|
|
||||||
return New(s).Fields()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Names returns a slice of field names. For more info refer to Struct types
|
|
||||||
// Names() method. It panics if s's kind is not struct.
|
|
||||||
func Names(s interface{}) []string {
|
|
||||||
return New(s).Names()
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsZero returns true if all fields is equal to a zero value. For more info
|
|
||||||
// refer to Struct types IsZero() method. It panics if s's kind is not struct.
|
|
||||||
func IsZero(s interface{}) bool {
|
|
||||||
return New(s).IsZero()
|
|
||||||
}
|
|
||||||
|
|
||||||
// HasZero returns true if any field is equal to a zero value. For more info
|
|
||||||
// refer to Struct types HasZero() method. It panics if s's kind is not struct.
|
|
||||||
func HasZero(s interface{}) bool {
|
|
||||||
return New(s).HasZero()
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsStruct returns true if the given variable is a struct or a pointer to
|
|
||||||
// struct.
|
|
||||||
func IsStruct(s interface{}) bool {
|
|
||||||
v := reflect.ValueOf(s)
|
|
||||||
if v.Kind() == reflect.Ptr {
|
|
||||||
v = v.Elem()
|
|
||||||
}
|
|
||||||
|
|
||||||
// uninitialized zero value of a struct
|
|
||||||
if v.Kind() == reflect.Invalid {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return v.Kind() == reflect.Struct
|
|
||||||
}
|
|
||||||
|
|
||||||
// Name returns the structs's type name within its package. It returns an
|
|
||||||
// empty string for unnamed types. It panics if s's kind is not struct.
|
|
||||||
func Name(s interface{}) string {
|
|
||||||
return New(s).Name()
|
|
||||||
}
|
|
32
vendor/github.com/fatih/structs/tags.go
generated
vendored
32
vendor/github.com/fatih/structs/tags.go
generated
vendored
|
@ -1,32 +0,0 @@
|
||||||
package structs
|
|
||||||
|
|
||||||
import "strings"
|
|
||||||
|
|
||||||
// tagOptions contains a slice of tag options
|
|
||||||
type tagOptions []string
|
|
||||||
|
|
||||||
// Has returns true if the given optiton is available in tagOptions
|
|
||||||
func (t tagOptions) Has(opt string) bool {
|
|
||||||
for _, tagOpt := range t {
|
|
||||||
if tagOpt == opt {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseTag splits a struct field's tag into its name and a list of options
|
|
||||||
// which comes after a name. A tag is in the form of: "name,option1,option2".
|
|
||||||
// The name can be neglectected.
|
|
||||||
func parseTag(tag string) (string, tagOptions) {
|
|
||||||
// tag is one of followings:
|
|
||||||
// ""
|
|
||||||
// "name"
|
|
||||||
// "name,opt"
|
|
||||||
// "name,opt,opt2"
|
|
||||||
// ",opt"
|
|
||||||
|
|
||||||
res := strings.Split(tag, ",")
|
|
||||||
return res[0], res[1:]
|
|
||||||
}
|
|
354
vendor/github.com/hashicorp/errwrap/LICENSE
generated
vendored
354
vendor/github.com/hashicorp/errwrap/LICENSE
generated
vendored
|
@ -1,354 +0,0 @@
|
||||||
Mozilla Public License, version 2.0
|
|
||||||
|
|
||||||
1. Definitions
|
|
||||||
|
|
||||||
1.1. “Contributor”
|
|
||||||
|
|
||||||
means each individual or legal entity that creates, contributes to the
|
|
||||||
creation of, or owns Covered Software.
|
|
||||||
|
|
||||||
1.2. “Contributor Version”
|
|
||||||
|
|
||||||
means the combination of the Contributions of others (if any) used by a
|
|
||||||
Contributor and that particular Contributor’s Contribution.
|
|
||||||
|
|
||||||
1.3. “Contribution”
|
|
||||||
|
|
||||||
means Covered Software of a particular Contributor.
|
|
||||||
|
|
||||||
1.4. “Covered Software”
|
|
||||||
|
|
||||||
means Source Code Form to which the initial Contributor has attached the
|
|
||||||
notice in Exhibit A, the Executable Form of such Source Code Form, and
|
|
||||||
Modifications of such Source Code Form, in each case including portions
|
|
||||||
thereof.
|
|
||||||
|
|
||||||
1.5. “Incompatible With Secondary Licenses”
|
|
||||||
means
|
|
||||||
|
|
||||||
a. that the initial Contributor has attached the notice described in
|
|
||||||
Exhibit B to the Covered Software; or
|
|
||||||
|
|
||||||
b. that the Covered Software was made available under the terms of version
|
|
||||||
1.1 or earlier of the License, but not also under the terms of a
|
|
||||||
Secondary License.
|
|
||||||
|
|
||||||
1.6. “Executable Form”
|
|
||||||
|
|
||||||
means any form of the work other than Source Code Form.
|
|
||||||
|
|
||||||
1.7. “Larger Work”
|
|
||||||
|
|
||||||
means a work that combines Covered Software with other material, in a separate
|
|
||||||
file or files, that is not Covered Software.
|
|
||||||
|
|
||||||
1.8. “License”
|
|
||||||
|
|
||||||
means this document.
|
|
||||||
|
|
||||||
1.9. “Licensable”
|
|
||||||
|
|
||||||
means having the right to grant, to the maximum extent possible, whether at the
|
|
||||||
time of the initial grant or subsequently, any and all of the rights conveyed by
|
|
||||||
this License.
|
|
||||||
|
|
||||||
1.10. “Modifications”
|
|
||||||
|
|
||||||
means any of the following:
|
|
||||||
|
|
||||||
a. any file in Source Code Form that results from an addition to, deletion
|
|
||||||
from, or modification of the contents of Covered Software; or
|
|
||||||
|
|
||||||
b. any new file in Source Code Form that contains any Covered Software.
|
|
||||||
|
|
||||||
1.11. “Patent Claims” of a Contributor
|
|
||||||
|
|
||||||
means any patent claim(s), including without limitation, method, process,
|
|
||||||
and apparatus claims, in any patent Licensable by such Contributor that
|
|
||||||
would be infringed, but for the grant of the License, by the making,
|
|
||||||
using, selling, offering for sale, having made, import, or transfer of
|
|
||||||
either its Contributions or its Contributor Version.
|
|
||||||
|
|
||||||
1.12. “Secondary License”
|
|
||||||
|
|
||||||
means either the GNU General Public License, Version 2.0, the GNU Lesser
|
|
||||||
General Public License, Version 2.1, the GNU Affero General Public
|
|
||||||
License, Version 3.0, or any later versions of those licenses.
|
|
||||||
|
|
||||||
1.13. “Source Code Form”
|
|
||||||
|
|
||||||
means the form of the work preferred for making modifications.
|
|
||||||
|
|
||||||
1.14. “You” (or “Your”)
|
|
||||||
|
|
||||||
means an individual or a legal entity exercising rights under this
|
|
||||||
License. For legal entities, “You” includes any entity that controls, is
|
|
||||||
controlled by, or is under common control with You. For purposes of this
|
|
||||||
definition, “control” means (a) the power, direct or indirect, to cause
|
|
||||||
the direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (b) ownership of more than fifty percent (50%) of the
|
|
||||||
outstanding shares or beneficial ownership of such entity.
|
|
||||||
|
|
||||||
|
|
||||||
2. License Grants and Conditions
|
|
||||||
|
|
||||||
2.1. Grants
|
|
||||||
|
|
||||||
Each Contributor hereby grants You a world-wide, royalty-free,
|
|
||||||
non-exclusive license:
|
|
||||||
|
|
||||||
a. under intellectual property rights (other than patent or trademark)
|
|
||||||
Licensable by such Contributor to use, reproduce, make available,
|
|
||||||
modify, display, perform, distribute, and otherwise exploit its
|
|
||||||
Contributions, either on an unmodified basis, with Modifications, or as
|
|
||||||
part of a Larger Work; and
|
|
||||||
|
|
||||||
b. under Patent Claims of such Contributor to make, use, sell, offer for
|
|
||||||
sale, have made, import, and otherwise transfer either its Contributions
|
|
||||||
or its Contributor Version.
|
|
||||||
|
|
||||||
2.2. Effective Date
|
|
||||||
|
|
||||||
The licenses granted in Section 2.1 with respect to any Contribution become
|
|
||||||
effective for each Contribution on the date the Contributor first distributes
|
|
||||||
such Contribution.
|
|
||||||
|
|
||||||
2.3. Limitations on Grant Scope
|
|
||||||
|
|
||||||
The licenses granted in this Section 2 are the only rights granted under this
|
|
||||||
License. No additional rights or licenses will be implied from the distribution
|
|
||||||
or licensing of Covered Software under this License. Notwithstanding Section
|
|
||||||
2.1(b) above, no patent license is granted by a Contributor:
|
|
||||||
|
|
||||||
a. for any code that a Contributor has removed from Covered Software; or
|
|
||||||
|
|
||||||
b. for infringements caused by: (i) Your and any other third party’s
|
|
||||||
modifications of Covered Software, or (ii) the combination of its
|
|
||||||
Contributions with other software (except as part of its Contributor
|
|
||||||
Version); or
|
|
||||||
|
|
||||||
c. under Patent Claims infringed by Covered Software in the absence of its
|
|
||||||
Contributions.
|
|
||||||
|
|
||||||
This License does not grant any rights in the trademarks, service marks, or
|
|
||||||
logos of any Contributor (except as may be necessary to comply with the
|
|
||||||
notice requirements in Section 3.4).
|
|
||||||
|
|
||||||
2.4. Subsequent Licenses
|
|
||||||
|
|
||||||
No Contributor makes additional grants as a result of Your choice to
|
|
||||||
distribute the Covered Software under a subsequent version of this License
|
|
||||||
(see Section 10.2) or under the terms of a Secondary License (if permitted
|
|
||||||
under the terms of Section 3.3).
|
|
||||||
|
|
||||||
2.5. Representation
|
|
||||||
|
|
||||||
Each Contributor represents that the Contributor believes its Contributions
|
|
||||||
are its original creation(s) or it has sufficient rights to grant the
|
|
||||||
rights to its Contributions conveyed by this License.
|
|
||||||
|
|
||||||
2.6. Fair Use
|
|
||||||
|
|
||||||
This License is not intended to limit any rights You have under applicable
|
|
||||||
copyright doctrines of fair use, fair dealing, or other equivalents.
|
|
||||||
|
|
||||||
2.7. Conditions
|
|
||||||
|
|
||||||
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
|
|
||||||
Section 2.1.
|
|
||||||
|
|
||||||
|
|
||||||
3. Responsibilities
|
|
||||||
|
|
||||||
3.1. Distribution of Source Form
|
|
||||||
|
|
||||||
All distribution of Covered Software in Source Code Form, including any
|
|
||||||
Modifications that You create or to which You contribute, must be under the
|
|
||||||
terms of this License. You must inform recipients that the Source Code Form
|
|
||||||
of the Covered Software is governed by the terms of this License, and how
|
|
||||||
they can obtain a copy of this License. You may not attempt to alter or
|
|
||||||
restrict the recipients’ rights in the Source Code Form.
|
|
||||||
|
|
||||||
3.2. Distribution of Executable Form
|
|
||||||
|
|
||||||
If You distribute Covered Software in Executable Form then:
|
|
||||||
|
|
||||||
a. such Covered Software must also be made available in Source Code Form,
|
|
||||||
as described in Section 3.1, and You must inform recipients of the
|
|
||||||
Executable Form how they can obtain a copy of such Source Code Form by
|
|
||||||
reasonable means in a timely manner, at a charge no more than the cost
|
|
||||||
of distribution to the recipient; and
|
|
||||||
|
|
||||||
b. You may distribute such Executable Form under the terms of this License,
|
|
||||||
or sublicense it under different terms, provided that the license for
|
|
||||||
the Executable Form does not attempt to limit or alter the recipients’
|
|
||||||
rights in the Source Code Form under this License.
|
|
||||||
|
|
||||||
3.3. Distribution of a Larger Work
|
|
||||||
|
|
||||||
You may create and distribute a Larger Work under terms of Your choice,
|
|
||||||
provided that You also comply with the requirements of this License for the
|
|
||||||
Covered Software. If the Larger Work is a combination of Covered Software
|
|
||||||
with a work governed by one or more Secondary Licenses, and the Covered
|
|
||||||
Software is not Incompatible With Secondary Licenses, this License permits
|
|
||||||
You to additionally distribute such Covered Software under the terms of
|
|
||||||
such Secondary License(s), so that the recipient of the Larger Work may, at
|
|
||||||
their option, further distribute the Covered Software under the terms of
|
|
||||||
either this License or such Secondary License(s).
|
|
||||||
|
|
||||||
3.4. Notices
|
|
||||||
|
|
||||||
You may not remove or alter the substance of any license notices (including
|
|
||||||
copyright notices, patent notices, disclaimers of warranty, or limitations
|
|
||||||
of liability) contained within the Source Code Form of the Covered
|
|
||||||
Software, except that You may alter any license notices to the extent
|
|
||||||
required to remedy known factual inaccuracies.
|
|
||||||
|
|
||||||
3.5. Application of Additional Terms
|
|
||||||
|
|
||||||
You may choose to offer, and to charge a fee for, warranty, support,
|
|
||||||
indemnity or liability obligations to one or more recipients of Covered
|
|
||||||
Software. However, You may do so only on Your own behalf, and not on behalf
|
|
||||||
of any Contributor. You must make it absolutely clear that any such
|
|
||||||
warranty, support, indemnity, or liability obligation is offered by You
|
|
||||||
alone, and You hereby agree to indemnify every Contributor for any
|
|
||||||
liability incurred by such Contributor as a result of warranty, support,
|
|
||||||
indemnity or liability terms You offer. You may include additional
|
|
||||||
disclaimers of warranty and limitations of liability specific to any
|
|
||||||
jurisdiction.
|
|
||||||
|
|
||||||
4. Inability to Comply Due to Statute or Regulation
|
|
||||||
|
|
||||||
If it is impossible for You to comply with any of the terms of this License
|
|
||||||
with respect to some or all of the Covered Software due to statute, judicial
|
|
||||||
order, or regulation then You must: (a) comply with the terms of this License
|
|
||||||
to the maximum extent possible; and (b) describe the limitations and the code
|
|
||||||
they affect. Such description must be placed in a text file included with all
|
|
||||||
distributions of the Covered Software under this License. Except to the
|
|
||||||
extent prohibited by statute or regulation, such description must be
|
|
||||||
sufficiently detailed for a recipient of ordinary skill to be able to
|
|
||||||
understand it.
|
|
||||||
|
|
||||||
5. Termination
|
|
||||||
|
|
||||||
5.1. The rights granted under this License will terminate automatically if You
|
|
||||||
fail to comply with any of its terms. However, if You become compliant,
|
|
||||||
then the rights granted under this License from a particular Contributor
|
|
||||||
are reinstated (a) provisionally, unless and until such Contributor
|
|
||||||
explicitly and finally terminates Your grants, and (b) on an ongoing basis,
|
|
||||||
if such Contributor fails to notify You of the non-compliance by some
|
|
||||||
reasonable means prior to 60 days after You have come back into compliance.
|
|
||||||
Moreover, Your grants from a particular Contributor are reinstated on an
|
|
||||||
ongoing basis if such Contributor notifies You of the non-compliance by
|
|
||||||
some reasonable means, this is the first time You have received notice of
|
|
||||||
non-compliance with this License from such Contributor, and You become
|
|
||||||
compliant prior to 30 days after Your receipt of the notice.
|
|
||||||
|
|
||||||
5.2. If You initiate litigation against any entity by asserting a patent
|
|
||||||
infringement claim (excluding declaratory judgment actions, counter-claims,
|
|
||||||
and cross-claims) alleging that a Contributor Version directly or
|
|
||||||
indirectly infringes any patent, then the rights granted to You by any and
|
|
||||||
all Contributors for the Covered Software under Section 2.1 of this License
|
|
||||||
shall terminate.
|
|
||||||
|
|
||||||
5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
|
|
||||||
license agreements (excluding distributors and resellers) which have been
|
|
||||||
validly granted by You or Your distributors under this License prior to
|
|
||||||
termination shall survive termination.
|
|
||||||
|
|
||||||
6. Disclaimer of Warranty
|
|
||||||
|
|
||||||
Covered Software is provided under this License on an “as is” basis, without
|
|
||||||
warranty of any kind, either expressed, implied, or statutory, including,
|
|
||||||
without limitation, warranties that the Covered Software is free of defects,
|
|
||||||
merchantable, fit for a particular purpose or non-infringing. The entire
|
|
||||||
risk as to the quality and performance of the Covered Software is with You.
|
|
||||||
Should any Covered Software prove defective in any respect, You (not any
|
|
||||||
Contributor) assume the cost of any necessary servicing, repair, or
|
|
||||||
correction. This disclaimer of warranty constitutes an essential part of this
|
|
||||||
License. No use of any Covered Software is authorized under this License
|
|
||||||
except under this disclaimer.
|
|
||||||
|
|
||||||
7. Limitation of Liability
|
|
||||||
|
|
||||||
Under no circumstances and under no legal theory, whether tort (including
|
|
||||||
negligence), contract, or otherwise, shall any Contributor, or anyone who
|
|
||||||
distributes Covered Software as permitted above, be liable to You for any
|
|
||||||
direct, indirect, special, incidental, or consequential damages of any
|
|
||||||
character including, without limitation, damages for lost profits, loss of
|
|
||||||
goodwill, work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses, even if such party shall have been
|
|
||||||
informed of the possibility of such damages. This limitation of liability
|
|
||||||
shall not apply to liability for death or personal injury resulting from such
|
|
||||||
party’s negligence to the extent applicable law prohibits such limitation.
|
|
||||||
Some jurisdictions do not allow the exclusion or limitation of incidental or
|
|
||||||
consequential damages, so this exclusion and limitation may not apply to You.
|
|
||||||
|
|
||||||
8. Litigation
|
|
||||||
|
|
||||||
Any litigation relating to this License may be brought only in the courts of
|
|
||||||
a jurisdiction where the defendant maintains its principal place of business
|
|
||||||
and such litigation shall be governed by laws of that jurisdiction, without
|
|
||||||
reference to its conflict-of-law provisions. Nothing in this Section shall
|
|
||||||
prevent a party’s ability to bring cross-claims or counter-claims.
|
|
||||||
|
|
||||||
9. Miscellaneous
|
|
||||||
|
|
||||||
This License represents the complete agreement concerning the subject matter
|
|
||||||
hereof. If any provision of this License is held to be unenforceable, such
|
|
||||||
provision shall be reformed only to the extent necessary to make it
|
|
||||||
enforceable. Any law or regulation which provides that the language of a
|
|
||||||
contract shall be construed against the drafter shall not be used to construe
|
|
||||||
this License against a Contributor.
|
|
||||||
|
|
||||||
|
|
||||||
10. Versions of the License
|
|
||||||
|
|
||||||
10.1. New Versions
|
|
||||||
|
|
||||||
Mozilla Foundation is the license steward. Except as provided in Section
|
|
||||||
10.3, no one other than the license steward has the right to modify or
|
|
||||||
publish new versions of this License. Each version will be given a
|
|
||||||
distinguishing version number.
|
|
||||||
|
|
||||||
10.2. Effect of New Versions
|
|
||||||
|
|
||||||
You may distribute the Covered Software under the terms of the version of
|
|
||||||
the License under which You originally received the Covered Software, or
|
|
||||||
under the terms of any subsequent version published by the license
|
|
||||||
steward.
|
|
||||||
|
|
||||||
10.3. Modified Versions
|
|
||||||
|
|
||||||
If you create software not governed by this License, and you want to
|
|
||||||
create a new license for such software, you may create and use a modified
|
|
||||||
version of this License if you rename the license and remove any
|
|
||||||
references to the name of the license steward (except to note that such
|
|
||||||
modified license differs from this License).
|
|
||||||
|
|
||||||
10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses
|
|
||||||
If You choose to distribute Source Code Form that is Incompatible With
|
|
||||||
Secondary Licenses under the terms of this version of the License, the
|
|
||||||
notice described in Exhibit B of this License must be attached.
|
|
||||||
|
|
||||||
Exhibit A - Source Code Form License Notice
|
|
||||||
|
|
||||||
This Source Code Form is subject to the
|
|
||||||
terms of the Mozilla Public License, v.
|
|
||||||
2.0. If a copy of the MPL was not
|
|
||||||
distributed with this file, You can
|
|
||||||
obtain one at
|
|
||||||
http://mozilla.org/MPL/2.0/.
|
|
||||||
|
|
||||||
If it is not possible or desirable to put the notice in a particular file, then
|
|
||||||
You may include the notice in a location (such as a LICENSE file in a relevant
|
|
||||||
directory) where a recipient would be likely to look for such a notice.
|
|
||||||
|
|
||||||
You may add additional accurate notices of copyright ownership.
|
|
||||||
|
|
||||||
Exhibit B - “Incompatible With Secondary Licenses” Notice
|
|
||||||
|
|
||||||
This Source Code Form is “Incompatible
|
|
||||||
With Secondary Licenses”, as defined by
|
|
||||||
the Mozilla Public License, v. 2.0.
|
|
||||||
|
|
89
vendor/github.com/hashicorp/errwrap/README.md
generated
vendored
89
vendor/github.com/hashicorp/errwrap/README.md
generated
vendored
|
@ -1,89 +0,0 @@
|
||||||
# errwrap
|
|
||||||
|
|
||||||
`errwrap` is a package for Go that formalizes the pattern of wrapping errors
|
|
||||||
and checking if an error contains another error.
|
|
||||||
|
|
||||||
There is a common pattern in Go of taking a returned `error` value and
|
|
||||||
then wrapping it (such as with `fmt.Errorf`) before returning it. The problem
|
|
||||||
with this pattern is that you completely lose the original `error` structure.
|
|
||||||
|
|
||||||
Arguably the _correct_ approach is that you should make a custom structure
|
|
||||||
implementing the `error` interface, and have the original error as a field
|
|
||||||
on that structure, such [as this example](http://golang.org/pkg/os/#PathError).
|
|
||||||
This is a good approach, but you have to know the entire chain of possible
|
|
||||||
rewrapping that happens, when you might just care about one.
|
|
||||||
|
|
||||||
`errwrap` formalizes this pattern (it doesn't matter what approach you use
|
|
||||||
above) by giving a single interface for wrapping errors, checking if a specific
|
|
||||||
error is wrapped, and extracting that error.
|
|
||||||
|
|
||||||
## Installation and Docs
|
|
||||||
|
|
||||||
Install using `go get github.com/hashicorp/errwrap`.
|
|
||||||
|
|
||||||
Full documentation is available at
|
|
||||||
http://godoc.org/github.com/hashicorp/errwrap
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
#### Basic Usage
|
|
||||||
|
|
||||||
Below is a very basic example of its usage:
|
|
||||||
|
|
||||||
```go
|
|
||||||
// A function that always returns an error, but wraps it, like a real
|
|
||||||
// function might.
|
|
||||||
func tryOpen() error {
|
|
||||||
_, err := os.Open("/i/dont/exist")
|
|
||||||
if err != nil {
|
|
||||||
return errwrap.Wrapf("Doesn't exist: {{err}}", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
err := tryOpen()
|
|
||||||
|
|
||||||
// We can use the Contains helpers to check if an error contains
|
|
||||||
// another error. It is safe to do this with a nil error, or with
|
|
||||||
// an error that doesn't even use the errwrap package.
|
|
||||||
if errwrap.Contains(err, ErrNotExist) {
|
|
||||||
// Do something
|
|
||||||
}
|
|
||||||
if errwrap.ContainsType(err, new(os.PathError)) {
|
|
||||||
// Do something
|
|
||||||
}
|
|
||||||
|
|
||||||
// Or we can use the associated `Get` functions to just extract
|
|
||||||
// a specific error. This would return nil if that specific error doesn't
|
|
||||||
// exist.
|
|
||||||
perr := errwrap.GetType(err, new(os.PathError))
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Custom Types
|
|
||||||
|
|
||||||
If you're already making custom types that properly wrap errors, then
|
|
||||||
you can get all the functionality of `errwraps.Contains` and such by
|
|
||||||
implementing the `Wrapper` interface with just one function. Example:
|
|
||||||
|
|
||||||
```go
|
|
||||||
type AppError {
|
|
||||||
Code ErrorCode
|
|
||||||
Err error
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *AppError) WrappedErrors() []error {
|
|
||||||
return []error{e.Err}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Now this works:
|
|
||||||
|
|
||||||
```go
|
|
||||||
err := &AppError{Err: fmt.Errorf("an error")}
|
|
||||||
if errwrap.ContainsType(err, fmt.Errorf("")) {
|
|
||||||
// This will work!
|
|
||||||
}
|
|
||||||
```
|
|
169
vendor/github.com/hashicorp/errwrap/errwrap.go
generated
vendored
169
vendor/github.com/hashicorp/errwrap/errwrap.go
generated
vendored
|
@ -1,169 +0,0 @@
|
||||||
// Package errwrap implements methods to formalize error wrapping in Go.
|
|
||||||
//
|
|
||||||
// All of the top-level functions that take an `error` are built to be able
|
|
||||||
// to take any error, not just wrapped errors. This allows you to use errwrap
|
|
||||||
// without having to type-check and type-cast everywhere.
|
|
||||||
package errwrap
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"reflect"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// WalkFunc is the callback called for Walk.
|
|
||||||
type WalkFunc func(error)
|
|
||||||
|
|
||||||
// Wrapper is an interface that can be implemented by custom types to
|
|
||||||
// have all the Contains, Get, etc. functions in errwrap work.
|
|
||||||
//
|
|
||||||
// When Walk reaches a Wrapper, it will call the callback for every
|
|
||||||
// wrapped error in addition to the wrapper itself. Since all the top-level
|
|
||||||
// functions in errwrap use Walk, this means that all those functions work
|
|
||||||
// with your custom type.
|
|
||||||
type Wrapper interface {
|
|
||||||
WrappedErrors() []error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wrap defines that outer wraps inner, returning an error type that
|
|
||||||
// can be cleanly used with the other methods in this package, such as
|
|
||||||
// Contains, GetAll, etc.
|
|
||||||
//
|
|
||||||
// This function won't modify the error message at all (the outer message
|
|
||||||
// will be used).
|
|
||||||
func Wrap(outer, inner error) error {
|
|
||||||
return &wrappedError{
|
|
||||||
Outer: outer,
|
|
||||||
Inner: inner,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wrapf wraps an error with a formatting message. This is similar to using
|
|
||||||
// `fmt.Errorf` to wrap an error. If you're using `fmt.Errorf` to wrap
|
|
||||||
// errors, you should replace it with this.
|
|
||||||
//
|
|
||||||
// format is the format of the error message. The string '{{err}}' will
|
|
||||||
// be replaced with the original error message.
|
|
||||||
func Wrapf(format string, err error) error {
|
|
||||||
outerMsg := "<nil>"
|
|
||||||
if err != nil {
|
|
||||||
outerMsg = err.Error()
|
|
||||||
}
|
|
||||||
|
|
||||||
outer := errors.New(strings.Replace(
|
|
||||||
format, "{{err}}", outerMsg, -1))
|
|
||||||
|
|
||||||
return Wrap(outer, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Contains checks if the given error contains an error with the
|
|
||||||
// message msg. If err is not a wrapped error, this will always return
|
|
||||||
// false unless the error itself happens to match this msg.
|
|
||||||
func Contains(err error, msg string) bool {
|
|
||||||
return len(GetAll(err, msg)) > 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// ContainsType checks if the given error contains an error with
|
|
||||||
// the same concrete type as v. If err is not a wrapped error, this will
|
|
||||||
// check the err itself.
|
|
||||||
func ContainsType(err error, v interface{}) bool {
|
|
||||||
return len(GetAllType(err, v)) > 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get is the same as GetAll but returns the deepest matching error.
|
|
||||||
func Get(err error, msg string) error {
|
|
||||||
es := GetAll(err, msg)
|
|
||||||
if len(es) > 0 {
|
|
||||||
return es[len(es)-1]
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetType is the same as GetAllType but returns the deepest matching error.
|
|
||||||
func GetType(err error, v interface{}) error {
|
|
||||||
es := GetAllType(err, v)
|
|
||||||
if len(es) > 0 {
|
|
||||||
return es[len(es)-1]
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetAll gets all the errors that might be wrapped in err with the
|
|
||||||
// given message. The order of the errors is such that the outermost
|
|
||||||
// matching error (the most recent wrap) is index zero, and so on.
|
|
||||||
func GetAll(err error, msg string) []error {
|
|
||||||
var result []error
|
|
||||||
|
|
||||||
Walk(err, func(err error) {
|
|
||||||
if err.Error() == msg {
|
|
||||||
result = append(result, err)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetAllType gets all the errors that are the same type as v.
|
|
||||||
//
|
|
||||||
// The order of the return value is the same as described in GetAll.
|
|
||||||
func GetAllType(err error, v interface{}) []error {
|
|
||||||
var result []error
|
|
||||||
|
|
||||||
var search string
|
|
||||||
if v != nil {
|
|
||||||
search = reflect.TypeOf(v).String()
|
|
||||||
}
|
|
||||||
Walk(err, func(err error) {
|
|
||||||
var needle string
|
|
||||||
if err != nil {
|
|
||||||
needle = reflect.TypeOf(err).String()
|
|
||||||
}
|
|
||||||
|
|
||||||
if needle == search {
|
|
||||||
result = append(result, err)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
// Walk walks all the wrapped errors in err and calls the callback. If
|
|
||||||
// err isn't a wrapped error, this will be called once for err. If err
|
|
||||||
// is a wrapped error, the callback will be called for both the wrapper
|
|
||||||
// that implements error as well as the wrapped error itself.
|
|
||||||
func Walk(err error, cb WalkFunc) {
|
|
||||||
if err == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
switch e := err.(type) {
|
|
||||||
case *wrappedError:
|
|
||||||
cb(e.Outer)
|
|
||||||
Walk(e.Inner, cb)
|
|
||||||
case Wrapper:
|
|
||||||
cb(err)
|
|
||||||
|
|
||||||
for _, err := range e.WrappedErrors() {
|
|
||||||
Walk(err, cb)
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
cb(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// wrappedError is an implementation of error that has both the
|
|
||||||
// outer and inner errors.
|
|
||||||
type wrappedError struct {
|
|
||||||
Outer error
|
|
||||||
Inner error
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *wrappedError) Error() string {
|
|
||||||
return w.Outer.Error()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *wrappedError) WrappedErrors() []error {
|
|
||||||
return []error{w.Outer, w.Inner}
|
|
||||||
}
|
|
363
vendor/github.com/hashicorp/go-cleanhttp/LICENSE
generated
vendored
363
vendor/github.com/hashicorp/go-cleanhttp/LICENSE
generated
vendored
|
@ -1,363 +0,0 @@
|
||||||
Mozilla Public License, version 2.0
|
|
||||||
|
|
||||||
1. Definitions
|
|
||||||
|
|
||||||
1.1. "Contributor"
|
|
||||||
|
|
||||||
means each individual or legal entity that creates, contributes to the
|
|
||||||
creation of, or owns Covered Software.
|
|
||||||
|
|
||||||
1.2. "Contributor Version"
|
|
||||||
|
|
||||||
means the combination of the Contributions of others (if any) used by a
|
|
||||||
Contributor and that particular Contributor's Contribution.
|
|
||||||
|
|
||||||
1.3. "Contribution"
|
|
||||||
|
|
||||||
means Covered Software of a particular Contributor.
|
|
||||||
|
|
||||||
1.4. "Covered Software"
|
|
||||||
|
|
||||||
means Source Code Form to which the initial Contributor has attached the
|
|
||||||
notice in Exhibit A, the Executable Form of such Source Code Form, and
|
|
||||||
Modifications of such Source Code Form, in each case including portions
|
|
||||||
thereof.
|
|
||||||
|
|
||||||
1.5. "Incompatible With Secondary Licenses"
|
|
||||||
means
|
|
||||||
|
|
||||||
a. that the initial Contributor has attached the notice described in
|
|
||||||
Exhibit B to the Covered Software; or
|
|
||||||
|
|
||||||
b. that the Covered Software was made available under the terms of
|
|
||||||
version 1.1 or earlier of the License, but not also under the terms of
|
|
||||||
a Secondary License.
|
|
||||||
|
|
||||||
1.6. "Executable Form"
|
|
||||||
|
|
||||||
means any form of the work other than Source Code Form.
|
|
||||||
|
|
||||||
1.7. "Larger Work"
|
|
||||||
|
|
||||||
means a work that combines Covered Software with other material, in a
|
|
||||||
separate file or files, that is not Covered Software.
|
|
||||||
|
|
||||||
1.8. "License"
|
|
||||||
|
|
||||||
means this document.
|
|
||||||
|
|
||||||
1.9. "Licensable"
|
|
||||||
|
|
||||||
means having the right to grant, to the maximum extent possible, whether
|
|
||||||
at the time of the initial grant or subsequently, any and all of the
|
|
||||||
rights conveyed by this License.
|
|
||||||
|
|
||||||
1.10. "Modifications"
|
|
||||||
|
|
||||||
means any of the following:
|
|
||||||
|
|
||||||
a. any file in Source Code Form that results from an addition to,
|
|
||||||
deletion from, or modification of the contents of Covered Software; or
|
|
||||||
|
|
||||||
b. any new file in Source Code Form that contains any Covered Software.
|
|
||||||
|
|
||||||
1.11. "Patent Claims" of a Contributor
|
|
||||||
|
|
||||||
means any patent claim(s), including without limitation, method,
|
|
||||||
process, and apparatus claims, in any patent Licensable by such
|
|
||||||
Contributor that would be infringed, but for the grant of the License,
|
|
||||||
by the making, using, selling, offering for sale, having made, import,
|
|
||||||
or transfer of either its Contributions or its Contributor Version.
|
|
||||||
|
|
||||||
1.12. "Secondary License"
|
|
||||||
|
|
||||||
means either the GNU General Public License, Version 2.0, the GNU Lesser
|
|
||||||
General Public License, Version 2.1, the GNU Affero General Public
|
|
||||||
License, Version 3.0, or any later versions of those licenses.
|
|
||||||
|
|
||||||
1.13. "Source Code Form"
|
|
||||||
|
|
||||||
means the form of the work preferred for making modifications.
|
|
||||||
|
|
||||||
1.14. "You" (or "Your")
|
|
||||||
|
|
||||||
means an individual or a legal entity exercising rights under this
|
|
||||||
License. For legal entities, "You" includes any entity that controls, is
|
|
||||||
controlled by, or is under common control with You. For purposes of this
|
|
||||||
definition, "control" means (a) the power, direct or indirect, to cause
|
|
||||||
the direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (b) ownership of more than fifty percent (50%) of the
|
|
||||||
outstanding shares or beneficial ownership of such entity.
|
|
||||||
|
|
||||||
|
|
||||||
2. License Grants and Conditions
|
|
||||||
|
|
||||||
2.1. Grants
|
|
||||||
|
|
||||||
Each Contributor hereby grants You a world-wide, royalty-free,
|
|
||||||
non-exclusive license:
|
|
||||||
|
|
||||||
a. under intellectual property rights (other than patent or trademark)
|
|
||||||
Licensable by such Contributor to use, reproduce, make available,
|
|
||||||
modify, display, perform, distribute, and otherwise exploit its
|
|
||||||
Contributions, either on an unmodified basis, with Modifications, or
|
|
||||||
as part of a Larger Work; and
|
|
||||||
|
|
||||||
b. under Patent Claims of such Contributor to make, use, sell, offer for
|
|
||||||
sale, have made, import, and otherwise transfer either its
|
|
||||||
Contributions or its Contributor Version.
|
|
||||||
|
|
||||||
2.2. Effective Date
|
|
||||||
|
|
||||||
The licenses granted in Section 2.1 with respect to any Contribution
|
|
||||||
become effective for each Contribution on the date the Contributor first
|
|
||||||
distributes such Contribution.
|
|
||||||
|
|
||||||
2.3. Limitations on Grant Scope
|
|
||||||
|
|
||||||
The licenses granted in this Section 2 are the only rights granted under
|
|
||||||
this License. No additional rights or licenses will be implied from the
|
|
||||||
distribution or licensing of Covered Software under this License.
|
|
||||||
Notwithstanding Section 2.1(b) above, no patent license is granted by a
|
|
||||||
Contributor:
|
|
||||||
|
|
||||||
a. for any code that a Contributor has removed from Covered Software; or
|
|
||||||
|
|
||||||
b. for infringements caused by: (i) Your and any other third party's
|
|
||||||
modifications of Covered Software, or (ii) the combination of its
|
|
||||||
Contributions with other software (except as part of its Contributor
|
|
||||||
Version); or
|
|
||||||
|
|
||||||
c. under Patent Claims infringed by Covered Software in the absence of
|
|
||||||
its Contributions.
|
|
||||||
|
|
||||||
This License does not grant any rights in the trademarks, service marks,
|
|
||||||
or logos of any Contributor (except as may be necessary to comply with
|
|
||||||
the notice requirements in Section 3.4).
|
|
||||||
|
|
||||||
2.4. Subsequent Licenses
|
|
||||||
|
|
||||||
No Contributor makes additional grants as a result of Your choice to
|
|
||||||
distribute the Covered Software under a subsequent version of this
|
|
||||||
License (see Section 10.2) or under the terms of a Secondary License (if
|
|
||||||
permitted under the terms of Section 3.3).
|
|
||||||
|
|
||||||
2.5. Representation
|
|
||||||
|
|
||||||
Each Contributor represents that the Contributor believes its
|
|
||||||
Contributions are its original creation(s) or it has sufficient rights to
|
|
||||||
grant the rights to its Contributions conveyed by this License.
|
|
||||||
|
|
||||||
2.6. Fair Use
|
|
||||||
|
|
||||||
This License is not intended to limit any rights You have under
|
|
||||||
applicable copyright doctrines of fair use, fair dealing, or other
|
|
||||||
equivalents.
|
|
||||||
|
|
||||||
2.7. Conditions
|
|
||||||
|
|
||||||
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
|
|
||||||
Section 2.1.
|
|
||||||
|
|
||||||
|
|
||||||
3. Responsibilities
|
|
||||||
|
|
||||||
3.1. Distribution of Source Form
|
|
||||||
|
|
||||||
All distribution of Covered Software in Source Code Form, including any
|
|
||||||
Modifications that You create or to which You contribute, must be under
|
|
||||||
the terms of this License. You must inform recipients that the Source
|
|
||||||
Code Form of the Covered Software is governed by the terms of this
|
|
||||||
License, and how they can obtain a copy of this License. You may not
|
|
||||||
attempt to alter or restrict the recipients' rights in the Source Code
|
|
||||||
Form.
|
|
||||||
|
|
||||||
3.2. Distribution of Executable Form
|
|
||||||
|
|
||||||
If You distribute Covered Software in Executable Form then:
|
|
||||||
|
|
||||||
a. such Covered Software must also be made available in Source Code Form,
|
|
||||||
as described in Section 3.1, and You must inform recipients of the
|
|
||||||
Executable Form how they can obtain a copy of such Source Code Form by
|
|
||||||
reasonable means in a timely manner, at a charge no more than the cost
|
|
||||||
of distribution to the recipient; and
|
|
||||||
|
|
||||||
b. You may distribute such Executable Form under the terms of this
|
|
||||||
License, or sublicense it under different terms, provided that the
|
|
||||||
license for the Executable Form does not attempt to limit or alter the
|
|
||||||
recipients' rights in the Source Code Form under this License.
|
|
||||||
|
|
||||||
3.3. Distribution of a Larger Work
|
|
||||||
|
|
||||||
You may create and distribute a Larger Work under terms of Your choice,
|
|
||||||
provided that You also comply with the requirements of this License for
|
|
||||||
the Covered Software. If the Larger Work is a combination of Covered
|
|
||||||
Software with a work governed by one or more Secondary Licenses, and the
|
|
||||||
Covered Software is not Incompatible With Secondary Licenses, this
|
|
||||||
License permits You to additionally distribute such Covered Software
|
|
||||||
under the terms of such Secondary License(s), so that the recipient of
|
|
||||||
the Larger Work may, at their option, further distribute the Covered
|
|
||||||
Software under the terms of either this License or such Secondary
|
|
||||||
License(s).
|
|
||||||
|
|
||||||
3.4. Notices
|
|
||||||
|
|
||||||
You may not remove or alter the substance of any license notices
|
|
||||||
(including copyright notices, patent notices, disclaimers of warranty, or
|
|
||||||
limitations of liability) contained within the Source Code Form of the
|
|
||||||
Covered Software, except that You may alter any license notices to the
|
|
||||||
extent required to remedy known factual inaccuracies.
|
|
||||||
|
|
||||||
3.5. Application of Additional Terms
|
|
||||||
|
|
||||||
You may choose to offer, and to charge a fee for, warranty, support,
|
|
||||||
indemnity or liability obligations to one or more recipients of Covered
|
|
||||||
Software. However, You may do so only on Your own behalf, and not on
|
|
||||||
behalf of any Contributor. You must make it absolutely clear that any
|
|
||||||
such warranty, support, indemnity, or liability obligation is offered by
|
|
||||||
You alone, and You hereby agree to indemnify every Contributor for any
|
|
||||||
liability incurred by such Contributor as a result of warranty, support,
|
|
||||||
indemnity or liability terms You offer. You may include additional
|
|
||||||
disclaimers of warranty and limitations of liability specific to any
|
|
||||||
jurisdiction.
|
|
||||||
|
|
||||||
4. Inability to Comply Due to Statute or Regulation
|
|
||||||
|
|
||||||
If it is impossible for You to comply with any of the terms of this License
|
|
||||||
with respect to some or all of the Covered Software due to statute,
|
|
||||||
judicial order, or regulation then You must: (a) comply with the terms of
|
|
||||||
this License to the maximum extent possible; and (b) describe the
|
|
||||||
limitations and the code they affect. Such description must be placed in a
|
|
||||||
text file included with all distributions of the Covered Software under
|
|
||||||
this License. Except to the extent prohibited by statute or regulation,
|
|
||||||
such description must be sufficiently detailed for a recipient of ordinary
|
|
||||||
skill to be able to understand it.
|
|
||||||
|
|
||||||
5. Termination
|
|
||||||
|
|
||||||
5.1. The rights granted under this License will terminate automatically if You
|
|
||||||
fail to comply with any of its terms. However, if You become compliant,
|
|
||||||
then the rights granted under this License from a particular Contributor
|
|
||||||
are reinstated (a) provisionally, unless and until such Contributor
|
|
||||||
explicitly and finally terminates Your grants, and (b) on an ongoing
|
|
||||||
basis, if such Contributor fails to notify You of the non-compliance by
|
|
||||||
some reasonable means prior to 60 days after You have come back into
|
|
||||||
compliance. Moreover, Your grants from a particular Contributor are
|
|
||||||
reinstated on an ongoing basis if such Contributor notifies You of the
|
|
||||||
non-compliance by some reasonable means, this is the first time You have
|
|
||||||
received notice of non-compliance with this License from such
|
|
||||||
Contributor, and You become compliant prior to 30 days after Your receipt
|
|
||||||
of the notice.
|
|
||||||
|
|
||||||
5.2. If You initiate litigation against any entity by asserting a patent
|
|
||||||
infringement claim (excluding declaratory judgment actions,
|
|
||||||
counter-claims, and cross-claims) alleging that a Contributor Version
|
|
||||||
directly or indirectly infringes any patent, then the rights granted to
|
|
||||||
You by any and all Contributors for the Covered Software under Section
|
|
||||||
2.1 of this License shall terminate.
|
|
||||||
|
|
||||||
5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
|
|
||||||
license agreements (excluding distributors and resellers) which have been
|
|
||||||
validly granted by You or Your distributors under this License prior to
|
|
||||||
termination shall survive termination.
|
|
||||||
|
|
||||||
6. Disclaimer of Warranty
|
|
||||||
|
|
||||||
Covered Software is provided under this License on an "as is" basis,
|
|
||||||
without warranty of any kind, either expressed, implied, or statutory,
|
|
||||||
including, without limitation, warranties that the Covered Software is free
|
|
||||||
of defects, merchantable, fit for a particular purpose or non-infringing.
|
|
||||||
The entire risk as to the quality and performance of the Covered Software
|
|
||||||
is with You. Should any Covered Software prove defective in any respect,
|
|
||||||
You (not any Contributor) assume the cost of any necessary servicing,
|
|
||||||
repair, or correction. This disclaimer of warranty constitutes an essential
|
|
||||||
part of this License. No use of any Covered Software is authorized under
|
|
||||||
this License except under this disclaimer.
|
|
||||||
|
|
||||||
7. Limitation of Liability
|
|
||||||
|
|
||||||
Under no circumstances and under no legal theory, whether tort (including
|
|
||||||
negligence), contract, or otherwise, shall any Contributor, or anyone who
|
|
||||||
distributes Covered Software as permitted above, be liable to You for any
|
|
||||||
direct, indirect, special, incidental, or consequential damages of any
|
|
||||||
character including, without limitation, damages for lost profits, loss of
|
|
||||||
goodwill, work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses, even if such party shall have been
|
|
||||||
informed of the possibility of such damages. This limitation of liability
|
|
||||||
shall not apply to liability for death or personal injury resulting from
|
|
||||||
such party's negligence to the extent applicable law prohibits such
|
|
||||||
limitation. Some jurisdictions do not allow the exclusion or limitation of
|
|
||||||
incidental or consequential damages, so this exclusion and limitation may
|
|
||||||
not apply to You.
|
|
||||||
|
|
||||||
8. Litigation
|
|
||||||
|
|
||||||
Any litigation relating to this License may be brought only in the courts
|
|
||||||
of a jurisdiction where the defendant maintains its principal place of
|
|
||||||
business and such litigation shall be governed by laws of that
|
|
||||||
jurisdiction, without reference to its conflict-of-law provisions. Nothing
|
|
||||||
in this Section shall prevent a party's ability to bring cross-claims or
|
|
||||||
counter-claims.
|
|
||||||
|
|
||||||
9. Miscellaneous
|
|
||||||
|
|
||||||
This License represents the complete agreement concerning the subject
|
|
||||||
matter hereof. If any provision of this License is held to be
|
|
||||||
unenforceable, such provision shall be reformed only to the extent
|
|
||||||
necessary to make it enforceable. Any law or regulation which provides that
|
|
||||||
the language of a contract shall be construed against the drafter shall not
|
|
||||||
be used to construe this License against a Contributor.
|
|
||||||
|
|
||||||
|
|
||||||
10. Versions of the License
|
|
||||||
|
|
||||||
10.1. New Versions
|
|
||||||
|
|
||||||
Mozilla Foundation is the license steward. Except as provided in Section
|
|
||||||
10.3, no one other than the license steward has the right to modify or
|
|
||||||
publish new versions of this License. Each version will be given a
|
|
||||||
distinguishing version number.
|
|
||||||
|
|
||||||
10.2. Effect of New Versions
|
|
||||||
|
|
||||||
You may distribute the Covered Software under the terms of the version
|
|
||||||
of the License under which You originally received the Covered Software,
|
|
||||||
or under the terms of any subsequent version published by the license
|
|
||||||
steward.
|
|
||||||
|
|
||||||
10.3. Modified Versions
|
|
||||||
|
|
||||||
If you create software not governed by this License, and you want to
|
|
||||||
create a new license for such software, you may create and use a
|
|
||||||
modified version of this License if you rename the license and remove
|
|
||||||
any references to the name of the license steward (except to note that
|
|
||||||
such modified license differs from this License).
|
|
||||||
|
|
||||||
10.4. Distributing Source Code Form that is Incompatible With Secondary
|
|
||||||
Licenses If You choose to distribute Source Code Form that is
|
|
||||||
Incompatible With Secondary Licenses under the terms of this version of
|
|
||||||
the License, the notice described in Exhibit B of this License must be
|
|
||||||
attached.
|
|
||||||
|
|
||||||
Exhibit A - Source Code Form License Notice
|
|
||||||
|
|
||||||
This Source Code Form is subject to the
|
|
||||||
terms of the Mozilla Public License, v.
|
|
||||||
2.0. If a copy of the MPL was not
|
|
||||||
distributed with this file, You can
|
|
||||||
obtain one at
|
|
||||||
http://mozilla.org/MPL/2.0/.
|
|
||||||
|
|
||||||
If it is not possible or desirable to put the notice in a particular file,
|
|
||||||
then You may include the notice in a location (such as a LICENSE file in a
|
|
||||||
relevant directory) where a recipient would be likely to look for such a
|
|
||||||
notice.
|
|
||||||
|
|
||||||
You may add additional accurate notices of copyright ownership.
|
|
||||||
|
|
||||||
Exhibit B - "Incompatible With Secondary Licenses" Notice
|
|
||||||
|
|
||||||
This Source Code Form is "Incompatible
|
|
||||||
With Secondary Licenses", as defined by
|
|
||||||
the Mozilla Public License, v. 2.0.
|
|
||||||
|
|
30
vendor/github.com/hashicorp/go-cleanhttp/README.md
generated
vendored
30
vendor/github.com/hashicorp/go-cleanhttp/README.md
generated
vendored
|
@ -1,30 +0,0 @@
|
||||||
# cleanhttp
|
|
||||||
|
|
||||||
Functions for accessing "clean" Go http.Client values
|
|
||||||
|
|
||||||
-------------
|
|
||||||
|
|
||||||
The Go standard library contains a default `http.Client` called
|
|
||||||
`http.DefaultClient`. It is a common idiom in Go code to start with
|
|
||||||
`http.DefaultClient` and tweak it as necessary, and in fact, this is
|
|
||||||
encouraged; from the `http` package documentation:
|
|
||||||
|
|
||||||
> The Client's Transport typically has internal state (cached TCP connections),
|
|
||||||
so Clients should be reused instead of created as needed. Clients are safe for
|
|
||||||
concurrent use by multiple goroutines.
|
|
||||||
|
|
||||||
Unfortunately, this is a shared value, and it is not uncommon for libraries to
|
|
||||||
assume that they are free to modify it at will. With enough dependencies, it
|
|
||||||
can be very easy to encounter strange problems and race conditions due to
|
|
||||||
manipulation of this shared value across libraries and goroutines (clients are
|
|
||||||
safe for concurrent use, but writing values to the client struct itself is not
|
|
||||||
protected).
|
|
||||||
|
|
||||||
Making things worse is the fact that a bare `http.Client` will use a default
|
|
||||||
`http.Transport` called `http.DefaultTransport`, which is another global value
|
|
||||||
that behaves the same way. So it is not simply enough to replace
|
|
||||||
`http.DefaultClient` with `&http.Client{}`.
|
|
||||||
|
|
||||||
This repository provides some simple functions to get a "clean" `http.Client`
|
|
||||||
-- one that uses the same default values as the Go standard library, but
|
|
||||||
returns a client that does not share any state with other clients.
|
|
53
vendor/github.com/hashicorp/go-cleanhttp/cleanhttp.go
generated
vendored
53
vendor/github.com/hashicorp/go-cleanhttp/cleanhttp.go
generated
vendored
|
@ -1,53 +0,0 @@
|
||||||
package cleanhttp
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
"net/http"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// DefaultTransport returns a new http.Transport with the same default values
|
|
||||||
// as http.DefaultTransport, but with idle connections and keepalives disabled.
|
|
||||||
func DefaultTransport() *http.Transport {
|
|
||||||
transport := DefaultPooledTransport()
|
|
||||||
transport.DisableKeepAlives = true
|
|
||||||
transport.MaxIdleConnsPerHost = -1
|
|
||||||
return transport
|
|
||||||
}
|
|
||||||
|
|
||||||
// DefaultPooledTransport returns a new http.Transport with similar default
|
|
||||||
// values to http.DefaultTransport. Do not use this for transient transports as
|
|
||||||
// it can leak file descriptors over time. Only use this for transports that
|
|
||||||
// will be re-used for the same host(s).
|
|
||||||
func DefaultPooledTransport() *http.Transport {
|
|
||||||
transport := &http.Transport{
|
|
||||||
Proxy: http.ProxyFromEnvironment,
|
|
||||||
Dial: (&net.Dialer{
|
|
||||||
Timeout: 30 * time.Second,
|
|
||||||
KeepAlive: 30 * time.Second,
|
|
||||||
}).Dial,
|
|
||||||
TLSHandshakeTimeout: 10 * time.Second,
|
|
||||||
DisableKeepAlives: false,
|
|
||||||
MaxIdleConnsPerHost: 1,
|
|
||||||
}
|
|
||||||
return transport
|
|
||||||
}
|
|
||||||
|
|
||||||
// DefaultClient returns a new http.Client with similar default values to
|
|
||||||
// http.Client, but with a non-shared Transport, idle connections disabled, and
|
|
||||||
// keepalives disabled.
|
|
||||||
func DefaultClient() *http.Client {
|
|
||||||
return &http.Client{
|
|
||||||
Transport: DefaultTransport(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DefaultPooledClient returns a new http.Client with the same default values
|
|
||||||
// as http.Client, but with a shared Transport. Do not use this function
|
|
||||||
// for transient clients as it can leak file descriptors over time. Only use
|
|
||||||
// this for clients that will be re-used for the same host(s).
|
|
||||||
func DefaultPooledClient() *http.Client {
|
|
||||||
return &http.Client{
|
|
||||||
Transport: DefaultPooledTransport(),
|
|
||||||
}
|
|
||||||
}
|
|
20
vendor/github.com/hashicorp/go-cleanhttp/doc.go
generated
vendored
20
vendor/github.com/hashicorp/go-cleanhttp/doc.go
generated
vendored
|
@ -1,20 +0,0 @@
|
||||||
// Package cleanhttp offers convenience utilities for acquiring "clean"
|
|
||||||
// http.Transport and http.Client structs.
|
|
||||||
//
|
|
||||||
// Values set on http.DefaultClient and http.DefaultTransport affect all
|
|
||||||
// callers. This can have detrimental effects, esepcially in TLS contexts,
|
|
||||||
// where client or root certificates set to talk to multiple endpoints can end
|
|
||||||
// up displacing each other, leading to hard-to-debug issues. This package
|
|
||||||
// provides non-shared http.Client and http.Transport structs to ensure that
|
|
||||||
// the configuration will not be overwritten by other parts of the application
|
|
||||||
// or dependencies.
|
|
||||||
//
|
|
||||||
// The DefaultClient and DefaultTransport functions disable idle connections
|
|
||||||
// and keepalives. Without ensuring that idle connections are closed before
|
|
||||||
// garbage collection, short-term clients/transports can leak file descriptors,
|
|
||||||
// eventually leading to "too many open files" errors. If you will be
|
|
||||||
// connecting to the same hosts repeatedly from the same client, you can use
|
|
||||||
// DefaultPooledClient to receive a client that has connection pooling
|
|
||||||
// semantics similar to http.DefaultClient.
|
|
||||||
//
|
|
||||||
package cleanhttp
|
|
353
vendor/github.com/hashicorp/go-multierror/LICENSE
generated
vendored
353
vendor/github.com/hashicorp/go-multierror/LICENSE
generated
vendored
|
@ -1,353 +0,0 @@
|
||||||
Mozilla Public License, version 2.0
|
|
||||||
|
|
||||||
1. Definitions
|
|
||||||
|
|
||||||
1.1. “Contributor”
|
|
||||||
|
|
||||||
means each individual or legal entity that creates, contributes to the
|
|
||||||
creation of, or owns Covered Software.
|
|
||||||
|
|
||||||
1.2. “Contributor Version”
|
|
||||||
|
|
||||||
means the combination of the Contributions of others (if any) used by a
|
|
||||||
Contributor and that particular Contributor’s Contribution.
|
|
||||||
|
|
||||||
1.3. “Contribution”
|
|
||||||
|
|
||||||
means Covered Software of a particular Contributor.
|
|
||||||
|
|
||||||
1.4. “Covered Software”
|
|
||||||
|
|
||||||
means Source Code Form to which the initial Contributor has attached the
|
|
||||||
notice in Exhibit A, the Executable Form of such Source Code Form, and
|
|
||||||
Modifications of such Source Code Form, in each case including portions
|
|
||||||
thereof.
|
|
||||||
|
|
||||||
1.5. “Incompatible With Secondary Licenses”
|
|
||||||
means
|
|
||||||
|
|
||||||
a. that the initial Contributor has attached the notice described in
|
|
||||||
Exhibit B to the Covered Software; or
|
|
||||||
|
|
||||||
b. that the Covered Software was made available under the terms of version
|
|
||||||
1.1 or earlier of the License, but not also under the terms of a
|
|
||||||
Secondary License.
|
|
||||||
|
|
||||||
1.6. “Executable Form”
|
|
||||||
|
|
||||||
means any form of the work other than Source Code Form.
|
|
||||||
|
|
||||||
1.7. “Larger Work”
|
|
||||||
|
|
||||||
means a work that combines Covered Software with other material, in a separate
|
|
||||||
file or files, that is not Covered Software.
|
|
||||||
|
|
||||||
1.8. “License”
|
|
||||||
|
|
||||||
means this document.
|
|
||||||
|
|
||||||
1.9. “Licensable”
|
|
||||||
|
|
||||||
means having the right to grant, to the maximum extent possible, whether at the
|
|
||||||
time of the initial grant or subsequently, any and all of the rights conveyed by
|
|
||||||
this License.
|
|
||||||
|
|
||||||
1.10. “Modifications”
|
|
||||||
|
|
||||||
means any of the following:
|
|
||||||
|
|
||||||
a. any file in Source Code Form that results from an addition to, deletion
|
|
||||||
from, or modification of the contents of Covered Software; or
|
|
||||||
|
|
||||||
b. any new file in Source Code Form that contains any Covered Software.
|
|
||||||
|
|
||||||
1.11. “Patent Claims” of a Contributor
|
|
||||||
|
|
||||||
means any patent claim(s), including without limitation, method, process,
|
|
||||||
and apparatus claims, in any patent Licensable by such Contributor that
|
|
||||||
would be infringed, but for the grant of the License, by the making,
|
|
||||||
using, selling, offering for sale, having made, import, or transfer of
|
|
||||||
either its Contributions or its Contributor Version.
|
|
||||||
|
|
||||||
1.12. “Secondary License”
|
|
||||||
|
|
||||||
means either the GNU General Public License, Version 2.0, the GNU Lesser
|
|
||||||
General Public License, Version 2.1, the GNU Affero General Public
|
|
||||||
License, Version 3.0, or any later versions of those licenses.
|
|
||||||
|
|
||||||
1.13. “Source Code Form”
|
|
||||||
|
|
||||||
means the form of the work preferred for making modifications.
|
|
||||||
|
|
||||||
1.14. “You” (or “Your”)
|
|
||||||
|
|
||||||
means an individual or a legal entity exercising rights under this
|
|
||||||
License. For legal entities, “You” includes any entity that controls, is
|
|
||||||
controlled by, or is under common control with You. For purposes of this
|
|
||||||
definition, “control” means (a) the power, direct or indirect, to cause
|
|
||||||
the direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (b) ownership of more than fifty percent (50%) of the
|
|
||||||
outstanding shares or beneficial ownership of such entity.
|
|
||||||
|
|
||||||
|
|
||||||
2. License Grants and Conditions
|
|
||||||
|
|
||||||
2.1. Grants
|
|
||||||
|
|
||||||
Each Contributor hereby grants You a world-wide, royalty-free,
|
|
||||||
non-exclusive license:
|
|
||||||
|
|
||||||
a. under intellectual property rights (other than patent or trademark)
|
|
||||||
Licensable by such Contributor to use, reproduce, make available,
|
|
||||||
modify, display, perform, distribute, and otherwise exploit its
|
|
||||||
Contributions, either on an unmodified basis, with Modifications, or as
|
|
||||||
part of a Larger Work; and
|
|
||||||
|
|
||||||
b. under Patent Claims of such Contributor to make, use, sell, offer for
|
|
||||||
sale, have made, import, and otherwise transfer either its Contributions
|
|
||||||
or its Contributor Version.
|
|
||||||
|
|
||||||
2.2. Effective Date
|
|
||||||
|
|
||||||
The licenses granted in Section 2.1 with respect to any Contribution become
|
|
||||||
effective for each Contribution on the date the Contributor first distributes
|
|
||||||
such Contribution.
|
|
||||||
|
|
||||||
2.3. Limitations on Grant Scope
|
|
||||||
|
|
||||||
The licenses granted in this Section 2 are the only rights granted under this
|
|
||||||
License. No additional rights or licenses will be implied from the distribution
|
|
||||||
or licensing of Covered Software under this License. Notwithstanding Section
|
|
||||||
2.1(b) above, no patent license is granted by a Contributor:
|
|
||||||
|
|
||||||
a. for any code that a Contributor has removed from Covered Software; or
|
|
||||||
|
|
||||||
b. for infringements caused by: (i) Your and any other third party’s
|
|
||||||
modifications of Covered Software, or (ii) the combination of its
|
|
||||||
Contributions with other software (except as part of its Contributor
|
|
||||||
Version); or
|
|
||||||
|
|
||||||
c. under Patent Claims infringed by Covered Software in the absence of its
|
|
||||||
Contributions.
|
|
||||||
|
|
||||||
This License does not grant any rights in the trademarks, service marks, or
|
|
||||||
logos of any Contributor (except as may be necessary to comply with the
|
|
||||||
notice requirements in Section 3.4).
|
|
||||||
|
|
||||||
2.4. Subsequent Licenses
|
|
||||||
|
|
||||||
No Contributor makes additional grants as a result of Your choice to
|
|
||||||
distribute the Covered Software under a subsequent version of this License
|
|
||||||
(see Section 10.2) or under the terms of a Secondary License (if permitted
|
|
||||||
under the terms of Section 3.3).
|
|
||||||
|
|
||||||
2.5. Representation
|
|
||||||
|
|
||||||
Each Contributor represents that the Contributor believes its Contributions
|
|
||||||
are its original creation(s) or it has sufficient rights to grant the
|
|
||||||
rights to its Contributions conveyed by this License.
|
|
||||||
|
|
||||||
2.6. Fair Use
|
|
||||||
|
|
||||||
This License is not intended to limit any rights You have under applicable
|
|
||||||
copyright doctrines of fair use, fair dealing, or other equivalents.
|
|
||||||
|
|
||||||
2.7. Conditions
|
|
||||||
|
|
||||||
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
|
|
||||||
Section 2.1.
|
|
||||||
|
|
||||||
|
|
||||||
3. Responsibilities
|
|
||||||
|
|
||||||
3.1. Distribution of Source Form
|
|
||||||
|
|
||||||
All distribution of Covered Software in Source Code Form, including any
|
|
||||||
Modifications that You create or to which You contribute, must be under the
|
|
||||||
terms of this License. You must inform recipients that the Source Code Form
|
|
||||||
of the Covered Software is governed by the terms of this License, and how
|
|
||||||
they can obtain a copy of this License. You may not attempt to alter or
|
|
||||||
restrict the recipients’ rights in the Source Code Form.
|
|
||||||
|
|
||||||
3.2. Distribution of Executable Form
|
|
||||||
|
|
||||||
If You distribute Covered Software in Executable Form then:
|
|
||||||
|
|
||||||
a. such Covered Software must also be made available in Source Code Form,
|
|
||||||
as described in Section 3.1, and You must inform recipients of the
|
|
||||||
Executable Form how they can obtain a copy of such Source Code Form by
|
|
||||||
reasonable means in a timely manner, at a charge no more than the cost
|
|
||||||
of distribution to the recipient; and
|
|
||||||
|
|
||||||
b. You may distribute such Executable Form under the terms of this License,
|
|
||||||
or sublicense it under different terms, provided that the license for
|
|
||||||
the Executable Form does not attempt to limit or alter the recipients’
|
|
||||||
rights in the Source Code Form under this License.
|
|
||||||
|
|
||||||
3.3. Distribution of a Larger Work
|
|
||||||
|
|
||||||
You may create and distribute a Larger Work under terms of Your choice,
|
|
||||||
provided that You also comply with the requirements of this License for the
|
|
||||||
Covered Software. If the Larger Work is a combination of Covered Software
|
|
||||||
with a work governed by one or more Secondary Licenses, and the Covered
|
|
||||||
Software is not Incompatible With Secondary Licenses, this License permits
|
|
||||||
You to additionally distribute such Covered Software under the terms of
|
|
||||||
such Secondary License(s), so that the recipient of the Larger Work may, at
|
|
||||||
their option, further distribute the Covered Software under the terms of
|
|
||||||
either this License or such Secondary License(s).
|
|
||||||
|
|
||||||
3.4. Notices
|
|
||||||
|
|
||||||
You may not remove or alter the substance of any license notices (including
|
|
||||||
copyright notices, patent notices, disclaimers of warranty, or limitations
|
|
||||||
of liability) contained within the Source Code Form of the Covered
|
|
||||||
Software, except that You may alter any license notices to the extent
|
|
||||||
required to remedy known factual inaccuracies.
|
|
||||||
|
|
||||||
3.5. Application of Additional Terms
|
|
||||||
|
|
||||||
You may choose to offer, and to charge a fee for, warranty, support,
|
|
||||||
indemnity or liability obligations to one or more recipients of Covered
|
|
||||||
Software. However, You may do so only on Your own behalf, and not on behalf
|
|
||||||
of any Contributor. You must make it absolutely clear that any such
|
|
||||||
warranty, support, indemnity, or liability obligation is offered by You
|
|
||||||
alone, and You hereby agree to indemnify every Contributor for any
|
|
||||||
liability incurred by such Contributor as a result of warranty, support,
|
|
||||||
indemnity or liability terms You offer. You may include additional
|
|
||||||
disclaimers of warranty and limitations of liability specific to any
|
|
||||||
jurisdiction.
|
|
||||||
|
|
||||||
4. Inability to Comply Due to Statute or Regulation
|
|
||||||
|
|
||||||
If it is impossible for You to comply with any of the terms of this License
|
|
||||||
with respect to some or all of the Covered Software due to statute, judicial
|
|
||||||
order, or regulation then You must: (a) comply with the terms of this License
|
|
||||||
to the maximum extent possible; and (b) describe the limitations and the code
|
|
||||||
they affect. Such description must be placed in a text file included with all
|
|
||||||
distributions of the Covered Software under this License. Except to the
|
|
||||||
extent prohibited by statute or regulation, such description must be
|
|
||||||
sufficiently detailed for a recipient of ordinary skill to be able to
|
|
||||||
understand it.
|
|
||||||
|
|
||||||
5. Termination
|
|
||||||
|
|
||||||
5.1. The rights granted under this License will terminate automatically if You
|
|
||||||
fail to comply with any of its terms. However, if You become compliant,
|
|
||||||
then the rights granted under this License from a particular Contributor
|
|
||||||
are reinstated (a) provisionally, unless and until such Contributor
|
|
||||||
explicitly and finally terminates Your grants, and (b) on an ongoing basis,
|
|
||||||
if such Contributor fails to notify You of the non-compliance by some
|
|
||||||
reasonable means prior to 60 days after You have come back into compliance.
|
|
||||||
Moreover, Your grants from a particular Contributor are reinstated on an
|
|
||||||
ongoing basis if such Contributor notifies You of the non-compliance by
|
|
||||||
some reasonable means, this is the first time You have received notice of
|
|
||||||
non-compliance with this License from such Contributor, and You become
|
|
||||||
compliant prior to 30 days after Your receipt of the notice.
|
|
||||||
|
|
||||||
5.2. If You initiate litigation against any entity by asserting a patent
|
|
||||||
infringement claim (excluding declaratory judgment actions, counter-claims,
|
|
||||||
and cross-claims) alleging that a Contributor Version directly or
|
|
||||||
indirectly infringes any patent, then the rights granted to You by any and
|
|
||||||
all Contributors for the Covered Software under Section 2.1 of this License
|
|
||||||
shall terminate.
|
|
||||||
|
|
||||||
5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
|
|
||||||
license agreements (excluding distributors and resellers) which have been
|
|
||||||
validly granted by You or Your distributors under this License prior to
|
|
||||||
termination shall survive termination.
|
|
||||||
|
|
||||||
6. Disclaimer of Warranty
|
|
||||||
|
|
||||||
Covered Software is provided under this License on an “as is” basis, without
|
|
||||||
warranty of any kind, either expressed, implied, or statutory, including,
|
|
||||||
without limitation, warranties that the Covered Software is free of defects,
|
|
||||||
merchantable, fit for a particular purpose or non-infringing. The entire
|
|
||||||
risk as to the quality and performance of the Covered Software is with You.
|
|
||||||
Should any Covered Software prove defective in any respect, You (not any
|
|
||||||
Contributor) assume the cost of any necessary servicing, repair, or
|
|
||||||
correction. This disclaimer of warranty constitutes an essential part of this
|
|
||||||
License. No use of any Covered Software is authorized under this License
|
|
||||||
except under this disclaimer.
|
|
||||||
|
|
||||||
7. Limitation of Liability
|
|
||||||
|
|
||||||
Under no circumstances and under no legal theory, whether tort (including
|
|
||||||
negligence), contract, or otherwise, shall any Contributor, or anyone who
|
|
||||||
distributes Covered Software as permitted above, be liable to You for any
|
|
||||||
direct, indirect, special, incidental, or consequential damages of any
|
|
||||||
character including, without limitation, damages for lost profits, loss of
|
|
||||||
goodwill, work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses, even if such party shall have been
|
|
||||||
informed of the possibility of such damages. This limitation of liability
|
|
||||||
shall not apply to liability for death or personal injury resulting from such
|
|
||||||
party’s negligence to the extent applicable law prohibits such limitation.
|
|
||||||
Some jurisdictions do not allow the exclusion or limitation of incidental or
|
|
||||||
consequential damages, so this exclusion and limitation may not apply to You.
|
|
||||||
|
|
||||||
8. Litigation
|
|
||||||
|
|
||||||
Any litigation relating to this License may be brought only in the courts of
|
|
||||||
a jurisdiction where the defendant maintains its principal place of business
|
|
||||||
and such litigation shall be governed by laws of that jurisdiction, without
|
|
||||||
reference to its conflict-of-law provisions. Nothing in this Section shall
|
|
||||||
prevent a party’s ability to bring cross-claims or counter-claims.
|
|
||||||
|
|
||||||
9. Miscellaneous
|
|
||||||
|
|
||||||
This License represents the complete agreement concerning the subject matter
|
|
||||||
hereof. If any provision of this License is held to be unenforceable, such
|
|
||||||
provision shall be reformed only to the extent necessary to make it
|
|
||||||
enforceable. Any law or regulation which provides that the language of a
|
|
||||||
contract shall be construed against the drafter shall not be used to construe
|
|
||||||
this License against a Contributor.
|
|
||||||
|
|
||||||
|
|
||||||
10. Versions of the License
|
|
||||||
|
|
||||||
10.1. New Versions
|
|
||||||
|
|
||||||
Mozilla Foundation is the license steward. Except as provided in Section
|
|
||||||
10.3, no one other than the license steward has the right to modify or
|
|
||||||
publish new versions of this License. Each version will be given a
|
|
||||||
distinguishing version number.
|
|
||||||
|
|
||||||
10.2. Effect of New Versions
|
|
||||||
|
|
||||||
You may distribute the Covered Software under the terms of the version of
|
|
||||||
the License under which You originally received the Covered Software, or
|
|
||||||
under the terms of any subsequent version published by the license
|
|
||||||
steward.
|
|
||||||
|
|
||||||
10.3. Modified Versions
|
|
||||||
|
|
||||||
If you create software not governed by this License, and you want to
|
|
||||||
create a new license for such software, you may create and use a modified
|
|
||||||
version of this License if you rename the license and remove any
|
|
||||||
references to the name of the license steward (except to note that such
|
|
||||||
modified license differs from this License).
|
|
||||||
|
|
||||||
10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses
|
|
||||||
If You choose to distribute Source Code Form that is Incompatible With
|
|
||||||
Secondary Licenses under the terms of this version of the License, the
|
|
||||||
notice described in Exhibit B of this License must be attached.
|
|
||||||
|
|
||||||
Exhibit A - Source Code Form License Notice
|
|
||||||
|
|
||||||
This Source Code Form is subject to the
|
|
||||||
terms of the Mozilla Public License, v.
|
|
||||||
2.0. If a copy of the MPL was not
|
|
||||||
distributed with this file, You can
|
|
||||||
obtain one at
|
|
||||||
http://mozilla.org/MPL/2.0/.
|
|
||||||
|
|
||||||
If it is not possible or desirable to put the notice in a particular file, then
|
|
||||||
You may include the notice in a location (such as a LICENSE file in a relevant
|
|
||||||
directory) where a recipient would be likely to look for such a notice.
|
|
||||||
|
|
||||||
You may add additional accurate notices of copyright ownership.
|
|
||||||
|
|
||||||
Exhibit B - “Incompatible With Secondary Licenses” Notice
|
|
||||||
|
|
||||||
This Source Code Form is “Incompatible
|
|
||||||
With Secondary Licenses”, as defined by
|
|
||||||
the Mozilla Public License, v. 2.0.
|
|
91
vendor/github.com/hashicorp/go-multierror/README.md
generated
vendored
91
vendor/github.com/hashicorp/go-multierror/README.md
generated
vendored
|
@ -1,91 +0,0 @@
|
||||||
# go-multierror
|
|
||||||
|
|
||||||
`go-multierror` is a package for Go that provides a mechanism for
|
|
||||||
representing a list of `error` values as a single `error`.
|
|
||||||
|
|
||||||
This allows a function in Go to return an `error` that might actually
|
|
||||||
be a list of errors. If the caller knows this, they can unwrap the
|
|
||||||
list and access the errors. If the caller doesn't know, the error
|
|
||||||
formats to a nice human-readable format.
|
|
||||||
|
|
||||||
`go-multierror` implements the
|
|
||||||
[errwrap](https://github.com/hashicorp/errwrap) interface so that it can
|
|
||||||
be used with that library, as well.
|
|
||||||
|
|
||||||
## Installation and Docs
|
|
||||||
|
|
||||||
Install using `go get github.com/hashicorp/go-multierror`.
|
|
||||||
|
|
||||||
Full documentation is available at
|
|
||||||
http://godoc.org/github.com/hashicorp/go-multierror
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
go-multierror is easy to use and purposely built to be unobtrusive in
|
|
||||||
existing Go applications/libraries that may not be aware of it.
|
|
||||||
|
|
||||||
**Building a list of errors**
|
|
||||||
|
|
||||||
The `Append` function is used to create a list of errors. This function
|
|
||||||
behaves a lot like the Go built-in `append` function: it doesn't matter
|
|
||||||
if the first argument is nil, a `multierror.Error`, or any other `error`,
|
|
||||||
the function behaves as you would expect.
|
|
||||||
|
|
||||||
```go
|
|
||||||
var result error
|
|
||||||
|
|
||||||
if err := step1(); err != nil {
|
|
||||||
result = multierror.Append(result, err)
|
|
||||||
}
|
|
||||||
if err := step2(); err != nil {
|
|
||||||
result = multierror.Append(result, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
```
|
|
||||||
|
|
||||||
**Customizing the formatting of the errors**
|
|
||||||
|
|
||||||
By specifying a custom `ErrorFormat`, you can customize the format
|
|
||||||
of the `Error() string` function:
|
|
||||||
|
|
||||||
```go
|
|
||||||
var result *multierror.Error
|
|
||||||
|
|
||||||
// ... accumulate errors here, maybe using Append
|
|
||||||
|
|
||||||
if result != nil {
|
|
||||||
result.ErrorFormat = func([]error) string {
|
|
||||||
return "errors!"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Accessing the list of errors**
|
|
||||||
|
|
||||||
`multierror.Error` implements `error` so if the caller doesn't know about
|
|
||||||
multierror, it will work just fine. But if you're aware a multierror might
|
|
||||||
be returned, you can use type switches to access the list of errors:
|
|
||||||
|
|
||||||
```go
|
|
||||||
if err := something(); err != nil {
|
|
||||||
if merr, ok := err.(*multierror.Error); ok {
|
|
||||||
// Use merr.Errors
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Returning a multierror only if there are errors**
|
|
||||||
|
|
||||||
If you build a `multierror.Error`, you can use the `ErrorOrNil` function
|
|
||||||
to return an `error` implementation only if there are errors to return:
|
|
||||||
|
|
||||||
```go
|
|
||||||
var result *multierror.Error
|
|
||||||
|
|
||||||
// ... accumulate errors here
|
|
||||||
|
|
||||||
// Return the `error` only if errors were added to the multierror, otherwise
|
|
||||||
// return nil since there are no errors.
|
|
||||||
return result.ErrorOrNil()
|
|
||||||
```
|
|
37
vendor/github.com/hashicorp/go-multierror/append.go
generated
vendored
37
vendor/github.com/hashicorp/go-multierror/append.go
generated
vendored
|
@ -1,37 +0,0 @@
|
||||||
package multierror
|
|
||||||
|
|
||||||
// Append is a helper function that will append more errors
|
|
||||||
// onto an Error in order to create a larger multi-error.
|
|
||||||
//
|
|
||||||
// If err is not a multierror.Error, then it will be turned into
|
|
||||||
// one. If any of the errs are multierr.Error, they will be flattened
|
|
||||||
// one level into err.
|
|
||||||
func Append(err error, errs ...error) *Error {
|
|
||||||
switch err := err.(type) {
|
|
||||||
case *Error:
|
|
||||||
// Typed nils can reach here, so initialize if we are nil
|
|
||||||
if err == nil {
|
|
||||||
err = new(Error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Go through each error and flatten
|
|
||||||
for _, e := range errs {
|
|
||||||
switch e := e.(type) {
|
|
||||||
case *Error:
|
|
||||||
err.Errors = append(err.Errors, e.Errors...)
|
|
||||||
default:
|
|
||||||
err.Errors = append(err.Errors, e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
default:
|
|
||||||
newErrs := make([]error, 0, len(errs)+1)
|
|
||||||
if err != nil {
|
|
||||||
newErrs = append(newErrs, err)
|
|
||||||
}
|
|
||||||
newErrs = append(newErrs, errs...)
|
|
||||||
|
|
||||||
return Append(&Error{}, newErrs...)
|
|
||||||
}
|
|
||||||
}
|
|
26
vendor/github.com/hashicorp/go-multierror/flatten.go
generated
vendored
26
vendor/github.com/hashicorp/go-multierror/flatten.go
generated
vendored
|
@ -1,26 +0,0 @@
|
||||||
package multierror
|
|
||||||
|
|
||||||
// Flatten flattens the given error, merging any *Errors together into
|
|
||||||
// a single *Error.
|
|
||||||
func Flatten(err error) error {
|
|
||||||
// If it isn't an *Error, just return the error as-is
|
|
||||||
if _, ok := err.(*Error); !ok {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, make the result and flatten away!
|
|
||||||
flatErr := new(Error)
|
|
||||||
flatten(err, flatErr)
|
|
||||||
return flatErr
|
|
||||||
}
|
|
||||||
|
|
||||||
func flatten(err error, flatErr *Error) {
|
|
||||||
switch err := err.(type) {
|
|
||||||
case *Error:
|
|
||||||
for _, e := range err.Errors {
|
|
||||||
flatten(e, flatErr)
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
flatErr.Errors = append(flatErr.Errors, err)
|
|
||||||
}
|
|
||||||
}
|
|
23
vendor/github.com/hashicorp/go-multierror/format.go
generated
vendored
23
vendor/github.com/hashicorp/go-multierror/format.go
generated
vendored
|
@ -1,23 +0,0 @@
|
||||||
package multierror
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ErrorFormatFunc is a function callback that is called by Error to
|
|
||||||
// turn the list of errors into a string.
|
|
||||||
type ErrorFormatFunc func([]error) string
|
|
||||||
|
|
||||||
// ListFormatFunc is a basic formatter that outputs the number of errors
|
|
||||||
// that occurred along with a bullet point list of the errors.
|
|
||||||
func ListFormatFunc(es []error) string {
|
|
||||||
points := make([]string, len(es))
|
|
||||||
for i, err := range es {
|
|
||||||
points[i] = fmt.Sprintf("* %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return fmt.Sprintf(
|
|
||||||
"%d error(s) occurred:\n\n%s",
|
|
||||||
len(es), strings.Join(points, "\n"))
|
|
||||||
}
|
|
51
vendor/github.com/hashicorp/go-multierror/multierror.go
generated
vendored
51
vendor/github.com/hashicorp/go-multierror/multierror.go
generated
vendored
|
@ -1,51 +0,0 @@
|
||||||
package multierror
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Error is an error type to track multiple errors. This is used to
|
|
||||||
// accumulate errors in cases and return them as a single "error".
|
|
||||||
type Error struct {
|
|
||||||
Errors []error
|
|
||||||
ErrorFormat ErrorFormatFunc
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Error) Error() string {
|
|
||||||
fn := e.ErrorFormat
|
|
||||||
if fn == nil {
|
|
||||||
fn = ListFormatFunc
|
|
||||||
}
|
|
||||||
|
|
||||||
return fn(e.Errors)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrorOrNil returns an error interface if this Error represents
|
|
||||||
// a list of errors, or returns nil if the list of errors is empty. This
|
|
||||||
// function is useful at the end of accumulation to make sure that the value
|
|
||||||
// returned represents the existence of errors.
|
|
||||||
func (e *Error) ErrorOrNil() error {
|
|
||||||
if e == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if len(e.Errors) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Error) GoString() string {
|
|
||||||
return fmt.Sprintf("*%#v", *e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WrappedErrors returns the list of errors that this Error is wrapping.
|
|
||||||
// It is an implementatin of the errwrap.Wrapper interface so that
|
|
||||||
// multierror.Error can be used with that library.
|
|
||||||
//
|
|
||||||
// This method is not safe to be called concurrently and is no different
|
|
||||||
// than accessing the Errors field directly. It is implementd only to
|
|
||||||
// satisfy the errwrap.Wrapper interface.
|
|
||||||
func (e *Error) WrappedErrors() []error {
|
|
||||||
return e.Errors
|
|
||||||
}
|
|
37
vendor/github.com/hashicorp/go-multierror/prefix.go
generated
vendored
37
vendor/github.com/hashicorp/go-multierror/prefix.go
generated
vendored
|
@ -1,37 +0,0 @@
|
||||||
package multierror
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/hashicorp/errwrap"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Prefix is a helper function that will prefix some text
|
|
||||||
// to the given error. If the error is a multierror.Error, then
|
|
||||||
// it will be prefixed to each wrapped error.
|
|
||||||
//
|
|
||||||
// This is useful to use when appending multiple multierrors
|
|
||||||
// together in order to give better scoping.
|
|
||||||
func Prefix(err error, prefix string) error {
|
|
||||||
if err == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
format := fmt.Sprintf("%s {{err}}", prefix)
|
|
||||||
switch err := err.(type) {
|
|
||||||
case *Error:
|
|
||||||
// Typed nils can reach here, so initialize if we are nil
|
|
||||||
if err == nil {
|
|
||||||
err = new(Error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wrap each of the errors
|
|
||||||
for i, e := range err.Errors {
|
|
||||||
err.Errors[i] = errwrap.Wrapf(format, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
default:
|
|
||||||
return errwrap.Wrapf(format, err)
|
|
||||||
}
|
|
||||||
}
|
|
12
vendor/github.com/hashicorp/go-rootcerts/.travis.yml
generated
vendored
12
vendor/github.com/hashicorp/go-rootcerts/.travis.yml
generated
vendored
|
@ -1,12 +0,0 @@
|
||||||
sudo: false
|
|
||||||
|
|
||||||
language: go
|
|
||||||
|
|
||||||
go:
|
|
||||||
- 1.6
|
|
||||||
|
|
||||||
branches:
|
|
||||||
only:
|
|
||||||
- master
|
|
||||||
|
|
||||||
script: make test
|
|
363
vendor/github.com/hashicorp/go-rootcerts/LICENSE
generated
vendored
363
vendor/github.com/hashicorp/go-rootcerts/LICENSE
generated
vendored
|
@ -1,363 +0,0 @@
|
||||||
Mozilla Public License, version 2.0
|
|
||||||
|
|
||||||
1. Definitions
|
|
||||||
|
|
||||||
1.1. "Contributor"
|
|
||||||
|
|
||||||
means each individual or legal entity that creates, contributes to the
|
|
||||||
creation of, or owns Covered Software.
|
|
||||||
|
|
||||||
1.2. "Contributor Version"
|
|
||||||
|
|
||||||
means the combination of the Contributions of others (if any) used by a
|
|
||||||
Contributor and that particular Contributor's Contribution.
|
|
||||||
|
|
||||||
1.3. "Contribution"
|
|
||||||
|
|
||||||
means Covered Software of a particular Contributor.
|
|
||||||
|
|
||||||
1.4. "Covered Software"
|
|
||||||
|
|
||||||
means Source Code Form to which the initial Contributor has attached the
|
|
||||||
notice in Exhibit A, the Executable Form of such Source Code Form, and
|
|
||||||
Modifications of such Source Code Form, in each case including portions
|
|
||||||
thereof.
|
|
||||||
|
|
||||||
1.5. "Incompatible With Secondary Licenses"
|
|
||||||
means
|
|
||||||
|
|
||||||
a. that the initial Contributor has attached the notice described in
|
|
||||||
Exhibit B to the Covered Software; or
|
|
||||||
|
|
||||||
b. that the Covered Software was made available under the terms of
|
|
||||||
version 1.1 or earlier of the License, but not also under the terms of
|
|
||||||
a Secondary License.
|
|
||||||
|
|
||||||
1.6. "Executable Form"
|
|
||||||
|
|
||||||
means any form of the work other than Source Code Form.
|
|
||||||
|
|
||||||
1.7. "Larger Work"
|
|
||||||
|
|
||||||
means a work that combines Covered Software with other material, in a
|
|
||||||
separate file or files, that is not Covered Software.
|
|
||||||
|
|
||||||
1.8. "License"
|
|
||||||
|
|
||||||
means this document.
|
|
||||||
|
|
||||||
1.9. "Licensable"
|
|
||||||
|
|
||||||
means having the right to grant, to the maximum extent possible, whether
|
|
||||||
at the time of the initial grant or subsequently, any and all of the
|
|
||||||
rights conveyed by this License.
|
|
||||||
|
|
||||||
1.10. "Modifications"
|
|
||||||
|
|
||||||
means any of the following:
|
|
||||||
|
|
||||||
a. any file in Source Code Form that results from an addition to,
|
|
||||||
deletion from, or modification of the contents of Covered Software; or
|
|
||||||
|
|
||||||
b. any new file in Source Code Form that contains any Covered Software.
|
|
||||||
|
|
||||||
1.11. "Patent Claims" of a Contributor
|
|
||||||
|
|
||||||
means any patent claim(s), including without limitation, method,
|
|
||||||
process, and apparatus claims, in any patent Licensable by such
|
|
||||||
Contributor that would be infringed, but for the grant of the License,
|
|
||||||
by the making, using, selling, offering for sale, having made, import,
|
|
||||||
or transfer of either its Contributions or its Contributor Version.
|
|
||||||
|
|
||||||
1.12. "Secondary License"
|
|
||||||
|
|
||||||
means either the GNU General Public License, Version 2.0, the GNU Lesser
|
|
||||||
General Public License, Version 2.1, the GNU Affero General Public
|
|
||||||
License, Version 3.0, or any later versions of those licenses.
|
|
||||||
|
|
||||||
1.13. "Source Code Form"
|
|
||||||
|
|
||||||
means the form of the work preferred for making modifications.
|
|
||||||
|
|
||||||
1.14. "You" (or "Your")
|
|
||||||
|
|
||||||
means an individual or a legal entity exercising rights under this
|
|
||||||
License. For legal entities, "You" includes any entity that controls, is
|
|
||||||
controlled by, or is under common control with You. For purposes of this
|
|
||||||
definition, "control" means (a) the power, direct or indirect, to cause
|
|
||||||
the direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (b) ownership of more than fifty percent (50%) of the
|
|
||||||
outstanding shares or beneficial ownership of such entity.
|
|
||||||
|
|
||||||
|
|
||||||
2. License Grants and Conditions
|
|
||||||
|
|
||||||
2.1. Grants
|
|
||||||
|
|
||||||
Each Contributor hereby grants You a world-wide, royalty-free,
|
|
||||||
non-exclusive license:
|
|
||||||
|
|
||||||
a. under intellectual property rights (other than patent or trademark)
|
|
||||||
Licensable by such Contributor to use, reproduce, make available,
|
|
||||||
modify, display, perform, distribute, and otherwise exploit its
|
|
||||||
Contributions, either on an unmodified basis, with Modifications, or
|
|
||||||
as part of a Larger Work; and
|
|
||||||
|
|
||||||
b. under Patent Claims of such Contributor to make, use, sell, offer for
|
|
||||||
sale, have made, import, and otherwise transfer either its
|
|
||||||
Contributions or its Contributor Version.
|
|
||||||
|
|
||||||
2.2. Effective Date
|
|
||||||
|
|
||||||
The licenses granted in Section 2.1 with respect to any Contribution
|
|
||||||
become effective for each Contribution on the date the Contributor first
|
|
||||||
distributes such Contribution.
|
|
||||||
|
|
||||||
2.3. Limitations on Grant Scope
|
|
||||||
|
|
||||||
The licenses granted in this Section 2 are the only rights granted under
|
|
||||||
this License. No additional rights or licenses will be implied from the
|
|
||||||
distribution or licensing of Covered Software under this License.
|
|
||||||
Notwithstanding Section 2.1(b) above, no patent license is granted by a
|
|
||||||
Contributor:
|
|
||||||
|
|
||||||
a. for any code that a Contributor has removed from Covered Software; or
|
|
||||||
|
|
||||||
b. for infringements caused by: (i) Your and any other third party's
|
|
||||||
modifications of Covered Software, or (ii) the combination of its
|
|
||||||
Contributions with other software (except as part of its Contributor
|
|
||||||
Version); or
|
|
||||||
|
|
||||||
c. under Patent Claims infringed by Covered Software in the absence of
|
|
||||||
its Contributions.
|
|
||||||
|
|
||||||
This License does not grant any rights in the trademarks, service marks,
|
|
||||||
or logos of any Contributor (except as may be necessary to comply with
|
|
||||||
the notice requirements in Section 3.4).
|
|
||||||
|
|
||||||
2.4. Subsequent Licenses
|
|
||||||
|
|
||||||
No Contributor makes additional grants as a result of Your choice to
|
|
||||||
distribute the Covered Software under a subsequent version of this
|
|
||||||
License (see Section 10.2) or under the terms of a Secondary License (if
|
|
||||||
permitted under the terms of Section 3.3).
|
|
||||||
|
|
||||||
2.5. Representation
|
|
||||||
|
|
||||||
Each Contributor represents that the Contributor believes its
|
|
||||||
Contributions are its original creation(s) or it has sufficient rights to
|
|
||||||
grant the rights to its Contributions conveyed by this License.
|
|
||||||
|
|
||||||
2.6. Fair Use
|
|
||||||
|
|
||||||
This License is not intended to limit any rights You have under
|
|
||||||
applicable copyright doctrines of fair use, fair dealing, or other
|
|
||||||
equivalents.
|
|
||||||
|
|
||||||
2.7. Conditions
|
|
||||||
|
|
||||||
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
|
|
||||||
Section 2.1.
|
|
||||||
|
|
||||||
|
|
||||||
3. Responsibilities
|
|
||||||
|
|
||||||
3.1. Distribution of Source Form
|
|
||||||
|
|
||||||
All distribution of Covered Software in Source Code Form, including any
|
|
||||||
Modifications that You create or to which You contribute, must be under
|
|
||||||
the terms of this License. You must inform recipients that the Source
|
|
||||||
Code Form of the Covered Software is governed by the terms of this
|
|
||||||
License, and how they can obtain a copy of this License. You may not
|
|
||||||
attempt to alter or restrict the recipients' rights in the Source Code
|
|
||||||
Form.
|
|
||||||
|
|
||||||
3.2. Distribution of Executable Form
|
|
||||||
|
|
||||||
If You distribute Covered Software in Executable Form then:
|
|
||||||
|
|
||||||
a. such Covered Software must also be made available in Source Code Form,
|
|
||||||
as described in Section 3.1, and You must inform recipients of the
|
|
||||||
Executable Form how they can obtain a copy of such Source Code Form by
|
|
||||||
reasonable means in a timely manner, at a charge no more than the cost
|
|
||||||
of distribution to the recipient; and
|
|
||||||
|
|
||||||
b. You may distribute such Executable Form under the terms of this
|
|
||||||
License, or sublicense it under different terms, provided that the
|
|
||||||
license for the Executable Form does not attempt to limit or alter the
|
|
||||||
recipients' rights in the Source Code Form under this License.
|
|
||||||
|
|
||||||
3.3. Distribution of a Larger Work
|
|
||||||
|
|
||||||
You may create and distribute a Larger Work under terms of Your choice,
|
|
||||||
provided that You also comply with the requirements of this License for
|
|
||||||
the Covered Software. If the Larger Work is a combination of Covered
|
|
||||||
Software with a work governed by one or more Secondary Licenses, and the
|
|
||||||
Covered Software is not Incompatible With Secondary Licenses, this
|
|
||||||
License permits You to additionally distribute such Covered Software
|
|
||||||
under the terms of such Secondary License(s), so that the recipient of
|
|
||||||
the Larger Work may, at their option, further distribute the Covered
|
|
||||||
Software under the terms of either this License or such Secondary
|
|
||||||
License(s).
|
|
||||||
|
|
||||||
3.4. Notices
|
|
||||||
|
|
||||||
You may not remove or alter the substance of any license notices
|
|
||||||
(including copyright notices, patent notices, disclaimers of warranty, or
|
|
||||||
limitations of liability) contained within the Source Code Form of the
|
|
||||||
Covered Software, except that You may alter any license notices to the
|
|
||||||
extent required to remedy known factual inaccuracies.
|
|
||||||
|
|
||||||
3.5. Application of Additional Terms
|
|
||||||
|
|
||||||
You may choose to offer, and to charge a fee for, warranty, support,
|
|
||||||
indemnity or liability obligations to one or more recipients of Covered
|
|
||||||
Software. However, You may do so only on Your own behalf, and not on
|
|
||||||
behalf of any Contributor. You must make it absolutely clear that any
|
|
||||||
such warranty, support, indemnity, or liability obligation is offered by
|
|
||||||
You alone, and You hereby agree to indemnify every Contributor for any
|
|
||||||
liability incurred by such Contributor as a result of warranty, support,
|
|
||||||
indemnity or liability terms You offer. You may include additional
|
|
||||||
disclaimers of warranty and limitations of liability specific to any
|
|
||||||
jurisdiction.
|
|
||||||
|
|
||||||
4. Inability to Comply Due to Statute or Regulation
|
|
||||||
|
|
||||||
If it is impossible for You to comply with any of the terms of this License
|
|
||||||
with respect to some or all of the Covered Software due to statute,
|
|
||||||
judicial order, or regulation then You must: (a) comply with the terms of
|
|
||||||
this License to the maximum extent possible; and (b) describe the
|
|
||||||
limitations and the code they affect. Such description must be placed in a
|
|
||||||
text file included with all distributions of the Covered Software under
|
|
||||||
this License. Except to the extent prohibited by statute or regulation,
|
|
||||||
such description must be sufficiently detailed for a recipient of ordinary
|
|
||||||
skill to be able to understand it.
|
|
||||||
|
|
||||||
5. Termination
|
|
||||||
|
|
||||||
5.1. The rights granted under this License will terminate automatically if You
|
|
||||||
fail to comply with any of its terms. However, if You become compliant,
|
|
||||||
then the rights granted under this License from a particular Contributor
|
|
||||||
are reinstated (a) provisionally, unless and until such Contributor
|
|
||||||
explicitly and finally terminates Your grants, and (b) on an ongoing
|
|
||||||
basis, if such Contributor fails to notify You of the non-compliance by
|
|
||||||
some reasonable means prior to 60 days after You have come back into
|
|
||||||
compliance. Moreover, Your grants from a particular Contributor are
|
|
||||||
reinstated on an ongoing basis if such Contributor notifies You of the
|
|
||||||
non-compliance by some reasonable means, this is the first time You have
|
|
||||||
received notice of non-compliance with this License from such
|
|
||||||
Contributor, and You become compliant prior to 30 days after Your receipt
|
|
||||||
of the notice.
|
|
||||||
|
|
||||||
5.2. If You initiate litigation against any entity by asserting a patent
|
|
||||||
infringement claim (excluding declaratory judgment actions,
|
|
||||||
counter-claims, and cross-claims) alleging that a Contributor Version
|
|
||||||
directly or indirectly infringes any patent, then the rights granted to
|
|
||||||
You by any and all Contributors for the Covered Software under Section
|
|
||||||
2.1 of this License shall terminate.
|
|
||||||
|
|
||||||
5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
|
|
||||||
license agreements (excluding distributors and resellers) which have been
|
|
||||||
validly granted by You or Your distributors under this License prior to
|
|
||||||
termination shall survive termination.
|
|
||||||
|
|
||||||
6. Disclaimer of Warranty
|
|
||||||
|
|
||||||
Covered Software is provided under this License on an "as is" basis,
|
|
||||||
without warranty of any kind, either expressed, implied, or statutory,
|
|
||||||
including, without limitation, warranties that the Covered Software is free
|
|
||||||
of defects, merchantable, fit for a particular purpose or non-infringing.
|
|
||||||
The entire risk as to the quality and performance of the Covered Software
|
|
||||||
is with You. Should any Covered Software prove defective in any respect,
|
|
||||||
You (not any Contributor) assume the cost of any necessary servicing,
|
|
||||||
repair, or correction. This disclaimer of warranty constitutes an essential
|
|
||||||
part of this License. No use of any Covered Software is authorized under
|
|
||||||
this License except under this disclaimer.
|
|
||||||
|
|
||||||
7. Limitation of Liability
|
|
||||||
|
|
||||||
Under no circumstances and under no legal theory, whether tort (including
|
|
||||||
negligence), contract, or otherwise, shall any Contributor, or anyone who
|
|
||||||
distributes Covered Software as permitted above, be liable to You for any
|
|
||||||
direct, indirect, special, incidental, or consequential damages of any
|
|
||||||
character including, without limitation, damages for lost profits, loss of
|
|
||||||
goodwill, work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses, even if such party shall have been
|
|
||||||
informed of the possibility of such damages. This limitation of liability
|
|
||||||
shall not apply to liability for death or personal injury resulting from
|
|
||||||
such party's negligence to the extent applicable law prohibits such
|
|
||||||
limitation. Some jurisdictions do not allow the exclusion or limitation of
|
|
||||||
incidental or consequential damages, so this exclusion and limitation may
|
|
||||||
not apply to You.
|
|
||||||
|
|
||||||
8. Litigation
|
|
||||||
|
|
||||||
Any litigation relating to this License may be brought only in the courts
|
|
||||||
of a jurisdiction where the defendant maintains its principal place of
|
|
||||||
business and such litigation shall be governed by laws of that
|
|
||||||
jurisdiction, without reference to its conflict-of-law provisions. Nothing
|
|
||||||
in this Section shall prevent a party's ability to bring cross-claims or
|
|
||||||
counter-claims.
|
|
||||||
|
|
||||||
9. Miscellaneous
|
|
||||||
|
|
||||||
This License represents the complete agreement concerning the subject
|
|
||||||
matter hereof. If any provision of this License is held to be
|
|
||||||
unenforceable, such provision shall be reformed only to the extent
|
|
||||||
necessary to make it enforceable. Any law or regulation which provides that
|
|
||||||
the language of a contract shall be construed against the drafter shall not
|
|
||||||
be used to construe this License against a Contributor.
|
|
||||||
|
|
||||||
|
|
||||||
10. Versions of the License
|
|
||||||
|
|
||||||
10.1. New Versions
|
|
||||||
|
|
||||||
Mozilla Foundation is the license steward. Except as provided in Section
|
|
||||||
10.3, no one other than the license steward has the right to modify or
|
|
||||||
publish new versions of this License. Each version will be given a
|
|
||||||
distinguishing version number.
|
|
||||||
|
|
||||||
10.2. Effect of New Versions
|
|
||||||
|
|
||||||
You may distribute the Covered Software under the terms of the version
|
|
||||||
of the License under which You originally received the Covered Software,
|
|
||||||
or under the terms of any subsequent version published by the license
|
|
||||||
steward.
|
|
||||||
|
|
||||||
10.3. Modified Versions
|
|
||||||
|
|
||||||
If you create software not governed by this License, and you want to
|
|
||||||
create a new license for such software, you may create and use a
|
|
||||||
modified version of this License if you rename the license and remove
|
|
||||||
any references to the name of the license steward (except to note that
|
|
||||||
such modified license differs from this License).
|
|
||||||
|
|
||||||
10.4. Distributing Source Code Form that is Incompatible With Secondary
|
|
||||||
Licenses If You choose to distribute Source Code Form that is
|
|
||||||
Incompatible With Secondary Licenses under the terms of this version of
|
|
||||||
the License, the notice described in Exhibit B of this License must be
|
|
||||||
attached.
|
|
||||||
|
|
||||||
Exhibit A - Source Code Form License Notice
|
|
||||||
|
|
||||||
This Source Code Form is subject to the
|
|
||||||
terms of the Mozilla Public License, v.
|
|
||||||
2.0. If a copy of the MPL was not
|
|
||||||
distributed with this file, You can
|
|
||||||
obtain one at
|
|
||||||
http://mozilla.org/MPL/2.0/.
|
|
||||||
|
|
||||||
If it is not possible or desirable to put the notice in a particular file,
|
|
||||||
then You may include the notice in a location (such as a LICENSE file in a
|
|
||||||
relevant directory) where a recipient would be likely to look for such a
|
|
||||||
notice.
|
|
||||||
|
|
||||||
You may add additional accurate notices of copyright ownership.
|
|
||||||
|
|
||||||
Exhibit B - "Incompatible With Secondary Licenses" Notice
|
|
||||||
|
|
||||||
This Source Code Form is "Incompatible
|
|
||||||
With Secondary Licenses", as defined by
|
|
||||||
the Mozilla Public License, v. 2.0.
|
|
||||||
|
|
8
vendor/github.com/hashicorp/go-rootcerts/Makefile
generated
vendored
8
vendor/github.com/hashicorp/go-rootcerts/Makefile
generated
vendored
|
@ -1,8 +0,0 @@
|
||||||
TEST?=./...
|
|
||||||
|
|
||||||
test:
|
|
||||||
go test $(TEST) $(TESTARGS) -timeout=3s -parallel=4
|
|
||||||
go vet $(TEST)
|
|
||||||
go test $(TEST) -race
|
|
||||||
|
|
||||||
.PHONY: test
|
|
43
vendor/github.com/hashicorp/go-rootcerts/README.md
generated
vendored
43
vendor/github.com/hashicorp/go-rootcerts/README.md
generated
vendored
|
@ -1,43 +0,0 @@
|
||||||
# rootcerts
|
|
||||||
|
|
||||||
Functions for loading root certificates for TLS connections.
|
|
||||||
|
|
||||||
-----
|
|
||||||
|
|
||||||
Go's standard library `crypto/tls` provides a common mechanism for configuring
|
|
||||||
TLS connections in `tls.Config`. The `RootCAs` field on this struct is a pool
|
|
||||||
of certificates for the client to use as a trust store when verifying server
|
|
||||||
certificates.
|
|
||||||
|
|
||||||
This library contains utility functions for loading certificates destined for
|
|
||||||
that field, as well as one other important thing:
|
|
||||||
|
|
||||||
When the `RootCAs` field is `nil`, the standard library attempts to load the
|
|
||||||
host's root CA set. This behavior is OS-specific, and the Darwin
|
|
||||||
implementation contains [a bug that prevents trusted certificates from the
|
|
||||||
System and Login keychains from being loaded][1]. This library contains
|
|
||||||
Darwin-specific behavior that works around that bug.
|
|
||||||
|
|
||||||
[1]: https://github.com/golang/go/issues/14514
|
|
||||||
|
|
||||||
## Example Usage
|
|
||||||
|
|
||||||
Here's a snippet demonstrating how this library is meant to be used:
|
|
||||||
|
|
||||||
```go
|
|
||||||
func httpClient() (*http.Client, error)
|
|
||||||
tlsConfig := &tls.Config{}
|
|
||||||
err := rootcerts.ConfigureTLS(tlsConfig, &rootcerts.Config{
|
|
||||||
CAFile: os.Getenv("MYAPP_CAFILE"),
|
|
||||||
CAPath: os.Getenv("MYAPP_CAPATH"),
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
c := cleanhttp.DefaultClient()
|
|
||||||
t := cleanhttp.DefaultTransport()
|
|
||||||
t.TLSClientConfig = tlsConfig
|
|
||||||
c.Transport = t
|
|
||||||
return c, nil
|
|
||||||
}
|
|
||||||
```
|
|
9
vendor/github.com/hashicorp/go-rootcerts/doc.go
generated
vendored
9
vendor/github.com/hashicorp/go-rootcerts/doc.go
generated
vendored
|
@ -1,9 +0,0 @@
|
||||||
// Package rootcerts contains functions to aid in loading CA certificates for
|
|
||||||
// TLS connections.
|
|
||||||
//
|
|
||||||
// In addition, its default behavior on Darwin works around an open issue [1]
|
|
||||||
// in Go's crypto/x509 that prevents certicates from being loaded from the
|
|
||||||
// System or Login keychains.
|
|
||||||
//
|
|
||||||
// [1] https://github.com/golang/go/issues/14514
|
|
||||||
package rootcerts
|
|
103
vendor/github.com/hashicorp/go-rootcerts/rootcerts.go
generated
vendored
103
vendor/github.com/hashicorp/go-rootcerts/rootcerts.go
generated
vendored
|
@ -1,103 +0,0 @@
|
||||||
package rootcerts
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/tls"
|
|
||||||
"crypto/x509"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Config determines where LoadCACerts will load certificates from. When both
|
|
||||||
// CAFile and CAPath are blank, this library's functions will either load
|
|
||||||
// system roots explicitly and return them, or set the CertPool to nil to allow
|
|
||||||
// Go's standard library to load system certs.
|
|
||||||
type Config struct {
|
|
||||||
// CAFile is a path to a PEM-encoded certificate file or bundle. Takes
|
|
||||||
// precedence over CAPath.
|
|
||||||
CAFile string
|
|
||||||
|
|
||||||
// CAPath is a path to a directory populated with PEM-encoded certificates.
|
|
||||||
CAPath string
|
|
||||||
}
|
|
||||||
|
|
||||||
// ConfigureTLS sets up the RootCAs on the provided tls.Config based on the
|
|
||||||
// Config specified.
|
|
||||||
func ConfigureTLS(t *tls.Config, c *Config) error {
|
|
||||||
if t == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
pool, err := LoadCACerts(c)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
t.RootCAs = pool
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadCACerts loads a CertPool based on the Config specified.
|
|
||||||
func LoadCACerts(c *Config) (*x509.CertPool, error) {
|
|
||||||
if c == nil {
|
|
||||||
c = &Config{}
|
|
||||||
}
|
|
||||||
if c.CAFile != "" {
|
|
||||||
return LoadCAFile(c.CAFile)
|
|
||||||
}
|
|
||||||
if c.CAPath != "" {
|
|
||||||
return LoadCAPath(c.CAPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
return LoadSystemCAs()
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadCAFile loads a single PEM-encoded file from the path specified.
|
|
||||||
func LoadCAFile(caFile string) (*x509.CertPool, error) {
|
|
||||||
pool := x509.NewCertPool()
|
|
||||||
|
|
||||||
pem, err := ioutil.ReadFile(caFile)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("Error loading CA File: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
ok := pool.AppendCertsFromPEM(pem)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("Error loading CA File: Couldn't parse PEM in: %s", caFile)
|
|
||||||
}
|
|
||||||
|
|
||||||
return pool, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadCAPath walks the provided path and loads all certificates encounted into
|
|
||||||
// a pool.
|
|
||||||
func LoadCAPath(caPath string) (*x509.CertPool, error) {
|
|
||||||
pool := x509.NewCertPool()
|
|
||||||
walkFn := func(path string, info os.FileInfo, err error) error {
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if info.IsDir() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
pem, err := ioutil.ReadFile(path)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error loading file from CAPath: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
ok := pool.AppendCertsFromPEM(pem)
|
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("Error loading CA Path: Couldn't parse PEM in: %s", path)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
err := filepath.Walk(caPath, walkFn)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return pool, nil
|
|
||||||
}
|
|
12
vendor/github.com/hashicorp/go-rootcerts/rootcerts_base.go
generated
vendored
12
vendor/github.com/hashicorp/go-rootcerts/rootcerts_base.go
generated
vendored
|
@ -1,12 +0,0 @@
|
||||||
// +build !darwin
|
|
||||||
|
|
||||||
package rootcerts
|
|
||||||
|
|
||||||
import "crypto/x509"
|
|
||||||
|
|
||||||
// LoadSystemCAs does nothing on non-Darwin systems. We return nil so that
|
|
||||||
// default behavior of standard TLS config libraries is triggered, which is to
|
|
||||||
// load system certs.
|
|
||||||
func LoadSystemCAs() (*x509.CertPool, error) {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
48
vendor/github.com/hashicorp/go-rootcerts/rootcerts_darwin.go
generated
vendored
48
vendor/github.com/hashicorp/go-rootcerts/rootcerts_darwin.go
generated
vendored
|
@ -1,48 +0,0 @@
|
||||||
package rootcerts
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/x509"
|
|
||||||
"os/exec"
|
|
||||||
"path"
|
|
||||||
|
|
||||||
"github.com/mitchellh/go-homedir"
|
|
||||||
)
|
|
||||||
|
|
||||||
// LoadSystemCAs has special behavior on Darwin systems to work around
|
|
||||||
func LoadSystemCAs() (*x509.CertPool, error) {
|
|
||||||
pool := x509.NewCertPool()
|
|
||||||
|
|
||||||
for _, keychain := range certKeychains() {
|
|
||||||
err := addCertsFromKeychain(pool, keychain)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return pool, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func addCertsFromKeychain(pool *x509.CertPool, keychain string) error {
|
|
||||||
cmd := exec.Command("/usr/bin/security", "find-certificate", "-a", "-p", keychain)
|
|
||||||
data, err := cmd.Output()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
pool.AppendCertsFromPEM(data)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func certKeychains() []string {
|
|
||||||
keychains := []string{
|
|
||||||
"/System/Library/Keychains/SystemRootCertificates.keychain",
|
|
||||||
"/Library/Keychains/System.keychain",
|
|
||||||
}
|
|
||||||
home, err := homedir.Dir()
|
|
||||||
if err == nil {
|
|
||||||
loginKeychain := path.Join(home, "Library", "Keychains", "login.keychain")
|
|
||||||
keychains = append(keychains, loginKeychain)
|
|
||||||
}
|
|
||||||
return keychains
|
|
||||||
}
|
|
9
vendor/github.com/hashicorp/hcl/.gitignore
generated
vendored
9
vendor/github.com/hashicorp/hcl/.gitignore
generated
vendored
|
@ -1,9 +0,0 @@
|
||||||
y.output
|
|
||||||
|
|
||||||
# ignore intellij files
|
|
||||||
.idea
|
|
||||||
*.iml
|
|
||||||
*.ipr
|
|
||||||
*.iws
|
|
||||||
|
|
||||||
*.test
|
|
3
vendor/github.com/hashicorp/hcl/.travis.yml
generated
vendored
3
vendor/github.com/hashicorp/hcl/.travis.yml
generated
vendored
|
@ -1,3 +0,0 @@
|
||||||
sudo: false
|
|
||||||
language: go
|
|
||||||
go: 1.7
|
|
354
vendor/github.com/hashicorp/hcl/LICENSE
generated
vendored
354
vendor/github.com/hashicorp/hcl/LICENSE
generated
vendored
|
@ -1,354 +0,0 @@
|
||||||
Mozilla Public License, version 2.0
|
|
||||||
|
|
||||||
1. Definitions
|
|
||||||
|
|
||||||
1.1. “Contributor”
|
|
||||||
|
|
||||||
means each individual or legal entity that creates, contributes to the
|
|
||||||
creation of, or owns Covered Software.
|
|
||||||
|
|
||||||
1.2. “Contributor Version”
|
|
||||||
|
|
||||||
means the combination of the Contributions of others (if any) used by a
|
|
||||||
Contributor and that particular Contributor’s Contribution.
|
|
||||||
|
|
||||||
1.3. “Contribution”
|
|
||||||
|
|
||||||
means Covered Software of a particular Contributor.
|
|
||||||
|
|
||||||
1.4. “Covered Software”
|
|
||||||
|
|
||||||
means Source Code Form to which the initial Contributor has attached the
|
|
||||||
notice in Exhibit A, the Executable Form of such Source Code Form, and
|
|
||||||
Modifications of such Source Code Form, in each case including portions
|
|
||||||
thereof.
|
|
||||||
|
|
||||||
1.5. “Incompatible With Secondary Licenses”
|
|
||||||
means
|
|
||||||
|
|
||||||
a. that the initial Contributor has attached the notice described in
|
|
||||||
Exhibit B to the Covered Software; or
|
|
||||||
|
|
||||||
b. that the Covered Software was made available under the terms of version
|
|
||||||
1.1 or earlier of the License, but not also under the terms of a
|
|
||||||
Secondary License.
|
|
||||||
|
|
||||||
1.6. “Executable Form”
|
|
||||||
|
|
||||||
means any form of the work other than Source Code Form.
|
|
||||||
|
|
||||||
1.7. “Larger Work”
|
|
||||||
|
|
||||||
means a work that combines Covered Software with other material, in a separate
|
|
||||||
file or files, that is not Covered Software.
|
|
||||||
|
|
||||||
1.8. “License”
|
|
||||||
|
|
||||||
means this document.
|
|
||||||
|
|
||||||
1.9. “Licensable”
|
|
||||||
|
|
||||||
means having the right to grant, to the maximum extent possible, whether at the
|
|
||||||
time of the initial grant or subsequently, any and all of the rights conveyed by
|
|
||||||
this License.
|
|
||||||
|
|
||||||
1.10. “Modifications”
|
|
||||||
|
|
||||||
means any of the following:
|
|
||||||
|
|
||||||
a. any file in Source Code Form that results from an addition to, deletion
|
|
||||||
from, or modification of the contents of Covered Software; or
|
|
||||||
|
|
||||||
b. any new file in Source Code Form that contains any Covered Software.
|
|
||||||
|
|
||||||
1.11. “Patent Claims” of a Contributor
|
|
||||||
|
|
||||||
means any patent claim(s), including without limitation, method, process,
|
|
||||||
and apparatus claims, in any patent Licensable by such Contributor that
|
|
||||||
would be infringed, but for the grant of the License, by the making,
|
|
||||||
using, selling, offering for sale, having made, import, or transfer of
|
|
||||||
either its Contributions or its Contributor Version.
|
|
||||||
|
|
||||||
1.12. “Secondary License”
|
|
||||||
|
|
||||||
means either the GNU General Public License, Version 2.0, the GNU Lesser
|
|
||||||
General Public License, Version 2.1, the GNU Affero General Public
|
|
||||||
License, Version 3.0, or any later versions of those licenses.
|
|
||||||
|
|
||||||
1.13. “Source Code Form”
|
|
||||||
|
|
||||||
means the form of the work preferred for making modifications.
|
|
||||||
|
|
||||||
1.14. “You” (or “Your”)
|
|
||||||
|
|
||||||
means an individual or a legal entity exercising rights under this
|
|
||||||
License. For legal entities, “You” includes any entity that controls, is
|
|
||||||
controlled by, or is under common control with You. For purposes of this
|
|
||||||
definition, “control” means (a) the power, direct or indirect, to cause
|
|
||||||
the direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (b) ownership of more than fifty percent (50%) of the
|
|
||||||
outstanding shares or beneficial ownership of such entity.
|
|
||||||
|
|
||||||
|
|
||||||
2. License Grants and Conditions
|
|
||||||
|
|
||||||
2.1. Grants
|
|
||||||
|
|
||||||
Each Contributor hereby grants You a world-wide, royalty-free,
|
|
||||||
non-exclusive license:
|
|
||||||
|
|
||||||
a. under intellectual property rights (other than patent or trademark)
|
|
||||||
Licensable by such Contributor to use, reproduce, make available,
|
|
||||||
modify, display, perform, distribute, and otherwise exploit its
|
|
||||||
Contributions, either on an unmodified basis, with Modifications, or as
|
|
||||||
part of a Larger Work; and
|
|
||||||
|
|
||||||
b. under Patent Claims of such Contributor to make, use, sell, offer for
|
|
||||||
sale, have made, import, and otherwise transfer either its Contributions
|
|
||||||
or its Contributor Version.
|
|
||||||
|
|
||||||
2.2. Effective Date
|
|
||||||
|
|
||||||
The licenses granted in Section 2.1 with respect to any Contribution become
|
|
||||||
effective for each Contribution on the date the Contributor first distributes
|
|
||||||
such Contribution.
|
|
||||||
|
|
||||||
2.3. Limitations on Grant Scope
|
|
||||||
|
|
||||||
The licenses granted in this Section 2 are the only rights granted under this
|
|
||||||
License. No additional rights or licenses will be implied from the distribution
|
|
||||||
or licensing of Covered Software under this License. Notwithstanding Section
|
|
||||||
2.1(b) above, no patent license is granted by a Contributor:
|
|
||||||
|
|
||||||
a. for any code that a Contributor has removed from Covered Software; or
|
|
||||||
|
|
||||||
b. for infringements caused by: (i) Your and any other third party’s
|
|
||||||
modifications of Covered Software, or (ii) the combination of its
|
|
||||||
Contributions with other software (except as part of its Contributor
|
|
||||||
Version); or
|
|
||||||
|
|
||||||
c. under Patent Claims infringed by Covered Software in the absence of its
|
|
||||||
Contributions.
|
|
||||||
|
|
||||||
This License does not grant any rights in the trademarks, service marks, or
|
|
||||||
logos of any Contributor (except as may be necessary to comply with the
|
|
||||||
notice requirements in Section 3.4).
|
|
||||||
|
|
||||||
2.4. Subsequent Licenses
|
|
||||||
|
|
||||||
No Contributor makes additional grants as a result of Your choice to
|
|
||||||
distribute the Covered Software under a subsequent version of this License
|
|
||||||
(see Section 10.2) or under the terms of a Secondary License (if permitted
|
|
||||||
under the terms of Section 3.3).
|
|
||||||
|
|
||||||
2.5. Representation
|
|
||||||
|
|
||||||
Each Contributor represents that the Contributor believes its Contributions
|
|
||||||
are its original creation(s) or it has sufficient rights to grant the
|
|
||||||
rights to its Contributions conveyed by this License.
|
|
||||||
|
|
||||||
2.6. Fair Use
|
|
||||||
|
|
||||||
This License is not intended to limit any rights You have under applicable
|
|
||||||
copyright doctrines of fair use, fair dealing, or other equivalents.
|
|
||||||
|
|
||||||
2.7. Conditions
|
|
||||||
|
|
||||||
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
|
|
||||||
Section 2.1.
|
|
||||||
|
|
||||||
|
|
||||||
3. Responsibilities
|
|
||||||
|
|
||||||
3.1. Distribution of Source Form
|
|
||||||
|
|
||||||
All distribution of Covered Software in Source Code Form, including any
|
|
||||||
Modifications that You create or to which You contribute, must be under the
|
|
||||||
terms of this License. You must inform recipients that the Source Code Form
|
|
||||||
of the Covered Software is governed by the terms of this License, and how
|
|
||||||
they can obtain a copy of this License. You may not attempt to alter or
|
|
||||||
restrict the recipients’ rights in the Source Code Form.
|
|
||||||
|
|
||||||
3.2. Distribution of Executable Form
|
|
||||||
|
|
||||||
If You distribute Covered Software in Executable Form then:
|
|
||||||
|
|
||||||
a. such Covered Software must also be made available in Source Code Form,
|
|
||||||
as described in Section 3.1, and You must inform recipients of the
|
|
||||||
Executable Form how they can obtain a copy of such Source Code Form by
|
|
||||||
reasonable means in a timely manner, at a charge no more than the cost
|
|
||||||
of distribution to the recipient; and
|
|
||||||
|
|
||||||
b. You may distribute such Executable Form under the terms of this License,
|
|
||||||
or sublicense it under different terms, provided that the license for
|
|
||||||
the Executable Form does not attempt to limit or alter the recipients’
|
|
||||||
rights in the Source Code Form under this License.
|
|
||||||
|
|
||||||
3.3. Distribution of a Larger Work
|
|
||||||
|
|
||||||
You may create and distribute a Larger Work under terms of Your choice,
|
|
||||||
provided that You also comply with the requirements of this License for the
|
|
||||||
Covered Software. If the Larger Work is a combination of Covered Software
|
|
||||||
with a work governed by one or more Secondary Licenses, and the Covered
|
|
||||||
Software is not Incompatible With Secondary Licenses, this License permits
|
|
||||||
You to additionally distribute such Covered Software under the terms of
|
|
||||||
such Secondary License(s), so that the recipient of the Larger Work may, at
|
|
||||||
their option, further distribute the Covered Software under the terms of
|
|
||||||
either this License or such Secondary License(s).
|
|
||||||
|
|
||||||
3.4. Notices
|
|
||||||
|
|
||||||
You may not remove or alter the substance of any license notices (including
|
|
||||||
copyright notices, patent notices, disclaimers of warranty, or limitations
|
|
||||||
of liability) contained within the Source Code Form of the Covered
|
|
||||||
Software, except that You may alter any license notices to the extent
|
|
||||||
required to remedy known factual inaccuracies.
|
|
||||||
|
|
||||||
3.5. Application of Additional Terms
|
|
||||||
|
|
||||||
You may choose to offer, and to charge a fee for, warranty, support,
|
|
||||||
indemnity or liability obligations to one or more recipients of Covered
|
|
||||||
Software. However, You may do so only on Your own behalf, and not on behalf
|
|
||||||
of any Contributor. You must make it absolutely clear that any such
|
|
||||||
warranty, support, indemnity, or liability obligation is offered by You
|
|
||||||
alone, and You hereby agree to indemnify every Contributor for any
|
|
||||||
liability incurred by such Contributor as a result of warranty, support,
|
|
||||||
indemnity or liability terms You offer. You may include additional
|
|
||||||
disclaimers of warranty and limitations of liability specific to any
|
|
||||||
jurisdiction.
|
|
||||||
|
|
||||||
4. Inability to Comply Due to Statute or Regulation
|
|
||||||
|
|
||||||
If it is impossible for You to comply with any of the terms of this License
|
|
||||||
with respect to some or all of the Covered Software due to statute, judicial
|
|
||||||
order, or regulation then You must: (a) comply with the terms of this License
|
|
||||||
to the maximum extent possible; and (b) describe the limitations and the code
|
|
||||||
they affect. Such description must be placed in a text file included with all
|
|
||||||
distributions of the Covered Software under this License. Except to the
|
|
||||||
extent prohibited by statute or regulation, such description must be
|
|
||||||
sufficiently detailed for a recipient of ordinary skill to be able to
|
|
||||||
understand it.
|
|
||||||
|
|
||||||
5. Termination
|
|
||||||
|
|
||||||
5.1. The rights granted under this License will terminate automatically if You
|
|
||||||
fail to comply with any of its terms. However, if You become compliant,
|
|
||||||
then the rights granted under this License from a particular Contributor
|
|
||||||
are reinstated (a) provisionally, unless and until such Contributor
|
|
||||||
explicitly and finally terminates Your grants, and (b) on an ongoing basis,
|
|
||||||
if such Contributor fails to notify You of the non-compliance by some
|
|
||||||
reasonable means prior to 60 days after You have come back into compliance.
|
|
||||||
Moreover, Your grants from a particular Contributor are reinstated on an
|
|
||||||
ongoing basis if such Contributor notifies You of the non-compliance by
|
|
||||||
some reasonable means, this is the first time You have received notice of
|
|
||||||
non-compliance with this License from such Contributor, and You become
|
|
||||||
compliant prior to 30 days after Your receipt of the notice.
|
|
||||||
|
|
||||||
5.2. If You initiate litigation against any entity by asserting a patent
|
|
||||||
infringement claim (excluding declaratory judgment actions, counter-claims,
|
|
||||||
and cross-claims) alleging that a Contributor Version directly or
|
|
||||||
indirectly infringes any patent, then the rights granted to You by any and
|
|
||||||
all Contributors for the Covered Software under Section 2.1 of this License
|
|
||||||
shall terminate.
|
|
||||||
|
|
||||||
5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
|
|
||||||
license agreements (excluding distributors and resellers) which have been
|
|
||||||
validly granted by You or Your distributors under this License prior to
|
|
||||||
termination shall survive termination.
|
|
||||||
|
|
||||||
6. Disclaimer of Warranty
|
|
||||||
|
|
||||||
Covered Software is provided under this License on an “as is” basis, without
|
|
||||||
warranty of any kind, either expressed, implied, or statutory, including,
|
|
||||||
without limitation, warranties that the Covered Software is free of defects,
|
|
||||||
merchantable, fit for a particular purpose or non-infringing. The entire
|
|
||||||
risk as to the quality and performance of the Covered Software is with You.
|
|
||||||
Should any Covered Software prove defective in any respect, You (not any
|
|
||||||
Contributor) assume the cost of any necessary servicing, repair, or
|
|
||||||
correction. This disclaimer of warranty constitutes an essential part of this
|
|
||||||
License. No use of any Covered Software is authorized under this License
|
|
||||||
except under this disclaimer.
|
|
||||||
|
|
||||||
7. Limitation of Liability
|
|
||||||
|
|
||||||
Under no circumstances and under no legal theory, whether tort (including
|
|
||||||
negligence), contract, or otherwise, shall any Contributor, or anyone who
|
|
||||||
distributes Covered Software as permitted above, be liable to You for any
|
|
||||||
direct, indirect, special, incidental, or consequential damages of any
|
|
||||||
character including, without limitation, damages for lost profits, loss of
|
|
||||||
goodwill, work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses, even if such party shall have been
|
|
||||||
informed of the possibility of such damages. This limitation of liability
|
|
||||||
shall not apply to liability for death or personal injury resulting from such
|
|
||||||
party’s negligence to the extent applicable law prohibits such limitation.
|
|
||||||
Some jurisdictions do not allow the exclusion or limitation of incidental or
|
|
||||||
consequential damages, so this exclusion and limitation may not apply to You.
|
|
||||||
|
|
||||||
8. Litigation
|
|
||||||
|
|
||||||
Any litigation relating to this License may be brought only in the courts of
|
|
||||||
a jurisdiction where the defendant maintains its principal place of business
|
|
||||||
and such litigation shall be governed by laws of that jurisdiction, without
|
|
||||||
reference to its conflict-of-law provisions. Nothing in this Section shall
|
|
||||||
prevent a party’s ability to bring cross-claims or counter-claims.
|
|
||||||
|
|
||||||
9. Miscellaneous
|
|
||||||
|
|
||||||
This License represents the complete agreement concerning the subject matter
|
|
||||||
hereof. If any provision of this License is held to be unenforceable, such
|
|
||||||
provision shall be reformed only to the extent necessary to make it
|
|
||||||
enforceable. Any law or regulation which provides that the language of a
|
|
||||||
contract shall be construed against the drafter shall not be used to construe
|
|
||||||
this License against a Contributor.
|
|
||||||
|
|
||||||
|
|
||||||
10. Versions of the License
|
|
||||||
|
|
||||||
10.1. New Versions
|
|
||||||
|
|
||||||
Mozilla Foundation is the license steward. Except as provided in Section
|
|
||||||
10.3, no one other than the license steward has the right to modify or
|
|
||||||
publish new versions of this License. Each version will be given a
|
|
||||||
distinguishing version number.
|
|
||||||
|
|
||||||
10.2. Effect of New Versions
|
|
||||||
|
|
||||||
You may distribute the Covered Software under the terms of the version of
|
|
||||||
the License under which You originally received the Covered Software, or
|
|
||||||
under the terms of any subsequent version published by the license
|
|
||||||
steward.
|
|
||||||
|
|
||||||
10.3. Modified Versions
|
|
||||||
|
|
||||||
If you create software not governed by this License, and you want to
|
|
||||||
create a new license for such software, you may create and use a modified
|
|
||||||
version of this License if you rename the license and remove any
|
|
||||||
references to the name of the license steward (except to note that such
|
|
||||||
modified license differs from this License).
|
|
||||||
|
|
||||||
10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses
|
|
||||||
If You choose to distribute Source Code Form that is Incompatible With
|
|
||||||
Secondary Licenses under the terms of this version of the License, the
|
|
||||||
notice described in Exhibit B of this License must be attached.
|
|
||||||
|
|
||||||
Exhibit A - Source Code Form License Notice
|
|
||||||
|
|
||||||
This Source Code Form is subject to the
|
|
||||||
terms of the Mozilla Public License, v.
|
|
||||||
2.0. If a copy of the MPL was not
|
|
||||||
distributed with this file, You can
|
|
||||||
obtain one at
|
|
||||||
http://mozilla.org/MPL/2.0/.
|
|
||||||
|
|
||||||
If it is not possible or desirable to put the notice in a particular file, then
|
|
||||||
You may include the notice in a location (such as a LICENSE file in a relevant
|
|
||||||
directory) where a recipient would be likely to look for such a notice.
|
|
||||||
|
|
||||||
You may add additional accurate notices of copyright ownership.
|
|
||||||
|
|
||||||
Exhibit B - “Incompatible With Secondary Licenses” Notice
|
|
||||||
|
|
||||||
This Source Code Form is “Incompatible
|
|
||||||
With Secondary Licenses”, as defined by
|
|
||||||
the Mozilla Public License, v. 2.0.
|
|
||||||
|
|
18
vendor/github.com/hashicorp/hcl/Makefile
generated
vendored
18
vendor/github.com/hashicorp/hcl/Makefile
generated
vendored
|
@ -1,18 +0,0 @@
|
||||||
TEST?=./...
|
|
||||||
|
|
||||||
default: test
|
|
||||||
|
|
||||||
fmt: generate
|
|
||||||
go fmt ./...
|
|
||||||
|
|
||||||
test: generate
|
|
||||||
go get -t ./...
|
|
||||||
go test $(TEST) $(TESTARGS)
|
|
||||||
|
|
||||||
generate:
|
|
||||||
go generate ./...
|
|
||||||
|
|
||||||
updatedeps:
|
|
||||||
go get -u golang.org/x/tools/cmd/stringer
|
|
||||||
|
|
||||||
.PHONY: default generate test updatedeps
|
|
125
vendor/github.com/hashicorp/hcl/README.md
generated
vendored
125
vendor/github.com/hashicorp/hcl/README.md
generated
vendored
|
@ -1,125 +0,0 @@
|
||||||
# HCL
|
|
||||||
|
|
||||||
[![GoDoc](https://godoc.org/github.com/hashicorp/hcl?status.png)](https://godoc.org/github.com/hashicorp/hcl) [![Build Status](https://travis-ci.org/hashicorp/hcl.svg?branch=master)](https://travis-ci.org/hashicorp/hcl)
|
|
||||||
|
|
||||||
HCL (HashiCorp Configuration Language) is a configuration language built
|
|
||||||
by HashiCorp. The goal of HCL is to build a structured configuration language
|
|
||||||
that is both human and machine friendly for use with command-line tools, but
|
|
||||||
specifically targeted towards DevOps tools, servers, etc.
|
|
||||||
|
|
||||||
HCL is also fully JSON compatible. That is, JSON can be used as completely
|
|
||||||
valid input to a system expecting HCL. This helps makes systems
|
|
||||||
interoperable with other systems.
|
|
||||||
|
|
||||||
HCL is heavily inspired by
|
|
||||||
[libucl](https://github.com/vstakhov/libucl),
|
|
||||||
nginx configuration, and others similar.
|
|
||||||
|
|
||||||
## Why?
|
|
||||||
|
|
||||||
A common question when viewing HCL is to ask the question: why not
|
|
||||||
JSON, YAML, etc.?
|
|
||||||
|
|
||||||
Prior to HCL, the tools we built at [HashiCorp](http://www.hashicorp.com)
|
|
||||||
used a variety of configuration languages from full programming languages
|
|
||||||
such as Ruby to complete data structure languages such as JSON. What we
|
|
||||||
learned is that some people wanted human-friendly configuration languages
|
|
||||||
and some people wanted machine-friendly languages.
|
|
||||||
|
|
||||||
JSON fits a nice balance in this, but is fairly verbose and most
|
|
||||||
importantly doesn't support comments. With YAML, we found that beginners
|
|
||||||
had a really hard time determining what the actual structure was, and
|
|
||||||
ended up guessing more often than not whether to use a hyphen, colon, etc.
|
|
||||||
in order to represent some configuration key.
|
|
||||||
|
|
||||||
Full programming languages such as Ruby enable complex behavior
|
|
||||||
a configuration language shouldn't usually allow, and also forces
|
|
||||||
people to learn some set of Ruby.
|
|
||||||
|
|
||||||
Because of this, we decided to create our own configuration language
|
|
||||||
that is JSON-compatible. Our configuration language (HCL) is designed
|
|
||||||
to be written and modified by humans. The API for HCL allows JSON
|
|
||||||
as an input so that it is also machine-friendly (machines can generate
|
|
||||||
JSON instead of trying to generate HCL).
|
|
||||||
|
|
||||||
Our goal with HCL is not to alienate other configuration languages.
|
|
||||||
It is instead to provide HCL as a specialized language for our tools,
|
|
||||||
and JSON as the interoperability layer.
|
|
||||||
|
|
||||||
## Syntax
|
|
||||||
|
|
||||||
For a complete grammar, please see the parser itself. A high-level overview
|
|
||||||
of the syntax and grammar is listed here.
|
|
||||||
|
|
||||||
* Single line comments start with `#` or `//`
|
|
||||||
|
|
||||||
* Multi-line comments are wrapped in `/*` and `*/`. Nested block comments
|
|
||||||
are not allowed. A multi-line comment (also known as a block comment)
|
|
||||||
terminates at the first `*/` found.
|
|
||||||
|
|
||||||
* Values are assigned with the syntax `key = value` (whitespace doesn't
|
|
||||||
matter). The value can be any primitive: a string, number, boolean,
|
|
||||||
object, or list.
|
|
||||||
|
|
||||||
* Strings are double-quoted and can contain any UTF-8 characters.
|
|
||||||
Example: `"Hello, World"`
|
|
||||||
|
|
||||||
* Multi-line strings start with `<<EOF` at the end of a line, and end
|
|
||||||
with `EOF` on its own line ([here documents](https://en.wikipedia.org/wiki/Here_document)).
|
|
||||||
Any text may be used in place of `EOF`. Example:
|
|
||||||
```
|
|
||||||
<<FOO
|
|
||||||
hello
|
|
||||||
world
|
|
||||||
FOO
|
|
||||||
```
|
|
||||||
|
|
||||||
* Numbers are assumed to be base 10. If you prefix a number with 0x,
|
|
||||||
it is treated as a hexadecimal. If it is prefixed with 0, it is
|
|
||||||
treated as an octal. Numbers can be in scientific notation: "1e10".
|
|
||||||
|
|
||||||
* Boolean values: `true`, `false`
|
|
||||||
|
|
||||||
* Arrays can be made by wrapping it in `[]`. Example:
|
|
||||||
`["foo", "bar", 42]`. Arrays can contain primitives,
|
|
||||||
other arrays, and objects. As an alternative, lists
|
|
||||||
of objects can be created with repeated blocks, using
|
|
||||||
this structure:
|
|
||||||
|
|
||||||
```hcl
|
|
||||||
service {
|
|
||||||
key = "value"
|
|
||||||
}
|
|
||||||
|
|
||||||
service {
|
|
||||||
key = "value"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Objects and nested objects are created using the structure shown below:
|
|
||||||
|
|
||||||
```
|
|
||||||
variable "ami" {
|
|
||||||
description = "the AMI to use"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
This would be equivalent to the following json:
|
|
||||||
``` json
|
|
||||||
{
|
|
||||||
"variable": {
|
|
||||||
"ami": {
|
|
||||||
"description": "the AMI to use"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Thanks
|
|
||||||
|
|
||||||
Thanks to:
|
|
||||||
|
|
||||||
* [@vstakhov](https://github.com/vstakhov) - The original libucl parser
|
|
||||||
and syntax that HCL was based off of.
|
|
||||||
|
|
||||||
* [@fatih](https://github.com/fatih) - The rewritten HCL parser
|
|
||||||
in pure Go (no goyacc) and support for a printer.
|
|
19
vendor/github.com/hashicorp/hcl/appveyor.yml
generated
vendored
19
vendor/github.com/hashicorp/hcl/appveyor.yml
generated
vendored
|
@ -1,19 +0,0 @@
|
||||||
version: "build-{branch}-{build}"
|
|
||||||
image: Visual Studio 2015
|
|
||||||
clone_folder: c:\gopath\src\github.com\hashicorp\hcl
|
|
||||||
environment:
|
|
||||||
GOPATH: c:\gopath
|
|
||||||
init:
|
|
||||||
- git config --global core.autocrlf true
|
|
||||||
install:
|
|
||||||
- cmd: >-
|
|
||||||
echo %Path%
|
|
||||||
|
|
||||||
go version
|
|
||||||
|
|
||||||
go env
|
|
||||||
|
|
||||||
go get -t ./...
|
|
||||||
|
|
||||||
build_script:
|
|
||||||
- cmd: go test -v ./...
|
|
716
vendor/github.com/hashicorp/hcl/decoder.go
generated
vendored
716
vendor/github.com/hashicorp/hcl/decoder.go
generated
vendored
|
@ -1,716 +0,0 @@
|
||||||
package hcl
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"reflect"
|
|
||||||
"sort"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/hashicorp/hcl/hcl/ast"
|
|
||||||
"github.com/hashicorp/hcl/hcl/parser"
|
|
||||||
"github.com/hashicorp/hcl/hcl/token"
|
|
||||||
)
|
|
||||||
|
|
||||||
// This is the tag to use with structures to have settings for HCL
|
|
||||||
const tagName = "hcl"
|
|
||||||
|
|
||||||
var (
|
|
||||||
// nodeType holds a reference to the type of ast.Node
|
|
||||||
nodeType reflect.Type = findNodeType()
|
|
||||||
)
|
|
||||||
|
|
||||||
// Unmarshal accepts a byte slice as input and writes the
|
|
||||||
// data to the value pointed to by v.
|
|
||||||
func Unmarshal(bs []byte, v interface{}) error {
|
|
||||||
root, err := parse(bs)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return DecodeObject(v, root)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decode reads the given input and decodes it into the structure
|
|
||||||
// given by `out`.
|
|
||||||
func Decode(out interface{}, in string) error {
|
|
||||||
obj, err := Parse(in)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return DecodeObject(out, obj)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecodeObject is a lower-level version of Decode. It decodes a
|
|
||||||
// raw Object into the given output.
|
|
||||||
func DecodeObject(out interface{}, n ast.Node) error {
|
|
||||||
val := reflect.ValueOf(out)
|
|
||||||
if val.Kind() != reflect.Ptr {
|
|
||||||
return errors.New("result must be a pointer")
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we have the file, we really decode the root node
|
|
||||||
if f, ok := n.(*ast.File); ok {
|
|
||||||
n = f.Node
|
|
||||||
}
|
|
||||||
|
|
||||||
var d decoder
|
|
||||||
return d.decode("root", n, val.Elem())
|
|
||||||
}
|
|
||||||
|
|
||||||
type decoder struct {
|
|
||||||
stack []reflect.Kind
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *decoder) decode(name string, node ast.Node, result reflect.Value) error {
|
|
||||||
k := result
|
|
||||||
|
|
||||||
// If we have an interface with a valid value, we use that
|
|
||||||
// for the check.
|
|
||||||
if result.Kind() == reflect.Interface {
|
|
||||||
elem := result.Elem()
|
|
||||||
if elem.IsValid() {
|
|
||||||
k = elem
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Push current onto stack unless it is an interface.
|
|
||||||
if k.Kind() != reflect.Interface {
|
|
||||||
d.stack = append(d.stack, k.Kind())
|
|
||||||
|
|
||||||
// Schedule a pop
|
|
||||||
defer func() {
|
|
||||||
d.stack = d.stack[:len(d.stack)-1]
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
switch k.Kind() {
|
|
||||||
case reflect.Bool:
|
|
||||||
return d.decodeBool(name, node, result)
|
|
||||||
case reflect.Float64:
|
|
||||||
return d.decodeFloat(name, node, result)
|
|
||||||
case reflect.Int:
|
|
||||||
return d.decodeInt(name, node, result)
|
|
||||||
case reflect.Interface:
|
|
||||||
// When we see an interface, we make our own thing
|
|
||||||
return d.decodeInterface(name, node, result)
|
|
||||||
case reflect.Map:
|
|
||||||
return d.decodeMap(name, node, result)
|
|
||||||
case reflect.Ptr:
|
|
||||||
return d.decodePtr(name, node, result)
|
|
||||||
case reflect.Slice:
|
|
||||||
return d.decodeSlice(name, node, result)
|
|
||||||
case reflect.String:
|
|
||||||
return d.decodeString(name, node, result)
|
|
||||||
case reflect.Struct:
|
|
||||||
return d.decodeStruct(name, node, result)
|
|
||||||
default:
|
|
||||||
return &parser.PosError{
|
|
||||||
Pos: node.Pos(),
|
|
||||||
Err: fmt.Errorf("%s: unknown kind to decode into: %s", name, k.Kind()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *decoder) decodeBool(name string, node ast.Node, result reflect.Value) error {
|
|
||||||
switch n := node.(type) {
|
|
||||||
case *ast.LiteralType:
|
|
||||||
if n.Token.Type == token.BOOL {
|
|
||||||
v, err := strconv.ParseBool(n.Token.Text)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
result.Set(reflect.ValueOf(v))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return &parser.PosError{
|
|
||||||
Pos: node.Pos(),
|
|
||||||
Err: fmt.Errorf("%s: unknown type %T", name, node),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *decoder) decodeFloat(name string, node ast.Node, result reflect.Value) error {
|
|
||||||
switch n := node.(type) {
|
|
||||||
case *ast.LiteralType:
|
|
||||||
if n.Token.Type == token.FLOAT {
|
|
||||||
v, err := strconv.ParseFloat(n.Token.Text, 64)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
result.Set(reflect.ValueOf(v))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return &parser.PosError{
|
|
||||||
Pos: node.Pos(),
|
|
||||||
Err: fmt.Errorf("%s: unknown type %T", name, node),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *decoder) decodeInt(name string, node ast.Node, result reflect.Value) error {
|
|
||||||
switch n := node.(type) {
|
|
||||||
case *ast.LiteralType:
|
|
||||||
switch n.Token.Type {
|
|
||||||
case token.NUMBER:
|
|
||||||
v, err := strconv.ParseInt(n.Token.Text, 0, 0)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
result.Set(reflect.ValueOf(int(v)))
|
|
||||||
return nil
|
|
||||||
case token.STRING:
|
|
||||||
v, err := strconv.ParseInt(n.Token.Value().(string), 0, 0)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
result.Set(reflect.ValueOf(int(v)))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return &parser.PosError{
|
|
||||||
Pos: node.Pos(),
|
|
||||||
Err: fmt.Errorf("%s: unknown type %T", name, node),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *decoder) decodeInterface(name string, node ast.Node, result reflect.Value) error {
|
|
||||||
// When we see an ast.Node, we retain the value to enable deferred decoding.
|
|
||||||
// Very useful in situations where we want to preserve ast.Node information
|
|
||||||
// like Pos
|
|
||||||
if result.Type() == nodeType && result.CanSet() {
|
|
||||||
result.Set(reflect.ValueOf(node))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var set reflect.Value
|
|
||||||
redecode := true
|
|
||||||
|
|
||||||
// For testing types, ObjectType should just be treated as a list. We
|
|
||||||
// set this to a temporary var because we want to pass in the real node.
|
|
||||||
testNode := node
|
|
||||||
if ot, ok := node.(*ast.ObjectType); ok {
|
|
||||||
testNode = ot.List
|
|
||||||
}
|
|
||||||
|
|
||||||
switch n := testNode.(type) {
|
|
||||||
case *ast.ObjectList:
|
|
||||||
// If we're at the root or we're directly within a slice, then we
|
|
||||||
// decode objects into map[string]interface{}, otherwise we decode
|
|
||||||
// them into lists.
|
|
||||||
if len(d.stack) == 0 || d.stack[len(d.stack)-1] == reflect.Slice {
|
|
||||||
var temp map[string]interface{}
|
|
||||||
tempVal := reflect.ValueOf(temp)
|
|
||||||
result := reflect.MakeMap(
|
|
||||||
reflect.MapOf(
|
|
||||||
reflect.TypeOf(""),
|
|
||||||
tempVal.Type().Elem()))
|
|
||||||
|
|
||||||
set = result
|
|
||||||
} else {
|
|
||||||
var temp []map[string]interface{}
|
|
||||||
tempVal := reflect.ValueOf(temp)
|
|
||||||
result := reflect.MakeSlice(
|
|
||||||
reflect.SliceOf(tempVal.Type().Elem()), 0, len(n.Items))
|
|
||||||
set = result
|
|
||||||
}
|
|
||||||
case *ast.ObjectType:
|
|
||||||
// If we're at the root or we're directly within a slice, then we
|
|
||||||
// decode objects into map[string]interface{}, otherwise we decode
|
|
||||||
// them into lists.
|
|
||||||
if len(d.stack) == 0 || d.stack[len(d.stack)-1] == reflect.Slice {
|
|
||||||
var temp map[string]interface{}
|
|
||||||
tempVal := reflect.ValueOf(temp)
|
|
||||||
result := reflect.MakeMap(
|
|
||||||
reflect.MapOf(
|
|
||||||
reflect.TypeOf(""),
|
|
||||||
tempVal.Type().Elem()))
|
|
||||||
|
|
||||||
set = result
|
|
||||||
} else {
|
|
||||||
var temp []map[string]interface{}
|
|
||||||
tempVal := reflect.ValueOf(temp)
|
|
||||||
result := reflect.MakeSlice(
|
|
||||||
reflect.SliceOf(tempVal.Type().Elem()), 0, 1)
|
|
||||||
set = result
|
|
||||||
}
|
|
||||||
case *ast.ListType:
|
|
||||||
var temp []interface{}
|
|
||||||
tempVal := reflect.ValueOf(temp)
|
|
||||||
result := reflect.MakeSlice(
|
|
||||||
reflect.SliceOf(tempVal.Type().Elem()), 0, 0)
|
|
||||||
set = result
|
|
||||||
case *ast.LiteralType:
|
|
||||||
switch n.Token.Type {
|
|
||||||
case token.BOOL:
|
|
||||||
var result bool
|
|
||||||
set = reflect.Indirect(reflect.New(reflect.TypeOf(result)))
|
|
||||||
case token.FLOAT:
|
|
||||||
var result float64
|
|
||||||
set = reflect.Indirect(reflect.New(reflect.TypeOf(result)))
|
|
||||||
case token.NUMBER:
|
|
||||||
var result int
|
|
||||||
set = reflect.Indirect(reflect.New(reflect.TypeOf(result)))
|
|
||||||
case token.STRING, token.HEREDOC:
|
|
||||||
set = reflect.Indirect(reflect.New(reflect.TypeOf("")))
|
|
||||||
default:
|
|
||||||
return &parser.PosError{
|
|
||||||
Pos: node.Pos(),
|
|
||||||
Err: fmt.Errorf("%s: cannot decode into interface: %T", name, node),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return fmt.Errorf(
|
|
||||||
"%s: cannot decode into interface: %T",
|
|
||||||
name, node)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the result to what its supposed to be, then reset
|
|
||||||
// result so we don't reflect into this method anymore.
|
|
||||||
result.Set(set)
|
|
||||||
|
|
||||||
if redecode {
|
|
||||||
// Revisit the node so that we can use the newly instantiated
|
|
||||||
// thing and populate it.
|
|
||||||
if err := d.decode(name, node, result); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *decoder) decodeMap(name string, node ast.Node, result reflect.Value) error {
|
|
||||||
if item, ok := node.(*ast.ObjectItem); ok {
|
|
||||||
node = &ast.ObjectList{Items: []*ast.ObjectItem{item}}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ot, ok := node.(*ast.ObjectType); ok {
|
|
||||||
node = ot.List
|
|
||||||
}
|
|
||||||
|
|
||||||
n, ok := node.(*ast.ObjectList)
|
|
||||||
if !ok {
|
|
||||||
return &parser.PosError{
|
|
||||||
Pos: node.Pos(),
|
|
||||||
Err: fmt.Errorf("%s: not an object type for map (%T)", name, node),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we have an interface, then we can address the interface,
|
|
||||||
// but not the slice itself, so get the element but set the interface
|
|
||||||
set := result
|
|
||||||
if result.Kind() == reflect.Interface {
|
|
||||||
result = result.Elem()
|
|
||||||
}
|
|
||||||
|
|
||||||
resultType := result.Type()
|
|
||||||
resultElemType := resultType.Elem()
|
|
||||||
resultKeyType := resultType.Key()
|
|
||||||
if resultKeyType.Kind() != reflect.String {
|
|
||||||
return &parser.PosError{
|
|
||||||
Pos: node.Pos(),
|
|
||||||
Err: fmt.Errorf("%s: map must have string keys", name),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make a map if it is nil
|
|
||||||
resultMap := result
|
|
||||||
if result.IsNil() {
|
|
||||||
resultMap = reflect.MakeMap(
|
|
||||||
reflect.MapOf(resultKeyType, resultElemType))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Go through each element and decode it.
|
|
||||||
done := make(map[string]struct{})
|
|
||||||
for _, item := range n.Items {
|
|
||||||
if item.Val == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// github.com/hashicorp/terraform/issue/5740
|
|
||||||
if len(item.Keys) == 0 {
|
|
||||||
return &parser.PosError{
|
|
||||||
Pos: node.Pos(),
|
|
||||||
Err: fmt.Errorf("%s: map must have string keys", name),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the key we're dealing with, which is the first item
|
|
||||||
keyStr := item.Keys[0].Token.Value().(string)
|
|
||||||
|
|
||||||
// If we've already processed this key, then ignore it
|
|
||||||
if _, ok := done[keyStr]; ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine the value. If we have more than one key, then we
|
|
||||||
// get the objectlist of only these keys.
|
|
||||||
itemVal := item.Val
|
|
||||||
if len(item.Keys) > 1 {
|
|
||||||
itemVal = n.Filter(keyStr)
|
|
||||||
done[keyStr] = struct{}{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make the field name
|
|
||||||
fieldName := fmt.Sprintf("%s.%s", name, keyStr)
|
|
||||||
|
|
||||||
// Get the key/value as reflection values
|
|
||||||
key := reflect.ValueOf(keyStr)
|
|
||||||
val := reflect.Indirect(reflect.New(resultElemType))
|
|
||||||
|
|
||||||
// If we have a pre-existing value in the map, use that
|
|
||||||
oldVal := resultMap.MapIndex(key)
|
|
||||||
if oldVal.IsValid() {
|
|
||||||
val.Set(oldVal)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decode!
|
|
||||||
if err := d.decode(fieldName, itemVal, val); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the value on the map
|
|
||||||
resultMap.SetMapIndex(key, val)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the final map if we can
|
|
||||||
set.Set(resultMap)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *decoder) decodePtr(name string, node ast.Node, result reflect.Value) error {
|
|
||||||
// Create an element of the concrete (non pointer) type and decode
|
|
||||||
// into that. Then set the value of the pointer to this type.
|
|
||||||
resultType := result.Type()
|
|
||||||
resultElemType := resultType.Elem()
|
|
||||||
val := reflect.New(resultElemType)
|
|
||||||
if err := d.decode(name, node, reflect.Indirect(val)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
result.Set(val)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *decoder) decodeSlice(name string, node ast.Node, result reflect.Value) error {
|
|
||||||
// If we have an interface, then we can address the interface,
|
|
||||||
// but not the slice itself, so get the element but set the interface
|
|
||||||
set := result
|
|
||||||
if result.Kind() == reflect.Interface {
|
|
||||||
result = result.Elem()
|
|
||||||
}
|
|
||||||
// Create the slice if it isn't nil
|
|
||||||
resultType := result.Type()
|
|
||||||
resultElemType := resultType.Elem()
|
|
||||||
if result.IsNil() {
|
|
||||||
resultSliceType := reflect.SliceOf(resultElemType)
|
|
||||||
result = reflect.MakeSlice(
|
|
||||||
resultSliceType, 0, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Figure out the items we'll be copying into the slice
|
|
||||||
var items []ast.Node
|
|
||||||
switch n := node.(type) {
|
|
||||||
case *ast.ObjectList:
|
|
||||||
items = make([]ast.Node, len(n.Items))
|
|
||||||
for i, item := range n.Items {
|
|
||||||
items[i] = item
|
|
||||||
}
|
|
||||||
case *ast.ObjectType:
|
|
||||||
items = []ast.Node{n}
|
|
||||||
case *ast.ListType:
|
|
||||||
items = n.List
|
|
||||||
default:
|
|
||||||
return &parser.PosError{
|
|
||||||
Pos: node.Pos(),
|
|
||||||
Err: fmt.Errorf("unknown slice type: %T", node),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, item := range items {
|
|
||||||
fieldName := fmt.Sprintf("%s[%d]", name, i)
|
|
||||||
|
|
||||||
// Decode
|
|
||||||
val := reflect.Indirect(reflect.New(resultElemType))
|
|
||||||
|
|
||||||
// if item is an object that was decoded from ambiguous JSON and
|
|
||||||
// flattened, make sure it's expanded if it needs to decode into a
|
|
||||||
// defined structure.
|
|
||||||
item := expandObject(item, val)
|
|
||||||
|
|
||||||
if err := d.decode(fieldName, item, val); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Append it onto the slice
|
|
||||||
result = reflect.Append(result, val)
|
|
||||||
}
|
|
||||||
|
|
||||||
set.Set(result)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// expandObject detects if an ambiguous JSON object was flattened to a List which
|
|
||||||
// should be decoded into a struct, and expands the ast to properly deocode.
|
|
||||||
func expandObject(node ast.Node, result reflect.Value) ast.Node {
|
|
||||||
item, ok := node.(*ast.ObjectItem)
|
|
||||||
if !ok {
|
|
||||||
return node
|
|
||||||
}
|
|
||||||
|
|
||||||
elemType := result.Type()
|
|
||||||
|
|
||||||
// our target type must be a struct
|
|
||||||
switch elemType.Kind() {
|
|
||||||
case reflect.Ptr:
|
|
||||||
switch elemType.Elem().Kind() {
|
|
||||||
case reflect.Struct:
|
|
||||||
//OK
|
|
||||||
default:
|
|
||||||
return node
|
|
||||||
}
|
|
||||||
case reflect.Struct:
|
|
||||||
//OK
|
|
||||||
default:
|
|
||||||
return node
|
|
||||||
}
|
|
||||||
|
|
||||||
// A list value will have a key and field name. If it had more fields,
|
|
||||||
// it wouldn't have been flattened.
|
|
||||||
if len(item.Keys) != 2 {
|
|
||||||
return node
|
|
||||||
}
|
|
||||||
|
|
||||||
keyToken := item.Keys[0].Token
|
|
||||||
item.Keys = item.Keys[1:]
|
|
||||||
|
|
||||||
// we need to un-flatten the ast enough to decode
|
|
||||||
newNode := &ast.ObjectItem{
|
|
||||||
Keys: []*ast.ObjectKey{
|
|
||||||
&ast.ObjectKey{
|
|
||||||
Token: keyToken,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Val: &ast.ObjectType{
|
|
||||||
List: &ast.ObjectList{
|
|
||||||
Items: []*ast.ObjectItem{item},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
return newNode
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *decoder) decodeString(name string, node ast.Node, result reflect.Value) error {
|
|
||||||
switch n := node.(type) {
|
|
||||||
case *ast.LiteralType:
|
|
||||||
switch n.Token.Type {
|
|
||||||
case token.NUMBER:
|
|
||||||
result.Set(reflect.ValueOf(n.Token.Text).Convert(result.Type()))
|
|
||||||
return nil
|
|
||||||
case token.STRING, token.HEREDOC:
|
|
||||||
result.Set(reflect.ValueOf(n.Token.Value()).Convert(result.Type()))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return &parser.PosError{
|
|
||||||
Pos: node.Pos(),
|
|
||||||
Err: fmt.Errorf("%s: unknown type for string %T", name, node),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *decoder) decodeStruct(name string, node ast.Node, result reflect.Value) error {
|
|
||||||
var item *ast.ObjectItem
|
|
||||||
if it, ok := node.(*ast.ObjectItem); ok {
|
|
||||||
item = it
|
|
||||||
node = it.Val
|
|
||||||
}
|
|
||||||
|
|
||||||
if ot, ok := node.(*ast.ObjectType); ok {
|
|
||||||
node = ot.List
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle the special case where the object itself is a literal. Previously
|
|
||||||
// the yacc parser would always ensure top-level elements were arrays. The new
|
|
||||||
// parser does not make the same guarantees, thus we need to convert any
|
|
||||||
// top-level literal elements into a list.
|
|
||||||
if _, ok := node.(*ast.LiteralType); ok && item != nil {
|
|
||||||
node = &ast.ObjectList{Items: []*ast.ObjectItem{item}}
|
|
||||||
}
|
|
||||||
|
|
||||||
list, ok := node.(*ast.ObjectList)
|
|
||||||
if !ok {
|
|
||||||
return &parser.PosError{
|
|
||||||
Pos: node.Pos(),
|
|
||||||
Err: fmt.Errorf("%s: not an object type for struct (%T)", name, node),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This slice will keep track of all the structs we'll be decoding.
|
|
||||||
// There can be more than one struct if there are embedded structs
|
|
||||||
// that are squashed.
|
|
||||||
structs := make([]reflect.Value, 1, 5)
|
|
||||||
structs[0] = result
|
|
||||||
|
|
||||||
// Compile the list of all the fields that we're going to be decoding
|
|
||||||
// from all the structs.
|
|
||||||
fields := make(map[*reflect.StructField]reflect.Value)
|
|
||||||
for len(structs) > 0 {
|
|
||||||
structVal := structs[0]
|
|
||||||
structs = structs[1:]
|
|
||||||
|
|
||||||
structType := structVal.Type()
|
|
||||||
for i := 0; i < structType.NumField(); i++ {
|
|
||||||
fieldType := structType.Field(i)
|
|
||||||
tagParts := strings.Split(fieldType.Tag.Get(tagName), ",")
|
|
||||||
|
|
||||||
// Ignore fields with tag name "-"
|
|
||||||
if tagParts[0] == "-" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if fieldType.Anonymous {
|
|
||||||
fieldKind := fieldType.Type.Kind()
|
|
||||||
if fieldKind != reflect.Struct {
|
|
||||||
return &parser.PosError{
|
|
||||||
Pos: node.Pos(),
|
|
||||||
Err: fmt.Errorf("%s: unsupported type to struct: %s",
|
|
||||||
fieldType.Name, fieldKind),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// We have an embedded field. We "squash" the fields down
|
|
||||||
// if specified in the tag.
|
|
||||||
squash := false
|
|
||||||
for _, tag := range tagParts[1:] {
|
|
||||||
if tag == "squash" {
|
|
||||||
squash = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if squash {
|
|
||||||
structs = append(
|
|
||||||
structs, result.FieldByName(fieldType.Name))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Normal struct field, store it away
|
|
||||||
fields[&fieldType] = structVal.Field(i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
usedKeys := make(map[string]struct{})
|
|
||||||
decodedFields := make([]string, 0, len(fields))
|
|
||||||
decodedFieldsVal := make([]reflect.Value, 0)
|
|
||||||
unusedKeysVal := make([]reflect.Value, 0)
|
|
||||||
for fieldType, field := range fields {
|
|
||||||
if !field.IsValid() {
|
|
||||||
// This should never happen
|
|
||||||
panic("field is not valid")
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we can't set the field, then it is unexported or something,
|
|
||||||
// and we just continue onwards.
|
|
||||||
if !field.CanSet() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
fieldName := fieldType.Name
|
|
||||||
|
|
||||||
tagValue := fieldType.Tag.Get(tagName)
|
|
||||||
tagParts := strings.SplitN(tagValue, ",", 2)
|
|
||||||
if len(tagParts) >= 2 {
|
|
||||||
switch tagParts[1] {
|
|
||||||
case "decodedFields":
|
|
||||||
decodedFieldsVal = append(decodedFieldsVal, field)
|
|
||||||
continue
|
|
||||||
case "key":
|
|
||||||
if item == nil {
|
|
||||||
return &parser.PosError{
|
|
||||||
Pos: node.Pos(),
|
|
||||||
Err: fmt.Errorf("%s: %s asked for 'key', impossible",
|
|
||||||
name, fieldName),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
field.SetString(item.Keys[0].Token.Value().(string))
|
|
||||||
continue
|
|
||||||
case "unusedKeys":
|
|
||||||
unusedKeysVal = append(unusedKeysVal, field)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if tagParts[0] != "" {
|
|
||||||
fieldName = tagParts[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine the element we'll use to decode. If it is a single
|
|
||||||
// match (only object with the field), then we decode it exactly.
|
|
||||||
// If it is a prefix match, then we decode the matches.
|
|
||||||
filter := list.Filter(fieldName)
|
|
||||||
|
|
||||||
prefixMatches := filter.Children()
|
|
||||||
matches := filter.Elem()
|
|
||||||
if len(matches.Items) == 0 && len(prefixMatches.Items) == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Track the used key
|
|
||||||
usedKeys[fieldName] = struct{}{}
|
|
||||||
|
|
||||||
// Create the field name and decode. We range over the elements
|
|
||||||
// because we actually want the value.
|
|
||||||
fieldName = fmt.Sprintf("%s.%s", name, fieldName)
|
|
||||||
if len(prefixMatches.Items) > 0 {
|
|
||||||
if err := d.decode(fieldName, prefixMatches, field); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, match := range matches.Items {
|
|
||||||
var decodeNode ast.Node = match.Val
|
|
||||||
if ot, ok := decodeNode.(*ast.ObjectType); ok {
|
|
||||||
decodeNode = &ast.ObjectList{Items: ot.List.Items}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := d.decode(fieldName, decodeNode, field); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
decodedFields = append(decodedFields, fieldType.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(decodedFieldsVal) > 0 {
|
|
||||||
// Sort it so that it is deterministic
|
|
||||||
sort.Strings(decodedFields)
|
|
||||||
|
|
||||||
for _, v := range decodedFieldsVal {
|
|
||||||
v.Set(reflect.ValueOf(decodedFields))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// findNodeType returns the type of ast.Node
|
|
||||||
func findNodeType() reflect.Type {
|
|
||||||
var nodeContainer struct {
|
|
||||||
Node ast.Node
|
|
||||||
}
|
|
||||||
value := reflect.ValueOf(nodeContainer).FieldByName("Node")
|
|
||||||
return value.Type()
|
|
||||||
}
|
|
11
vendor/github.com/hashicorp/hcl/hcl.go
generated
vendored
11
vendor/github.com/hashicorp/hcl/hcl.go
generated
vendored
|
@ -1,11 +0,0 @@
|
||||||
// Package hcl decodes HCL into usable Go structures.
|
|
||||||
//
|
|
||||||
// hcl input can come in either pure HCL format or JSON format.
|
|
||||||
// It can be parsed into an AST, and then decoded into a structure,
|
|
||||||
// or it can be decoded directly from a string into a structure.
|
|
||||||
//
|
|
||||||
// If you choose to parse HCL into a raw AST, the benefit is that you
|
|
||||||
// can write custom visitor implementations to implement custom
|
|
||||||
// semantic checks. By default, HCL does not perform any semantic
|
|
||||||
// checks.
|
|
||||||
package hcl
|
|
218
vendor/github.com/hashicorp/hcl/hcl/ast/ast.go
generated
vendored
218
vendor/github.com/hashicorp/hcl/hcl/ast/ast.go
generated
vendored
|
@ -1,218 +0,0 @@
|
||||||
// Package ast declares the types used to represent syntax trees for HCL
|
|
||||||
// (HashiCorp Configuration Language)
|
|
||||||
package ast
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/hashicorp/hcl/hcl/token"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Node is an element in the abstract syntax tree.
|
|
||||||
type Node interface {
|
|
||||||
node()
|
|
||||||
Pos() token.Pos
|
|
||||||
}
|
|
||||||
|
|
||||||
func (File) node() {}
|
|
||||||
func (ObjectList) node() {}
|
|
||||||
func (ObjectKey) node() {}
|
|
||||||
func (ObjectItem) node() {}
|
|
||||||
func (Comment) node() {}
|
|
||||||
func (CommentGroup) node() {}
|
|
||||||
func (ObjectType) node() {}
|
|
||||||
func (LiteralType) node() {}
|
|
||||||
func (ListType) node() {}
|
|
||||||
|
|
||||||
// File represents a single HCL file
|
|
||||||
type File struct {
|
|
||||||
Node Node // usually a *ObjectList
|
|
||||||
Comments []*CommentGroup // list of all comments in the source
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *File) Pos() token.Pos {
|
|
||||||
return f.Node.Pos()
|
|
||||||
}
|
|
||||||
|
|
||||||
// ObjectList represents a list of ObjectItems. An HCL file itself is an
|
|
||||||
// ObjectList.
|
|
||||||
type ObjectList struct {
|
|
||||||
Items []*ObjectItem
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o *ObjectList) Add(item *ObjectItem) {
|
|
||||||
o.Items = append(o.Items, item)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filter filters out the objects with the given key list as a prefix.
|
|
||||||
//
|
|
||||||
// The returned list of objects contain ObjectItems where the keys have
|
|
||||||
// this prefix already stripped off. This might result in objects with
|
|
||||||
// zero-length key lists if they have no children.
|
|
||||||
//
|
|
||||||
// If no matches are found, an empty ObjectList (non-nil) is returned.
|
|
||||||
func (o *ObjectList) Filter(keys ...string) *ObjectList {
|
|
||||||
var result ObjectList
|
|
||||||
for _, item := range o.Items {
|
|
||||||
// If there aren't enough keys, then ignore this
|
|
||||||
if len(item.Keys) < len(keys) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
match := true
|
|
||||||
for i, key := range item.Keys[:len(keys)] {
|
|
||||||
key := key.Token.Value().(string)
|
|
||||||
if key != keys[i] && !strings.EqualFold(key, keys[i]) {
|
|
||||||
match = false
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !match {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Strip off the prefix from the children
|
|
||||||
newItem := *item
|
|
||||||
newItem.Keys = newItem.Keys[len(keys):]
|
|
||||||
result.Add(&newItem)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &result
|
|
||||||
}
|
|
||||||
|
|
||||||
// Children returns further nested objects (key length > 0) within this
|
|
||||||
// ObjectList. This should be used with Filter to get at child items.
|
|
||||||
func (o *ObjectList) Children() *ObjectList {
|
|
||||||
var result ObjectList
|
|
||||||
for _, item := range o.Items {
|
|
||||||
if len(item.Keys) > 0 {
|
|
||||||
result.Add(item)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return &result
|
|
||||||
}
|
|
||||||
|
|
||||||
// Elem returns items in the list that are direct element assignments
|
|
||||||
// (key length == 0). This should be used with Filter to get at elements.
|
|
||||||
func (o *ObjectList) Elem() *ObjectList {
|
|
||||||
var result ObjectList
|
|
||||||
for _, item := range o.Items {
|
|
||||||
if len(item.Keys) == 0 {
|
|
||||||
result.Add(item)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return &result
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o *ObjectList) Pos() token.Pos {
|
|
||||||
// always returns the uninitiliazed position
|
|
||||||
return o.Items[0].Pos()
|
|
||||||
}
|
|
||||||
|
|
||||||
// ObjectItem represents a HCL Object Item. An item is represented with a key
|
|
||||||
// (or keys). It can be an assignment or an object (both normal and nested)
|
|
||||||
type ObjectItem struct {
|
|
||||||
// keys is only one length long if it's of type assignment. If it's a
|
|
||||||
// nested object it can be larger than one. In that case "assign" is
|
|
||||||
// invalid as there is no assignments for a nested object.
|
|
||||||
Keys []*ObjectKey
|
|
||||||
|
|
||||||
// assign contains the position of "=", if any
|
|
||||||
Assign token.Pos
|
|
||||||
|
|
||||||
// val is the item itself. It can be an object,list, number, bool or a
|
|
||||||
// string. If key length is larger than one, val can be only of type
|
|
||||||
// Object.
|
|
||||||
Val Node
|
|
||||||
|
|
||||||
LeadComment *CommentGroup // associated lead comment
|
|
||||||
LineComment *CommentGroup // associated line comment
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o *ObjectItem) Pos() token.Pos {
|
|
||||||
// I'm not entirely sure what causes this, but removing this causes
|
|
||||||
// a test failure. We should investigate at some point.
|
|
||||||
if len(o.Keys) == 0 {
|
|
||||||
return token.Pos{}
|
|
||||||
}
|
|
||||||
|
|
||||||
return o.Keys[0].Pos()
|
|
||||||
}
|
|
||||||
|
|
||||||
// ObjectKeys are either an identifier or of type string.
|
|
||||||
type ObjectKey struct {
|
|
||||||
Token token.Token
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o *ObjectKey) Pos() token.Pos {
|
|
||||||
return o.Token.Pos
|
|
||||||
}
|
|
||||||
|
|
||||||
// LiteralType represents a literal of basic type. Valid types are:
|
|
||||||
// token.NUMBER, token.FLOAT, token.BOOL and token.STRING
|
|
||||||
type LiteralType struct {
|
|
||||||
Token token.Token
|
|
||||||
|
|
||||||
// associated line comment, only when used in a list
|
|
||||||
LineComment *CommentGroup
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *LiteralType) Pos() token.Pos {
|
|
||||||
return l.Token.Pos
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListStatement represents a HCL List type
|
|
||||||
type ListType struct {
|
|
||||||
Lbrack token.Pos // position of "["
|
|
||||||
Rbrack token.Pos // position of "]"
|
|
||||||
List []Node // the elements in lexical order
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *ListType) Pos() token.Pos {
|
|
||||||
return l.Lbrack
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *ListType) Add(node Node) {
|
|
||||||
l.List = append(l.List, node)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ObjectType represents a HCL Object Type
|
|
||||||
type ObjectType struct {
|
|
||||||
Lbrace token.Pos // position of "{"
|
|
||||||
Rbrace token.Pos // position of "}"
|
|
||||||
List *ObjectList // the nodes in lexical order
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o *ObjectType) Pos() token.Pos {
|
|
||||||
return o.Lbrace
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comment node represents a single //, # style or /*- style commment
|
|
||||||
type Comment struct {
|
|
||||||
Start token.Pos // position of / or #
|
|
||||||
Text string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Comment) Pos() token.Pos {
|
|
||||||
return c.Start
|
|
||||||
}
|
|
||||||
|
|
||||||
// CommentGroup node represents a sequence of comments with no other tokens and
|
|
||||||
// no empty lines between.
|
|
||||||
type CommentGroup struct {
|
|
||||||
List []*Comment // len(List) > 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *CommentGroup) Pos() token.Pos {
|
|
||||||
return c.List[0].Pos()
|
|
||||||
}
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
|
||||||
// GoStringer
|
|
||||||
//-------------------------------------------------------------------
|
|
||||||
|
|
||||||
func (o *ObjectKey) GoString() string { return fmt.Sprintf("*%#v", *o) }
|
|
||||||
func (o *ObjectList) GoString() string { return fmt.Sprintf("*%#v", *o) }
|
|
52
vendor/github.com/hashicorp/hcl/hcl/ast/walk.go
generated
vendored
52
vendor/github.com/hashicorp/hcl/hcl/ast/walk.go
generated
vendored
|
@ -1,52 +0,0 @@
|
||||||
package ast
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
// WalkFunc describes a function to be called for each node during a Walk. The
|
|
||||||
// returned node can be used to rewrite the AST. Walking stops the returned
|
|
||||||
// bool is false.
|
|
||||||
type WalkFunc func(Node) (Node, bool)
|
|
||||||
|
|
||||||
// Walk traverses an AST in depth-first order: It starts by calling fn(node);
|
|
||||||
// node must not be nil. If fn returns true, Walk invokes fn recursively for
|
|
||||||
// each of the non-nil children of node, followed by a call of fn(nil). The
|
|
||||||
// returned node of fn can be used to rewrite the passed node to fn.
|
|
||||||
func Walk(node Node, fn WalkFunc) Node {
|
|
||||||
rewritten, ok := fn(node)
|
|
||||||
if !ok {
|
|
||||||
return rewritten
|
|
||||||
}
|
|
||||||
|
|
||||||
switch n := node.(type) {
|
|
||||||
case *File:
|
|
||||||
n.Node = Walk(n.Node, fn)
|
|
||||||
case *ObjectList:
|
|
||||||
for i, item := range n.Items {
|
|
||||||
n.Items[i] = Walk(item, fn).(*ObjectItem)
|
|
||||||
}
|
|
||||||
case *ObjectKey:
|
|
||||||
// nothing to do
|
|
||||||
case *ObjectItem:
|
|
||||||
for i, k := range n.Keys {
|
|
||||||
n.Keys[i] = Walk(k, fn).(*ObjectKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
if n.Val != nil {
|
|
||||||
n.Val = Walk(n.Val, fn)
|
|
||||||
}
|
|
||||||
case *LiteralType:
|
|
||||||
// nothing to do
|
|
||||||
case *ListType:
|
|
||||||
for i, l := range n.List {
|
|
||||||
n.List[i] = Walk(l, fn)
|
|
||||||
}
|
|
||||||
case *ObjectType:
|
|
||||||
n.List = Walk(n.List, fn).(*ObjectList)
|
|
||||||
default:
|
|
||||||
// should we panic here?
|
|
||||||
fmt.Printf("unknown type: %T\n", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn(nil)
|
|
||||||
return rewritten
|
|
||||||
}
|
|
17
vendor/github.com/hashicorp/hcl/hcl/parser/error.go
generated
vendored
17
vendor/github.com/hashicorp/hcl/hcl/parser/error.go
generated
vendored
|
@ -1,17 +0,0 @@
|
||||||
package parser
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/hashicorp/hcl/hcl/token"
|
|
||||||
)
|
|
||||||
|
|
||||||
// PosError is a parse error that contains a position.
|
|
||||||
type PosError struct {
|
|
||||||
Pos token.Pos
|
|
||||||
Err error
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *PosError) Error() string {
|
|
||||||
return fmt.Sprintf("At %s: %s", e.Pos, e.Err)
|
|
||||||
}
|
|
489
vendor/github.com/hashicorp/hcl/hcl/parser/parser.go
generated
vendored
489
vendor/github.com/hashicorp/hcl/hcl/parser/parser.go
generated
vendored
|
@ -1,489 +0,0 @@
|
||||||
// Package parser implements a parser for HCL (HashiCorp Configuration
|
|
||||||
// Language)
|
|
||||||
package parser
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/hashicorp/hcl/hcl/ast"
|
|
||||||
"github.com/hashicorp/hcl/hcl/scanner"
|
|
||||||
"github.com/hashicorp/hcl/hcl/token"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Parser struct {
|
|
||||||
sc *scanner.Scanner
|
|
||||||
|
|
||||||
// Last read token
|
|
||||||
tok token.Token
|
|
||||||
commaPrev token.Token
|
|
||||||
|
|
||||||
comments []*ast.CommentGroup
|
|
||||||
leadComment *ast.CommentGroup // last lead comment
|
|
||||||
lineComment *ast.CommentGroup // last line comment
|
|
||||||
|
|
||||||
enableTrace bool
|
|
||||||
indent int
|
|
||||||
n int // buffer size (max = 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func newParser(src []byte) *Parser {
|
|
||||||
return &Parser{
|
|
||||||
sc: scanner.New(src),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse returns the fully parsed source and returns the abstract syntax tree.
|
|
||||||
func Parse(src []byte) (*ast.File, error) {
|
|
||||||
p := newParser(src)
|
|
||||||
return p.Parse()
|
|
||||||
}
|
|
||||||
|
|
||||||
var errEofToken = errors.New("EOF token found")
|
|
||||||
|
|
||||||
// Parse returns the fully parsed source and returns the abstract syntax tree.
|
|
||||||
func (p *Parser) Parse() (*ast.File, error) {
|
|
||||||
f := &ast.File{}
|
|
||||||
var err, scerr error
|
|
||||||
p.sc.Error = func(pos token.Pos, msg string) {
|
|
||||||
scerr = &PosError{Pos: pos, Err: errors.New(msg)}
|
|
||||||
}
|
|
||||||
|
|
||||||
f.Node, err = p.objectList()
|
|
||||||
if scerr != nil {
|
|
||||||
return nil, scerr
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
f.Comments = p.comments
|
|
||||||
return f, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Parser) objectList() (*ast.ObjectList, error) {
|
|
||||||
defer un(trace(p, "ParseObjectList"))
|
|
||||||
node := &ast.ObjectList{}
|
|
||||||
|
|
||||||
for {
|
|
||||||
n, err := p.objectItem()
|
|
||||||
if err == errEofToken {
|
|
||||||
break // we are finished
|
|
||||||
}
|
|
||||||
|
|
||||||
// we don't return a nil node, because might want to use already
|
|
||||||
// collected items.
|
|
||||||
if err != nil {
|
|
||||||
return node, err
|
|
||||||
}
|
|
||||||
|
|
||||||
node.Add(n)
|
|
||||||
|
|
||||||
// object lists can be optionally comma-delimited e.g. when a list of maps
|
|
||||||
// is being expressed, so a comma is allowed here - it's simply consumed
|
|
||||||
tok := p.scan()
|
|
||||||
if tok.Type != token.COMMA {
|
|
||||||
p.unscan()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return node, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Parser) consumeComment() (comment *ast.Comment, endline int) {
|
|
||||||
endline = p.tok.Pos.Line
|
|
||||||
|
|
||||||
// count the endline if it's multiline comment, ie starting with /*
|
|
||||||
if len(p.tok.Text) > 1 && p.tok.Text[1] == '*' {
|
|
||||||
// don't use range here - no need to decode Unicode code points
|
|
||||||
for i := 0; i < len(p.tok.Text); i++ {
|
|
||||||
if p.tok.Text[i] == '\n' {
|
|
||||||
endline++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
comment = &ast.Comment{Start: p.tok.Pos, Text: p.tok.Text}
|
|
||||||
p.tok = p.sc.Scan()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Parser) consumeCommentGroup(n int) (comments *ast.CommentGroup, endline int) {
|
|
||||||
var list []*ast.Comment
|
|
||||||
endline = p.tok.Pos.Line
|
|
||||||
|
|
||||||
for p.tok.Type == token.COMMENT && p.tok.Pos.Line <= endline+n {
|
|
||||||
var comment *ast.Comment
|
|
||||||
comment, endline = p.consumeComment()
|
|
||||||
list = append(list, comment)
|
|
||||||
}
|
|
||||||
|
|
||||||
// add comment group to the comments list
|
|
||||||
comments = &ast.CommentGroup{List: list}
|
|
||||||
p.comments = append(p.comments, comments)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// objectItem parses a single object item
|
|
||||||
func (p *Parser) objectItem() (*ast.ObjectItem, error) {
|
|
||||||
defer un(trace(p, "ParseObjectItem"))
|
|
||||||
|
|
||||||
keys, err := p.objectKey()
|
|
||||||
if len(keys) > 0 && err == errEofToken {
|
|
||||||
// We ignore eof token here since it is an error if we didn't
|
|
||||||
// receive a value (but we did receive a key) for the item.
|
|
||||||
err = nil
|
|
||||||
}
|
|
||||||
if len(keys) > 0 && err != nil && p.tok.Type == token.RBRACE {
|
|
||||||
// This is a strange boolean statement, but what it means is:
|
|
||||||
// We have keys with no value, and we're likely in an object
|
|
||||||
// (since RBrace ends an object). For this, we set err to nil so
|
|
||||||
// we continue and get the error below of having the wrong value
|
|
||||||
// type.
|
|
||||||
err = nil
|
|
||||||
|
|
||||||
// Reset the token type so we don't think it completed fine. See
|
|
||||||
// objectType which uses p.tok.Type to check if we're done with
|
|
||||||
// the object.
|
|
||||||
p.tok.Type = token.EOF
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
o := &ast.ObjectItem{
|
|
||||||
Keys: keys,
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.leadComment != nil {
|
|
||||||
o.LeadComment = p.leadComment
|
|
||||||
p.leadComment = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
switch p.tok.Type {
|
|
||||||
case token.ASSIGN:
|
|
||||||
o.Assign = p.tok.Pos
|
|
||||||
o.Val, err = p.object()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
case token.LBRACE:
|
|
||||||
o.Val, err = p.objectType()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
keyStr := make([]string, 0, len(keys))
|
|
||||||
for _, k := range keys {
|
|
||||||
keyStr = append(keyStr, k.Token.Text)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, fmt.Errorf(
|
|
||||||
"key '%s' expected start of object ('{') or assignment ('=')",
|
|
||||||
strings.Join(keyStr, " "))
|
|
||||||
}
|
|
||||||
|
|
||||||
// do a look-ahead for line comment
|
|
||||||
p.scan()
|
|
||||||
if len(keys) > 0 && o.Val.Pos().Line == keys[0].Pos().Line && p.lineComment != nil {
|
|
||||||
o.LineComment = p.lineComment
|
|
||||||
p.lineComment = nil
|
|
||||||
}
|
|
||||||
p.unscan()
|
|
||||||
return o, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// objectKey parses an object key and returns a ObjectKey AST
|
|
||||||
func (p *Parser) objectKey() ([]*ast.ObjectKey, error) {
|
|
||||||
keyCount := 0
|
|
||||||
keys := make([]*ast.ObjectKey, 0)
|
|
||||||
|
|
||||||
for {
|
|
||||||
tok := p.scan()
|
|
||||||
switch tok.Type {
|
|
||||||
case token.EOF:
|
|
||||||
// It is very important to also return the keys here as well as
|
|
||||||
// the error. This is because we need to be able to tell if we
|
|
||||||
// did parse keys prior to finding the EOF, or if we just found
|
|
||||||
// a bare EOF.
|
|
||||||
return keys, errEofToken
|
|
||||||
case token.ASSIGN:
|
|
||||||
// assignment or object only, but not nested objects. this is not
|
|
||||||
// allowed: `foo bar = {}`
|
|
||||||
if keyCount > 1 {
|
|
||||||
return nil, &PosError{
|
|
||||||
Pos: p.tok.Pos,
|
|
||||||
Err: fmt.Errorf("nested object expected: LBRACE got: %s", p.tok.Type),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if keyCount == 0 {
|
|
||||||
return nil, &PosError{
|
|
||||||
Pos: p.tok.Pos,
|
|
||||||
Err: errors.New("no object keys found!"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return keys, nil
|
|
||||||
case token.LBRACE:
|
|
||||||
var err error
|
|
||||||
|
|
||||||
// If we have no keys, then it is a syntax error. i.e. {{}} is not
|
|
||||||
// allowed.
|
|
||||||
if len(keys) == 0 {
|
|
||||||
err = &PosError{
|
|
||||||
Pos: p.tok.Pos,
|
|
||||||
Err: fmt.Errorf("expected: IDENT | STRING got: %s", p.tok.Type),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// object
|
|
||||||
return keys, err
|
|
||||||
case token.IDENT, token.STRING:
|
|
||||||
keyCount++
|
|
||||||
keys = append(keys, &ast.ObjectKey{Token: p.tok})
|
|
||||||
case token.ILLEGAL:
|
|
||||||
fmt.Println("illegal")
|
|
||||||
default:
|
|
||||||
return keys, &PosError{
|
|
||||||
Pos: p.tok.Pos,
|
|
||||||
Err: fmt.Errorf("expected: IDENT | STRING | ASSIGN | LBRACE got: %s", p.tok.Type),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// object parses any type of object, such as number, bool, string, object or
|
|
||||||
// list.
|
|
||||||
func (p *Parser) object() (ast.Node, error) {
|
|
||||||
defer un(trace(p, "ParseType"))
|
|
||||||
tok := p.scan()
|
|
||||||
|
|
||||||
switch tok.Type {
|
|
||||||
case token.NUMBER, token.FLOAT, token.BOOL, token.STRING, token.HEREDOC:
|
|
||||||
return p.literalType()
|
|
||||||
case token.LBRACE:
|
|
||||||
return p.objectType()
|
|
||||||
case token.LBRACK:
|
|
||||||
return p.listType()
|
|
||||||
case token.COMMENT:
|
|
||||||
// implement comment
|
|
||||||
case token.EOF:
|
|
||||||
return nil, errEofToken
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, &PosError{
|
|
||||||
Pos: tok.Pos,
|
|
||||||
Err: fmt.Errorf("Unknown token: %+v", tok),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// objectType parses an object type and returns a ObjectType AST
|
|
||||||
func (p *Parser) objectType() (*ast.ObjectType, error) {
|
|
||||||
defer un(trace(p, "ParseObjectType"))
|
|
||||||
|
|
||||||
// we assume that the currently scanned token is a LBRACE
|
|
||||||
o := &ast.ObjectType{
|
|
||||||
Lbrace: p.tok.Pos,
|
|
||||||
}
|
|
||||||
|
|
||||||
l, err := p.objectList()
|
|
||||||
|
|
||||||
// if we hit RBRACE, we are good to go (means we parsed all Items), if it's
|
|
||||||
// not a RBRACE, it's an syntax error and we just return it.
|
|
||||||
if err != nil && p.tok.Type != token.RBRACE {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there is no error, we should be at a RBRACE to end the object
|
|
||||||
if p.tok.Type != token.RBRACE {
|
|
||||||
return nil, fmt.Errorf("object expected closing RBRACE got: %s", p.tok.Type)
|
|
||||||
}
|
|
||||||
|
|
||||||
o.List = l
|
|
||||||
o.Rbrace = p.tok.Pos // advanced via parseObjectList
|
|
||||||
return o, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// listType parses a list type and returns a ListType AST
|
|
||||||
func (p *Parser) listType() (*ast.ListType, error) {
|
|
||||||
defer un(trace(p, "ParseListType"))
|
|
||||||
|
|
||||||
// we assume that the currently scanned token is a LBRACK
|
|
||||||
l := &ast.ListType{
|
|
||||||
Lbrack: p.tok.Pos,
|
|
||||||
}
|
|
||||||
|
|
||||||
needComma := false
|
|
||||||
for {
|
|
||||||
tok := p.scan()
|
|
||||||
if needComma {
|
|
||||||
switch tok.Type {
|
|
||||||
case token.COMMA, token.RBRACK:
|
|
||||||
default:
|
|
||||||
return nil, &PosError{
|
|
||||||
Pos: tok.Pos,
|
|
||||||
Err: fmt.Errorf(
|
|
||||||
"error parsing list, expected comma or list end, got: %s",
|
|
||||||
tok.Type),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
switch tok.Type {
|
|
||||||
case token.NUMBER, token.FLOAT, token.STRING, token.HEREDOC:
|
|
||||||
node, err := p.literalType()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
l.Add(node)
|
|
||||||
needComma = true
|
|
||||||
case token.COMMA:
|
|
||||||
// get next list item or we are at the end
|
|
||||||
// do a look-ahead for line comment
|
|
||||||
p.scan()
|
|
||||||
if p.lineComment != nil && len(l.List) > 0 {
|
|
||||||
lit, ok := l.List[len(l.List)-1].(*ast.LiteralType)
|
|
||||||
if ok {
|
|
||||||
lit.LineComment = p.lineComment
|
|
||||||
l.List[len(l.List)-1] = lit
|
|
||||||
p.lineComment = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
p.unscan()
|
|
||||||
|
|
||||||
needComma = false
|
|
||||||
continue
|
|
||||||
case token.LBRACE:
|
|
||||||
// Looks like a nested object, so parse it out
|
|
||||||
node, err := p.objectType()
|
|
||||||
if err != nil {
|
|
||||||
return nil, &PosError{
|
|
||||||
Pos: tok.Pos,
|
|
||||||
Err: fmt.Errorf(
|
|
||||||
"error while trying to parse object within list: %s", err),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
l.Add(node)
|
|
||||||
needComma = true
|
|
||||||
case token.BOOL:
|
|
||||||
// TODO(arslan) should we support? not supported by HCL yet
|
|
||||||
case token.LBRACK:
|
|
||||||
// TODO(arslan) should we support nested lists? Even though it's
|
|
||||||
// written in README of HCL, it's not a part of the grammar
|
|
||||||
// (not defined in parse.y)
|
|
||||||
case token.RBRACK:
|
|
||||||
// finished
|
|
||||||
l.Rbrack = p.tok.Pos
|
|
||||||
return l, nil
|
|
||||||
default:
|
|
||||||
return nil, &PosError{
|
|
||||||
Pos: tok.Pos,
|
|
||||||
Err: fmt.Errorf("unexpected token while parsing list: %s", tok.Type),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// literalType parses a literal type and returns a LiteralType AST
|
|
||||||
func (p *Parser) literalType() (*ast.LiteralType, error) {
|
|
||||||
defer un(trace(p, "ParseLiteral"))
|
|
||||||
|
|
||||||
return &ast.LiteralType{
|
|
||||||
Token: p.tok,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// scan returns the next token from the underlying scanner. If a token has
|
|
||||||
// been unscanned then read that instead. In the process, it collects any
|
|
||||||
// comment groups encountered, and remembers the last lead and line comments.
|
|
||||||
func (p *Parser) scan() token.Token {
|
|
||||||
// If we have a token on the buffer, then return it.
|
|
||||||
if p.n != 0 {
|
|
||||||
p.n = 0
|
|
||||||
return p.tok
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise read the next token from the scanner and Save it to the buffer
|
|
||||||
// in case we unscan later.
|
|
||||||
prev := p.tok
|
|
||||||
p.tok = p.sc.Scan()
|
|
||||||
|
|
||||||
if p.tok.Type == token.COMMENT {
|
|
||||||
var comment *ast.CommentGroup
|
|
||||||
var endline int
|
|
||||||
|
|
||||||
// fmt.Printf("p.tok.Pos.Line = %+v prev: %d endline %d \n",
|
|
||||||
// p.tok.Pos.Line, prev.Pos.Line, endline)
|
|
||||||
if p.tok.Pos.Line == prev.Pos.Line {
|
|
||||||
// The comment is on same line as the previous token; it
|
|
||||||
// cannot be a lead comment but may be a line comment.
|
|
||||||
comment, endline = p.consumeCommentGroup(0)
|
|
||||||
if p.tok.Pos.Line != endline {
|
|
||||||
// The next token is on a different line, thus
|
|
||||||
// the last comment group is a line comment.
|
|
||||||
p.lineComment = comment
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// consume successor comments, if any
|
|
||||||
endline = -1
|
|
||||||
for p.tok.Type == token.COMMENT {
|
|
||||||
comment, endline = p.consumeCommentGroup(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
if endline+1 == p.tok.Pos.Line && p.tok.Type != token.RBRACE {
|
|
||||||
switch p.tok.Type {
|
|
||||||
case token.RBRACE, token.RBRACK:
|
|
||||||
// Do not count for these cases
|
|
||||||
default:
|
|
||||||
// The next token is following on the line immediately after the
|
|
||||||
// comment group, thus the last comment group is a lead comment.
|
|
||||||
p.leadComment = comment
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return p.tok
|
|
||||||
}
|
|
||||||
|
|
||||||
// unscan pushes the previously read token back onto the buffer.
|
|
||||||
func (p *Parser) unscan() {
|
|
||||||
p.n = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
// Parsing support
|
|
||||||
|
|
||||||
func (p *Parser) printTrace(a ...interface{}) {
|
|
||||||
if !p.enableTrace {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const dots = ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "
|
|
||||||
const n = len(dots)
|
|
||||||
fmt.Printf("%5d:%3d: ", p.tok.Pos.Line, p.tok.Pos.Column)
|
|
||||||
|
|
||||||
i := 2 * p.indent
|
|
||||||
for i > n {
|
|
||||||
fmt.Print(dots)
|
|
||||||
i -= n
|
|
||||||
}
|
|
||||||
// i <= n
|
|
||||||
fmt.Print(dots[0:i])
|
|
||||||
fmt.Println(a...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func trace(p *Parser, msg string) *Parser {
|
|
||||||
p.printTrace(msg, "(")
|
|
||||||
p.indent++
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// Usage pattern: defer un(trace(p, "..."))
|
|
||||||
func un(p *Parser) {
|
|
||||||
p.indent--
|
|
||||||
p.printTrace(")")
|
|
||||||
}
|
|
645
vendor/github.com/hashicorp/hcl/hcl/scanner/scanner.go
generated
vendored
645
vendor/github.com/hashicorp/hcl/hcl/scanner/scanner.go
generated
vendored
|
@ -1,645 +0,0 @@
|
||||||
// Package scanner implements a scanner for HCL (HashiCorp Configuration
|
|
||||||
// Language) source text.
|
|
||||||
package scanner
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"regexp"
|
|
||||||
"unicode"
|
|
||||||
"unicode/utf8"
|
|
||||||
|
|
||||||
"github.com/hashicorp/hcl/hcl/token"
|
|
||||||
)
|
|
||||||
|
|
||||||
// eof represents a marker rune for the end of the reader.
|
|
||||||
const eof = rune(0)
|
|
||||||
|
|
||||||
// Scanner defines a lexical scanner
|
|
||||||
type Scanner struct {
|
|
||||||
buf *bytes.Buffer // Source buffer for advancing and scanning
|
|
||||||
src []byte // Source buffer for immutable access
|
|
||||||
|
|
||||||
// Source Position
|
|
||||||
srcPos token.Pos // current position
|
|
||||||
prevPos token.Pos // previous position, used for peek() method
|
|
||||||
|
|
||||||
lastCharLen int // length of last character in bytes
|
|
||||||
lastLineLen int // length of last line in characters (for correct column reporting)
|
|
||||||
|
|
||||||
tokStart int // token text start position
|
|
||||||
tokEnd int // token text end position
|
|
||||||
|
|
||||||
// Error is called for each error encountered. If no Error
|
|
||||||
// function is set, the error is reported to os.Stderr.
|
|
||||||
Error func(pos token.Pos, msg string)
|
|
||||||
|
|
||||||
// ErrorCount is incremented by one for each error encountered.
|
|
||||||
ErrorCount int
|
|
||||||
|
|
||||||
// tokPos is the start position of most recently scanned token; set by
|
|
||||||
// Scan. The Filename field is always left untouched by the Scanner. If
|
|
||||||
// an error is reported (via Error) and Position is invalid, the scanner is
|
|
||||||
// not inside a token.
|
|
||||||
tokPos token.Pos
|
|
||||||
}
|
|
||||||
|
|
||||||
// New creates and initializes a new instance of Scanner using src as
|
|
||||||
// its source content.
|
|
||||||
func New(src []byte) *Scanner {
|
|
||||||
// even though we accept a src, we read from a io.Reader compatible type
|
|
||||||
// (*bytes.Buffer). So in the future we might easily change it to streaming
|
|
||||||
// read.
|
|
||||||
b := bytes.NewBuffer(src)
|
|
||||||
s := &Scanner{
|
|
||||||
buf: b,
|
|
||||||
src: src,
|
|
||||||
}
|
|
||||||
|
|
||||||
// srcPosition always starts with 1
|
|
||||||
s.srcPos.Line = 1
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
// next reads the next rune from the bufferred reader. Returns the rune(0) if
|
|
||||||
// an error occurs (or io.EOF is returned).
|
|
||||||
func (s *Scanner) next() rune {
|
|
||||||
ch, size, err := s.buf.ReadRune()
|
|
||||||
if err != nil {
|
|
||||||
// advance for error reporting
|
|
||||||
s.srcPos.Column++
|
|
||||||
s.srcPos.Offset += size
|
|
||||||
s.lastCharLen = size
|
|
||||||
return eof
|
|
||||||
}
|
|
||||||
|
|
||||||
if ch == utf8.RuneError && size == 1 {
|
|
||||||
s.srcPos.Column++
|
|
||||||
s.srcPos.Offset += size
|
|
||||||
s.lastCharLen = size
|
|
||||||
s.err("illegal UTF-8 encoding")
|
|
||||||
return ch
|
|
||||||
}
|
|
||||||
|
|
||||||
// remember last position
|
|
||||||
s.prevPos = s.srcPos
|
|
||||||
|
|
||||||
s.srcPos.Column++
|
|
||||||
s.lastCharLen = size
|
|
||||||
s.srcPos.Offset += size
|
|
||||||
|
|
||||||
if ch == '\n' {
|
|
||||||
s.srcPos.Line++
|
|
||||||
s.lastLineLen = s.srcPos.Column
|
|
||||||
s.srcPos.Column = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// debug
|
|
||||||
// fmt.Printf("ch: %q, offset:column: %d:%d\n", ch, s.srcPos.Offset, s.srcPos.Column)
|
|
||||||
return ch
|
|
||||||
}
|
|
||||||
|
|
||||||
// unread unreads the previous read Rune and updates the source position
|
|
||||||
func (s *Scanner) unread() {
|
|
||||||
if err := s.buf.UnreadRune(); err != nil {
|
|
||||||
panic(err) // this is user fault, we should catch it
|
|
||||||
}
|
|
||||||
s.srcPos = s.prevPos // put back last position
|
|
||||||
}
|
|
||||||
|
|
||||||
// peek returns the next rune without advancing the reader.
|
|
||||||
func (s *Scanner) peek() rune {
|
|
||||||
peek, _, err := s.buf.ReadRune()
|
|
||||||
if err != nil {
|
|
||||||
return eof
|
|
||||||
}
|
|
||||||
|
|
||||||
s.buf.UnreadRune()
|
|
||||||
return peek
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scan scans the next token and returns the token.
|
|
||||||
func (s *Scanner) Scan() token.Token {
|
|
||||||
ch := s.next()
|
|
||||||
|
|
||||||
// skip white space
|
|
||||||
for isWhitespace(ch) {
|
|
||||||
ch = s.next()
|
|
||||||
}
|
|
||||||
|
|
||||||
var tok token.Type
|
|
||||||
|
|
||||||
// token text markings
|
|
||||||
s.tokStart = s.srcPos.Offset - s.lastCharLen
|
|
||||||
|
|
||||||
// token position, initial next() is moving the offset by one(size of rune
|
|
||||||
// actually), though we are interested with the starting point
|
|
||||||
s.tokPos.Offset = s.srcPos.Offset - s.lastCharLen
|
|
||||||
if s.srcPos.Column > 0 {
|
|
||||||
// common case: last character was not a '\n'
|
|
||||||
s.tokPos.Line = s.srcPos.Line
|
|
||||||
s.tokPos.Column = s.srcPos.Column
|
|
||||||
} else {
|
|
||||||
// last character was a '\n'
|
|
||||||
// (we cannot be at the beginning of the source
|
|
||||||
// since we have called next() at least once)
|
|
||||||
s.tokPos.Line = s.srcPos.Line - 1
|
|
||||||
s.tokPos.Column = s.lastLineLen
|
|
||||||
}
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case isLetter(ch):
|
|
||||||
tok = token.IDENT
|
|
||||||
lit := s.scanIdentifier()
|
|
||||||
if lit == "true" || lit == "false" {
|
|
||||||
tok = token.BOOL
|
|
||||||
}
|
|
||||||
case isDecimal(ch):
|
|
||||||
tok = s.scanNumber(ch)
|
|
||||||
default:
|
|
||||||
switch ch {
|
|
||||||
case eof:
|
|
||||||
tok = token.EOF
|
|
||||||
case '"':
|
|
||||||
tok = token.STRING
|
|
||||||
s.scanString()
|
|
||||||
case '#', '/':
|
|
||||||
tok = token.COMMENT
|
|
||||||
s.scanComment(ch)
|
|
||||||
case '.':
|
|
||||||
tok = token.PERIOD
|
|
||||||
ch = s.peek()
|
|
||||||
if isDecimal(ch) {
|
|
||||||
tok = token.FLOAT
|
|
||||||
ch = s.scanMantissa(ch)
|
|
||||||
ch = s.scanExponent(ch)
|
|
||||||
}
|
|
||||||
case '<':
|
|
||||||
tok = token.HEREDOC
|
|
||||||
s.scanHeredoc()
|
|
||||||
case '[':
|
|
||||||
tok = token.LBRACK
|
|
||||||
case ']':
|
|
||||||
tok = token.RBRACK
|
|
||||||
case '{':
|
|
||||||
tok = token.LBRACE
|
|
||||||
case '}':
|
|
||||||
tok = token.RBRACE
|
|
||||||
case ',':
|
|
||||||
tok = token.COMMA
|
|
||||||
case '=':
|
|
||||||
tok = token.ASSIGN
|
|
||||||
case '+':
|
|
||||||
tok = token.ADD
|
|
||||||
case '-':
|
|
||||||
if isDecimal(s.peek()) {
|
|
||||||
ch := s.next()
|
|
||||||
tok = s.scanNumber(ch)
|
|
||||||
} else {
|
|
||||||
tok = token.SUB
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
s.err("illegal char")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// finish token ending
|
|
||||||
s.tokEnd = s.srcPos.Offset
|
|
||||||
|
|
||||||
// create token literal
|
|
||||||
var tokenText string
|
|
||||||
if s.tokStart >= 0 {
|
|
||||||
tokenText = string(s.src[s.tokStart:s.tokEnd])
|
|
||||||
}
|
|
||||||
s.tokStart = s.tokEnd // ensure idempotency of tokenText() call
|
|
||||||
|
|
||||||
return token.Token{
|
|
||||||
Type: tok,
|
|
||||||
Pos: s.tokPos,
|
|
||||||
Text: tokenText,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Scanner) scanComment(ch rune) {
|
|
||||||
// single line comments
|
|
||||||
if ch == '#' || (ch == '/' && s.peek() != '*') {
|
|
||||||
if ch == '/' && s.peek() != '/' {
|
|
||||||
s.err("expected '/' for comment")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
ch = s.next()
|
|
||||||
for ch != '\n' && ch >= 0 && ch != eof {
|
|
||||||
ch = s.next()
|
|
||||||
}
|
|
||||||
if ch != eof && ch >= 0 {
|
|
||||||
s.unread()
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// be sure we get the character after /* This allows us to find comment's
|
|
||||||
// that are not erminated
|
|
||||||
if ch == '/' {
|
|
||||||
s.next()
|
|
||||||
ch = s.next() // read character after "/*"
|
|
||||||
}
|
|
||||||
|
|
||||||
// look for /* - style comments
|
|
||||||
for {
|
|
||||||
if ch < 0 || ch == eof {
|
|
||||||
s.err("comment not terminated")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
ch0 := ch
|
|
||||||
ch = s.next()
|
|
||||||
if ch0 == '*' && ch == '/' {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// scanNumber scans a HCL number definition starting with the given rune
|
|
||||||
func (s *Scanner) scanNumber(ch rune) token.Type {
|
|
||||||
if ch == '0' {
|
|
||||||
// check for hexadecimal, octal or float
|
|
||||||
ch = s.next()
|
|
||||||
if ch == 'x' || ch == 'X' {
|
|
||||||
// hexadecimal
|
|
||||||
ch = s.next()
|
|
||||||
found := false
|
|
||||||
for isHexadecimal(ch) {
|
|
||||||
ch = s.next()
|
|
||||||
found = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if !found {
|
|
||||||
s.err("illegal hexadecimal number")
|
|
||||||
}
|
|
||||||
|
|
||||||
if ch != eof {
|
|
||||||
s.unread()
|
|
||||||
}
|
|
||||||
|
|
||||||
return token.NUMBER
|
|
||||||
}
|
|
||||||
|
|
||||||
// now it's either something like: 0421(octal) or 0.1231(float)
|
|
||||||
illegalOctal := false
|
|
||||||
for isDecimal(ch) {
|
|
||||||
ch = s.next()
|
|
||||||
if ch == '8' || ch == '9' {
|
|
||||||
// this is just a possibility. For example 0159 is illegal, but
|
|
||||||
// 0159.23 is valid. So we mark a possible illegal octal. If
|
|
||||||
// the next character is not a period, we'll print the error.
|
|
||||||
illegalOctal = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ch == 'e' || ch == 'E' {
|
|
||||||
ch = s.scanExponent(ch)
|
|
||||||
return token.FLOAT
|
|
||||||
}
|
|
||||||
|
|
||||||
if ch == '.' {
|
|
||||||
ch = s.scanFraction(ch)
|
|
||||||
|
|
||||||
if ch == 'e' || ch == 'E' {
|
|
||||||
ch = s.next()
|
|
||||||
ch = s.scanExponent(ch)
|
|
||||||
}
|
|
||||||
return token.FLOAT
|
|
||||||
}
|
|
||||||
|
|
||||||
if illegalOctal {
|
|
||||||
s.err("illegal octal number")
|
|
||||||
}
|
|
||||||
|
|
||||||
if ch != eof {
|
|
||||||
s.unread()
|
|
||||||
}
|
|
||||||
return token.NUMBER
|
|
||||||
}
|
|
||||||
|
|
||||||
s.scanMantissa(ch)
|
|
||||||
ch = s.next() // seek forward
|
|
||||||
if ch == 'e' || ch == 'E' {
|
|
||||||
ch = s.scanExponent(ch)
|
|
||||||
return token.FLOAT
|
|
||||||
}
|
|
||||||
|
|
||||||
if ch == '.' {
|
|
||||||
ch = s.scanFraction(ch)
|
|
||||||
if ch == 'e' || ch == 'E' {
|
|
||||||
ch = s.next()
|
|
||||||
ch = s.scanExponent(ch)
|
|
||||||
}
|
|
||||||
return token.FLOAT
|
|
||||||
}
|
|
||||||
|
|
||||||
if ch != eof {
|
|
||||||
s.unread()
|
|
||||||
}
|
|
||||||
return token.NUMBER
|
|
||||||
}
|
|
||||||
|
|
||||||
// scanMantissa scans the mantissa begining from the rune. It returns the next
|
|
||||||
// non decimal rune. It's used to determine wheter it's a fraction or exponent.
|
|
||||||
func (s *Scanner) scanMantissa(ch rune) rune {
|
|
||||||
scanned := false
|
|
||||||
for isDecimal(ch) {
|
|
||||||
ch = s.next()
|
|
||||||
scanned = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if scanned && ch != eof {
|
|
||||||
s.unread()
|
|
||||||
}
|
|
||||||
return ch
|
|
||||||
}
|
|
||||||
|
|
||||||
// scanFraction scans the fraction after the '.' rune
|
|
||||||
func (s *Scanner) scanFraction(ch rune) rune {
|
|
||||||
if ch == '.' {
|
|
||||||
ch = s.peek() // we peek just to see if we can move forward
|
|
||||||
ch = s.scanMantissa(ch)
|
|
||||||
}
|
|
||||||
return ch
|
|
||||||
}
|
|
||||||
|
|
||||||
// scanExponent scans the remaining parts of an exponent after the 'e' or 'E'
|
|
||||||
// rune.
|
|
||||||
func (s *Scanner) scanExponent(ch rune) rune {
|
|
||||||
if ch == 'e' || ch == 'E' {
|
|
||||||
ch = s.next()
|
|
||||||
if ch == '-' || ch == '+' {
|
|
||||||
ch = s.next()
|
|
||||||
}
|
|
||||||
ch = s.scanMantissa(ch)
|
|
||||||
}
|
|
||||||
return ch
|
|
||||||
}
|
|
||||||
|
|
||||||
// scanHeredoc scans a heredoc string
|
|
||||||
func (s *Scanner) scanHeredoc() {
|
|
||||||
// Scan the second '<' in example: '<<EOF'
|
|
||||||
if s.next() != '<' {
|
|
||||||
s.err("heredoc expected second '<', didn't see it")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the original offset so we can read just the heredoc ident
|
|
||||||
offs := s.srcPos.Offset
|
|
||||||
|
|
||||||
// Scan the identifier
|
|
||||||
ch := s.next()
|
|
||||||
|
|
||||||
// Indented heredoc syntax
|
|
||||||
if ch == '-' {
|
|
||||||
ch = s.next()
|
|
||||||
}
|
|
||||||
|
|
||||||
for isLetter(ch) || isDigit(ch) {
|
|
||||||
ch = s.next()
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we reached an EOF then that is not good
|
|
||||||
if ch == eof {
|
|
||||||
s.err("heredoc not terminated")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ignore the '\r' in Windows line endings
|
|
||||||
if ch == '\r' {
|
|
||||||
if s.peek() == '\n' {
|
|
||||||
ch = s.next()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we didn't reach a newline then that is also not good
|
|
||||||
if ch != '\n' {
|
|
||||||
s.err("invalid characters in heredoc anchor")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read the identifier
|
|
||||||
identBytes := s.src[offs : s.srcPos.Offset-s.lastCharLen]
|
|
||||||
if len(identBytes) == 0 {
|
|
||||||
s.err("zero-length heredoc anchor")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var identRegexp *regexp.Regexp
|
|
||||||
if identBytes[0] == '-' {
|
|
||||||
identRegexp = regexp.MustCompile(fmt.Sprintf(`[[:space:]]*%s\z`, identBytes[1:]))
|
|
||||||
} else {
|
|
||||||
identRegexp = regexp.MustCompile(fmt.Sprintf(`[[:space:]]*%s\z`, identBytes))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read the actual string value
|
|
||||||
lineStart := s.srcPos.Offset
|
|
||||||
for {
|
|
||||||
ch := s.next()
|
|
||||||
|
|
||||||
// Special newline handling.
|
|
||||||
if ch == '\n' {
|
|
||||||
// Math is fast, so we first compare the byte counts to see if we have a chance
|
|
||||||
// of seeing the same identifier - if the length is less than the number of bytes
|
|
||||||
// in the identifier, this cannot be a valid terminator.
|
|
||||||
lineBytesLen := s.srcPos.Offset - s.lastCharLen - lineStart
|
|
||||||
if lineBytesLen >= len(identBytes) && identRegexp.Match(s.src[lineStart:s.srcPos.Offset-s.lastCharLen]) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// Not an anchor match, record the start of a new line
|
|
||||||
lineStart = s.srcPos.Offset
|
|
||||||
}
|
|
||||||
|
|
||||||
if ch == eof {
|
|
||||||
s.err("heredoc not terminated")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// scanString scans a quoted string
|
|
||||||
func (s *Scanner) scanString() {
|
|
||||||
braces := 0
|
|
||||||
for {
|
|
||||||
// '"' opening already consumed
|
|
||||||
// read character after quote
|
|
||||||
ch := s.next()
|
|
||||||
|
|
||||||
if ch < 0 || ch == eof {
|
|
||||||
s.err("literal not terminated")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if ch == '"' && braces == 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we're going into a ${} then we can ignore quotes for awhile
|
|
||||||
if braces == 0 && ch == '$' && s.peek() == '{' {
|
|
||||||
braces++
|
|
||||||
s.next()
|
|
||||||
} else if braces > 0 && ch == '{' {
|
|
||||||
braces++
|
|
||||||
}
|
|
||||||
if braces > 0 && ch == '}' {
|
|
||||||
braces--
|
|
||||||
}
|
|
||||||
|
|
||||||
if ch == '\\' {
|
|
||||||
s.scanEscape()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// scanEscape scans an escape sequence
|
|
||||||
func (s *Scanner) scanEscape() rune {
|
|
||||||
// http://en.cppreference.com/w/cpp/language/escape
|
|
||||||
ch := s.next() // read character after '/'
|
|
||||||
switch ch {
|
|
||||||
case 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', '"':
|
|
||||||
// nothing to do
|
|
||||||
case '0', '1', '2', '3', '4', '5', '6', '7':
|
|
||||||
// octal notation
|
|
||||||
ch = s.scanDigits(ch, 8, 3)
|
|
||||||
case 'x':
|
|
||||||
// hexademical notation
|
|
||||||
ch = s.scanDigits(s.next(), 16, 2)
|
|
||||||
case 'u':
|
|
||||||
// universal character name
|
|
||||||
ch = s.scanDigits(s.next(), 16, 4)
|
|
||||||
case 'U':
|
|
||||||
// universal character name
|
|
||||||
ch = s.scanDigits(s.next(), 16, 8)
|
|
||||||
default:
|
|
||||||
s.err("illegal char escape")
|
|
||||||
}
|
|
||||||
return ch
|
|
||||||
}
|
|
||||||
|
|
||||||
// scanDigits scans a rune with the given base for n times. For example an
|
|
||||||
// octal notation \184 would yield in scanDigits(ch, 8, 3)
|
|
||||||
func (s *Scanner) scanDigits(ch rune, base, n int) rune {
|
|
||||||
start := n
|
|
||||||
for n > 0 && digitVal(ch) < base {
|
|
||||||
ch = s.next()
|
|
||||||
if ch == eof {
|
|
||||||
// If we see an EOF, we halt any more scanning of digits
|
|
||||||
// immediately.
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
n--
|
|
||||||
}
|
|
||||||
if n > 0 {
|
|
||||||
s.err("illegal char escape")
|
|
||||||
}
|
|
||||||
|
|
||||||
if n != start {
|
|
||||||
// we scanned all digits, put the last non digit char back,
|
|
||||||
// only if we read anything at all
|
|
||||||
s.unread()
|
|
||||||
}
|
|
||||||
|
|
||||||
return ch
|
|
||||||
}
|
|
||||||
|
|
||||||
// scanIdentifier scans an identifier and returns the literal string
|
|
||||||
func (s *Scanner) scanIdentifier() string {
|
|
||||||
offs := s.srcPos.Offset - s.lastCharLen
|
|
||||||
ch := s.next()
|
|
||||||
for isLetter(ch) || isDigit(ch) || ch == '-' || ch == '.' {
|
|
||||||
ch = s.next()
|
|
||||||
}
|
|
||||||
|
|
||||||
if ch != eof {
|
|
||||||
s.unread() // we got identifier, put back latest char
|
|
||||||
}
|
|
||||||
|
|
||||||
return string(s.src[offs:s.srcPos.Offset])
|
|
||||||
}
|
|
||||||
|
|
||||||
// recentPosition returns the position of the character immediately after the
|
|
||||||
// character or token returned by the last call to Scan.
|
|
||||||
func (s *Scanner) recentPosition() (pos token.Pos) {
|
|
||||||
pos.Offset = s.srcPos.Offset - s.lastCharLen
|
|
||||||
switch {
|
|
||||||
case s.srcPos.Column > 0:
|
|
||||||
// common case: last character was not a '\n'
|
|
||||||
pos.Line = s.srcPos.Line
|
|
||||||
pos.Column = s.srcPos.Column
|
|
||||||
case s.lastLineLen > 0:
|
|
||||||
// last character was a '\n'
|
|
||||||
// (we cannot be at the beginning of the source
|
|
||||||
// since we have called next() at least once)
|
|
||||||
pos.Line = s.srcPos.Line - 1
|
|
||||||
pos.Column = s.lastLineLen
|
|
||||||
default:
|
|
||||||
// at the beginning of the source
|
|
||||||
pos.Line = 1
|
|
||||||
pos.Column = 1
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// err prints the error of any scanning to s.Error function. If the function is
|
|
||||||
// not defined, by default it prints them to os.Stderr
|
|
||||||
func (s *Scanner) err(msg string) {
|
|
||||||
s.ErrorCount++
|
|
||||||
pos := s.recentPosition()
|
|
||||||
|
|
||||||
if s.Error != nil {
|
|
||||||
s.Error(pos, msg)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Fprintf(os.Stderr, "%s: %s\n", pos, msg)
|
|
||||||
}
|
|
||||||
|
|
||||||
// isHexadecimal returns true if the given rune is a letter
|
|
||||||
func isLetter(ch rune) bool {
|
|
||||||
return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' || ch >= 0x80 && unicode.IsLetter(ch)
|
|
||||||
}
|
|
||||||
|
|
||||||
// isDigit returns true if the given rune is a decimal digit
|
|
||||||
func isDigit(ch rune) bool {
|
|
||||||
return '0' <= ch && ch <= '9' || ch >= 0x80 && unicode.IsDigit(ch)
|
|
||||||
}
|
|
||||||
|
|
||||||
// isDecimal returns true if the given rune is a decimal number
|
|
||||||
func isDecimal(ch rune) bool {
|
|
||||||
return '0' <= ch && ch <= '9'
|
|
||||||
}
|
|
||||||
|
|
||||||
// isHexadecimal returns true if the given rune is an hexadecimal number
|
|
||||||
func isHexadecimal(ch rune) bool {
|
|
||||||
return '0' <= ch && ch <= '9' || 'a' <= ch && ch <= 'f' || 'A' <= ch && ch <= 'F'
|
|
||||||
}
|
|
||||||
|
|
||||||
// isWhitespace returns true if the rune is a space, tab, newline or carriage return
|
|
||||||
func isWhitespace(ch rune) bool {
|
|
||||||
return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r'
|
|
||||||
}
|
|
||||||
|
|
||||||
// digitVal returns the integer value of a given octal,decimal or hexadecimal rune
|
|
||||||
func digitVal(ch rune) int {
|
|
||||||
switch {
|
|
||||||
case '0' <= ch && ch <= '9':
|
|
||||||
return int(ch - '0')
|
|
||||||
case 'a' <= ch && ch <= 'f':
|
|
||||||
return int(ch - 'a' + 10)
|
|
||||||
case 'A' <= ch && ch <= 'F':
|
|
||||||
return int(ch - 'A' + 10)
|
|
||||||
}
|
|
||||||
return 16 // larger than any legal digit val
|
|
||||||
}
|
|
244
vendor/github.com/hashicorp/hcl/hcl/strconv/quote.go
generated
vendored
244
vendor/github.com/hashicorp/hcl/hcl/strconv/quote.go
generated
vendored
|
@ -1,244 +0,0 @@
|
||||||
package strconv
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"unicode/utf8"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ErrSyntax indicates that a value does not have the right syntax for the target type.
|
|
||||||
var ErrSyntax = errors.New("invalid syntax")
|
|
||||||
|
|
||||||
// Unquote interprets s as a single-quoted, double-quoted,
|
|
||||||
// or backquoted Go string literal, returning the string value
|
|
||||||
// that s quotes. (If s is single-quoted, it would be a Go
|
|
||||||
// character literal; Unquote returns the corresponding
|
|
||||||
// one-character string.)
|
|
||||||
func Unquote(s string) (t string, err error) {
|
|
||||||
n := len(s)
|
|
||||||
if n < 2 {
|
|
||||||
return "", ErrSyntax
|
|
||||||
}
|
|
||||||
quote := s[0]
|
|
||||||
if quote != s[n-1] {
|
|
||||||
return "", ErrSyntax
|
|
||||||
}
|
|
||||||
s = s[1 : n-1]
|
|
||||||
|
|
||||||
if quote != '"' {
|
|
||||||
return "", ErrSyntax
|
|
||||||
}
|
|
||||||
|
|
||||||
// Is it trivial? Avoid allocation.
|
|
||||||
if !contains(s, '\\') && !contains(s, quote) && !contains(s, '$') {
|
|
||||||
switch quote {
|
|
||||||
case '"':
|
|
||||||
return s, nil
|
|
||||||
case '\'':
|
|
||||||
r, size := utf8.DecodeRuneInString(s)
|
|
||||||
if size == len(s) && (r != utf8.RuneError || size != 1) {
|
|
||||||
return s, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var runeTmp [utf8.UTFMax]byte
|
|
||||||
buf := make([]byte, 0, 3*len(s)/2) // Try to avoid more allocations.
|
|
||||||
for len(s) > 0 {
|
|
||||||
// If we're starting a '${}' then let it through un-unquoted.
|
|
||||||
// Specifically: we don't unquote any characters within the `${}`
|
|
||||||
// section, except for escaped backslashes, which we handle specifically.
|
|
||||||
if s[0] == '$' && len(s) > 1 && s[1] == '{' {
|
|
||||||
buf = append(buf, '$', '{')
|
|
||||||
s = s[2:]
|
|
||||||
|
|
||||||
// Continue reading until we find the closing brace, copying as-is
|
|
||||||
braces := 1
|
|
||||||
for len(s) > 0 && braces > 0 {
|
|
||||||
r, size := utf8.DecodeRuneInString(s)
|
|
||||||
if r == utf8.RuneError {
|
|
||||||
return "", ErrSyntax
|
|
||||||
}
|
|
||||||
|
|
||||||
s = s[size:]
|
|
||||||
|
|
||||||
// We special case escaped backslashes in interpolations, converting
|
|
||||||
// them to their unescaped equivalents.
|
|
||||||
if r == '\\' {
|
|
||||||
q, _ := utf8.DecodeRuneInString(s)
|
|
||||||
switch q {
|
|
||||||
case '\\':
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
n := utf8.EncodeRune(runeTmp[:], r)
|
|
||||||
buf = append(buf, runeTmp[:n]...)
|
|
||||||
|
|
||||||
switch r {
|
|
||||||
case '{':
|
|
||||||
braces++
|
|
||||||
case '}':
|
|
||||||
braces--
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if braces != 0 {
|
|
||||||
return "", ErrSyntax
|
|
||||||
}
|
|
||||||
if len(s) == 0 {
|
|
||||||
// If there's no string left, we're done!
|
|
||||||
break
|
|
||||||
} else {
|
|
||||||
// If there's more left, we need to pop back up to the top of the loop
|
|
||||||
// in case there's another interpolation in this string.
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
c, multibyte, ss, err := unquoteChar(s, quote)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
s = ss
|
|
||||||
if c < utf8.RuneSelf || !multibyte {
|
|
||||||
buf = append(buf, byte(c))
|
|
||||||
} else {
|
|
||||||
n := utf8.EncodeRune(runeTmp[:], c)
|
|
||||||
buf = append(buf, runeTmp[:n]...)
|
|
||||||
}
|
|
||||||
if quote == '\'' && len(s) != 0 {
|
|
||||||
// single-quoted must be single character
|
|
||||||
return "", ErrSyntax
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return string(buf), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// contains reports whether the string contains the byte c.
|
|
||||||
func contains(s string, c byte) bool {
|
|
||||||
for i := 0; i < len(s); i++ {
|
|
||||||
if s[i] == c {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func unhex(b byte) (v rune, ok bool) {
|
|
||||||
c := rune(b)
|
|
||||||
switch {
|
|
||||||
case '0' <= c && c <= '9':
|
|
||||||
return c - '0', true
|
|
||||||
case 'a' <= c && c <= 'f':
|
|
||||||
return c - 'a' + 10, true
|
|
||||||
case 'A' <= c && c <= 'F':
|
|
||||||
return c - 'A' + 10, true
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func unquoteChar(s string, quote byte) (value rune, multibyte bool, tail string, err error) {
|
|
||||||
// easy cases
|
|
||||||
switch c := s[0]; {
|
|
||||||
case c == quote && (quote == '\'' || quote == '"'):
|
|
||||||
err = ErrSyntax
|
|
||||||
return
|
|
||||||
case c >= utf8.RuneSelf:
|
|
||||||
r, size := utf8.DecodeRuneInString(s)
|
|
||||||
return r, true, s[size:], nil
|
|
||||||
case c != '\\':
|
|
||||||
return rune(s[0]), false, s[1:], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// hard case: c is backslash
|
|
||||||
if len(s) <= 1 {
|
|
||||||
err = ErrSyntax
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c := s[1]
|
|
||||||
s = s[2:]
|
|
||||||
|
|
||||||
switch c {
|
|
||||||
case 'a':
|
|
||||||
value = '\a'
|
|
||||||
case 'b':
|
|
||||||
value = '\b'
|
|
||||||
case 'f':
|
|
||||||
value = '\f'
|
|
||||||
case 'n':
|
|
||||||
value = '\n'
|
|
||||||
case 'r':
|
|
||||||
value = '\r'
|
|
||||||
case 't':
|
|
||||||
value = '\t'
|
|
||||||
case 'v':
|
|
||||||
value = '\v'
|
|
||||||
case 'x', 'u', 'U':
|
|
||||||
n := 0
|
|
||||||
switch c {
|
|
||||||
case 'x':
|
|
||||||
n = 2
|
|
||||||
case 'u':
|
|
||||||
n = 4
|
|
||||||
case 'U':
|
|
||||||
n = 8
|
|
||||||
}
|
|
||||||
var v rune
|
|
||||||
if len(s) < n {
|
|
||||||
err = ErrSyntax
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for j := 0; j < n; j++ {
|
|
||||||
x, ok := unhex(s[j])
|
|
||||||
if !ok {
|
|
||||||
err = ErrSyntax
|
|
||||||
return
|
|
||||||
}
|
|
||||||
v = v<<4 | x
|
|
||||||
}
|
|
||||||
s = s[n:]
|
|
||||||
if c == 'x' {
|
|
||||||
// single-byte string, possibly not UTF-8
|
|
||||||
value = v
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if v > utf8.MaxRune {
|
|
||||||
err = ErrSyntax
|
|
||||||
return
|
|
||||||
}
|
|
||||||
value = v
|
|
||||||
multibyte = true
|
|
||||||
case '0', '1', '2', '3', '4', '5', '6', '7':
|
|
||||||
v := rune(c) - '0'
|
|
||||||
if len(s) < 2 {
|
|
||||||
err = ErrSyntax
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for j := 0; j < 2; j++ { // one digit already; two more
|
|
||||||
x := rune(s[j]) - '0'
|
|
||||||
if x < 0 || x > 7 {
|
|
||||||
err = ErrSyntax
|
|
||||||
return
|
|
||||||
}
|
|
||||||
v = (v << 3) | x
|
|
||||||
}
|
|
||||||
s = s[2:]
|
|
||||||
if v > 255 {
|
|
||||||
err = ErrSyntax
|
|
||||||
return
|
|
||||||
}
|
|
||||||
value = v
|
|
||||||
case '\\':
|
|
||||||
value = '\\'
|
|
||||||
case '\'', '"':
|
|
||||||
if c != quote {
|
|
||||||
err = ErrSyntax
|
|
||||||
return
|
|
||||||
}
|
|
||||||
value = rune(c)
|
|
||||||
default:
|
|
||||||
err = ErrSyntax
|
|
||||||
return
|
|
||||||
}
|
|
||||||
tail = s
|
|
||||||
return
|
|
||||||
}
|
|
46
vendor/github.com/hashicorp/hcl/hcl/token/position.go
generated
vendored
46
vendor/github.com/hashicorp/hcl/hcl/token/position.go
generated
vendored
|
@ -1,46 +0,0 @@
|
||||||
package token
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
// Pos describes an arbitrary source position
|
|
||||||
// including the file, line, and column location.
|
|
||||||
// A Position is valid if the line number is > 0.
|
|
||||||
type Pos struct {
|
|
||||||
Filename string // filename, if any
|
|
||||||
Offset int // offset, starting at 0
|
|
||||||
Line int // line number, starting at 1
|
|
||||||
Column int // column number, starting at 1 (character count)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsValid returns true if the position is valid.
|
|
||||||
func (p *Pos) IsValid() bool { return p.Line > 0 }
|
|
||||||
|
|
||||||
// String returns a string in one of several forms:
|
|
||||||
//
|
|
||||||
// file:line:column valid position with file name
|
|
||||||
// line:column valid position without file name
|
|
||||||
// file invalid position with file name
|
|
||||||
// - invalid position without file name
|
|
||||||
func (p Pos) String() string {
|
|
||||||
s := p.Filename
|
|
||||||
if p.IsValid() {
|
|
||||||
if s != "" {
|
|
||||||
s += ":"
|
|
||||||
}
|
|
||||||
s += fmt.Sprintf("%d:%d", p.Line, p.Column)
|
|
||||||
}
|
|
||||||
if s == "" {
|
|
||||||
s = "-"
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
// Before reports whether the position p is before u.
|
|
||||||
func (p Pos) Before(u Pos) bool {
|
|
||||||
return u.Offset > p.Offset || u.Line > p.Line
|
|
||||||
}
|
|
||||||
|
|
||||||
// After reports whether the position p is after u.
|
|
||||||
func (p Pos) After(u Pos) bool {
|
|
||||||
return u.Offset < p.Offset || u.Line < p.Line
|
|
||||||
}
|
|
219
vendor/github.com/hashicorp/hcl/hcl/token/token.go
generated
vendored
219
vendor/github.com/hashicorp/hcl/hcl/token/token.go
generated
vendored
|
@ -1,219 +0,0 @@
|
||||||
// Package token defines constants representing the lexical tokens for HCL
|
|
||||||
// (HashiCorp Configuration Language)
|
|
||||||
package token
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
hclstrconv "github.com/hashicorp/hcl/hcl/strconv"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Token defines a single HCL token which can be obtained via the Scanner
|
|
||||||
type Token struct {
|
|
||||||
Type Type
|
|
||||||
Pos Pos
|
|
||||||
Text string
|
|
||||||
JSON bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// Type is the set of lexical tokens of the HCL (HashiCorp Configuration Language)
|
|
||||||
type Type int
|
|
||||||
|
|
||||||
const (
|
|
||||||
// Special tokens
|
|
||||||
ILLEGAL Type = iota
|
|
||||||
EOF
|
|
||||||
COMMENT
|
|
||||||
|
|
||||||
identifier_beg
|
|
||||||
IDENT // literals
|
|
||||||
literal_beg
|
|
||||||
NUMBER // 12345
|
|
||||||
FLOAT // 123.45
|
|
||||||
BOOL // true,false
|
|
||||||
STRING // "abc"
|
|
||||||
HEREDOC // <<FOO\nbar\nFOO
|
|
||||||
literal_end
|
|
||||||
identifier_end
|
|
||||||
|
|
||||||
operator_beg
|
|
||||||
LBRACK // [
|
|
||||||
LBRACE // {
|
|
||||||
COMMA // ,
|
|
||||||
PERIOD // .
|
|
||||||
|
|
||||||
RBRACK // ]
|
|
||||||
RBRACE // }
|
|
||||||
|
|
||||||
ASSIGN // =
|
|
||||||
ADD // +
|
|
||||||
SUB // -
|
|
||||||
operator_end
|
|
||||||
)
|
|
||||||
|
|
||||||
var tokens = [...]string{
|
|
||||||
ILLEGAL: "ILLEGAL",
|
|
||||||
|
|
||||||
EOF: "EOF",
|
|
||||||
COMMENT: "COMMENT",
|
|
||||||
|
|
||||||
IDENT: "IDENT",
|
|
||||||
NUMBER: "NUMBER",
|
|
||||||
FLOAT: "FLOAT",
|
|
||||||
BOOL: "BOOL",
|
|
||||||
STRING: "STRING",
|
|
||||||
|
|
||||||
LBRACK: "LBRACK",
|
|
||||||
LBRACE: "LBRACE",
|
|
||||||
COMMA: "COMMA",
|
|
||||||
PERIOD: "PERIOD",
|
|
||||||
HEREDOC: "HEREDOC",
|
|
||||||
|
|
||||||
RBRACK: "RBRACK",
|
|
||||||
RBRACE: "RBRACE",
|
|
||||||
|
|
||||||
ASSIGN: "ASSIGN",
|
|
||||||
ADD: "ADD",
|
|
||||||
SUB: "SUB",
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns the string corresponding to the token tok.
|
|
||||||
func (t Type) String() string {
|
|
||||||
s := ""
|
|
||||||
if 0 <= t && t < Type(len(tokens)) {
|
|
||||||
s = tokens[t]
|
|
||||||
}
|
|
||||||
if s == "" {
|
|
||||||
s = "token(" + strconv.Itoa(int(t)) + ")"
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsIdentifier returns true for tokens corresponding to identifiers and basic
|
|
||||||
// type literals; it returns false otherwise.
|
|
||||||
func (t Type) IsIdentifier() bool { return identifier_beg < t && t < identifier_end }
|
|
||||||
|
|
||||||
// IsLiteral returns true for tokens corresponding to basic type literals; it
|
|
||||||
// returns false otherwise.
|
|
||||||
func (t Type) IsLiteral() bool { return literal_beg < t && t < literal_end }
|
|
||||||
|
|
||||||
// IsOperator returns true for tokens corresponding to operators and
|
|
||||||
// delimiters; it returns false otherwise.
|
|
||||||
func (t Type) IsOperator() bool { return operator_beg < t && t < operator_end }
|
|
||||||
|
|
||||||
// String returns the token's literal text. Note that this is only
|
|
||||||
// applicable for certain token types, such as token.IDENT,
|
|
||||||
// token.STRING, etc..
|
|
||||||
func (t Token) String() string {
|
|
||||||
return fmt.Sprintf("%s %s %s", t.Pos.String(), t.Type.String(), t.Text)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Value returns the properly typed value for this token. The type of
|
|
||||||
// the returned interface{} is guaranteed based on the Type field.
|
|
||||||
//
|
|
||||||
// This can only be called for literal types. If it is called for any other
|
|
||||||
// type, this will panic.
|
|
||||||
func (t Token) Value() interface{} {
|
|
||||||
switch t.Type {
|
|
||||||
case BOOL:
|
|
||||||
if t.Text == "true" {
|
|
||||||
return true
|
|
||||||
} else if t.Text == "false" {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
panic("unknown bool value: " + t.Text)
|
|
||||||
case FLOAT:
|
|
||||||
v, err := strconv.ParseFloat(t.Text, 64)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return float64(v)
|
|
||||||
case NUMBER:
|
|
||||||
v, err := strconv.ParseInt(t.Text, 0, 64)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return int64(v)
|
|
||||||
case IDENT:
|
|
||||||
return t.Text
|
|
||||||
case HEREDOC:
|
|
||||||
return unindentHeredoc(t.Text)
|
|
||||||
case STRING:
|
|
||||||
// Determine the Unquote method to use. If it came from JSON,
|
|
||||||
// then we need to use the built-in unquote since we have to
|
|
||||||
// escape interpolations there.
|
|
||||||
f := hclstrconv.Unquote
|
|
||||||
if t.JSON {
|
|
||||||
f = strconv.Unquote
|
|
||||||
}
|
|
||||||
|
|
||||||
// This case occurs if json null is used
|
|
||||||
if t.Text == "" {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
v, err := f(t.Text)
|
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Sprintf("unquote %s err: %s", t.Text, err))
|
|
||||||
}
|
|
||||||
|
|
||||||
return v
|
|
||||||
default:
|
|
||||||
panic(fmt.Sprintf("unimplemented Value for type: %s", t.Type))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// unindentHeredoc returns the string content of a HEREDOC if it is started with <<
|
|
||||||
// and the content of a HEREDOC with the hanging indent removed if it is started with
|
|
||||||
// a <<-, and the terminating line is at least as indented as the least indented line.
|
|
||||||
func unindentHeredoc(heredoc string) string {
|
|
||||||
// We need to find the end of the marker
|
|
||||||
idx := strings.IndexByte(heredoc, '\n')
|
|
||||||
if idx == -1 {
|
|
||||||
panic("heredoc doesn't contain newline")
|
|
||||||
}
|
|
||||||
|
|
||||||
unindent := heredoc[2] == '-'
|
|
||||||
|
|
||||||
// We can optimize if the heredoc isn't marked for indentation
|
|
||||||
if !unindent {
|
|
||||||
return string(heredoc[idx+1 : len(heredoc)-idx+1])
|
|
||||||
}
|
|
||||||
|
|
||||||
// We need to unindent each line based on the indentation level of the marker
|
|
||||||
lines := strings.Split(string(heredoc[idx+1:len(heredoc)-idx+2]), "\n")
|
|
||||||
whitespacePrefix := lines[len(lines)-1]
|
|
||||||
|
|
||||||
isIndented := true
|
|
||||||
for _, v := range lines {
|
|
||||||
if strings.HasPrefix(v, whitespacePrefix) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
isIndented = false
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// If all lines are not at least as indented as the terminating mark, return the
|
|
||||||
// heredoc as is, but trim the leading space from the marker on the final line.
|
|
||||||
if !isIndented {
|
|
||||||
return strings.TrimRight(string(heredoc[idx+1:len(heredoc)-idx+1]), " \t")
|
|
||||||
}
|
|
||||||
|
|
||||||
unindentedLines := make([]string, len(lines))
|
|
||||||
for k, v := range lines {
|
|
||||||
if k == len(lines)-1 {
|
|
||||||
unindentedLines[k] = ""
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
unindentedLines[k] = strings.TrimPrefix(v, whitespacePrefix)
|
|
||||||
}
|
|
||||||
|
|
||||||
return strings.Join(unindentedLines, "\n")
|
|
||||||
}
|
|
111
vendor/github.com/hashicorp/hcl/json/parser/flatten.go
generated
vendored
111
vendor/github.com/hashicorp/hcl/json/parser/flatten.go
generated
vendored
|
@ -1,111 +0,0 @@
|
||||||
package parser
|
|
||||||
|
|
||||||
import "github.com/hashicorp/hcl/hcl/ast"
|
|
||||||
|
|
||||||
// flattenObjects takes an AST node, walks it, and flattens
|
|
||||||
func flattenObjects(node ast.Node) {
|
|
||||||
ast.Walk(node, func(n ast.Node) (ast.Node, bool) {
|
|
||||||
// We only care about lists, because this is what we modify
|
|
||||||
list, ok := n.(*ast.ObjectList)
|
|
||||||
if !ok {
|
|
||||||
return n, true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rebuild the item list
|
|
||||||
items := make([]*ast.ObjectItem, 0, len(list.Items))
|
|
||||||
frontier := make([]*ast.ObjectItem, len(list.Items))
|
|
||||||
copy(frontier, list.Items)
|
|
||||||
for len(frontier) > 0 {
|
|
||||||
// Pop the current item
|
|
||||||
n := len(frontier)
|
|
||||||
item := frontier[n-1]
|
|
||||||
frontier = frontier[:n-1]
|
|
||||||
|
|
||||||
switch v := item.Val.(type) {
|
|
||||||
case *ast.ObjectType:
|
|
||||||
items, frontier = flattenObjectType(v, item, items, frontier)
|
|
||||||
case *ast.ListType:
|
|
||||||
items, frontier = flattenListType(v, item, items, frontier)
|
|
||||||
default:
|
|
||||||
items = append(items, item)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reverse the list since the frontier model runs things backwards
|
|
||||||
for i := len(items)/2 - 1; i >= 0; i-- {
|
|
||||||
opp := len(items) - 1 - i
|
|
||||||
items[i], items[opp] = items[opp], items[i]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Done! Set the original items
|
|
||||||
list.Items = items
|
|
||||||
return n, true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func flattenListType(
|
|
||||||
ot *ast.ListType,
|
|
||||||
item *ast.ObjectItem,
|
|
||||||
items []*ast.ObjectItem,
|
|
||||||
frontier []*ast.ObjectItem) ([]*ast.ObjectItem, []*ast.ObjectItem) {
|
|
||||||
// All the elements of this object must also be objects!
|
|
||||||
for _, subitem := range ot.List {
|
|
||||||
if _, ok := subitem.(*ast.ObjectType); !ok {
|
|
||||||
items = append(items, item)
|
|
||||||
return items, frontier
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Great! We have a match go through all the items and flatten
|
|
||||||
for _, elem := range ot.List {
|
|
||||||
// Add it to the frontier so that we can recurse
|
|
||||||
frontier = append(frontier, &ast.ObjectItem{
|
|
||||||
Keys: item.Keys,
|
|
||||||
Assign: item.Assign,
|
|
||||||
Val: elem,
|
|
||||||
LeadComment: item.LeadComment,
|
|
||||||
LineComment: item.LineComment,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return items, frontier
|
|
||||||
}
|
|
||||||
|
|
||||||
func flattenObjectType(
|
|
||||||
ot *ast.ObjectType,
|
|
||||||
item *ast.ObjectItem,
|
|
||||||
items []*ast.ObjectItem,
|
|
||||||
frontier []*ast.ObjectItem) ([]*ast.ObjectItem, []*ast.ObjectItem) {
|
|
||||||
// If the list has no items we do not have to flatten anything
|
|
||||||
if ot.List.Items == nil {
|
|
||||||
items = append(items, item)
|
|
||||||
return items, frontier
|
|
||||||
}
|
|
||||||
|
|
||||||
// All the elements of this object must also be objects!
|
|
||||||
for _, subitem := range ot.List.Items {
|
|
||||||
if _, ok := subitem.Val.(*ast.ObjectType); !ok {
|
|
||||||
items = append(items, item)
|
|
||||||
return items, frontier
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Great! We have a match go through all the items and flatten
|
|
||||||
for _, subitem := range ot.List.Items {
|
|
||||||
// Copy the new key
|
|
||||||
keys := make([]*ast.ObjectKey, len(item.Keys)+len(subitem.Keys))
|
|
||||||
copy(keys, item.Keys)
|
|
||||||
copy(keys[len(item.Keys):], subitem.Keys)
|
|
||||||
|
|
||||||
// Add it to the frontier so that we can recurse
|
|
||||||
frontier = append(frontier, &ast.ObjectItem{
|
|
||||||
Keys: keys,
|
|
||||||
Assign: item.Assign,
|
|
||||||
Val: subitem.Val,
|
|
||||||
LeadComment: item.LeadComment,
|
|
||||||
LineComment: item.LineComment,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return items, frontier
|
|
||||||
}
|
|
303
vendor/github.com/hashicorp/hcl/json/parser/parser.go
generated
vendored
303
vendor/github.com/hashicorp/hcl/json/parser/parser.go
generated
vendored
|
@ -1,303 +0,0 @@
|
||||||
package parser
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/hashicorp/hcl/hcl/ast"
|
|
||||||
"github.com/hashicorp/hcl/json/scanner"
|
|
||||||
"github.com/hashicorp/hcl/json/token"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Parser struct {
|
|
||||||
sc *scanner.Scanner
|
|
||||||
|
|
||||||
// Last read token
|
|
||||||
tok token.Token
|
|
||||||
commaPrev token.Token
|
|
||||||
|
|
||||||
enableTrace bool
|
|
||||||
indent int
|
|
||||||
n int // buffer size (max = 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func newParser(src []byte) *Parser {
|
|
||||||
return &Parser{
|
|
||||||
sc: scanner.New(src),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse returns the fully parsed source and returns the abstract syntax tree.
|
|
||||||
func Parse(src []byte) (*ast.File, error) {
|
|
||||||
p := newParser(src)
|
|
||||||
return p.Parse()
|
|
||||||
}
|
|
||||||
|
|
||||||
var errEofToken = errors.New("EOF token found")
|
|
||||||
|
|
||||||
// Parse returns the fully parsed source and returns the abstract syntax tree.
|
|
||||||
func (p *Parser) Parse() (*ast.File, error) {
|
|
||||||
f := &ast.File{}
|
|
||||||
var err, scerr error
|
|
||||||
p.sc.Error = func(pos token.Pos, msg string) {
|
|
||||||
scerr = fmt.Errorf("%s: %s", pos, msg)
|
|
||||||
}
|
|
||||||
|
|
||||||
// The root must be an object in JSON
|
|
||||||
object, err := p.object()
|
|
||||||
if scerr != nil {
|
|
||||||
return nil, scerr
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// We make our final node an object list so it is more HCL compatible
|
|
||||||
f.Node = object.List
|
|
||||||
|
|
||||||
// Flatten it, which finds patterns and turns them into more HCL-like
|
|
||||||
// AST trees.
|
|
||||||
flattenObjects(f.Node)
|
|
||||||
|
|
||||||
return f, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Parser) objectList() (*ast.ObjectList, error) {
|
|
||||||
defer un(trace(p, "ParseObjectList"))
|
|
||||||
node := &ast.ObjectList{}
|
|
||||||
|
|
||||||
for {
|
|
||||||
n, err := p.objectItem()
|
|
||||||
if err == errEofToken {
|
|
||||||
break // we are finished
|
|
||||||
}
|
|
||||||
|
|
||||||
// we don't return a nil node, because might want to use already
|
|
||||||
// collected items.
|
|
||||||
if err != nil {
|
|
||||||
return node, err
|
|
||||||
}
|
|
||||||
|
|
||||||
node.Add(n)
|
|
||||||
|
|
||||||
// Check for a followup comma. If it isn't a comma, then we're done
|
|
||||||
if tok := p.scan(); tok.Type != token.COMMA {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return node, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// objectItem parses a single object item
|
|
||||||
func (p *Parser) objectItem() (*ast.ObjectItem, error) {
|
|
||||||
defer un(trace(p, "ParseObjectItem"))
|
|
||||||
|
|
||||||
keys, err := p.objectKey()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
o := &ast.ObjectItem{
|
|
||||||
Keys: keys,
|
|
||||||
}
|
|
||||||
|
|
||||||
switch p.tok.Type {
|
|
||||||
case token.COLON:
|
|
||||||
o.Val, err = p.objectValue()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return o, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// objectKey parses an object key and returns a ObjectKey AST
|
|
||||||
func (p *Parser) objectKey() ([]*ast.ObjectKey, error) {
|
|
||||||
keyCount := 0
|
|
||||||
keys := make([]*ast.ObjectKey, 0)
|
|
||||||
|
|
||||||
for {
|
|
||||||
tok := p.scan()
|
|
||||||
switch tok.Type {
|
|
||||||
case token.EOF:
|
|
||||||
return nil, errEofToken
|
|
||||||
case token.STRING:
|
|
||||||
keyCount++
|
|
||||||
keys = append(keys, &ast.ObjectKey{
|
|
||||||
Token: p.tok.HCLToken(),
|
|
||||||
})
|
|
||||||
case token.COLON:
|
|
||||||
// If we have a zero keycount it means that we never got
|
|
||||||
// an object key, i.e. `{ :`. This is a syntax error.
|
|
||||||
if keyCount == 0 {
|
|
||||||
return nil, fmt.Errorf("expected: STRING got: %s", p.tok.Type)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Done
|
|
||||||
return keys, nil
|
|
||||||
case token.ILLEGAL:
|
|
||||||
fmt.Println("illegal")
|
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("expected: STRING got: %s", p.tok.Type)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// object parses any type of object, such as number, bool, string, object or
|
|
||||||
// list.
|
|
||||||
func (p *Parser) objectValue() (ast.Node, error) {
|
|
||||||
defer un(trace(p, "ParseObjectValue"))
|
|
||||||
tok := p.scan()
|
|
||||||
|
|
||||||
switch tok.Type {
|
|
||||||
case token.NUMBER, token.FLOAT, token.BOOL, token.NULL, token.STRING:
|
|
||||||
return p.literalType()
|
|
||||||
case token.LBRACE:
|
|
||||||
return p.objectType()
|
|
||||||
case token.LBRACK:
|
|
||||||
return p.listType()
|
|
||||||
case token.EOF:
|
|
||||||
return nil, errEofToken
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, fmt.Errorf("Expected object value, got unknown token: %+v", tok)
|
|
||||||
}
|
|
||||||
|
|
||||||
// object parses any type of object, such as number, bool, string, object or
|
|
||||||
// list.
|
|
||||||
func (p *Parser) object() (*ast.ObjectType, error) {
|
|
||||||
defer un(trace(p, "ParseType"))
|
|
||||||
tok := p.scan()
|
|
||||||
|
|
||||||
switch tok.Type {
|
|
||||||
case token.LBRACE:
|
|
||||||
return p.objectType()
|
|
||||||
case token.EOF:
|
|
||||||
return nil, errEofToken
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, fmt.Errorf("Expected object, got unknown token: %+v", tok)
|
|
||||||
}
|
|
||||||
|
|
||||||
// objectType parses an object type and returns a ObjectType AST
|
|
||||||
func (p *Parser) objectType() (*ast.ObjectType, error) {
|
|
||||||
defer un(trace(p, "ParseObjectType"))
|
|
||||||
|
|
||||||
// we assume that the currently scanned token is a LBRACE
|
|
||||||
o := &ast.ObjectType{}
|
|
||||||
|
|
||||||
l, err := p.objectList()
|
|
||||||
|
|
||||||
// if we hit RBRACE, we are good to go (means we parsed all Items), if it's
|
|
||||||
// not a RBRACE, it's an syntax error and we just return it.
|
|
||||||
if err != nil && p.tok.Type != token.RBRACE {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
o.List = l
|
|
||||||
return o, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// listType parses a list type and returns a ListType AST
|
|
||||||
func (p *Parser) listType() (*ast.ListType, error) {
|
|
||||||
defer un(trace(p, "ParseListType"))
|
|
||||||
|
|
||||||
// we assume that the currently scanned token is a LBRACK
|
|
||||||
l := &ast.ListType{}
|
|
||||||
|
|
||||||
for {
|
|
||||||
tok := p.scan()
|
|
||||||
switch tok.Type {
|
|
||||||
case token.NUMBER, token.FLOAT, token.STRING:
|
|
||||||
node, err := p.literalType()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
l.Add(node)
|
|
||||||
case token.COMMA:
|
|
||||||
continue
|
|
||||||
case token.LBRACE:
|
|
||||||
node, err := p.objectType()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
l.Add(node)
|
|
||||||
case token.BOOL:
|
|
||||||
// TODO(arslan) should we support? not supported by HCL yet
|
|
||||||
case token.LBRACK:
|
|
||||||
// TODO(arslan) should we support nested lists? Even though it's
|
|
||||||
// written in README of HCL, it's not a part of the grammar
|
|
||||||
// (not defined in parse.y)
|
|
||||||
case token.RBRACK:
|
|
||||||
// finished
|
|
||||||
return l, nil
|
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("unexpected token while parsing list: %s", tok.Type)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// literalType parses a literal type and returns a LiteralType AST
|
|
||||||
func (p *Parser) literalType() (*ast.LiteralType, error) {
|
|
||||||
defer un(trace(p, "ParseLiteral"))
|
|
||||||
|
|
||||||
return &ast.LiteralType{
|
|
||||||
Token: p.tok.HCLToken(),
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// scan returns the next token from the underlying scanner. If a token has
|
|
||||||
// been unscanned then read that instead.
|
|
||||||
func (p *Parser) scan() token.Token {
|
|
||||||
// If we have a token on the buffer, then return it.
|
|
||||||
if p.n != 0 {
|
|
||||||
p.n = 0
|
|
||||||
return p.tok
|
|
||||||
}
|
|
||||||
|
|
||||||
p.tok = p.sc.Scan()
|
|
||||||
return p.tok
|
|
||||||
}
|
|
||||||
|
|
||||||
// unscan pushes the previously read token back onto the buffer.
|
|
||||||
func (p *Parser) unscan() {
|
|
||||||
p.n = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
// Parsing support
|
|
||||||
|
|
||||||
func (p *Parser) printTrace(a ...interface{}) {
|
|
||||||
if !p.enableTrace {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const dots = ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "
|
|
||||||
const n = len(dots)
|
|
||||||
fmt.Printf("%5d:%3d: ", p.tok.Pos.Line, p.tok.Pos.Column)
|
|
||||||
|
|
||||||
i := 2 * p.indent
|
|
||||||
for i > n {
|
|
||||||
fmt.Print(dots)
|
|
||||||
i -= n
|
|
||||||
}
|
|
||||||
// i <= n
|
|
||||||
fmt.Print(dots[0:i])
|
|
||||||
fmt.Println(a...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func trace(p *Parser, msg string) *Parser {
|
|
||||||
p.printTrace(msg, "(")
|
|
||||||
p.indent++
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// Usage pattern: defer un(trace(p, "..."))
|
|
||||||
func un(p *Parser) {
|
|
||||||
p.indent--
|
|
||||||
p.printTrace(")")
|
|
||||||
}
|
|
451
vendor/github.com/hashicorp/hcl/json/scanner/scanner.go
generated
vendored
451
vendor/github.com/hashicorp/hcl/json/scanner/scanner.go
generated
vendored
|
@ -1,451 +0,0 @@
|
||||||
package scanner
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"unicode"
|
|
||||||
"unicode/utf8"
|
|
||||||
|
|
||||||
"github.com/hashicorp/hcl/json/token"
|
|
||||||
)
|
|
||||||
|
|
||||||
// eof represents a marker rune for the end of the reader.
|
|
||||||
const eof = rune(0)
|
|
||||||
|
|
||||||
// Scanner defines a lexical scanner
|
|
||||||
type Scanner struct {
|
|
||||||
buf *bytes.Buffer // Source buffer for advancing and scanning
|
|
||||||
src []byte // Source buffer for immutable access
|
|
||||||
|
|
||||||
// Source Position
|
|
||||||
srcPos token.Pos // current position
|
|
||||||
prevPos token.Pos // previous position, used for peek() method
|
|
||||||
|
|
||||||
lastCharLen int // length of last character in bytes
|
|
||||||
lastLineLen int // length of last line in characters (for correct column reporting)
|
|
||||||
|
|
||||||
tokStart int // token text start position
|
|
||||||
tokEnd int // token text end position
|
|
||||||
|
|
||||||
// Error is called for each error encountered. If no Error
|
|
||||||
// function is set, the error is reported to os.Stderr.
|
|
||||||
Error func(pos token.Pos, msg string)
|
|
||||||
|
|
||||||
// ErrorCount is incremented by one for each error encountered.
|
|
||||||
ErrorCount int
|
|
||||||
|
|
||||||
// tokPos is the start position of most recently scanned token; set by
|
|
||||||
// Scan. The Filename field is always left untouched by the Scanner. If
|
|
||||||
// an error is reported (via Error) and Position is invalid, the scanner is
|
|
||||||
// not inside a token.
|
|
||||||
tokPos token.Pos
|
|
||||||
}
|
|
||||||
|
|
||||||
// New creates and initializes a new instance of Scanner using src as
|
|
||||||
// its source content.
|
|
||||||
func New(src []byte) *Scanner {
|
|
||||||
// even though we accept a src, we read from a io.Reader compatible type
|
|
||||||
// (*bytes.Buffer). So in the future we might easily change it to streaming
|
|
||||||
// read.
|
|
||||||
b := bytes.NewBuffer(src)
|
|
||||||
s := &Scanner{
|
|
||||||
buf: b,
|
|
||||||
src: src,
|
|
||||||
}
|
|
||||||
|
|
||||||
// srcPosition always starts with 1
|
|
||||||
s.srcPos.Line = 1
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
// next reads the next rune from the bufferred reader. Returns the rune(0) if
|
|
||||||
// an error occurs (or io.EOF is returned).
|
|
||||||
func (s *Scanner) next() rune {
|
|
||||||
ch, size, err := s.buf.ReadRune()
|
|
||||||
if err != nil {
|
|
||||||
// advance for error reporting
|
|
||||||
s.srcPos.Column++
|
|
||||||
s.srcPos.Offset += size
|
|
||||||
s.lastCharLen = size
|
|
||||||
return eof
|
|
||||||
}
|
|
||||||
|
|
||||||
if ch == utf8.RuneError && size == 1 {
|
|
||||||
s.srcPos.Column++
|
|
||||||
s.srcPos.Offset += size
|
|
||||||
s.lastCharLen = size
|
|
||||||
s.err("illegal UTF-8 encoding")
|
|
||||||
return ch
|
|
||||||
}
|
|
||||||
|
|
||||||
// remember last position
|
|
||||||
s.prevPos = s.srcPos
|
|
||||||
|
|
||||||
s.srcPos.Column++
|
|
||||||
s.lastCharLen = size
|
|
||||||
s.srcPos.Offset += size
|
|
||||||
|
|
||||||
if ch == '\n' {
|
|
||||||
s.srcPos.Line++
|
|
||||||
s.lastLineLen = s.srcPos.Column
|
|
||||||
s.srcPos.Column = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// debug
|
|
||||||
// fmt.Printf("ch: %q, offset:column: %d:%d\n", ch, s.srcPos.Offset, s.srcPos.Column)
|
|
||||||
return ch
|
|
||||||
}
|
|
||||||
|
|
||||||
// unread unreads the previous read Rune and updates the source position
|
|
||||||
func (s *Scanner) unread() {
|
|
||||||
if err := s.buf.UnreadRune(); err != nil {
|
|
||||||
panic(err) // this is user fault, we should catch it
|
|
||||||
}
|
|
||||||
s.srcPos = s.prevPos // put back last position
|
|
||||||
}
|
|
||||||
|
|
||||||
// peek returns the next rune without advancing the reader.
|
|
||||||
func (s *Scanner) peek() rune {
|
|
||||||
peek, _, err := s.buf.ReadRune()
|
|
||||||
if err != nil {
|
|
||||||
return eof
|
|
||||||
}
|
|
||||||
|
|
||||||
s.buf.UnreadRune()
|
|
||||||
return peek
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scan scans the next token and returns the token.
|
|
||||||
func (s *Scanner) Scan() token.Token {
|
|
||||||
ch := s.next()
|
|
||||||
|
|
||||||
// skip white space
|
|
||||||
for isWhitespace(ch) {
|
|
||||||
ch = s.next()
|
|
||||||
}
|
|
||||||
|
|
||||||
var tok token.Type
|
|
||||||
|
|
||||||
// token text markings
|
|
||||||
s.tokStart = s.srcPos.Offset - s.lastCharLen
|
|
||||||
|
|
||||||
// token position, initial next() is moving the offset by one(size of rune
|
|
||||||
// actually), though we are interested with the starting point
|
|
||||||
s.tokPos.Offset = s.srcPos.Offset - s.lastCharLen
|
|
||||||
if s.srcPos.Column > 0 {
|
|
||||||
// common case: last character was not a '\n'
|
|
||||||
s.tokPos.Line = s.srcPos.Line
|
|
||||||
s.tokPos.Column = s.srcPos.Column
|
|
||||||
} else {
|
|
||||||
// last character was a '\n'
|
|
||||||
// (we cannot be at the beginning of the source
|
|
||||||
// since we have called next() at least once)
|
|
||||||
s.tokPos.Line = s.srcPos.Line - 1
|
|
||||||
s.tokPos.Column = s.lastLineLen
|
|
||||||
}
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case isLetter(ch):
|
|
||||||
lit := s.scanIdentifier()
|
|
||||||
if lit == "true" || lit == "false" {
|
|
||||||
tok = token.BOOL
|
|
||||||
} else if lit == "null" {
|
|
||||||
tok = token.NULL
|
|
||||||
} else {
|
|
||||||
s.err("illegal char")
|
|
||||||
}
|
|
||||||
case isDecimal(ch):
|
|
||||||
tok = s.scanNumber(ch)
|
|
||||||
default:
|
|
||||||
switch ch {
|
|
||||||
case eof:
|
|
||||||
tok = token.EOF
|
|
||||||
case '"':
|
|
||||||
tok = token.STRING
|
|
||||||
s.scanString()
|
|
||||||
case '.':
|
|
||||||
tok = token.PERIOD
|
|
||||||
ch = s.peek()
|
|
||||||
if isDecimal(ch) {
|
|
||||||
tok = token.FLOAT
|
|
||||||
ch = s.scanMantissa(ch)
|
|
||||||
ch = s.scanExponent(ch)
|
|
||||||
}
|
|
||||||
case '[':
|
|
||||||
tok = token.LBRACK
|
|
||||||
case ']':
|
|
||||||
tok = token.RBRACK
|
|
||||||
case '{':
|
|
||||||
tok = token.LBRACE
|
|
||||||
case '}':
|
|
||||||
tok = token.RBRACE
|
|
||||||
case ',':
|
|
||||||
tok = token.COMMA
|
|
||||||
case ':':
|
|
||||||
tok = token.COLON
|
|
||||||
case '-':
|
|
||||||
if isDecimal(s.peek()) {
|
|
||||||
ch := s.next()
|
|
||||||
tok = s.scanNumber(ch)
|
|
||||||
} else {
|
|
||||||
s.err("illegal char")
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
s.err("illegal char: " + string(ch))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// finish token ending
|
|
||||||
s.tokEnd = s.srcPos.Offset
|
|
||||||
|
|
||||||
// create token literal
|
|
||||||
var tokenText string
|
|
||||||
if s.tokStart >= 0 {
|
|
||||||
tokenText = string(s.src[s.tokStart:s.tokEnd])
|
|
||||||
}
|
|
||||||
s.tokStart = s.tokEnd // ensure idempotency of tokenText() call
|
|
||||||
|
|
||||||
return token.Token{
|
|
||||||
Type: tok,
|
|
||||||
Pos: s.tokPos,
|
|
||||||
Text: tokenText,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// scanNumber scans a HCL number definition starting with the given rune
|
|
||||||
func (s *Scanner) scanNumber(ch rune) token.Type {
|
|
||||||
zero := ch == '0'
|
|
||||||
pos := s.srcPos
|
|
||||||
|
|
||||||
s.scanMantissa(ch)
|
|
||||||
ch = s.next() // seek forward
|
|
||||||
if ch == 'e' || ch == 'E' {
|
|
||||||
ch = s.scanExponent(ch)
|
|
||||||
return token.FLOAT
|
|
||||||
}
|
|
||||||
|
|
||||||
if ch == '.' {
|
|
||||||
ch = s.scanFraction(ch)
|
|
||||||
if ch == 'e' || ch == 'E' {
|
|
||||||
ch = s.next()
|
|
||||||
ch = s.scanExponent(ch)
|
|
||||||
}
|
|
||||||
return token.FLOAT
|
|
||||||
}
|
|
||||||
|
|
||||||
if ch != eof {
|
|
||||||
s.unread()
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we have a larger number and this is zero, error
|
|
||||||
if zero && pos != s.srcPos {
|
|
||||||
s.err("numbers cannot start with 0")
|
|
||||||
}
|
|
||||||
|
|
||||||
return token.NUMBER
|
|
||||||
}
|
|
||||||
|
|
||||||
// scanMantissa scans the mantissa begining from the rune. It returns the next
|
|
||||||
// non decimal rune. It's used to determine wheter it's a fraction or exponent.
|
|
||||||
func (s *Scanner) scanMantissa(ch rune) rune {
|
|
||||||
scanned := false
|
|
||||||
for isDecimal(ch) {
|
|
||||||
ch = s.next()
|
|
||||||
scanned = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if scanned && ch != eof {
|
|
||||||
s.unread()
|
|
||||||
}
|
|
||||||
return ch
|
|
||||||
}
|
|
||||||
|
|
||||||
// scanFraction scans the fraction after the '.' rune
|
|
||||||
func (s *Scanner) scanFraction(ch rune) rune {
|
|
||||||
if ch == '.' {
|
|
||||||
ch = s.peek() // we peek just to see if we can move forward
|
|
||||||
ch = s.scanMantissa(ch)
|
|
||||||
}
|
|
||||||
return ch
|
|
||||||
}
|
|
||||||
|
|
||||||
// scanExponent scans the remaining parts of an exponent after the 'e' or 'E'
|
|
||||||
// rune.
|
|
||||||
func (s *Scanner) scanExponent(ch rune) rune {
|
|
||||||
if ch == 'e' || ch == 'E' {
|
|
||||||
ch = s.next()
|
|
||||||
if ch == '-' || ch == '+' {
|
|
||||||
ch = s.next()
|
|
||||||
}
|
|
||||||
ch = s.scanMantissa(ch)
|
|
||||||
}
|
|
||||||
return ch
|
|
||||||
}
|
|
||||||
|
|
||||||
// scanString scans a quoted string
|
|
||||||
func (s *Scanner) scanString() {
|
|
||||||
braces := 0
|
|
||||||
for {
|
|
||||||
// '"' opening already consumed
|
|
||||||
// read character after quote
|
|
||||||
ch := s.next()
|
|
||||||
|
|
||||||
if ch == '\n' || ch < 0 || ch == eof {
|
|
||||||
s.err("literal not terminated")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if ch == '"' {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we're going into a ${} then we can ignore quotes for awhile
|
|
||||||
if braces == 0 && ch == '$' && s.peek() == '{' {
|
|
||||||
braces++
|
|
||||||
s.next()
|
|
||||||
} else if braces > 0 && ch == '{' {
|
|
||||||
braces++
|
|
||||||
}
|
|
||||||
if braces > 0 && ch == '}' {
|
|
||||||
braces--
|
|
||||||
}
|
|
||||||
|
|
||||||
if ch == '\\' {
|
|
||||||
s.scanEscape()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// scanEscape scans an escape sequence
|
|
||||||
func (s *Scanner) scanEscape() rune {
|
|
||||||
// http://en.cppreference.com/w/cpp/language/escape
|
|
||||||
ch := s.next() // read character after '/'
|
|
||||||
switch ch {
|
|
||||||
case 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', '"':
|
|
||||||
// nothing to do
|
|
||||||
case '0', '1', '2', '3', '4', '5', '6', '7':
|
|
||||||
// octal notation
|
|
||||||
ch = s.scanDigits(ch, 8, 3)
|
|
||||||
case 'x':
|
|
||||||
// hexademical notation
|
|
||||||
ch = s.scanDigits(s.next(), 16, 2)
|
|
||||||
case 'u':
|
|
||||||
// universal character name
|
|
||||||
ch = s.scanDigits(s.next(), 16, 4)
|
|
||||||
case 'U':
|
|
||||||
// universal character name
|
|
||||||
ch = s.scanDigits(s.next(), 16, 8)
|
|
||||||
default:
|
|
||||||
s.err("illegal char escape")
|
|
||||||
}
|
|
||||||
return ch
|
|
||||||
}
|
|
||||||
|
|
||||||
// scanDigits scans a rune with the given base for n times. For example an
|
|
||||||
// octal notation \184 would yield in scanDigits(ch, 8, 3)
|
|
||||||
func (s *Scanner) scanDigits(ch rune, base, n int) rune {
|
|
||||||
for n > 0 && digitVal(ch) < base {
|
|
||||||
ch = s.next()
|
|
||||||
n--
|
|
||||||
}
|
|
||||||
if n > 0 {
|
|
||||||
s.err("illegal char escape")
|
|
||||||
}
|
|
||||||
|
|
||||||
// we scanned all digits, put the last non digit char back
|
|
||||||
s.unread()
|
|
||||||
return ch
|
|
||||||
}
|
|
||||||
|
|
||||||
// scanIdentifier scans an identifier and returns the literal string
|
|
||||||
func (s *Scanner) scanIdentifier() string {
|
|
||||||
offs := s.srcPos.Offset - s.lastCharLen
|
|
||||||
ch := s.next()
|
|
||||||
for isLetter(ch) || isDigit(ch) || ch == '-' {
|
|
||||||
ch = s.next()
|
|
||||||
}
|
|
||||||
|
|
||||||
if ch != eof {
|
|
||||||
s.unread() // we got identifier, put back latest char
|
|
||||||
}
|
|
||||||
|
|
||||||
return string(s.src[offs:s.srcPos.Offset])
|
|
||||||
}
|
|
||||||
|
|
||||||
// recentPosition returns the position of the character immediately after the
|
|
||||||
// character or token returned by the last call to Scan.
|
|
||||||
func (s *Scanner) recentPosition() (pos token.Pos) {
|
|
||||||
pos.Offset = s.srcPos.Offset - s.lastCharLen
|
|
||||||
switch {
|
|
||||||
case s.srcPos.Column > 0:
|
|
||||||
// common case: last character was not a '\n'
|
|
||||||
pos.Line = s.srcPos.Line
|
|
||||||
pos.Column = s.srcPos.Column
|
|
||||||
case s.lastLineLen > 0:
|
|
||||||
// last character was a '\n'
|
|
||||||
// (we cannot be at the beginning of the source
|
|
||||||
// since we have called next() at least once)
|
|
||||||
pos.Line = s.srcPos.Line - 1
|
|
||||||
pos.Column = s.lastLineLen
|
|
||||||
default:
|
|
||||||
// at the beginning of the source
|
|
||||||
pos.Line = 1
|
|
||||||
pos.Column = 1
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// err prints the error of any scanning to s.Error function. If the function is
|
|
||||||
// not defined, by default it prints them to os.Stderr
|
|
||||||
func (s *Scanner) err(msg string) {
|
|
||||||
s.ErrorCount++
|
|
||||||
pos := s.recentPosition()
|
|
||||||
|
|
||||||
if s.Error != nil {
|
|
||||||
s.Error(pos, msg)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Fprintf(os.Stderr, "%s: %s\n", pos, msg)
|
|
||||||
}
|
|
||||||
|
|
||||||
// isHexadecimal returns true if the given rune is a letter
|
|
||||||
func isLetter(ch rune) bool {
|
|
||||||
return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' || ch >= 0x80 && unicode.IsLetter(ch)
|
|
||||||
}
|
|
||||||
|
|
||||||
// isHexadecimal returns true if the given rune is a decimal digit
|
|
||||||
func isDigit(ch rune) bool {
|
|
||||||
return '0' <= ch && ch <= '9' || ch >= 0x80 && unicode.IsDigit(ch)
|
|
||||||
}
|
|
||||||
|
|
||||||
// isHexadecimal returns true if the given rune is a decimal number
|
|
||||||
func isDecimal(ch rune) bool {
|
|
||||||
return '0' <= ch && ch <= '9'
|
|
||||||
}
|
|
||||||
|
|
||||||
// isHexadecimal returns true if the given rune is an hexadecimal number
|
|
||||||
func isHexadecimal(ch rune) bool {
|
|
||||||
return '0' <= ch && ch <= '9' || 'a' <= ch && ch <= 'f' || 'A' <= ch && ch <= 'F'
|
|
||||||
}
|
|
||||||
|
|
||||||
// isWhitespace returns true if the rune is a space, tab, newline or carriage return
|
|
||||||
func isWhitespace(ch rune) bool {
|
|
||||||
return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r'
|
|
||||||
}
|
|
||||||
|
|
||||||
// digitVal returns the integer value of a given octal,decimal or hexadecimal rune
|
|
||||||
func digitVal(ch rune) int {
|
|
||||||
switch {
|
|
||||||
case '0' <= ch && ch <= '9':
|
|
||||||
return int(ch - '0')
|
|
||||||
case 'a' <= ch && ch <= 'f':
|
|
||||||
return int(ch - 'a' + 10)
|
|
||||||
case 'A' <= ch && ch <= 'F':
|
|
||||||
return int(ch - 'A' + 10)
|
|
||||||
}
|
|
||||||
return 16 // larger than any legal digit val
|
|
||||||
}
|
|
46
vendor/github.com/hashicorp/hcl/json/token/position.go
generated
vendored
46
vendor/github.com/hashicorp/hcl/json/token/position.go
generated
vendored
|
@ -1,46 +0,0 @@
|
||||||
package token
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
// Pos describes an arbitrary source position
|
|
||||||
// including the file, line, and column location.
|
|
||||||
// A Position is valid if the line number is > 0.
|
|
||||||
type Pos struct {
|
|
||||||
Filename string // filename, if any
|
|
||||||
Offset int // offset, starting at 0
|
|
||||||
Line int // line number, starting at 1
|
|
||||||
Column int // column number, starting at 1 (character count)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsValid returns true if the position is valid.
|
|
||||||
func (p *Pos) IsValid() bool { return p.Line > 0 }
|
|
||||||
|
|
||||||
// String returns a string in one of several forms:
|
|
||||||
//
|
|
||||||
// file:line:column valid position with file name
|
|
||||||
// line:column valid position without file name
|
|
||||||
// file invalid position with file name
|
|
||||||
// - invalid position without file name
|
|
||||||
func (p Pos) String() string {
|
|
||||||
s := p.Filename
|
|
||||||
if p.IsValid() {
|
|
||||||
if s != "" {
|
|
||||||
s += ":"
|
|
||||||
}
|
|
||||||
s += fmt.Sprintf("%d:%d", p.Line, p.Column)
|
|
||||||
}
|
|
||||||
if s == "" {
|
|
||||||
s = "-"
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
// Before reports whether the position p is before u.
|
|
||||||
func (p Pos) Before(u Pos) bool {
|
|
||||||
return u.Offset > p.Offset || u.Line > p.Line
|
|
||||||
}
|
|
||||||
|
|
||||||
// After reports whether the position p is after u.
|
|
||||||
func (p Pos) After(u Pos) bool {
|
|
||||||
return u.Offset < p.Offset || u.Line < p.Line
|
|
||||||
}
|
|
118
vendor/github.com/hashicorp/hcl/json/token/token.go
generated
vendored
118
vendor/github.com/hashicorp/hcl/json/token/token.go
generated
vendored
|
@ -1,118 +0,0 @@
|
||||||
package token
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
hcltoken "github.com/hashicorp/hcl/hcl/token"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Token defines a single HCL token which can be obtained via the Scanner
|
|
||||||
type Token struct {
|
|
||||||
Type Type
|
|
||||||
Pos Pos
|
|
||||||
Text string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Type is the set of lexical tokens of the HCL (HashiCorp Configuration Language)
|
|
||||||
type Type int
|
|
||||||
|
|
||||||
const (
|
|
||||||
// Special tokens
|
|
||||||
ILLEGAL Type = iota
|
|
||||||
EOF
|
|
||||||
|
|
||||||
identifier_beg
|
|
||||||
literal_beg
|
|
||||||
NUMBER // 12345
|
|
||||||
FLOAT // 123.45
|
|
||||||
BOOL // true,false
|
|
||||||
STRING // "abc"
|
|
||||||
NULL // null
|
|
||||||
literal_end
|
|
||||||
identifier_end
|
|
||||||
|
|
||||||
operator_beg
|
|
||||||
LBRACK // [
|
|
||||||
LBRACE // {
|
|
||||||
COMMA // ,
|
|
||||||
PERIOD // .
|
|
||||||
COLON // :
|
|
||||||
|
|
||||||
RBRACK // ]
|
|
||||||
RBRACE // }
|
|
||||||
|
|
||||||
operator_end
|
|
||||||
)
|
|
||||||
|
|
||||||
var tokens = [...]string{
|
|
||||||
ILLEGAL: "ILLEGAL",
|
|
||||||
|
|
||||||
EOF: "EOF",
|
|
||||||
|
|
||||||
NUMBER: "NUMBER",
|
|
||||||
FLOAT: "FLOAT",
|
|
||||||
BOOL: "BOOL",
|
|
||||||
STRING: "STRING",
|
|
||||||
NULL: "NULL",
|
|
||||||
|
|
||||||
LBRACK: "LBRACK",
|
|
||||||
LBRACE: "LBRACE",
|
|
||||||
COMMA: "COMMA",
|
|
||||||
PERIOD: "PERIOD",
|
|
||||||
COLON: "COLON",
|
|
||||||
|
|
||||||
RBRACK: "RBRACK",
|
|
||||||
RBRACE: "RBRACE",
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns the string corresponding to the token tok.
|
|
||||||
func (t Type) String() string {
|
|
||||||
s := ""
|
|
||||||
if 0 <= t && t < Type(len(tokens)) {
|
|
||||||
s = tokens[t]
|
|
||||||
}
|
|
||||||
if s == "" {
|
|
||||||
s = "token(" + strconv.Itoa(int(t)) + ")"
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsIdentifier returns true for tokens corresponding to identifiers and basic
|
|
||||||
// type literals; it returns false otherwise.
|
|
||||||
func (t Type) IsIdentifier() bool { return identifier_beg < t && t < identifier_end }
|
|
||||||
|
|
||||||
// IsLiteral returns true for tokens corresponding to basic type literals; it
|
|
||||||
// returns false otherwise.
|
|
||||||
func (t Type) IsLiteral() bool { return literal_beg < t && t < literal_end }
|
|
||||||
|
|
||||||
// IsOperator returns true for tokens corresponding to operators and
|
|
||||||
// delimiters; it returns false otherwise.
|
|
||||||
func (t Type) IsOperator() bool { return operator_beg < t && t < operator_end }
|
|
||||||
|
|
||||||
// String returns the token's literal text. Note that this is only
|
|
||||||
// applicable for certain token types, such as token.IDENT,
|
|
||||||
// token.STRING, etc..
|
|
||||||
func (t Token) String() string {
|
|
||||||
return fmt.Sprintf("%s %s %s", t.Pos.String(), t.Type.String(), t.Text)
|
|
||||||
}
|
|
||||||
|
|
||||||
// HCLToken converts this token to an HCL token.
|
|
||||||
//
|
|
||||||
// The token type must be a literal type or this will panic.
|
|
||||||
func (t Token) HCLToken() hcltoken.Token {
|
|
||||||
switch t.Type {
|
|
||||||
case BOOL:
|
|
||||||
return hcltoken.Token{Type: hcltoken.BOOL, Text: t.Text}
|
|
||||||
case FLOAT:
|
|
||||||
return hcltoken.Token{Type: hcltoken.FLOAT, Text: t.Text}
|
|
||||||
case NULL:
|
|
||||||
return hcltoken.Token{Type: hcltoken.STRING, Text: ""}
|
|
||||||
case NUMBER:
|
|
||||||
return hcltoken.Token{Type: hcltoken.NUMBER, Text: t.Text}
|
|
||||||
case STRING:
|
|
||||||
return hcltoken.Token{Type: hcltoken.STRING, Text: t.Text, JSON: true}
|
|
||||||
default:
|
|
||||||
panic(fmt.Sprintf("unimplemented HCLToken for type: %s", t.Type))
|
|
||||||
}
|
|
||||||
}
|
|
38
vendor/github.com/hashicorp/hcl/lex.go
generated
vendored
38
vendor/github.com/hashicorp/hcl/lex.go
generated
vendored
|
@ -1,38 +0,0 @@
|
||||||
package hcl
|
|
||||||
|
|
||||||
import (
|
|
||||||
"unicode"
|
|
||||||
"unicode/utf8"
|
|
||||||
)
|
|
||||||
|
|
||||||
type lexModeValue byte
|
|
||||||
|
|
||||||
const (
|
|
||||||
lexModeUnknown lexModeValue = iota
|
|
||||||
lexModeHcl
|
|
||||||
lexModeJson
|
|
||||||
)
|
|
||||||
|
|
||||||
// lexMode returns whether we're going to be parsing in JSON
|
|
||||||
// mode or HCL mode.
|
|
||||||
func lexMode(v []byte) lexModeValue {
|
|
||||||
var (
|
|
||||||
r rune
|
|
||||||
w int
|
|
||||||
offset int
|
|
||||||
)
|
|
||||||
|
|
||||||
for {
|
|
||||||
r, w = utf8.DecodeRune(v[offset:])
|
|
||||||
offset += w
|
|
||||||
if unicode.IsSpace(r) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if r == '{' {
|
|
||||||
return lexModeJson
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
return lexModeHcl
|
|
||||||
}
|
|
39
vendor/github.com/hashicorp/hcl/parse.go
generated
vendored
39
vendor/github.com/hashicorp/hcl/parse.go
generated
vendored
|
@ -1,39 +0,0 @@
|
||||||
package hcl
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/hashicorp/hcl/hcl/ast"
|
|
||||||
hclParser "github.com/hashicorp/hcl/hcl/parser"
|
|
||||||
jsonParser "github.com/hashicorp/hcl/json/parser"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ParseBytes accepts as input byte slice and returns ast tree.
|
|
||||||
//
|
|
||||||
// Input can be either JSON or HCL
|
|
||||||
func ParseBytes(in []byte) (*ast.File, error) {
|
|
||||||
return parse(in)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseString accepts input as a string and returns ast tree.
|
|
||||||
func ParseString(input string) (*ast.File, error) {
|
|
||||||
return parse([]byte(input))
|
|
||||||
}
|
|
||||||
|
|
||||||
func parse(in []byte) (*ast.File, error) {
|
|
||||||
switch lexMode(in) {
|
|
||||||
case lexModeHcl:
|
|
||||||
return hclParser.Parse(in)
|
|
||||||
case lexModeJson:
|
|
||||||
return jsonParser.Parse(in)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, fmt.Errorf("unknown config format")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse parses the given input and returns the root object.
|
|
||||||
//
|
|
||||||
// The input format can be either HCL or JSON.
|
|
||||||
func Parse(input string) (*ast.File, error) {
|
|
||||||
return parse([]byte(input))
|
|
||||||
}
|
|
363
vendor/github.com/hashicorp/vault/LICENSE
generated
vendored
363
vendor/github.com/hashicorp/vault/LICENSE
generated
vendored
|
@ -1,363 +0,0 @@
|
||||||
Mozilla Public License, version 2.0
|
|
||||||
|
|
||||||
1. Definitions
|
|
||||||
|
|
||||||
1.1. "Contributor"
|
|
||||||
|
|
||||||
means each individual or legal entity that creates, contributes to the
|
|
||||||
creation of, or owns Covered Software.
|
|
||||||
|
|
||||||
1.2. "Contributor Version"
|
|
||||||
|
|
||||||
means the combination of the Contributions of others (if any) used by a
|
|
||||||
Contributor and that particular Contributor's Contribution.
|
|
||||||
|
|
||||||
1.3. "Contribution"
|
|
||||||
|
|
||||||
means Covered Software of a particular Contributor.
|
|
||||||
|
|
||||||
1.4. "Covered Software"
|
|
||||||
|
|
||||||
means Source Code Form to which the initial Contributor has attached the
|
|
||||||
notice in Exhibit A, the Executable Form of such Source Code Form, and
|
|
||||||
Modifications of such Source Code Form, in each case including portions
|
|
||||||
thereof.
|
|
||||||
|
|
||||||
1.5. "Incompatible With Secondary Licenses"
|
|
||||||
means
|
|
||||||
|
|
||||||
a. that the initial Contributor has attached the notice described in
|
|
||||||
Exhibit B to the Covered Software; or
|
|
||||||
|
|
||||||
b. that the Covered Software was made available under the terms of
|
|
||||||
version 1.1 or earlier of the License, but not also under the terms of
|
|
||||||
a Secondary License.
|
|
||||||
|
|
||||||
1.6. "Executable Form"
|
|
||||||
|
|
||||||
means any form of the work other than Source Code Form.
|
|
||||||
|
|
||||||
1.7. "Larger Work"
|
|
||||||
|
|
||||||
means a work that combines Covered Software with other material, in a
|
|
||||||
separate file or files, that is not Covered Software.
|
|
||||||
|
|
||||||
1.8. "License"
|
|
||||||
|
|
||||||
means this document.
|
|
||||||
|
|
||||||
1.9. "Licensable"
|
|
||||||
|
|
||||||
means having the right to grant, to the maximum extent possible, whether
|
|
||||||
at the time of the initial grant or subsequently, any and all of the
|
|
||||||
rights conveyed by this License.
|
|
||||||
|
|
||||||
1.10. "Modifications"
|
|
||||||
|
|
||||||
means any of the following:
|
|
||||||
|
|
||||||
a. any file in Source Code Form that results from an addition to,
|
|
||||||
deletion from, or modification of the contents of Covered Software; or
|
|
||||||
|
|
||||||
b. any new file in Source Code Form that contains any Covered Software.
|
|
||||||
|
|
||||||
1.11. "Patent Claims" of a Contributor
|
|
||||||
|
|
||||||
means any patent claim(s), including without limitation, method,
|
|
||||||
process, and apparatus claims, in any patent Licensable by such
|
|
||||||
Contributor that would be infringed, but for the grant of the License,
|
|
||||||
by the making, using, selling, offering for sale, having made, import,
|
|
||||||
or transfer of either its Contributions or its Contributor Version.
|
|
||||||
|
|
||||||
1.12. "Secondary License"
|
|
||||||
|
|
||||||
means either the GNU General Public License, Version 2.0, the GNU Lesser
|
|
||||||
General Public License, Version 2.1, the GNU Affero General Public
|
|
||||||
License, Version 3.0, or any later versions of those licenses.
|
|
||||||
|
|
||||||
1.13. "Source Code Form"
|
|
||||||
|
|
||||||
means the form of the work preferred for making modifications.
|
|
||||||
|
|
||||||
1.14. "You" (or "Your")
|
|
||||||
|
|
||||||
means an individual or a legal entity exercising rights under this
|
|
||||||
License. For legal entities, "You" includes any entity that controls, is
|
|
||||||
controlled by, or is under common control with You. For purposes of this
|
|
||||||
definition, "control" means (a) the power, direct or indirect, to cause
|
|
||||||
the direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (b) ownership of more than fifty percent (50%) of the
|
|
||||||
outstanding shares or beneficial ownership of such entity.
|
|
||||||
|
|
||||||
|
|
||||||
2. License Grants and Conditions
|
|
||||||
|
|
||||||
2.1. Grants
|
|
||||||
|
|
||||||
Each Contributor hereby grants You a world-wide, royalty-free,
|
|
||||||
non-exclusive license:
|
|
||||||
|
|
||||||
a. under intellectual property rights (other than patent or trademark)
|
|
||||||
Licensable by such Contributor to use, reproduce, make available,
|
|
||||||
modify, display, perform, distribute, and otherwise exploit its
|
|
||||||
Contributions, either on an unmodified basis, with Modifications, or
|
|
||||||
as part of a Larger Work; and
|
|
||||||
|
|
||||||
b. under Patent Claims of such Contributor to make, use, sell, offer for
|
|
||||||
sale, have made, import, and otherwise transfer either its
|
|
||||||
Contributions or its Contributor Version.
|
|
||||||
|
|
||||||
2.2. Effective Date
|
|
||||||
|
|
||||||
The licenses granted in Section 2.1 with respect to any Contribution
|
|
||||||
become effective for each Contribution on the date the Contributor first
|
|
||||||
distributes such Contribution.
|
|
||||||
|
|
||||||
2.3. Limitations on Grant Scope
|
|
||||||
|
|
||||||
The licenses granted in this Section 2 are the only rights granted under
|
|
||||||
this License. No additional rights or licenses will be implied from the
|
|
||||||
distribution or licensing of Covered Software under this License.
|
|
||||||
Notwithstanding Section 2.1(b) above, no patent license is granted by a
|
|
||||||
Contributor:
|
|
||||||
|
|
||||||
a. for any code that a Contributor has removed from Covered Software; or
|
|
||||||
|
|
||||||
b. for infringements caused by: (i) Your and any other third party's
|
|
||||||
modifications of Covered Software, or (ii) the combination of its
|
|
||||||
Contributions with other software (except as part of its Contributor
|
|
||||||
Version); or
|
|
||||||
|
|
||||||
c. under Patent Claims infringed by Covered Software in the absence of
|
|
||||||
its Contributions.
|
|
||||||
|
|
||||||
This License does not grant any rights in the trademarks, service marks,
|
|
||||||
or logos of any Contributor (except as may be necessary to comply with
|
|
||||||
the notice requirements in Section 3.4).
|
|
||||||
|
|
||||||
2.4. Subsequent Licenses
|
|
||||||
|
|
||||||
No Contributor makes additional grants as a result of Your choice to
|
|
||||||
distribute the Covered Software under a subsequent version of this
|
|
||||||
License (see Section 10.2) or under the terms of a Secondary License (if
|
|
||||||
permitted under the terms of Section 3.3).
|
|
||||||
|
|
||||||
2.5. Representation
|
|
||||||
|
|
||||||
Each Contributor represents that the Contributor believes its
|
|
||||||
Contributions are its original creation(s) or it has sufficient rights to
|
|
||||||
grant the rights to its Contributions conveyed by this License.
|
|
||||||
|
|
||||||
2.6. Fair Use
|
|
||||||
|
|
||||||
This License is not intended to limit any rights You have under
|
|
||||||
applicable copyright doctrines of fair use, fair dealing, or other
|
|
||||||
equivalents.
|
|
||||||
|
|
||||||
2.7. Conditions
|
|
||||||
|
|
||||||
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
|
|
||||||
Section 2.1.
|
|
||||||
|
|
||||||
|
|
||||||
3. Responsibilities
|
|
||||||
|
|
||||||
3.1. Distribution of Source Form
|
|
||||||
|
|
||||||
All distribution of Covered Software in Source Code Form, including any
|
|
||||||
Modifications that You create or to which You contribute, must be under
|
|
||||||
the terms of this License. You must inform recipients that the Source
|
|
||||||
Code Form of the Covered Software is governed by the terms of this
|
|
||||||
License, and how they can obtain a copy of this License. You may not
|
|
||||||
attempt to alter or restrict the recipients' rights in the Source Code
|
|
||||||
Form.
|
|
||||||
|
|
||||||
3.2. Distribution of Executable Form
|
|
||||||
|
|
||||||
If You distribute Covered Software in Executable Form then:
|
|
||||||
|
|
||||||
a. such Covered Software must also be made available in Source Code Form,
|
|
||||||
as described in Section 3.1, and You must inform recipients of the
|
|
||||||
Executable Form how they can obtain a copy of such Source Code Form by
|
|
||||||
reasonable means in a timely manner, at a charge no more than the cost
|
|
||||||
of distribution to the recipient; and
|
|
||||||
|
|
||||||
b. You may distribute such Executable Form under the terms of this
|
|
||||||
License, or sublicense it under different terms, provided that the
|
|
||||||
license for the Executable Form does not attempt to limit or alter the
|
|
||||||
recipients' rights in the Source Code Form under this License.
|
|
||||||
|
|
||||||
3.3. Distribution of a Larger Work
|
|
||||||
|
|
||||||
You may create and distribute a Larger Work under terms of Your choice,
|
|
||||||
provided that You also comply with the requirements of this License for
|
|
||||||
the Covered Software. If the Larger Work is a combination of Covered
|
|
||||||
Software with a work governed by one or more Secondary Licenses, and the
|
|
||||||
Covered Software is not Incompatible With Secondary Licenses, this
|
|
||||||
License permits You to additionally distribute such Covered Software
|
|
||||||
under the terms of such Secondary License(s), so that the recipient of
|
|
||||||
the Larger Work may, at their option, further distribute the Covered
|
|
||||||
Software under the terms of either this License or such Secondary
|
|
||||||
License(s).
|
|
||||||
|
|
||||||
3.4. Notices
|
|
||||||
|
|
||||||
You may not remove or alter the substance of any license notices
|
|
||||||
(including copyright notices, patent notices, disclaimers of warranty, or
|
|
||||||
limitations of liability) contained within the Source Code Form of the
|
|
||||||
Covered Software, except that You may alter any license notices to the
|
|
||||||
extent required to remedy known factual inaccuracies.
|
|
||||||
|
|
||||||
3.5. Application of Additional Terms
|
|
||||||
|
|
||||||
You may choose to offer, and to charge a fee for, warranty, support,
|
|
||||||
indemnity or liability obligations to one or more recipients of Covered
|
|
||||||
Software. However, You may do so only on Your own behalf, and not on
|
|
||||||
behalf of any Contributor. You must make it absolutely clear that any
|
|
||||||
such warranty, support, indemnity, or liability obligation is offered by
|
|
||||||
You alone, and You hereby agree to indemnify every Contributor for any
|
|
||||||
liability incurred by such Contributor as a result of warranty, support,
|
|
||||||
indemnity or liability terms You offer. You may include additional
|
|
||||||
disclaimers of warranty and limitations of liability specific to any
|
|
||||||
jurisdiction.
|
|
||||||
|
|
||||||
4. Inability to Comply Due to Statute or Regulation
|
|
||||||
|
|
||||||
If it is impossible for You to comply with any of the terms of this License
|
|
||||||
with respect to some or all of the Covered Software due to statute,
|
|
||||||
judicial order, or regulation then You must: (a) comply with the terms of
|
|
||||||
this License to the maximum extent possible; and (b) describe the
|
|
||||||
limitations and the code they affect. Such description must be placed in a
|
|
||||||
text file included with all distributions of the Covered Software under
|
|
||||||
this License. Except to the extent prohibited by statute or regulation,
|
|
||||||
such description must be sufficiently detailed for a recipient of ordinary
|
|
||||||
skill to be able to understand it.
|
|
||||||
|
|
||||||
5. Termination
|
|
||||||
|
|
||||||
5.1. The rights granted under this License will terminate automatically if You
|
|
||||||
fail to comply with any of its terms. However, if You become compliant,
|
|
||||||
then the rights granted under this License from a particular Contributor
|
|
||||||
are reinstated (a) provisionally, unless and until such Contributor
|
|
||||||
explicitly and finally terminates Your grants, and (b) on an ongoing
|
|
||||||
basis, if such Contributor fails to notify You of the non-compliance by
|
|
||||||
some reasonable means prior to 60 days after You have come back into
|
|
||||||
compliance. Moreover, Your grants from a particular Contributor are
|
|
||||||
reinstated on an ongoing basis if such Contributor notifies You of the
|
|
||||||
non-compliance by some reasonable means, this is the first time You have
|
|
||||||
received notice of non-compliance with this License from such
|
|
||||||
Contributor, and You become compliant prior to 30 days after Your receipt
|
|
||||||
of the notice.
|
|
||||||
|
|
||||||
5.2. If You initiate litigation against any entity by asserting a patent
|
|
||||||
infringement claim (excluding declaratory judgment actions,
|
|
||||||
counter-claims, and cross-claims) alleging that a Contributor Version
|
|
||||||
directly or indirectly infringes any patent, then the rights granted to
|
|
||||||
You by any and all Contributors for the Covered Software under Section
|
|
||||||
2.1 of this License shall terminate.
|
|
||||||
|
|
||||||
5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
|
|
||||||
license agreements (excluding distributors and resellers) which have been
|
|
||||||
validly granted by You or Your distributors under this License prior to
|
|
||||||
termination shall survive termination.
|
|
||||||
|
|
||||||
6. Disclaimer of Warranty
|
|
||||||
|
|
||||||
Covered Software is provided under this License on an "as is" basis,
|
|
||||||
without warranty of any kind, either expressed, implied, or statutory,
|
|
||||||
including, without limitation, warranties that the Covered Software is free
|
|
||||||
of defects, merchantable, fit for a particular purpose or non-infringing.
|
|
||||||
The entire risk as to the quality and performance of the Covered Software
|
|
||||||
is with You. Should any Covered Software prove defective in any respect,
|
|
||||||
You (not any Contributor) assume the cost of any necessary servicing,
|
|
||||||
repair, or correction. This disclaimer of warranty constitutes an essential
|
|
||||||
part of this License. No use of any Covered Software is authorized under
|
|
||||||
this License except under this disclaimer.
|
|
||||||
|
|
||||||
7. Limitation of Liability
|
|
||||||
|
|
||||||
Under no circumstances and under no legal theory, whether tort (including
|
|
||||||
negligence), contract, or otherwise, shall any Contributor, or anyone who
|
|
||||||
distributes Covered Software as permitted above, be liable to You for any
|
|
||||||
direct, indirect, special, incidental, or consequential damages of any
|
|
||||||
character including, without limitation, damages for lost profits, loss of
|
|
||||||
goodwill, work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses, even if such party shall have been
|
|
||||||
informed of the possibility of such damages. This limitation of liability
|
|
||||||
shall not apply to liability for death or personal injury resulting from
|
|
||||||
such party's negligence to the extent applicable law prohibits such
|
|
||||||
limitation. Some jurisdictions do not allow the exclusion or limitation of
|
|
||||||
incidental or consequential damages, so this exclusion and limitation may
|
|
||||||
not apply to You.
|
|
||||||
|
|
||||||
8. Litigation
|
|
||||||
|
|
||||||
Any litigation relating to this License may be brought only in the courts
|
|
||||||
of a jurisdiction where the defendant maintains its principal place of
|
|
||||||
business and such litigation shall be governed by laws of that
|
|
||||||
jurisdiction, without reference to its conflict-of-law provisions. Nothing
|
|
||||||
in this Section shall prevent a party's ability to bring cross-claims or
|
|
||||||
counter-claims.
|
|
||||||
|
|
||||||
9. Miscellaneous
|
|
||||||
|
|
||||||
This License represents the complete agreement concerning the subject
|
|
||||||
matter hereof. If any provision of this License is held to be
|
|
||||||
unenforceable, such provision shall be reformed only to the extent
|
|
||||||
necessary to make it enforceable. Any law or regulation which provides that
|
|
||||||
the language of a contract shall be construed against the drafter shall not
|
|
||||||
be used to construe this License against a Contributor.
|
|
||||||
|
|
||||||
|
|
||||||
10. Versions of the License
|
|
||||||
|
|
||||||
10.1. New Versions
|
|
||||||
|
|
||||||
Mozilla Foundation is the license steward. Except as provided in Section
|
|
||||||
10.3, no one other than the license steward has the right to modify or
|
|
||||||
publish new versions of this License. Each version will be given a
|
|
||||||
distinguishing version number.
|
|
||||||
|
|
||||||
10.2. Effect of New Versions
|
|
||||||
|
|
||||||
You may distribute the Covered Software under the terms of the version
|
|
||||||
of the License under which You originally received the Covered Software,
|
|
||||||
or under the terms of any subsequent version published by the license
|
|
||||||
steward.
|
|
||||||
|
|
||||||
10.3. Modified Versions
|
|
||||||
|
|
||||||
If you create software not governed by this License, and you want to
|
|
||||||
create a new license for such software, you may create and use a
|
|
||||||
modified version of this License if you rename the license and remove
|
|
||||||
any references to the name of the license steward (except to note that
|
|
||||||
such modified license differs from this License).
|
|
||||||
|
|
||||||
10.4. Distributing Source Code Form that is Incompatible With Secondary
|
|
||||||
Licenses If You choose to distribute Source Code Form that is
|
|
||||||
Incompatible With Secondary Licenses under the terms of this version of
|
|
||||||
the License, the notice described in Exhibit B of this License must be
|
|
||||||
attached.
|
|
||||||
|
|
||||||
Exhibit A - Source Code Form License Notice
|
|
||||||
|
|
||||||
This Source Code Form is subject to the
|
|
||||||
terms of the Mozilla Public License, v.
|
|
||||||
2.0. If a copy of the MPL was not
|
|
||||||
distributed with this file, You can
|
|
||||||
obtain one at
|
|
||||||
http://mozilla.org/MPL/2.0/.
|
|
||||||
|
|
||||||
If it is not possible or desirable to put the notice in a particular file,
|
|
||||||
then You may include the notice in a location (such as a LICENSE file in a
|
|
||||||
relevant directory) where a recipient would be likely to look for such a
|
|
||||||
notice.
|
|
||||||
|
|
||||||
You may add additional accurate notices of copyright ownership.
|
|
||||||
|
|
||||||
Exhibit B - "Incompatible With Secondary Licenses" Notice
|
|
||||||
|
|
||||||
This Source Code Form is "Incompatible
|
|
||||||
With Secondary Licenses", as defined by
|
|
||||||
the Mozilla Public License, v. 2.0.
|
|
||||||
|
|
611
vendor/github.com/hashicorp/vault/api/SPEC.md
generated
vendored
611
vendor/github.com/hashicorp/vault/api/SPEC.md
generated
vendored
|
@ -1,611 +0,0 @@
|
||||||
FORMAT: 1A
|
|
||||||
|
|
||||||
# vault
|
|
||||||
|
|
||||||
The Vault API gives you full access to the Vault project.
|
|
||||||
|
|
||||||
If you're browsing this API specifiction in GitHub or in raw
|
|
||||||
format, please excuse some of the odd formatting. This document
|
|
||||||
is in api-blueprint format that is read by viewers such as
|
|
||||||
Apiary.
|
|
||||||
|
|
||||||
## Sealed vs. Unsealed
|
|
||||||
|
|
||||||
Whenever an individual Vault server is started, it is started
|
|
||||||
in the _sealed_ state. In this state, it knows where its data
|
|
||||||
is located, but the data is encrypted and Vault doesn't have the
|
|
||||||
encryption keys to access it. Before Vault can operate, it must
|
|
||||||
be _unsealed_.
|
|
||||||
|
|
||||||
**Note:** Sealing/unsealing has no relationship to _authentication_
|
|
||||||
which is separate and still required once the Vault is unsealed.
|
|
||||||
|
|
||||||
Instead of being sealed with a single key, we utilize
|
|
||||||
[Shamir's Secret Sharing](http://en.wikipedia.org/wiki/Shamir%27s_Secret_Sharing)
|
|
||||||
to shard a key into _n_ parts such that _t_ parts are required
|
|
||||||
to reconstruct the original key, where `t <= n`. This means that
|
|
||||||
Vault itself doesn't know the original key, and no single person
|
|
||||||
has the original key (unless `n = 1`, or `t` parts are given to
|
|
||||||
a single person).
|
|
||||||
|
|
||||||
Unsealing is done via an unauthenticated
|
|
||||||
[unseal API](#reference/seal/unseal/unseal). This API takes a single
|
|
||||||
master shard and progresses the unsealing process. Once all shards
|
|
||||||
are given, the Vault is either unsealed or resets the unsealing
|
|
||||||
process if the key was invalid.
|
|
||||||
|
|
||||||
The entire seal/unseal state is server-wide. This allows multiple
|
|
||||||
distinct operators to use the unseal API (or more likely the
|
|
||||||
`vault unseal` command) from separate computers/networks and never
|
|
||||||
have to transmit their key in order to unseal the vault in a
|
|
||||||
distributed fashion.
|
|
||||||
|
|
||||||
## Transport
|
|
||||||
|
|
||||||
The API is expected to be accessed over a TLS connection at
|
|
||||||
all times, with a valid certificate that is verified by a well
|
|
||||||
behaved client.
|
|
||||||
|
|
||||||
## Authentication
|
|
||||||
|
|
||||||
Once the Vault is unsealed, every other operation requires
|
|
||||||
authentication. There are multiple methods for authentication
|
|
||||||
that can be enabled (see
|
|
||||||
[authentication](#reference/authentication)).
|
|
||||||
|
|
||||||
Authentication is done with the login endpoint. The login endpoint
|
|
||||||
returns an access token that is set as the `X-Vault-Token` header.
|
|
||||||
|
|
||||||
## Help
|
|
||||||
|
|
||||||
To retrieve the help for any API within Vault, including mounted
|
|
||||||
backends, credential providers, etc. then append `?help=1` to any
|
|
||||||
URL. If you have valid permission to access the path, then the help text
|
|
||||||
will be returned with the following structure:
|
|
||||||
|
|
||||||
{
|
|
||||||
"help": "help text"
|
|
||||||
}
|
|
||||||
|
|
||||||
## Error Response
|
|
||||||
|
|
||||||
A common JSON structure is always returned to return errors:
|
|
||||||
|
|
||||||
{
|
|
||||||
"errors": [
|
|
||||||
"message",
|
|
||||||
"another message"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
This structure will be sent down for any non-20x HTTP status.
|
|
||||||
|
|
||||||
## HTTP Status Codes
|
|
||||||
|
|
||||||
The following HTTP status codes are used throughout the API.
|
|
||||||
|
|
||||||
- `200` - Success with data.
|
|
||||||
- `204` - Success, no data returned.
|
|
||||||
- `400` - Invalid request, missing or invalid data.
|
|
||||||
- `403` - Forbidden, your authentication details are either
|
|
||||||
incorrect or you don't have access to this feature.
|
|
||||||
- `404` - Invalid path. This can both mean that the path truly
|
|
||||||
doesn't exist or that you don't have permission to view a
|
|
||||||
specific path. We use 404 in some cases to avoid state leakage.
|
|
||||||
- `429` - Rate limit exceeded. Try again after waiting some period
|
|
||||||
of time.
|
|
||||||
- `500` - Internal server error. An internal error has occurred,
|
|
||||||
try again later. If the error persists, report a bug.
|
|
||||||
- `503` - Vault is down for maintenance or is currently sealed.
|
|
||||||
Try again later.
|
|
||||||
|
|
||||||
# Group Initialization
|
|
||||||
|
|
||||||
## Initialization [/sys/init]
|
|
||||||
### Initialization Status [GET]
|
|
||||||
Returns the status of whether the vault is initialized or not. The
|
|
||||||
vault doesn't have to be unsealed for this operation.
|
|
||||||
|
|
||||||
+ Response 200 (application/json)
|
|
||||||
|
|
||||||
{
|
|
||||||
"initialized": true
|
|
||||||
}
|
|
||||||
|
|
||||||
### Initialize [POST]
|
|
||||||
Initialize the vault. This is an unauthenticated request to initially
|
|
||||||
setup a new vault. Although this is unauthenticated, it is still safe:
|
|
||||||
data cannot be in vault prior to initialization, and any future
|
|
||||||
authentication will fail if you didn't initialize it yourself.
|
|
||||||
Additionally, once initialized, a vault cannot be reinitialized.
|
|
||||||
|
|
||||||
This API is the only time Vault will ever be aware of your keys, and
|
|
||||||
the only time the keys will ever be returned in one unit. Care should
|
|
||||||
be taken to ensure that the output of this request is never logged,
|
|
||||||
and that the keys are properly distributed.
|
|
||||||
|
|
||||||
The response also contains the initial root token that can be used
|
|
||||||
as authentication in order to initially configure Vault once it is
|
|
||||||
unsealed. Just as with the unseal keys, this is the only time Vault is
|
|
||||||
ever aware of this token.
|
|
||||||
|
|
||||||
+ Request (application/json)
|
|
||||||
|
|
||||||
{
|
|
||||||
"secret_shares": 5,
|
|
||||||
"secret_threshold": 3,
|
|
||||||
}
|
|
||||||
|
|
||||||
+ Response 200 (application/json)
|
|
||||||
|
|
||||||
{
|
|
||||||
"keys": ["one", "two", "three"],
|
|
||||||
"root_token": "foo"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Group Seal/Unseal
|
|
||||||
|
|
||||||
## Seal Status [/sys/seal-status]
|
|
||||||
### Seal Status [GET]
|
|
||||||
Returns the status of whether the vault is currently
|
|
||||||
sealed or not, as well as the progress of unsealing.
|
|
||||||
|
|
||||||
The response has the following attributes:
|
|
||||||
|
|
||||||
- sealed (boolean) - If true, the vault is sealed. Otherwise,
|
|
||||||
it is unsealed.
|
|
||||||
- t (int) - The "t" value for the master key, or the number
|
|
||||||
of shards needed total to unseal the vault.
|
|
||||||
- n (int) - The "n" value for the master key, or the total
|
|
||||||
number of shards of the key distributed.
|
|
||||||
- progress (int) - The number of master key shards that have
|
|
||||||
been entered so far towards unsealing the vault.
|
|
||||||
|
|
||||||
+ Response 200 (application/json)
|
|
||||||
|
|
||||||
{
|
|
||||||
"sealed": true,
|
|
||||||
"t": 3,
|
|
||||||
"n": 5,
|
|
||||||
"progress": 1
|
|
||||||
}
|
|
||||||
|
|
||||||
## Seal [/sys/seal]
|
|
||||||
### Seal [PUT]
|
|
||||||
Seal the vault.
|
|
||||||
|
|
||||||
Sealing the vault locks Vault from any future operations on any
|
|
||||||
secrets or system configuration until the vault is once again
|
|
||||||
unsealed. Internally, sealing throws away the keys to access the
|
|
||||||
encrypted vault data, so Vault is unable to access the data without
|
|
||||||
unsealing to get the encryption keys.
|
|
||||||
|
|
||||||
+ Response 204
|
|
||||||
|
|
||||||
## Unseal [/sys/unseal]
|
|
||||||
### Unseal [PUT]
|
|
||||||
Unseal the vault.
|
|
||||||
|
|
||||||
Unseal the vault by entering a portion of the master key. The
|
|
||||||
response object will tell you if the unseal is complete or
|
|
||||||
only partial.
|
|
||||||
|
|
||||||
If the vault is already unsealed, this does nothing. It is
|
|
||||||
not an error, the return value just says the vault is unsealed.
|
|
||||||
Due to the architecture of Vault, we cannot validate whether
|
|
||||||
any portion of the unseal key given is valid until all keys
|
|
||||||
are inputted, therefore unsealing an already unsealed vault
|
|
||||||
is still a success even if the input key is invalid.
|
|
||||||
|
|
||||||
+ Request (application/json)
|
|
||||||
|
|
||||||
{
|
|
||||||
"key": "value"
|
|
||||||
}
|
|
||||||
|
|
||||||
+ Response 200 (application/json)
|
|
||||||
|
|
||||||
{
|
|
||||||
"sealed": true,
|
|
||||||
"t": 3,
|
|
||||||
"n": 5,
|
|
||||||
"progress": 1
|
|
||||||
}
|
|
||||||
|
|
||||||
# Group Authentication
|
|
||||||
|
|
||||||
## List Auth Methods [/sys/auth]
|
|
||||||
### List all auth methods [GET]
|
|
||||||
Lists all available authentication methods.
|
|
||||||
|
|
||||||
This returns the name of the authentication method as well as
|
|
||||||
a human-friendly long-form help text for the method that can be
|
|
||||||
shown to the user as documentation.
|
|
||||||
|
|
||||||
+ Response 200 (application/json)
|
|
||||||
|
|
||||||
{
|
|
||||||
"token": {
|
|
||||||
"type": "token",
|
|
||||||
"description": "Token authentication"
|
|
||||||
},
|
|
||||||
"oauth": {
|
|
||||||
"type": "oauth",
|
|
||||||
"description": "OAuth authentication"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
## Single Auth Method [/sys/auth/{id}]
|
|
||||||
|
|
||||||
+ Parameters
|
|
||||||
+ id (required, string) ... The ID of the auth method.
|
|
||||||
|
|
||||||
### Enable an auth method [PUT]
|
|
||||||
Enables an authentication method.
|
|
||||||
|
|
||||||
The body of the request depends on the authentication method
|
|
||||||
being used. Please reference the documentation for the specific
|
|
||||||
authentication method you're enabling in order to determine what
|
|
||||||
parameters you must give it.
|
|
||||||
|
|
||||||
If an authentication method is already enabled, then this can be
|
|
||||||
used to change the configuration, including even the type of
|
|
||||||
the configuration.
|
|
||||||
|
|
||||||
+ Request (application/json)
|
|
||||||
|
|
||||||
{
|
|
||||||
"type": "type",
|
|
||||||
"key": "value",
|
|
||||||
"key2": "value2"
|
|
||||||
}
|
|
||||||
|
|
||||||
+ Response 204
|
|
||||||
|
|
||||||
### Disable an auth method [DELETE]
|
|
||||||
Disables an authentication method. Previously authenticated sessions
|
|
||||||
are immediately invalidated.
|
|
||||||
|
|
||||||
+ Response 204
|
|
||||||
|
|
||||||
# Group Policies
|
|
||||||
|
|
||||||
Policies are named permission sets that identities returned by
|
|
||||||
credential stores are bound to. This separates _authentication_
|
|
||||||
from _authorization_.
|
|
||||||
|
|
||||||
## Policies [/sys/policy]
|
|
||||||
### List all Policies [GET]
|
|
||||||
|
|
||||||
List all the policies.
|
|
||||||
|
|
||||||
+ Response 200 (application/json)
|
|
||||||
|
|
||||||
{
|
|
||||||
"policies": ["root"]
|
|
||||||
}
|
|
||||||
|
|
||||||
## Single Policy [/sys/policy/{id}]
|
|
||||||
|
|
||||||
+ Parameters
|
|
||||||
+ id (required, string) ... The name of the policy
|
|
||||||
|
|
||||||
### Upsert [PUT]
|
|
||||||
|
|
||||||
Create or update a policy with the given ID.
|
|
||||||
|
|
||||||
+ Request (application/json)
|
|
||||||
|
|
||||||
{
|
|
||||||
"rules": "HCL"
|
|
||||||
}
|
|
||||||
|
|
||||||
+ Response 204
|
|
||||||
|
|
||||||
### Delete [DELETE]
|
|
||||||
|
|
||||||
Delete a policy with the given ID. Any identities bound to this
|
|
||||||
policy will immediately become "deny all" despite already being
|
|
||||||
authenticated.
|
|
||||||
|
|
||||||
+ Response 204
|
|
||||||
|
|
||||||
# Group Mounts
|
|
||||||
|
|
||||||
Logical backends are mounted at _mount points_, similar to
|
|
||||||
filesystems. This allows you to mount the "aws" logical backend
|
|
||||||
at the "aws-us-east" path, so all access is at `/aws-us-east/keys/foo`
|
|
||||||
for example. This enables multiple logical backends to be enabled.
|
|
||||||
|
|
||||||
## Mounts [/sys/mounts]
|
|
||||||
### List all mounts [GET]
|
|
||||||
|
|
||||||
Lists all the active mount points.
|
|
||||||
|
|
||||||
+ Response 200 (application/json)
|
|
||||||
|
|
||||||
{
|
|
||||||
"aws": {
|
|
||||||
"type": "aws",
|
|
||||||
"description": "AWS"
|
|
||||||
},
|
|
||||||
"pg": {
|
|
||||||
"type": "postgresql",
|
|
||||||
"description": "PostgreSQL dynamic users"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
## Single Mount [/sys/mounts/{path}]
|
|
||||||
### New Mount [POST]
|
|
||||||
|
|
||||||
Mount a logical backend to a new path.
|
|
||||||
|
|
||||||
Configuration for this new backend is done via the normal
|
|
||||||
read/write mechanism once it is mounted.
|
|
||||||
|
|
||||||
+ Request (application/json)
|
|
||||||
|
|
||||||
{
|
|
||||||
"type": "aws",
|
|
||||||
"description": "EU AWS tokens"
|
|
||||||
}
|
|
||||||
|
|
||||||
+ Response 204
|
|
||||||
|
|
||||||
### Unmount [DELETE]
|
|
||||||
|
|
||||||
Unmount a mount point.
|
|
||||||
|
|
||||||
+ Response 204
|
|
||||||
|
|
||||||
## Remount [/sys/remount]
|
|
||||||
### Remount [POST]
|
|
||||||
|
|
||||||
Move an already-mounted backend to a new path.
|
|
||||||
|
|
||||||
+ Request (application/json)
|
|
||||||
|
|
||||||
{
|
|
||||||
"from": "aws",
|
|
||||||
"to": "aws-east"
|
|
||||||
}
|
|
||||||
|
|
||||||
+ Response 204
|
|
||||||
|
|
||||||
# Group Audit Backends
|
|
||||||
|
|
||||||
Audit backends are responsible for shuttling the audit logs that
|
|
||||||
Vault generates to a durable system for future querying. By default,
|
|
||||||
audit logs are not stored anywhere.
|
|
||||||
|
|
||||||
## Audit Backends [/sys/audit]
|
|
||||||
### List Enabled Audit Backends [GET]
|
|
||||||
|
|
||||||
List all the enabled audit backends
|
|
||||||
|
|
||||||
+ Response 200 (application/json)
|
|
||||||
|
|
||||||
{
|
|
||||||
"file": {
|
|
||||||
"type": "file",
|
|
||||||
"description": "Send audit logs to a file",
|
|
||||||
"options": {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
## Single Audit Backend [/sys/audit/{path}]
|
|
||||||
|
|
||||||
+ Parameters
|
|
||||||
+ path (required, string) ... The path where the audit backend is mounted
|
|
||||||
|
|
||||||
### Enable [PUT]
|
|
||||||
|
|
||||||
Enable an audit backend.
|
|
||||||
|
|
||||||
+ Request (application/json)
|
|
||||||
|
|
||||||
{
|
|
||||||
"type": "file",
|
|
||||||
"description": "send to a file",
|
|
||||||
"options": {
|
|
||||||
"path": "/var/log/vault.audit.log"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+ Response 204
|
|
||||||
|
|
||||||
### Disable [DELETE]
|
|
||||||
|
|
||||||
Disable an audit backend.
|
|
||||||
|
|
||||||
+ Request (application/json)
|
|
||||||
|
|
||||||
+ Response 204
|
|
||||||
|
|
||||||
# Group Secrets
|
|
||||||
|
|
||||||
## Generic [/{mount}/{path}]
|
|
||||||
|
|
||||||
This group documents the general format of reading and writing
|
|
||||||
to Vault. The exact structure of the keyspace is defined by the
|
|
||||||
logical backends in use, so documentation related to
|
|
||||||
a specific backend should be referenced for details on what keys
|
|
||||||
and routes are expected.
|
|
||||||
|
|
||||||
The path for examples are `/prefix/path`, but in practice
|
|
||||||
these will be defined by the backends that are mounted. For
|
|
||||||
example, reading an AWS key might be at the `/aws/root` path.
|
|
||||||
These paths are defined by the logical backends.
|
|
||||||
|
|
||||||
+ Parameters
|
|
||||||
+ mount (required, string) ... The mount point for the
|
|
||||||
logical backend. Example: `aws`.
|
|
||||||
+ path (optional, string) ... The path within the backend
|
|
||||||
to read or write data.
|
|
||||||
|
|
||||||
### Read [GET]
|
|
||||||
|
|
||||||
Read data from vault.
|
|
||||||
|
|
||||||
The data read from the vault can either be a secret or
|
|
||||||
arbitrary configuration data. The type of data returned
|
|
||||||
depends on the path, and is defined by the logical backend.
|
|
||||||
|
|
||||||
If the return value is a secret, then the return structure
|
|
||||||
is a mixture of arbitrary key/value along with the following
|
|
||||||
fields which are guaranteed to exist:
|
|
||||||
|
|
||||||
- `lease_id` (string) - A unique ID used for renewal and
|
|
||||||
revocation.
|
|
||||||
|
|
||||||
- `renewable` (bool) - If true, then this key can be renewed.
|
|
||||||
If a key can't be renewed, then a new key must be requested
|
|
||||||
after the lease duration period.
|
|
||||||
|
|
||||||
- `lease_duration` (int) - The time in seconds that a secret is
|
|
||||||
valid for before it must be renewed.
|
|
||||||
|
|
||||||
- `lease_duration_max` (int) - The maximum amount of time in
|
|
||||||
seconds that a secret is valid for. This will always be
|
|
||||||
greater than or equal to `lease_duration`. The difference
|
|
||||||
between this and `lease_duration` is an overlap window
|
|
||||||
where multiple keys may be valid.
|
|
||||||
|
|
||||||
If the return value is not a secret, then the return structure
|
|
||||||
is an arbitrary JSON object.
|
|
||||||
|
|
||||||
+ Response 200 (application/json)
|
|
||||||
|
|
||||||
{
|
|
||||||
"lease_id": "UUID",
|
|
||||||
"lease_duration": 3600,
|
|
||||||
"key": "value"
|
|
||||||
}
|
|
||||||
|
|
||||||
### Write [PUT]
|
|
||||||
|
|
||||||
Write data to vault.
|
|
||||||
|
|
||||||
The behavior and arguments to the write are defined by
|
|
||||||
the logical backend.
|
|
||||||
|
|
||||||
+ Request (application/json)
|
|
||||||
|
|
||||||
{
|
|
||||||
"key": "value"
|
|
||||||
}
|
|
||||||
|
|
||||||
+ Response 204
|
|
||||||
|
|
||||||
# Group Lease Management
|
|
||||||
|
|
||||||
## Renew Key [/sys/renew/{id}]
|
|
||||||
|
|
||||||
+ Parameters
|
|
||||||
+ id (required, string) ... The `lease_id` of the secret
|
|
||||||
to renew.
|
|
||||||
|
|
||||||
### Renew [PUT]
|
|
||||||
|
|
||||||
+ Response 200 (application/json)
|
|
||||||
|
|
||||||
{
|
|
||||||
"lease_id": "...",
|
|
||||||
"lease_duration": 3600,
|
|
||||||
"access_key": "foo",
|
|
||||||
"secret_key": "bar"
|
|
||||||
}
|
|
||||||
|
|
||||||
## Revoke Key [/sys/revoke/{id}]
|
|
||||||
|
|
||||||
+ Parameters
|
|
||||||
+ id (required, string) ... The `lease_id` of the secret
|
|
||||||
to revoke.
|
|
||||||
|
|
||||||
### Revoke [PUT]
|
|
||||||
|
|
||||||
+ Response 204
|
|
||||||
|
|
||||||
# Group Backend: AWS
|
|
||||||
|
|
||||||
## Root Key [/aws/root]
|
|
||||||
### Set the Key [PUT]
|
|
||||||
|
|
||||||
Set the root key that the logical backend will use to create
|
|
||||||
new secrets, IAM policies, etc.
|
|
||||||
|
|
||||||
+ Request (application/json)
|
|
||||||
|
|
||||||
{
|
|
||||||
"access_key": "key",
|
|
||||||
"secret_key": "key",
|
|
||||||
"region": "us-east-1"
|
|
||||||
}
|
|
||||||
|
|
||||||
+ Response 204
|
|
||||||
|
|
||||||
## Policies [/aws/policies]
|
|
||||||
### List Policies [GET]
|
|
||||||
|
|
||||||
List all the policies that can be used to create keys.
|
|
||||||
|
|
||||||
+ Response 200 (application/json)
|
|
||||||
|
|
||||||
[{
|
|
||||||
"name": "root",
|
|
||||||
"description": "Root access"
|
|
||||||
}, {
|
|
||||||
"name": "web-deploy",
|
|
||||||
"description": "Enough permissions to deploy the web app."
|
|
||||||
}]
|
|
||||||
|
|
||||||
## Single Policy [/aws/policies/{name}]
|
|
||||||
|
|
||||||
+ Parameters
|
|
||||||
+ name (required, string) ... Name of the policy.
|
|
||||||
|
|
||||||
### Read [GET]
|
|
||||||
|
|
||||||
Read a policy.
|
|
||||||
|
|
||||||
+ Response 200 (application/json)
|
|
||||||
|
|
||||||
{
|
|
||||||
"policy": "base64-encoded policy"
|
|
||||||
}
|
|
||||||
|
|
||||||
### Upsert [PUT]
|
|
||||||
|
|
||||||
Create or update a policy.
|
|
||||||
|
|
||||||
+ Request (application/json)
|
|
||||||
|
|
||||||
{
|
|
||||||
"policy": "base64-encoded policy"
|
|
||||||
}
|
|
||||||
|
|
||||||
+ Response 204
|
|
||||||
|
|
||||||
### Delete [DELETE]
|
|
||||||
|
|
||||||
Delete the policy with the given name.
|
|
||||||
|
|
||||||
+ Response 204
|
|
||||||
|
|
||||||
## Generate Access Keys [/aws/keys/{policy}]
|
|
||||||
### Create [GET]
|
|
||||||
|
|
||||||
This generates a new keypair for the given policy.
|
|
||||||
|
|
||||||
+ Parameters
|
|
||||||
+ policy (required, string) ... The policy under which to create
|
|
||||||
the key pair.
|
|
||||||
|
|
||||||
+ Response 200 (application/json)
|
|
||||||
|
|
||||||
{
|
|
||||||
"lease_id": "...",
|
|
||||||
"lease_duration": 3600,
|
|
||||||
"access_key": "foo",
|
|
||||||
"secret_key": "bar"
|
|
||||||
}
|
|
11
vendor/github.com/hashicorp/vault/api/auth.go
generated
vendored
11
vendor/github.com/hashicorp/vault/api/auth.go
generated
vendored
|
@ -1,11 +0,0 @@
|
||||||
package api
|
|
||||||
|
|
||||||
// Auth is used to perform credential backend related operations.
|
|
||||||
type Auth struct {
|
|
||||||
c *Client
|
|
||||||
}
|
|
||||||
|
|
||||||
// Auth is used to return the client for credential-backend API calls.
|
|
||||||
func (c *Client) Auth() *Auth {
|
|
||||||
return &Auth{c: c}
|
|
||||||
}
|
|
223
vendor/github.com/hashicorp/vault/api/auth_token.go
generated
vendored
223
vendor/github.com/hashicorp/vault/api/auth_token.go
generated
vendored
|
@ -1,223 +0,0 @@
|
||||||
package api
|
|
||||||
|
|
||||||
// TokenAuth is used to perform token backend operations on Vault
|
|
||||||
type TokenAuth struct {
|
|
||||||
c *Client
|
|
||||||
}
|
|
||||||
|
|
||||||
// Token is used to return the client for token-backend API calls
|
|
||||||
func (a *Auth) Token() *TokenAuth {
|
|
||||||
return &TokenAuth{c: a.c}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *TokenAuth) Create(opts *TokenCreateRequest) (*Secret, error) {
|
|
||||||
r := c.c.NewRequest("POST", "/v1/auth/token/create")
|
|
||||||
if err := r.SetJSONBody(opts); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := c.c.RawRequest(r)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
return ParseSecret(resp.Body)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *TokenAuth) CreateOrphan(opts *TokenCreateRequest) (*Secret, error) {
|
|
||||||
r := c.c.NewRequest("POST", "/v1/auth/token/create-orphan")
|
|
||||||
if err := r.SetJSONBody(opts); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := c.c.RawRequest(r)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
return ParseSecret(resp.Body)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *TokenAuth) CreateWithRole(opts *TokenCreateRequest, roleName string) (*Secret, error) {
|
|
||||||
r := c.c.NewRequest("POST", "/v1/auth/token/create/"+roleName)
|
|
||||||
if err := r.SetJSONBody(opts); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := c.c.RawRequest(r)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
return ParseSecret(resp.Body)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *TokenAuth) Lookup(token string) (*Secret, error) {
|
|
||||||
r := c.c.NewRequest("POST", "/v1/auth/token/lookup")
|
|
||||||
if err := r.SetJSONBody(map[string]interface{}{
|
|
||||||
"token": token,
|
|
||||||
}); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := c.c.RawRequest(r)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
return ParseSecret(resp.Body)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *TokenAuth) LookupAccessor(accessor string) (*Secret, error) {
|
|
||||||
r := c.c.NewRequest("POST", "/v1/auth/token/lookup-accessor")
|
|
||||||
if err := r.SetJSONBody(map[string]interface{}{
|
|
||||||
"accessor": accessor,
|
|
||||||
}); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
resp, err := c.c.RawRequest(r)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
return ParseSecret(resp.Body)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *TokenAuth) LookupSelf() (*Secret, error) {
|
|
||||||
r := c.c.NewRequest("GET", "/v1/auth/token/lookup-self")
|
|
||||||
|
|
||||||
resp, err := c.c.RawRequest(r)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
return ParseSecret(resp.Body)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *TokenAuth) Renew(token string, increment int) (*Secret, error) {
|
|
||||||
r := c.c.NewRequest("PUT", "/v1/auth/token/renew")
|
|
||||||
if err := r.SetJSONBody(map[string]interface{}{
|
|
||||||
"token": token,
|
|
||||||
"increment": increment,
|
|
||||||
}); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := c.c.RawRequest(r)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
return ParseSecret(resp.Body)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *TokenAuth) RenewSelf(increment int) (*Secret, error) {
|
|
||||||
r := c.c.NewRequest("PUT", "/v1/auth/token/renew-self")
|
|
||||||
|
|
||||||
body := map[string]interface{}{"increment": increment}
|
|
||||||
if err := r.SetJSONBody(body); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := c.c.RawRequest(r)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
return ParseSecret(resp.Body)
|
|
||||||
}
|
|
||||||
|
|
||||||
// RevokeAccessor revokes a token associated with the given accessor
|
|
||||||
// along with all the child tokens.
|
|
||||||
func (c *TokenAuth) RevokeAccessor(accessor string) error {
|
|
||||||
r := c.c.NewRequest("POST", "/v1/auth/token/revoke-accessor")
|
|
||||||
if err := r.SetJSONBody(map[string]interface{}{
|
|
||||||
"accessor": accessor,
|
|
||||||
}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
resp, err := c.c.RawRequest(r)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// RevokeOrphan revokes a token without revoking the tree underneath it (so
|
|
||||||
// child tokens are orphaned rather than revoked)
|
|
||||||
func (c *TokenAuth) RevokeOrphan(token string) error {
|
|
||||||
r := c.c.NewRequest("PUT", "/v1/auth/token/revoke-orphan")
|
|
||||||
if err := r.SetJSONBody(map[string]interface{}{
|
|
||||||
"token": token,
|
|
||||||
}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := c.c.RawRequest(r)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// RevokeSelf revokes the token making the call. The `token` parameter is kept
|
|
||||||
// for backwards compatibility but is ignored; only the client's set token has
|
|
||||||
// an effect.
|
|
||||||
func (c *TokenAuth) RevokeSelf(token string) error {
|
|
||||||
r := c.c.NewRequest("PUT", "/v1/auth/token/revoke-self")
|
|
||||||
resp, err := c.c.RawRequest(r)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// RevokeTree is the "normal" revoke operation that revokes the given token and
|
|
||||||
// the entire tree underneath -- all of its child tokens, their child tokens,
|
|
||||||
// etc.
|
|
||||||
func (c *TokenAuth) RevokeTree(token string) error {
|
|
||||||
r := c.c.NewRequest("PUT", "/v1/auth/token/revoke")
|
|
||||||
if err := r.SetJSONBody(map[string]interface{}{
|
|
||||||
"token": token,
|
|
||||||
}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := c.c.RawRequest(r)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// TokenCreateRequest is the options structure for creating a token.
|
|
||||||
type TokenCreateRequest struct {
|
|
||||||
ID string `json:"id,omitempty"`
|
|
||||||
Policies []string `json:"policies,omitempty"`
|
|
||||||
Metadata map[string]string `json:"meta,omitempty"`
|
|
||||||
Lease string `json:"lease,omitempty"`
|
|
||||||
TTL string `json:"ttl,omitempty"`
|
|
||||||
ExplicitMaxTTL string `json:"explicit_max_ttl,omitempty"`
|
|
||||||
Period string `json:"period,omitempty"`
|
|
||||||
NoParent bool `json:"no_parent,omitempty"`
|
|
||||||
NoDefaultPolicy bool `json:"no_default_policy,omitempty"`
|
|
||||||
DisplayName string `json:"display_name"`
|
|
||||||
NumUses int `json:"num_uses"`
|
|
||||||
Renewable *bool `json:"renewable,omitempty"`
|
|
||||||
}
|
|
432
vendor/github.com/hashicorp/vault/api/client.go
generated
vendored
432
vendor/github.com/hashicorp/vault/api/client.go
generated
vendored
|
@ -1,432 +0,0 @@
|
||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/tls"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"os"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
"path"
|
|
||||||
|
|
||||||
"golang.org/x/net/http2"
|
|
||||||
|
|
||||||
"github.com/hashicorp/go-cleanhttp"
|
|
||||||
"github.com/hashicorp/go-rootcerts"
|
|
||||||
"github.com/sethgrid/pester"
|
|
||||||
)
|
|
||||||
|
|
||||||
const EnvVaultAddress = "VAULT_ADDR"
|
|
||||||
const EnvVaultCACert = "VAULT_CACERT"
|
|
||||||
const EnvVaultCAPath = "VAULT_CAPATH"
|
|
||||||
const EnvVaultClientCert = "VAULT_CLIENT_CERT"
|
|
||||||
const EnvVaultClientKey = "VAULT_CLIENT_KEY"
|
|
||||||
const EnvVaultInsecure = "VAULT_SKIP_VERIFY"
|
|
||||||
const EnvVaultTLSServerName = "VAULT_TLS_SERVER_NAME"
|
|
||||||
const EnvVaultWrapTTL = "VAULT_WRAP_TTL"
|
|
||||||
const EnvVaultMaxRetries = "VAULT_MAX_RETRIES"
|
|
||||||
const EnvVaultToken = "VAULT_TOKEN"
|
|
||||||
|
|
||||||
// WrappingLookupFunc is a function that, given an HTTP verb and a path,
|
|
||||||
// returns an optional string duration to be used for response wrapping (e.g.
|
|
||||||
// "15s", or simply "15"). The path will not begin with "/v1/" or "v1/" or "/",
|
|
||||||
// however, end-of-path forward slashes are not trimmed, so must match your
|
|
||||||
// called path precisely.
|
|
||||||
type WrappingLookupFunc func(operation, path string) string
|
|
||||||
|
|
||||||
// Config is used to configure the creation of the client.
|
|
||||||
type Config struct {
|
|
||||||
// Address is the address of the Vault server. This should be a complete
|
|
||||||
// URL such as "http://vault.example.com". If you need a custom SSL
|
|
||||||
// cert or want to enable insecure mode, you need to specify a custom
|
|
||||||
// HttpClient.
|
|
||||||
Address string
|
|
||||||
|
|
||||||
// HttpClient is the HTTP client to use, which will currently always have the
|
|
||||||
// same values as http.DefaultClient. This is used to control redirect behavior.
|
|
||||||
HttpClient *http.Client
|
|
||||||
|
|
||||||
redirectSetup sync.Once
|
|
||||||
|
|
||||||
// MaxRetries controls the maximum number of times to retry when a 5xx error
|
|
||||||
// occurs. Set to 0 or less to disable retrying. Defaults to 0.
|
|
||||||
MaxRetries int
|
|
||||||
}
|
|
||||||
|
|
||||||
// TLSConfig contains the parameters needed to configure TLS on the HTTP client
|
|
||||||
// used to communicate with Vault.
|
|
||||||
type TLSConfig struct {
|
|
||||||
// CACert is the path to a PEM-encoded CA cert file to use to verify the
|
|
||||||
// Vault server SSL certificate.
|
|
||||||
CACert string
|
|
||||||
|
|
||||||
// CAPath is the path to a directory of PEM-encoded CA cert files to verify
|
|
||||||
// the Vault server SSL certificate.
|
|
||||||
CAPath string
|
|
||||||
|
|
||||||
// ClientCert is the path to the certificate for Vault communication
|
|
||||||
ClientCert string
|
|
||||||
|
|
||||||
// ClientKey is the path to the private key for Vault communication
|
|
||||||
ClientKey string
|
|
||||||
|
|
||||||
// TLSServerName, if set, is used to set the SNI host when connecting via
|
|
||||||
// TLS.
|
|
||||||
TLSServerName string
|
|
||||||
|
|
||||||
// Insecure enables or disables SSL verification
|
|
||||||
Insecure bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// DefaultConfig returns a default configuration for the client. It is
|
|
||||||
// safe to modify the return value of this function.
|
|
||||||
//
|
|
||||||
// The default Address is https://127.0.0.1:8200, but this can be overridden by
|
|
||||||
// setting the `VAULT_ADDR` environment variable.
|
|
||||||
func DefaultConfig() *Config {
|
|
||||||
config := &Config{
|
|
||||||
Address: "https://127.0.0.1:8200",
|
|
||||||
HttpClient: cleanhttp.DefaultClient(),
|
|
||||||
}
|
|
||||||
config.HttpClient.Timeout = time.Second * 60
|
|
||||||
transport := config.HttpClient.Transport.(*http.Transport)
|
|
||||||
transport.TLSHandshakeTimeout = 10 * time.Second
|
|
||||||
transport.TLSClientConfig = &tls.Config{
|
|
||||||
MinVersion: tls.VersionTLS12,
|
|
||||||
}
|
|
||||||
|
|
||||||
if v := os.Getenv(EnvVaultAddress); v != "" {
|
|
||||||
config.Address = v
|
|
||||||
}
|
|
||||||
|
|
||||||
return config
|
|
||||||
}
|
|
||||||
|
|
||||||
// ConfigureTLS takes a set of TLS configurations and applies those to the the HTTP client.
|
|
||||||
func (c *Config) ConfigureTLS(t *TLSConfig) error {
|
|
||||||
if c.HttpClient == nil {
|
|
||||||
c.HttpClient = DefaultConfig().HttpClient
|
|
||||||
}
|
|
||||||
|
|
||||||
var clientCert tls.Certificate
|
|
||||||
foundClientCert := false
|
|
||||||
if t.CACert != "" || t.CAPath != "" || t.ClientCert != "" || t.ClientKey != "" || t.Insecure {
|
|
||||||
if t.ClientCert != "" && t.ClientKey != "" {
|
|
||||||
var err error
|
|
||||||
clientCert, err = tls.LoadX509KeyPair(t.ClientCert, t.ClientKey)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
foundClientCert = true
|
|
||||||
} else if t.ClientCert != "" || t.ClientKey != "" {
|
|
||||||
return fmt.Errorf("Both client cert and client key must be provided")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
clientTLSConfig := c.HttpClient.Transport.(*http.Transport).TLSClientConfig
|
|
||||||
rootConfig := &rootcerts.Config{
|
|
||||||
CAFile: t.CACert,
|
|
||||||
CAPath: t.CAPath,
|
|
||||||
}
|
|
||||||
if err := rootcerts.ConfigureTLS(clientTLSConfig, rootConfig); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
clientTLSConfig.InsecureSkipVerify = t.Insecure
|
|
||||||
|
|
||||||
if foundClientCert {
|
|
||||||
clientTLSConfig.Certificates = []tls.Certificate{clientCert}
|
|
||||||
}
|
|
||||||
if t.TLSServerName != "" {
|
|
||||||
clientTLSConfig.ServerName = t.TLSServerName
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReadEnvironment reads configuration information from the
|
|
||||||
// environment. If there is an error, no configuration value
|
|
||||||
// is updated.
|
|
||||||
func (c *Config) ReadEnvironment() error {
|
|
||||||
var envAddress string
|
|
||||||
var envCACert string
|
|
||||||
var envCAPath string
|
|
||||||
var envClientCert string
|
|
||||||
var envClientKey string
|
|
||||||
var envInsecure bool
|
|
||||||
var envTLSServerName string
|
|
||||||
var envMaxRetries *uint64
|
|
||||||
|
|
||||||
// Parse the environment variables
|
|
||||||
if v := os.Getenv(EnvVaultAddress); v != "" {
|
|
||||||
envAddress = v
|
|
||||||
}
|
|
||||||
if v := os.Getenv(EnvVaultMaxRetries); v != "" {
|
|
||||||
maxRetries, err := strconv.ParseUint(v, 10, 32)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
envMaxRetries = &maxRetries
|
|
||||||
}
|
|
||||||
if v := os.Getenv(EnvVaultCACert); v != "" {
|
|
||||||
envCACert = v
|
|
||||||
}
|
|
||||||
if v := os.Getenv(EnvVaultCAPath); v != "" {
|
|
||||||
envCAPath = v
|
|
||||||
}
|
|
||||||
if v := os.Getenv(EnvVaultClientCert); v != "" {
|
|
||||||
envClientCert = v
|
|
||||||
}
|
|
||||||
if v := os.Getenv(EnvVaultClientKey); v != "" {
|
|
||||||
envClientKey = v
|
|
||||||
}
|
|
||||||
if v := os.Getenv(EnvVaultInsecure); v != "" {
|
|
||||||
var err error
|
|
||||||
envInsecure, err = strconv.ParseBool(v)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Could not parse VAULT_SKIP_VERIFY")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if v := os.Getenv(EnvVaultTLSServerName); v != "" {
|
|
||||||
envTLSServerName = v
|
|
||||||
}
|
|
||||||
|
|
||||||
// Configure the HTTP clients TLS configuration.
|
|
||||||
t := &TLSConfig{
|
|
||||||
CACert: envCACert,
|
|
||||||
CAPath: envCAPath,
|
|
||||||
ClientCert: envClientCert,
|
|
||||||
ClientKey: envClientKey,
|
|
||||||
TLSServerName: envTLSServerName,
|
|
||||||
Insecure: envInsecure,
|
|
||||||
}
|
|
||||||
if err := c.ConfigureTLS(t); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if envAddress != "" {
|
|
||||||
c.Address = envAddress
|
|
||||||
}
|
|
||||||
|
|
||||||
if envMaxRetries != nil {
|
|
||||||
c.MaxRetries = int(*envMaxRetries) + 1
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Client is the client to the Vault API. Create a client with
|
|
||||||
// NewClient.
|
|
||||||
type Client struct {
|
|
||||||
addr *url.URL
|
|
||||||
config *Config
|
|
||||||
token string
|
|
||||||
wrappingLookupFunc WrappingLookupFunc
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewClient returns a new client for the given configuration.
|
|
||||||
//
|
|
||||||
// If the environment variable `VAULT_TOKEN` is present, the token will be
|
|
||||||
// automatically added to the client. Otherwise, you must manually call
|
|
||||||
// `SetToken()`.
|
|
||||||
func NewClient(c *Config) (*Client, error) {
|
|
||||||
if c == nil {
|
|
||||||
c = DefaultConfig()
|
|
||||||
if err := c.ReadEnvironment(); err != nil {
|
|
||||||
return nil, fmt.Errorf("error reading environment: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
u, err := url.Parse(c.Address)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.HttpClient == nil {
|
|
||||||
c.HttpClient = DefaultConfig().HttpClient
|
|
||||||
}
|
|
||||||
|
|
||||||
tp := c.HttpClient.Transport.(*http.Transport)
|
|
||||||
if err := http2.ConfigureTransport(tp); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
redirFunc := func() {
|
|
||||||
// Ensure redirects are not automatically followed
|
|
||||||
// Note that this is sane for the API client as it has its own
|
|
||||||
// redirect handling logic (and thus also for command/meta),
|
|
||||||
// but in e.g. http_test actual redirect handling is necessary
|
|
||||||
c.HttpClient.CheckRedirect = func(req *http.Request, via []*http.Request) error {
|
|
||||||
// Returning this value causes the Go net library to not close the
|
|
||||||
// response body and to nil out the error. Otherwise pester tries
|
|
||||||
// three times on every redirect because it sees an error from this
|
|
||||||
// function (to prevent redirects) passing through to it.
|
|
||||||
return http.ErrUseLastResponse
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
c.redirectSetup.Do(redirFunc)
|
|
||||||
|
|
||||||
client := &Client{
|
|
||||||
addr: u,
|
|
||||||
config: c,
|
|
||||||
}
|
|
||||||
|
|
||||||
if token := os.Getenv(EnvVaultToken); token != "" {
|
|
||||||
client.SetToken(token)
|
|
||||||
}
|
|
||||||
|
|
||||||
return client, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sets the address of Vault in the client. The format of address should be
|
|
||||||
// "<Scheme>://<Host>:<Port>". Setting this on a client will override the
|
|
||||||
// value of VAULT_ADDR environment variable.
|
|
||||||
func (c *Client) SetAddress(addr string) error {
|
|
||||||
var err error
|
|
||||||
if c.addr, err = url.Parse(addr); err != nil {
|
|
||||||
return fmt.Errorf("failed to set address: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Address returns the Vault URL the client is configured to connect to
|
|
||||||
func (c *Client) Address() string {
|
|
||||||
return c.addr.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetMaxRetries sets the number of retries that will be used in the case of certain errors
|
|
||||||
func (c *Client) SetMaxRetries(retries int) {
|
|
||||||
c.config.MaxRetries = retries
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetWrappingLookupFunc sets a lookup function that returns desired wrap TTLs
|
|
||||||
// for a given operation and path
|
|
||||||
func (c *Client) SetWrappingLookupFunc(lookupFunc WrappingLookupFunc) {
|
|
||||||
c.wrappingLookupFunc = lookupFunc
|
|
||||||
}
|
|
||||||
|
|
||||||
// Token returns the access token being used by this client. It will
|
|
||||||
// return the empty string if there is no token set.
|
|
||||||
func (c *Client) Token() string {
|
|
||||||
return c.token
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetToken sets the token directly. This won't perform any auth
|
|
||||||
// verification, it simply sets the token properly for future requests.
|
|
||||||
func (c *Client) SetToken(v string) {
|
|
||||||
c.token = v
|
|
||||||
}
|
|
||||||
|
|
||||||
// ClearToken deletes the token if it is set or does nothing otherwise.
|
|
||||||
func (c *Client) ClearToken() {
|
|
||||||
c.token = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewRequest creates a new raw request object to query the Vault server
|
|
||||||
// configured for this client. This is an advanced method and generally
|
|
||||||
// doesn't need to be called externally.
|
|
||||||
func (c *Client) NewRequest(method, requestPath string) *Request {
|
|
||||||
req := &Request{
|
|
||||||
Method: method,
|
|
||||||
URL: &url.URL{
|
|
||||||
User: c.addr.User,
|
|
||||||
Scheme: c.addr.Scheme,
|
|
||||||
Host: c.addr.Host,
|
|
||||||
Path: path.Join(c.addr.Path, requestPath),
|
|
||||||
},
|
|
||||||
ClientToken: c.token,
|
|
||||||
Params: make(map[string][]string),
|
|
||||||
}
|
|
||||||
|
|
||||||
var lookupPath string
|
|
||||||
switch {
|
|
||||||
case strings.HasPrefix(requestPath, "/v1/"):
|
|
||||||
lookupPath = strings.TrimPrefix(requestPath, "/v1/")
|
|
||||||
case strings.HasPrefix(requestPath, "v1/"):
|
|
||||||
lookupPath = strings.TrimPrefix(requestPath, "v1/")
|
|
||||||
default:
|
|
||||||
lookupPath = requestPath
|
|
||||||
}
|
|
||||||
if c.wrappingLookupFunc != nil {
|
|
||||||
req.WrapTTL = c.wrappingLookupFunc(method, lookupPath)
|
|
||||||
} else {
|
|
||||||
req.WrapTTL = DefaultWrappingLookupFunc(method, lookupPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
return req
|
|
||||||
}
|
|
||||||
|
|
||||||
// RawRequest performs the raw request given. This request may be against
|
|
||||||
// a Vault server not configured with this client. This is an advanced operation
|
|
||||||
// that generally won't need to be called externally.
|
|
||||||
func (c *Client) RawRequest(r *Request) (*Response, error) {
|
|
||||||
redirectCount := 0
|
|
||||||
START:
|
|
||||||
req, err := r.ToHTTP()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
client := pester.NewExtendedClient(c.config.HttpClient)
|
|
||||||
client.Backoff = pester.LinearJitterBackoff
|
|
||||||
client.MaxRetries = c.config.MaxRetries
|
|
||||||
|
|
||||||
var result *Response
|
|
||||||
resp, err := client.Do(req)
|
|
||||||
if resp != nil {
|
|
||||||
result = &Response{Response: resp}
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
if strings.Contains(err.Error(), "tls: oversized") {
|
|
||||||
err = fmt.Errorf(
|
|
||||||
"%s\n\n"+
|
|
||||||
"This error usually means that the server is running with TLS disabled\n"+
|
|
||||||
"but the client is configured to use TLS. Please either enable TLS\n"+
|
|
||||||
"on the server or run the client with -address set to an address\n"+
|
|
||||||
"that uses the http protocol:\n\n"+
|
|
||||||
" vault <command> -address http://<address>\n\n"+
|
|
||||||
"You can also set the VAULT_ADDR environment variable:\n\n\n"+
|
|
||||||
" VAULT_ADDR=http://<address> vault <command>\n\n"+
|
|
||||||
"where <address> is replaced by the actual address to the server.",
|
|
||||||
err)
|
|
||||||
}
|
|
||||||
return result, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for a redirect, only allowing for a single redirect
|
|
||||||
if (resp.StatusCode == 301 || resp.StatusCode == 302 || resp.StatusCode == 307) && redirectCount == 0 {
|
|
||||||
// Parse the updated location
|
|
||||||
respLoc, err := resp.Location()
|
|
||||||
if err != nil {
|
|
||||||
return result, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure a protocol downgrade doesn't happen
|
|
||||||
if req.URL.Scheme == "https" && respLoc.Scheme != "https" {
|
|
||||||
return result, fmt.Errorf("redirect would cause protocol downgrade")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the request
|
|
||||||
r.URL = respLoc
|
|
||||||
|
|
||||||
// Reset the request body if any
|
|
||||||
if err := r.ResetJSONBody(); err != nil {
|
|
||||||
return result, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Retry the request
|
|
||||||
redirectCount++
|
|
||||||
goto START
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := result.Error(); err != nil {
|
|
||||||
return result, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return result, nil
|
|
||||||
}
|
|
25
vendor/github.com/hashicorp/vault/api/help.go
generated
vendored
25
vendor/github.com/hashicorp/vault/api/help.go
generated
vendored
|
@ -1,25 +0,0 @@
|
||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Help reads the help information for the given path.
|
|
||||||
func (c *Client) Help(path string) (*Help, error) {
|
|
||||||
r := c.NewRequest("GET", fmt.Sprintf("/v1/%s", path))
|
|
||||||
r.Params.Add("help", "1")
|
|
||||||
resp, err := c.RawRequest(r)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
var result Help
|
|
||||||
err = resp.DecodeJSON(&result)
|
|
||||||
return &result, err
|
|
||||||
}
|
|
||||||
|
|
||||||
type Help struct {
|
|
||||||
Help string `json:"help"`
|
|
||||||
SeeAlso []string `json:"see_also"`
|
|
||||||
}
|
|
185
vendor/github.com/hashicorp/vault/api/logical.go
generated
vendored
185
vendor/github.com/hashicorp/vault/api/logical.go
generated
vendored
|
@ -1,185 +0,0 @@
|
||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/hashicorp/vault/helper/jsonutil"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
wrappedResponseLocation = "cubbyhole/response"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// The default TTL that will be used with `sys/wrapping/wrap`, can be
|
|
||||||
// changed
|
|
||||||
DefaultWrappingTTL = "5m"
|
|
||||||
|
|
||||||
// The default function used if no other function is set, which honors the
|
|
||||||
// env var and wraps `sys/wrapping/wrap`
|
|
||||||
DefaultWrappingLookupFunc = func(operation, path string) string {
|
|
||||||
if os.Getenv(EnvVaultWrapTTL) != "" {
|
|
||||||
return os.Getenv(EnvVaultWrapTTL)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (operation == "PUT" || operation == "POST") && path == "sys/wrapping/wrap" {
|
|
||||||
return DefaultWrappingTTL
|
|
||||||
}
|
|
||||||
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
// Logical is used to perform logical backend operations on Vault.
|
|
||||||
type Logical struct {
|
|
||||||
c *Client
|
|
||||||
}
|
|
||||||
|
|
||||||
// Logical is used to return the client for logical-backend API calls.
|
|
||||||
func (c *Client) Logical() *Logical {
|
|
||||||
return &Logical{c: c}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Logical) Read(path string) (*Secret, error) {
|
|
||||||
r := c.c.NewRequest("GET", "/v1/"+path)
|
|
||||||
resp, err := c.c.RawRequest(r)
|
|
||||||
if resp != nil {
|
|
||||||
defer resp.Body.Close()
|
|
||||||
}
|
|
||||||
if resp != nil && resp.StatusCode == 404 {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return ParseSecret(resp.Body)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Logical) List(path string) (*Secret, error) {
|
|
||||||
r := c.c.NewRequest("LIST", "/v1/"+path)
|
|
||||||
// Set this for broader compatibility, but we use LIST above to be able to
|
|
||||||
// handle the wrapping lookup function
|
|
||||||
r.Method = "GET"
|
|
||||||
r.Params.Set("list", "true")
|
|
||||||
resp, err := c.c.RawRequest(r)
|
|
||||||
if resp != nil {
|
|
||||||
defer resp.Body.Close()
|
|
||||||
}
|
|
||||||
if resp != nil && resp.StatusCode == 404 {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return ParseSecret(resp.Body)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Logical) Write(path string, data map[string]interface{}) (*Secret, error) {
|
|
||||||
r := c.c.NewRequest("PUT", "/v1/"+path)
|
|
||||||
if err := r.SetJSONBody(data); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := c.c.RawRequest(r)
|
|
||||||
if resp != nil {
|
|
||||||
defer resp.Body.Close()
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if resp.StatusCode == 200 {
|
|
||||||
return ParseSecret(resp.Body)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Logical) Delete(path string) (*Secret, error) {
|
|
||||||
r := c.c.NewRequest("DELETE", "/v1/"+path)
|
|
||||||
resp, err := c.c.RawRequest(r)
|
|
||||||
if resp != nil {
|
|
||||||
defer resp.Body.Close()
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if resp.StatusCode == 200 {
|
|
||||||
return ParseSecret(resp.Body)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Logical) Unwrap(wrappingToken string) (*Secret, error) {
|
|
||||||
var data map[string]interface{}
|
|
||||||
if wrappingToken != "" {
|
|
||||||
if c.c.Token() == "" {
|
|
||||||
c.c.SetToken(wrappingToken)
|
|
||||||
} else if wrappingToken != c.c.Token() {
|
|
||||||
data = map[string]interface{}{
|
|
||||||
"token": wrappingToken,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
r := c.c.NewRequest("PUT", "/v1/sys/wrapping/unwrap")
|
|
||||||
if err := r.SetJSONBody(data); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := c.c.RawRequest(r)
|
|
||||||
if resp != nil {
|
|
||||||
defer resp.Body.Close()
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
if resp != nil && resp.StatusCode != 404 {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if resp == nil {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
switch resp.StatusCode {
|
|
||||||
case http.StatusOK: // New method is supported
|
|
||||||
return ParseSecret(resp.Body)
|
|
||||||
case http.StatusNotFound: // Fall back to old method
|
|
||||||
default:
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if wrappingToken != "" {
|
|
||||||
origToken := c.c.Token()
|
|
||||||
defer c.c.SetToken(origToken)
|
|
||||||
c.c.SetToken(wrappingToken)
|
|
||||||
}
|
|
||||||
|
|
||||||
secret, err := c.Read(wrappedResponseLocation)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("error reading %s: %s", wrappedResponseLocation, err)
|
|
||||||
}
|
|
||||||
if secret == nil {
|
|
||||||
return nil, fmt.Errorf("no value found at %s", wrappedResponseLocation)
|
|
||||||
}
|
|
||||||
if secret.Data == nil {
|
|
||||||
return nil, fmt.Errorf("\"data\" not found in wrapping response")
|
|
||||||
}
|
|
||||||
if _, ok := secret.Data["response"]; !ok {
|
|
||||||
return nil, fmt.Errorf("\"response\" not found in wrapping response \"data\" map")
|
|
||||||
}
|
|
||||||
|
|
||||||
wrappedSecret := new(Secret)
|
|
||||||
buf := bytes.NewBufferString(secret.Data["response"].(string))
|
|
||||||
if err := jsonutil.DecodeJSONFromReader(buf, wrappedSecret); err != nil {
|
|
||||||
return nil, fmt.Errorf("error unmarshaling wrapped secret: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return wrappedSecret, nil
|
|
||||||
}
|
|
72
vendor/github.com/hashicorp/vault/api/request.go
generated
vendored
72
vendor/github.com/hashicorp/vault/api/request.go
generated
vendored
|
@ -1,72 +0,0 @@
|
||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Request is a raw request configuration structure used to initiate
|
|
||||||
// API requests to the Vault server.
|
|
||||||
type Request struct {
|
|
||||||
Method string
|
|
||||||
URL *url.URL
|
|
||||||
Params url.Values
|
|
||||||
ClientToken string
|
|
||||||
WrapTTL string
|
|
||||||
Obj interface{}
|
|
||||||
Body io.Reader
|
|
||||||
BodySize int64
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetJSONBody is used to set a request body that is a JSON-encoded value.
|
|
||||||
func (r *Request) SetJSONBody(val interface{}) error {
|
|
||||||
buf := bytes.NewBuffer(nil)
|
|
||||||
enc := json.NewEncoder(buf)
|
|
||||||
if err := enc.Encode(val); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
r.Obj = val
|
|
||||||
r.Body = buf
|
|
||||||
r.BodySize = int64(buf.Len())
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ResetJSONBody is used to reset the body for a redirect
|
|
||||||
func (r *Request) ResetJSONBody() error {
|
|
||||||
if r.Body == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return r.SetJSONBody(r.Obj)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToHTTP turns this request into a valid *http.Request for use with the
|
|
||||||
// net/http package.
|
|
||||||
func (r *Request) ToHTTP() (*http.Request, error) {
|
|
||||||
// Encode the query parameters
|
|
||||||
r.URL.RawQuery = r.Params.Encode()
|
|
||||||
|
|
||||||
// Create the HTTP request
|
|
||||||
req, err := http.NewRequest(r.Method, r.URL.RequestURI(), r.Body)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
req.URL.User = r.URL.User
|
|
||||||
req.URL.Scheme = r.URL.Scheme
|
|
||||||
req.URL.Host = r.URL.Host
|
|
||||||
req.Host = r.URL.Host
|
|
||||||
|
|
||||||
if len(r.ClientToken) != 0 {
|
|
||||||
req.Header.Set("X-Vault-Token", r.ClientToken)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(r.WrapTTL) != 0 {
|
|
||||||
req.Header.Set("X-Vault-Wrap-TTL", r.WrapTTL)
|
|
||||||
}
|
|
||||||
|
|
||||||
return req, nil
|
|
||||||
}
|
|
72
vendor/github.com/hashicorp/vault/api/response.go
generated
vendored
72
vendor/github.com/hashicorp/vault/api/response.go
generated
vendored
|
@ -1,72 +0,0 @@
|
||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/hashicorp/vault/helper/jsonutil"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Response is a raw response that wraps an HTTP response.
|
|
||||||
type Response struct {
|
|
||||||
*http.Response
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecodeJSON will decode the response body to a JSON structure. This
|
|
||||||
// will consume the response body, but will not close it. Close must
|
|
||||||
// still be called.
|
|
||||||
func (r *Response) DecodeJSON(out interface{}) error {
|
|
||||||
return jsonutil.DecodeJSONFromReader(r.Body, out)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error returns an error response if there is one. If there is an error,
|
|
||||||
// this will fully consume the response body, but will not close it. The
|
|
||||||
// body must still be closed manually.
|
|
||||||
func (r *Response) Error() error {
|
|
||||||
// 200 to 399 are okay status codes
|
|
||||||
if r.StatusCode >= 200 && r.StatusCode < 400 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// We have an error. Let's copy the body into our own buffer first,
|
|
||||||
// so that if we can't decode JSON, we can at least copy it raw.
|
|
||||||
var bodyBuf bytes.Buffer
|
|
||||||
if _, err := io.Copy(&bodyBuf, r.Body); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decode the error response if we can. Note that we wrap the bodyBuf
|
|
||||||
// in a bytes.Reader here so that the JSON decoder doesn't move the
|
|
||||||
// read pointer for the original buffer.
|
|
||||||
var resp ErrorResponse
|
|
||||||
if err := jsonutil.DecodeJSON(bodyBuf.Bytes(), &resp); err != nil {
|
|
||||||
// Ignore the decoding error and just drop the raw response
|
|
||||||
return fmt.Errorf(
|
|
||||||
"Error making API request.\n\n"+
|
|
||||||
"URL: %s %s\n"+
|
|
||||||
"Code: %d. Raw Message:\n\n%s",
|
|
||||||
r.Request.Method, r.Request.URL.String(),
|
|
||||||
r.StatusCode, bodyBuf.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
var errBody bytes.Buffer
|
|
||||||
errBody.WriteString(fmt.Sprintf(
|
|
||||||
"Error making API request.\n\n"+
|
|
||||||
"URL: %s %s\n"+
|
|
||||||
"Code: %d. Errors:\n\n",
|
|
||||||
r.Request.Method, r.Request.URL.String(),
|
|
||||||
r.StatusCode))
|
|
||||||
for _, err := range resp.Errors {
|
|
||||||
errBody.WriteString(fmt.Sprintf("* %s", err))
|
|
||||||
}
|
|
||||||
|
|
||||||
return fmt.Errorf(errBody.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrorResponse is the raw structure of errors when they're returned by the
|
|
||||||
// HTTP API.
|
|
||||||
type ErrorResponse struct {
|
|
||||||
Errors []string
|
|
||||||
}
|
|
68
vendor/github.com/hashicorp/vault/api/secret.go
generated
vendored
68
vendor/github.com/hashicorp/vault/api/secret.go
generated
vendored
|
@ -1,68 +0,0 @@
|
||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/hashicorp/vault/helper/jsonutil"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Secret is the structure returned for every secret within Vault.
|
|
||||||
type Secret struct {
|
|
||||||
// The request ID that generated this response
|
|
||||||
RequestID string `json:"request_id"`
|
|
||||||
|
|
||||||
LeaseID string `json:"lease_id"`
|
|
||||||
LeaseDuration int `json:"lease_duration"`
|
|
||||||
Renewable bool `json:"renewable"`
|
|
||||||
|
|
||||||
// Data is the actual contents of the secret. The format of the data
|
|
||||||
// is arbitrary and up to the secret backend.
|
|
||||||
Data map[string]interface{} `json:"data"`
|
|
||||||
|
|
||||||
// Warnings contains any warnings related to the operation. These
|
|
||||||
// are not issues that caused the command to fail, but that the
|
|
||||||
// client should be aware of.
|
|
||||||
Warnings []string `json:"warnings"`
|
|
||||||
|
|
||||||
// Auth, if non-nil, means that there was authentication information
|
|
||||||
// attached to this response.
|
|
||||||
Auth *SecretAuth `json:"auth,omitempty"`
|
|
||||||
|
|
||||||
// WrapInfo, if non-nil, means that the initial response was wrapped in the
|
|
||||||
// cubbyhole of the given token (which has a TTL of the given number of
|
|
||||||
// seconds)
|
|
||||||
WrapInfo *SecretWrapInfo `json:"wrap_info,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// SecretWrapInfo contains wrapping information if we have it. If what is
|
|
||||||
// contained is an authentication token, the accessor for the token will be
|
|
||||||
// available in WrappedAccessor.
|
|
||||||
type SecretWrapInfo struct {
|
|
||||||
Token string `json:"token"`
|
|
||||||
TTL int `json:"ttl"`
|
|
||||||
CreationTime time.Time `json:"creation_time"`
|
|
||||||
WrappedAccessor string `json:"wrapped_accessor"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// SecretAuth is the structure containing auth information if we have it.
|
|
||||||
type SecretAuth struct {
|
|
||||||
ClientToken string `json:"client_token"`
|
|
||||||
Accessor string `json:"accessor"`
|
|
||||||
Policies []string `json:"policies"`
|
|
||||||
Metadata map[string]string `json:"metadata"`
|
|
||||||
|
|
||||||
LeaseDuration int `json:"lease_duration"`
|
|
||||||
Renewable bool `json:"renewable"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseSecret is used to parse a secret value from JSON from an io.Reader.
|
|
||||||
func ParseSecret(r io.Reader) (*Secret, error) {
|
|
||||||
// First decode the JSON into a map[string]interface{}
|
|
||||||
var secret Secret
|
|
||||||
if err := jsonutil.DecodeJSONFromReader(r, &secret); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &secret, nil
|
|
||||||
}
|
|
38
vendor/github.com/hashicorp/vault/api/ssh.go
generated
vendored
38
vendor/github.com/hashicorp/vault/api/ssh.go
generated
vendored
|
@ -1,38 +0,0 @@
|
||||||
package api
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
// SSH is used to return a client to invoke operations on SSH backend.
|
|
||||||
type SSH struct {
|
|
||||||
c *Client
|
|
||||||
MountPoint string
|
|
||||||
}
|
|
||||||
|
|
||||||
// SSH returns the client for logical-backend API calls.
|
|
||||||
func (c *Client) SSH() *SSH {
|
|
||||||
return c.SSHWithMountPoint(SSHHelperDefaultMountPoint)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SSHWithMountPoint returns the client with specific SSH mount point.
|
|
||||||
func (c *Client) SSHWithMountPoint(mountPoint string) *SSH {
|
|
||||||
return &SSH{
|
|
||||||
c: c,
|
|
||||||
MountPoint: mountPoint,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Credential invokes the SSH backend API to create a credential to establish an SSH session.
|
|
||||||
func (c *SSH) Credential(role string, data map[string]interface{}) (*Secret, error) {
|
|
||||||
r := c.c.NewRequest("PUT", fmt.Sprintf("/v1/%s/creds/%s", c.MountPoint, role))
|
|
||||||
if err := r.SetJSONBody(data); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := c.c.RawRequest(r)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
return ParseSecret(resp.Body)
|
|
||||||
}
|
|
257
vendor/github.com/hashicorp/vault/api/ssh_agent.go
generated
vendored
257
vendor/github.com/hashicorp/vault/api/ssh_agent.go
generated
vendored
|
@ -1,257 +0,0 @@
|
||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/tls"
|
|
||||||
"crypto/x509"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/hashicorp/go-cleanhttp"
|
|
||||||
"github.com/hashicorp/go-multierror"
|
|
||||||
"github.com/hashicorp/go-rootcerts"
|
|
||||||
"github.com/hashicorp/hcl"
|
|
||||||
"github.com/hashicorp/hcl/hcl/ast"
|
|
||||||
"github.com/mitchellh/mapstructure"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// SSHHelperDefaultMountPoint is the default path at which SSH backend will be
|
|
||||||
// mounted in the Vault server.
|
|
||||||
SSHHelperDefaultMountPoint = "ssh"
|
|
||||||
|
|
||||||
// VerifyEchoRequest is the echo request message sent as OTP by the helper.
|
|
||||||
VerifyEchoRequest = "verify-echo-request"
|
|
||||||
|
|
||||||
// VerifyEchoResponse is the echo response message sent as a response to OTP
|
|
||||||
// matching echo request.
|
|
||||||
VerifyEchoResponse = "verify-echo-response"
|
|
||||||
)
|
|
||||||
|
|
||||||
// SSHHelper is a structure representing a vault-ssh-helper which can talk to vault server
|
|
||||||
// in order to verify the OTP entered by the user. It contains the path at which
|
|
||||||
// SSH backend is mounted at the server.
|
|
||||||
type SSHHelper struct {
|
|
||||||
c *Client
|
|
||||||
MountPoint string
|
|
||||||
}
|
|
||||||
|
|
||||||
// SSHVerifyResponse is a structure representing the fields in Vault server's
|
|
||||||
// response.
|
|
||||||
type SSHVerifyResponse struct {
|
|
||||||
// Usually empty. If the request OTP is echo request message, this will
|
|
||||||
// be set to the corresponding echo response message.
|
|
||||||
Message string `json:"message" structs:"message" mapstructure:"message"`
|
|
||||||
|
|
||||||
// Username associated with the OTP
|
|
||||||
Username string `json:"username" structs:"username" mapstructure:"username"`
|
|
||||||
|
|
||||||
// IP associated with the OTP
|
|
||||||
IP string `json:"ip" structs:"ip" mapstructure:"ip"`
|
|
||||||
|
|
||||||
// Name of the role against which the OTP was issued
|
|
||||||
RoleName string `json:"role_name" structs:"role_name" mapstructure:"role_name"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// SSHHelperConfig is a structure which represents the entries from the vault-ssh-helper's configuration file.
|
|
||||||
type SSHHelperConfig struct {
|
|
||||||
VaultAddr string `hcl:"vault_addr"`
|
|
||||||
SSHMountPoint string `hcl:"ssh_mount_point"`
|
|
||||||
CACert string `hcl:"ca_cert"`
|
|
||||||
CAPath string `hcl:"ca_path"`
|
|
||||||
AllowedCidrList string `hcl:"allowed_cidr_list"`
|
|
||||||
AllowedRoles string `hcl:"allowed_roles"`
|
|
||||||
TLSSkipVerify bool `hcl:"tls_skip_verify"`
|
|
||||||
TLSServerName string `hcl:"tls_server_name"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetTLSParameters sets the TLS parameters for this SSH agent.
|
|
||||||
func (c *SSHHelperConfig) SetTLSParameters(clientConfig *Config, certPool *x509.CertPool) {
|
|
||||||
tlsConfig := &tls.Config{
|
|
||||||
InsecureSkipVerify: c.TLSSkipVerify,
|
|
||||||
MinVersion: tls.VersionTLS12,
|
|
||||||
RootCAs: certPool,
|
|
||||||
ServerName: c.TLSServerName,
|
|
||||||
}
|
|
||||||
|
|
||||||
transport := cleanhttp.DefaultTransport()
|
|
||||||
transport.TLSClientConfig = tlsConfig
|
|
||||||
clientConfig.HttpClient.Transport = transport
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns true if any of the following conditions are true:
|
|
||||||
// * CA cert is configured
|
|
||||||
// * CA path is configured
|
|
||||||
// * configured to skip certificate verification
|
|
||||||
// * TLS server name is configured
|
|
||||||
//
|
|
||||||
func (c *SSHHelperConfig) shouldSetTLSParameters() bool {
|
|
||||||
return c.CACert != "" || c.CAPath != "" || c.TLSServerName != "" || c.TLSSkipVerify
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewClient returns a new client for the configuration. This client will be used by the
|
|
||||||
// vault-ssh-helper to communicate with Vault server and verify the OTP entered by user.
|
|
||||||
// If the configuration supplies Vault SSL certificates, then the client will
|
|
||||||
// have TLS configured in its transport.
|
|
||||||
func (c *SSHHelperConfig) NewClient() (*Client, error) {
|
|
||||||
// Creating a default client configuration for communicating with vault server.
|
|
||||||
clientConfig := DefaultConfig()
|
|
||||||
|
|
||||||
// Pointing the client to the actual address of vault server.
|
|
||||||
clientConfig.Address = c.VaultAddr
|
|
||||||
|
|
||||||
// Check if certificates are provided via config file.
|
|
||||||
if c.shouldSetTLSParameters() {
|
|
||||||
rootConfig := &rootcerts.Config{
|
|
||||||
CAFile: c.CACert,
|
|
||||||
CAPath: c.CAPath,
|
|
||||||
}
|
|
||||||
certPool, err := rootcerts.LoadCACerts(rootConfig)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// Enable TLS on the HTTP client information
|
|
||||||
c.SetTLSParameters(clientConfig, certPool)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Creating the client object for the given configuration
|
|
||||||
client, err := NewClient(clientConfig)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return client, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadSSHHelperConfig loads ssh-helper's configuration from the file and populates the corresponding
|
|
||||||
// in-memory structure.
|
|
||||||
//
|
|
||||||
// Vault address is a required parameter.
|
|
||||||
// Mount point defaults to "ssh".
|
|
||||||
func LoadSSHHelperConfig(path string) (*SSHHelperConfig, error) {
|
|
||||||
contents, err := ioutil.ReadFile(path)
|
|
||||||
if err != nil && !os.IsNotExist(err) {
|
|
||||||
return nil, multierror.Prefix(err, "ssh_helper:")
|
|
||||||
}
|
|
||||||
return ParseSSHHelperConfig(string(contents))
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseSSHHelperConfig parses the given contents as a string for the SSHHelper
|
|
||||||
// configuration.
|
|
||||||
func ParseSSHHelperConfig(contents string) (*SSHHelperConfig, error) {
|
|
||||||
root, err := hcl.Parse(string(contents))
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("ssh_helper: error parsing config: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
list, ok := root.Node.(*ast.ObjectList)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("ssh_helper: error parsing config: file doesn't contain a root object")
|
|
||||||
}
|
|
||||||
|
|
||||||
valid := []string{
|
|
||||||
"vault_addr",
|
|
||||||
"ssh_mount_point",
|
|
||||||
"ca_cert",
|
|
||||||
"ca_path",
|
|
||||||
"allowed_cidr_list",
|
|
||||||
"allowed_roles",
|
|
||||||
"tls_skip_verify",
|
|
||||||
"tls_server_name",
|
|
||||||
}
|
|
||||||
if err := checkHCLKeys(list, valid); err != nil {
|
|
||||||
return nil, multierror.Prefix(err, "ssh_helper:")
|
|
||||||
}
|
|
||||||
|
|
||||||
var c SSHHelperConfig
|
|
||||||
c.SSHMountPoint = SSHHelperDefaultMountPoint
|
|
||||||
if err := hcl.DecodeObject(&c, list); err != nil {
|
|
||||||
return nil, multierror.Prefix(err, "ssh_helper:")
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.VaultAddr == "" {
|
|
||||||
return nil, fmt.Errorf("ssh_helper: missing config 'vault_addr'")
|
|
||||||
}
|
|
||||||
return &c, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SSHHelper creates an SSHHelper object which can talk to Vault server with SSH backend
|
|
||||||
// mounted at default path ("ssh").
|
|
||||||
func (c *Client) SSHHelper() *SSHHelper {
|
|
||||||
return c.SSHHelperWithMountPoint(SSHHelperDefaultMountPoint)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SSHHelperWithMountPoint creates an SSHHelper object which can talk to Vault server with SSH backend
|
|
||||||
// mounted at a specific mount point.
|
|
||||||
func (c *Client) SSHHelperWithMountPoint(mountPoint string) *SSHHelper {
|
|
||||||
return &SSHHelper{
|
|
||||||
c: c,
|
|
||||||
MountPoint: mountPoint,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify verifies if the key provided by user is present in Vault server. The response
|
|
||||||
// will contain the IP address and username associated with the OTP. In case the
|
|
||||||
// OTP matches the echo request message, instead of searching an entry for the OTP,
|
|
||||||
// an echo response message is returned. This feature is used by ssh-helper to verify if
|
|
||||||
// its configured correctly.
|
|
||||||
func (c *SSHHelper) Verify(otp string) (*SSHVerifyResponse, error) {
|
|
||||||
data := map[string]interface{}{
|
|
||||||
"otp": otp,
|
|
||||||
}
|
|
||||||
verifyPath := fmt.Sprintf("/v1/%s/verify", c.MountPoint)
|
|
||||||
r := c.c.NewRequest("PUT", verifyPath)
|
|
||||||
if err := r.SetJSONBody(data); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := c.c.RawRequest(r)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
secret, err := ParseSecret(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if secret.Data == nil {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var verifyResp SSHVerifyResponse
|
|
||||||
err = mapstructure.Decode(secret.Data, &verifyResp)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &verifyResp, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkHCLKeys(node ast.Node, valid []string) error {
|
|
||||||
var list *ast.ObjectList
|
|
||||||
switch n := node.(type) {
|
|
||||||
case *ast.ObjectList:
|
|
||||||
list = n
|
|
||||||
case *ast.ObjectType:
|
|
||||||
list = n.List
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("cannot check HCL keys of type %T", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
validMap := make(map[string]struct{}, len(valid))
|
|
||||||
for _, v := range valid {
|
|
||||||
validMap[v] = struct{}{}
|
|
||||||
}
|
|
||||||
|
|
||||||
var result error
|
|
||||||
for _, item := range list.Items {
|
|
||||||
key := item.Keys[0].Token.Value().(string)
|
|
||||||
if _, ok := validMap[key]; !ok {
|
|
||||||
result = multierror.Append(result, fmt.Errorf(
|
|
||||||
"invalid key '%s' on line %d", key, item.Assign.Line))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
11
vendor/github.com/hashicorp/vault/api/sys.go
generated
vendored
11
vendor/github.com/hashicorp/vault/api/sys.go
generated
vendored
|
@ -1,11 +0,0 @@
|
||||||
package api
|
|
||||||
|
|
||||||
// Sys is used to perform system-related operations on Vault.
|
|
||||||
type Sys struct {
|
|
||||||
c *Client
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sys is used to return the client for sys-related API calls.
|
|
||||||
func (c *Client) Sys() *Sys {
|
|
||||||
return &Sys{c: c}
|
|
||||||
}
|
|
128
vendor/github.com/hashicorp/vault/api/sys_audit.go
generated
vendored
128
vendor/github.com/hashicorp/vault/api/sys_audit.go
generated
vendored
|
@ -1,128 +0,0 @@
|
||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/fatih/structs"
|
|
||||||
"github.com/mitchellh/mapstructure"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (c *Sys) AuditHash(path string, input string) (string, error) {
|
|
||||||
body := map[string]interface{}{
|
|
||||||
"input": input,
|
|
||||||
}
|
|
||||||
|
|
||||||
r := c.c.NewRequest("PUT", fmt.Sprintf("/v1/sys/audit-hash/%s", path))
|
|
||||||
if err := r.SetJSONBody(body); err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := c.c.RawRequest(r)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
type d struct {
|
|
||||||
Hash string `json:"hash"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var result d
|
|
||||||
err = resp.DecodeJSON(&result)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return result.Hash, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Sys) ListAudit() (map[string]*Audit, error) {
|
|
||||||
r := c.c.NewRequest("GET", "/v1/sys/audit")
|
|
||||||
resp, err := c.c.RawRequest(r)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
var result map[string]interface{}
|
|
||||||
err = resp.DecodeJSON(&result)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
mounts := map[string]*Audit{}
|
|
||||||
for k, v := range result {
|
|
||||||
switch v.(type) {
|
|
||||||
case map[string]interface{}:
|
|
||||||
default:
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
var res Audit
|
|
||||||
err = mapstructure.Decode(v, &res)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// Not a mount, some other api.Secret data
|
|
||||||
if res.Type == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
mounts[k] = &res
|
|
||||||
}
|
|
||||||
|
|
||||||
return mounts, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DEPRECATED: Use EnableAuditWithOptions instead
|
|
||||||
func (c *Sys) EnableAudit(
|
|
||||||
path string, auditType string, desc string, opts map[string]string) error {
|
|
||||||
return c.EnableAuditWithOptions(path, &EnableAuditOptions{
|
|
||||||
Type: auditType,
|
|
||||||
Description: desc,
|
|
||||||
Options: opts,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Sys) EnableAuditWithOptions(path string, options *EnableAuditOptions) error {
|
|
||||||
body := structs.Map(options)
|
|
||||||
|
|
||||||
r := c.c.NewRequest("PUT", fmt.Sprintf("/v1/sys/audit/%s", path))
|
|
||||||
if err := r.SetJSONBody(body); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := c.c.RawRequest(r)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Sys) DisableAudit(path string) error {
|
|
||||||
r := c.c.NewRequest("DELETE", fmt.Sprintf("/v1/sys/audit/%s", path))
|
|
||||||
resp, err := c.c.RawRequest(r)
|
|
||||||
if err == nil {
|
|
||||||
defer resp.Body.Close()
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Structures for the requests/resposne are all down here. They aren't
|
|
||||||
// individually documented because the map almost directly to the raw HTTP API
|
|
||||||
// documentation. Please refer to that documentation for more details.
|
|
||||||
|
|
||||||
type EnableAuditOptions struct {
|
|
||||||
Type string `json:"type" structs:"type"`
|
|
||||||
Description string `json:"description" structs:"description"`
|
|
||||||
Options map[string]string `json:"options" structs:"options"`
|
|
||||||
Local bool `json:"local" structs:"local"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Audit struct {
|
|
||||||
Path string
|
|
||||||
Type string
|
|
||||||
Description string
|
|
||||||
Options map[string]string
|
|
||||||
Local bool
|
|
||||||
}
|
|
100
vendor/github.com/hashicorp/vault/api/sys_auth.go
generated
vendored
100
vendor/github.com/hashicorp/vault/api/sys_auth.go
generated
vendored
|
@ -1,100 +0,0 @@
|
||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/fatih/structs"
|
|
||||||
"github.com/mitchellh/mapstructure"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (c *Sys) ListAuth() (map[string]*AuthMount, error) {
|
|
||||||
r := c.c.NewRequest("GET", "/v1/sys/auth")
|
|
||||||
resp, err := c.c.RawRequest(r)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
var result map[string]interface{}
|
|
||||||
err = resp.DecodeJSON(&result)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
mounts := map[string]*AuthMount{}
|
|
||||||
for k, v := range result {
|
|
||||||
switch v.(type) {
|
|
||||||
case map[string]interface{}:
|
|
||||||
default:
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
var res AuthMount
|
|
||||||
err = mapstructure.Decode(v, &res)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// Not a mount, some other api.Secret data
|
|
||||||
if res.Type == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
mounts[k] = &res
|
|
||||||
}
|
|
||||||
|
|
||||||
return mounts, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DEPRECATED: Use EnableAuthWithOptions instead
|
|
||||||
func (c *Sys) EnableAuth(path, authType, desc string) error {
|
|
||||||
return c.EnableAuthWithOptions(path, &EnableAuthOptions{
|
|
||||||
Type: authType,
|
|
||||||
Description: desc,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Sys) EnableAuthWithOptions(path string, options *EnableAuthOptions) error {
|
|
||||||
body := structs.Map(options)
|
|
||||||
|
|
||||||
r := c.c.NewRequest("POST", fmt.Sprintf("/v1/sys/auth/%s", path))
|
|
||||||
if err := r.SetJSONBody(body); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := c.c.RawRequest(r)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Sys) DisableAuth(path string) error {
|
|
||||||
r := c.c.NewRequest("DELETE", fmt.Sprintf("/v1/sys/auth/%s", path))
|
|
||||||
resp, err := c.c.RawRequest(r)
|
|
||||||
if err == nil {
|
|
||||||
defer resp.Body.Close()
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Structures for the requests/resposne are all down here. They aren't
|
|
||||||
// individually documentd because the map almost directly to the raw HTTP API
|
|
||||||
// documentation. Please refer to that documentation for more details.
|
|
||||||
|
|
||||||
type EnableAuthOptions struct {
|
|
||||||
Type string `json:"type" structs:"type"`
|
|
||||||
Description string `json:"description" structs:"description"`
|
|
||||||
Local bool `json:"local" structs:"local"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type AuthMount struct {
|
|
||||||
Type string `json:"type" structs:"type" mapstructure:"type"`
|
|
||||||
Description string `json:"description" structs:"description" mapstructure:"description"`
|
|
||||||
Config AuthConfigOutput `json:"config" structs:"config" mapstructure:"config"`
|
|
||||||
Local bool `json:"local" structs:"local" mapstructure:"local"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type AuthConfigOutput struct {
|
|
||||||
DefaultLeaseTTL int `json:"default_lease_ttl" structs:"default_lease_ttl" mapstructure:"default_lease_ttl"`
|
|
||||||
MaxLeaseTTL int `json:"max_lease_ttl" structs:"max_lease_ttl" mapstructure:"max_lease_ttl"`
|
|
||||||
}
|
|
43
vendor/github.com/hashicorp/vault/api/sys_capabilities.go
generated
vendored
43
vendor/github.com/hashicorp/vault/api/sys_capabilities.go
generated
vendored
|
@ -1,43 +0,0 @@
|
||||||
package api
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
func (c *Sys) CapabilitiesSelf(path string) ([]string, error) {
|
|
||||||
return c.Capabilities(c.c.Token(), path)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Sys) Capabilities(token, path string) ([]string, error) {
|
|
||||||
body := map[string]string{
|
|
||||||
"token": token,
|
|
||||||
"path": path,
|
|
||||||
}
|
|
||||||
|
|
||||||
reqPath := "/v1/sys/capabilities"
|
|
||||||
if token == c.c.Token() {
|
|
||||||
reqPath = fmt.Sprintf("%s-self", reqPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
r := c.c.NewRequest("POST", reqPath)
|
|
||||||
if err := r.SetJSONBody(body); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := c.c.RawRequest(r)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
var result map[string]interface{}
|
|
||||||
err = resp.DecodeJSON(&result)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var capabilities []string
|
|
||||||
capabilitiesRaw := result["capabilities"].([]interface{})
|
|
||||||
for _, capability := range capabilitiesRaw {
|
|
||||||
capabilities = append(capabilities, capability.(string))
|
|
||||||
}
|
|
||||||
return capabilities, nil
|
|
||||||
}
|
|
77
vendor/github.com/hashicorp/vault/api/sys_generate_root.go
generated
vendored
77
vendor/github.com/hashicorp/vault/api/sys_generate_root.go
generated
vendored
|
@ -1,77 +0,0 @@
|
||||||
package api
|
|
||||||
|
|
||||||
func (c *Sys) GenerateRootStatus() (*GenerateRootStatusResponse, error) {
|
|
||||||
r := c.c.NewRequest("GET", "/v1/sys/generate-root/attempt")
|
|
||||||
resp, err := c.c.RawRequest(r)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
var result GenerateRootStatusResponse
|
|
||||||
err = resp.DecodeJSON(&result)
|
|
||||||
return &result, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Sys) GenerateRootInit(otp, pgpKey string) (*GenerateRootStatusResponse, error) {
|
|
||||||
body := map[string]interface{}{
|
|
||||||
"otp": otp,
|
|
||||||
"pgp_key": pgpKey,
|
|
||||||
}
|
|
||||||
|
|
||||||
r := c.c.NewRequest("PUT", "/v1/sys/generate-root/attempt")
|
|
||||||
if err := r.SetJSONBody(body); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := c.c.RawRequest(r)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
var result GenerateRootStatusResponse
|
|
||||||
err = resp.DecodeJSON(&result)
|
|
||||||
return &result, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Sys) GenerateRootCancel() error {
|
|
||||||
r := c.c.NewRequest("DELETE", "/v1/sys/generate-root/attempt")
|
|
||||||
resp, err := c.c.RawRequest(r)
|
|
||||||
if err == nil {
|
|
||||||
defer resp.Body.Close()
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Sys) GenerateRootUpdate(shard, nonce string) (*GenerateRootStatusResponse, error) {
|
|
||||||
body := map[string]interface{}{
|
|
||||||
"key": shard,
|
|
||||||
"nonce": nonce,
|
|
||||||
}
|
|
||||||
|
|
||||||
r := c.c.NewRequest("PUT", "/v1/sys/generate-root/update")
|
|
||||||
if err := r.SetJSONBody(body); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := c.c.RawRequest(r)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
var result GenerateRootStatusResponse
|
|
||||||
err = resp.DecodeJSON(&result)
|
|
||||||
return &result, err
|
|
||||||
}
|
|
||||||
|
|
||||||
type GenerateRootStatusResponse struct {
|
|
||||||
Nonce string
|
|
||||||
Started bool
|
|
||||||
Progress int
|
|
||||||
Required int
|
|
||||||
Complete bool
|
|
||||||
EncodedRootToken string `json:"encoded_root_token"`
|
|
||||||
PGPFingerprint string `json:"pgp_fingerprint"`
|
|
||||||
}
|
|
54
vendor/github.com/hashicorp/vault/api/sys_init.go
generated
vendored
54
vendor/github.com/hashicorp/vault/api/sys_init.go
generated
vendored
|
@ -1,54 +0,0 @@
|
||||||
package api
|
|
||||||
|
|
||||||
func (c *Sys) InitStatus() (bool, error) {
|
|
||||||
r := c.c.NewRequest("GET", "/v1/sys/init")
|
|
||||||
resp, err := c.c.RawRequest(r)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
var result InitStatusResponse
|
|
||||||
err = resp.DecodeJSON(&result)
|
|
||||||
return result.Initialized, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Sys) Init(opts *InitRequest) (*InitResponse, error) {
|
|
||||||
r := c.c.NewRequest("PUT", "/v1/sys/init")
|
|
||||||
if err := r.SetJSONBody(opts); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := c.c.RawRequest(r)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
var result InitResponse
|
|
||||||
err = resp.DecodeJSON(&result)
|
|
||||||
return &result, err
|
|
||||||
}
|
|
||||||
|
|
||||||
type InitRequest struct {
|
|
||||||
SecretShares int `json:"secret_shares"`
|
|
||||||
SecretThreshold int `json:"secret_threshold"`
|
|
||||||
StoredShares int `json:"stored_shares"`
|
|
||||||
PGPKeys []string `json:"pgp_keys"`
|
|
||||||
RecoveryShares int `json:"recovery_shares"`
|
|
||||||
RecoveryThreshold int `json:"recovery_threshold"`
|
|
||||||
RecoveryPGPKeys []string `json:"recovery_pgp_keys"`
|
|
||||||
RootTokenPGPKey string `json:"root_token_pgp_key"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type InitStatusResponse struct {
|
|
||||||
Initialized bool
|
|
||||||
}
|
|
||||||
|
|
||||||
type InitResponse struct {
|
|
||||||
Keys []string `json:"keys"`
|
|
||||||
KeysB64 []string `json:"keys_base64"`
|
|
||||||
RecoveryKeys []string `json:"recovery_keys"`
|
|
||||||
RecoveryKeysB64 []string `json:"recovery_keys_base64"`
|
|
||||||
RootToken string `json:"root_token"`
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue