mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-13 02:33:34 +00:00
rebase: vendor dependencies for Vault API
Uses github.com/libopenstorage/secrets to communicate with Vault. This removes the need for maintaining our own limited Vault APIs. By adding the new dependency, several other packages got updated in the process. Unused indirect dependencies have been removed from go.mod. Signed-off-by: Niels de Vos <ndevos@redhat.com>
This commit is contained in:
committed by
mergify[bot]
parent
7824cb5ed7
commit
91774fc936
354
vendor/github.com/hashicorp/errwrap/LICENSE
generated
vendored
Normal file
354
vendor/github.com/hashicorp/errwrap/LICENSE
generated
vendored
Normal file
@ -0,0 +1,354 @@
|
||||
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
Normal file
89
vendor/github.com/hashicorp/errwrap/README.md
generated
vendored
Normal file
@ -0,0 +1,89 @@
|
||||
# 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, "does not exist") {
|
||||
// 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
Normal file
169
vendor/github.com/hashicorp/errwrap/errwrap.go
generated
vendored
Normal file
@ -0,0 +1,169 @@
|
||||
// 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}
|
||||
}
|
1
vendor/github.com/hashicorp/errwrap/go.mod
generated
vendored
Normal file
1
vendor/github.com/hashicorp/errwrap/go.mod
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
module github.com/hashicorp/errwrap
|
363
vendor/github.com/hashicorp/go-cleanhttp/LICENSE
generated
vendored
Normal file
363
vendor/github.com/hashicorp/go-cleanhttp/LICENSE
generated
vendored
Normal file
@ -0,0 +1,363 @@
|
||||
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
Normal file
30
vendor/github.com/hashicorp/go-cleanhttp/README.md
generated
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
# 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.
|
57
vendor/github.com/hashicorp/go-cleanhttp/cleanhttp.go
generated
vendored
Normal file
57
vendor/github.com/hashicorp/go-cleanhttp/cleanhttp.go
generated
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
package cleanhttp
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/http"
|
||||
"runtime"
|
||||
"time"
|
||||
)
|
||||
|
||||
// DefaultTransport returns a new http.Transport with similar default values to
|
||||
// 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,
|
||||
DialContext: (&net.Dialer{
|
||||
Timeout: 30 * time.Second,
|
||||
KeepAlive: 30 * time.Second,
|
||||
DualStack: true,
|
||||
}).DialContext,
|
||||
MaxIdleConns: 100,
|
||||
IdleConnTimeout: 90 * time.Second,
|
||||
TLSHandshakeTimeout: 10 * time.Second,
|
||||
ExpectContinueTimeout: 1 * time.Second,
|
||||
MaxIdleConnsPerHost: runtime.GOMAXPROCS(0) + 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 similar default values to
|
||||
// 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
Normal file
20
vendor/github.com/hashicorp/go-cleanhttp/doc.go
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
// 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
|
1
vendor/github.com/hashicorp/go-cleanhttp/go.mod
generated
vendored
Normal file
1
vendor/github.com/hashicorp/go-cleanhttp/go.mod
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
module github.com/hashicorp/go-cleanhttp
|
48
vendor/github.com/hashicorp/go-cleanhttp/handlers.go
generated
vendored
Normal file
48
vendor/github.com/hashicorp/go-cleanhttp/handlers.go
generated
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
package cleanhttp
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
// HandlerInput provides input options to cleanhttp's handlers
|
||||
type HandlerInput struct {
|
||||
ErrStatus int
|
||||
}
|
||||
|
||||
// PrintablePathCheckHandler is a middleware that ensures the request path
|
||||
// contains only printable runes.
|
||||
func PrintablePathCheckHandler(next http.Handler, input *HandlerInput) http.Handler {
|
||||
// Nil-check on input to make it optional
|
||||
if input == nil {
|
||||
input = &HandlerInput{
|
||||
ErrStatus: http.StatusBadRequest,
|
||||
}
|
||||
}
|
||||
|
||||
// Default to http.StatusBadRequest on error
|
||||
if input.ErrStatus == 0 {
|
||||
input.ErrStatus = http.StatusBadRequest
|
||||
}
|
||||
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r != nil {
|
||||
// Check URL path for non-printable characters
|
||||
idx := strings.IndexFunc(r.URL.Path, func(c rune) bool {
|
||||
return !unicode.IsPrint(c)
|
||||
})
|
||||
|
||||
if idx != -1 {
|
||||
w.WriteHeader(input.ErrStatus)
|
||||
return
|
||||
}
|
||||
|
||||
if next != nil {
|
||||
next.ServeHTTP(w, r)
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
})
|
||||
}
|
1
vendor/github.com/hashicorp/go-hclog/.gitignore
generated
vendored
Normal file
1
vendor/github.com/hashicorp/go-hclog/.gitignore
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
.idea*
|
21
vendor/github.com/hashicorp/go-hclog/LICENSE
generated
vendored
Normal file
21
vendor/github.com/hashicorp/go-hclog/LICENSE
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017 HashiCorp
|
||||
|
||||
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.
|
148
vendor/github.com/hashicorp/go-hclog/README.md
generated
vendored
Normal file
148
vendor/github.com/hashicorp/go-hclog/README.md
generated
vendored
Normal file
@ -0,0 +1,148 @@
|
||||
# go-hclog
|
||||
|
||||
[][godocs]
|
||||
|
||||
[godocs]: https://godoc.org/github.com/hashicorp/go-hclog
|
||||
|
||||
`go-hclog` is a package for Go that provides a simple key/value logging
|
||||
interface for use in development and production environments.
|
||||
|
||||
It provides logging levels that provide decreased output based upon the
|
||||
desired amount of output, unlike the standard library `log` package.
|
||||
|
||||
It provides `Printf` style logging of values via `hclog.Fmt()`.
|
||||
|
||||
It provides a human readable output mode for use in development as well as
|
||||
JSON output mode for production.
|
||||
|
||||
## Stability Note
|
||||
|
||||
While this library is fully open source and HashiCorp will be maintaining it
|
||||
(since we are and will be making extensive use of it), the API and output
|
||||
format is subject to minor changes as we fully bake and vet it in our projects.
|
||||
This notice will be removed once it's fully integrated into our major projects
|
||||
and no further changes are anticipated.
|
||||
|
||||
## Installation and Docs
|
||||
|
||||
Install using `go get github.com/hashicorp/go-hclog`.
|
||||
|
||||
Full documentation is available at
|
||||
http://godoc.org/github.com/hashicorp/go-hclog
|
||||
|
||||
## Usage
|
||||
|
||||
### Use the global logger
|
||||
|
||||
```go
|
||||
hclog.Default().Info("hello world")
|
||||
```
|
||||
|
||||
```text
|
||||
2017-07-05T16:15:55.167-0700 [INFO ] hello world
|
||||
```
|
||||
|
||||
(Note timestamps are removed in future examples for brevity.)
|
||||
|
||||
### Create a new logger
|
||||
|
||||
```go
|
||||
appLogger := hclog.New(&hclog.LoggerOptions{
|
||||
Name: "my-app",
|
||||
Level: hclog.LevelFromString("DEBUG"),
|
||||
})
|
||||
```
|
||||
|
||||
### Emit an Info level message with 2 key/value pairs
|
||||
|
||||
```go
|
||||
input := "5.5"
|
||||
_, err := strconv.ParseInt(input, 10, 32)
|
||||
if err != nil {
|
||||
appLogger.Info("Invalid input for ParseInt", "input", input, "error", err)
|
||||
}
|
||||
```
|
||||
|
||||
```text
|
||||
... [INFO ] my-app: Invalid input for ParseInt: input=5.5 error="strconv.ParseInt: parsing "5.5": invalid syntax"
|
||||
```
|
||||
|
||||
### Create a new Logger for a major subsystem
|
||||
|
||||
```go
|
||||
subsystemLogger := appLogger.Named("transport")
|
||||
subsystemLogger.Info("we are transporting something")
|
||||
```
|
||||
|
||||
```text
|
||||
... [INFO ] my-app.transport: we are transporting something
|
||||
```
|
||||
|
||||
Notice that logs emitted by `subsystemLogger` contain `my-app.transport`,
|
||||
reflecting both the application and subsystem names.
|
||||
|
||||
### Create a new Logger with fixed key/value pairs
|
||||
|
||||
Using `With()` will include a specific key-value pair in all messages emitted
|
||||
by that logger.
|
||||
|
||||
```go
|
||||
requestID := "5fb446b6-6eba-821d-df1b-cd7501b6a363"
|
||||
requestLogger := subsystemLogger.With("request", requestID)
|
||||
requestLogger.Info("we are transporting a request")
|
||||
```
|
||||
|
||||
```text
|
||||
... [INFO ] my-app.transport: we are transporting a request: request=5fb446b6-6eba-821d-df1b-cd7501b6a363
|
||||
```
|
||||
|
||||
This allows sub Loggers to be context specific without having to thread that
|
||||
into all the callers.
|
||||
|
||||
### Using `hclog.Fmt()`
|
||||
|
||||
```go
|
||||
var int totalBandwidth = 200
|
||||
appLogger.Info("total bandwidth exceeded", "bandwidth", hclog.Fmt("%d GB/s", totalBandwidth))
|
||||
```
|
||||
|
||||
```text
|
||||
... [INFO ] my-app: total bandwidth exceeded: bandwidth="200 GB/s"
|
||||
```
|
||||
|
||||
### Use this with code that uses the standard library logger
|
||||
|
||||
If you want to use the standard library's `log.Logger` interface you can wrap
|
||||
`hclog.Logger` by calling the `StandardLogger()` method. This allows you to use
|
||||
it with the familiar `Println()`, `Printf()`, etc. For example:
|
||||
|
||||
```go
|
||||
stdLogger := appLogger.StandardLogger(&hclog.StandardLoggerOptions{
|
||||
InferLevels: true,
|
||||
})
|
||||
// Printf() is provided by stdlib log.Logger interface, not hclog.Logger
|
||||
stdLogger.Printf("[DEBUG] %+v", stdLogger)
|
||||
```
|
||||
|
||||
```text
|
||||
... [DEBUG] my-app: &{mu:{state:0 sema:0} prefix: flag:0 out:0xc42000a0a0 buf:[]}
|
||||
```
|
||||
|
||||
Alternatively, you may configure the system-wide logger:
|
||||
|
||||
```go
|
||||
// log the standard logger from 'import "log"'
|
||||
log.SetOutput(appLogger.StandardWriter(&hclog.StandardLoggerOptions{InferLevels: true}))
|
||||
log.SetPrefix("")
|
||||
log.SetFlags(0)
|
||||
|
||||
log.Printf("[DEBUG] %d", 42)
|
||||
```
|
||||
|
||||
```text
|
||||
... [DEBUG] my-app: 42
|
||||
```
|
||||
|
||||
Notice that if `appLogger` is initialized with the `INFO` log level _and_ you
|
||||
specify `InferLevels: true`, you will not see any output here. You must change
|
||||
`appLogger` to `DEBUG` to see output. See the docs for more information.
|
27
vendor/github.com/hashicorp/go-hclog/colorize_unix.go
generated
vendored
Normal file
27
vendor/github.com/hashicorp/go-hclog/colorize_unix.go
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
// +build !windows
|
||||
|
||||
package hclog
|
||||
|
||||
import (
|
||||
"github.com/mattn/go-isatty"
|
||||
)
|
||||
|
||||
// setColorization will mutate the values of this logger
|
||||
// to approperately configure colorization options. It provides
|
||||
// a wrapper to the output stream on Windows systems.
|
||||
func (l *intLogger) setColorization(opts *LoggerOptions) {
|
||||
switch opts.Color {
|
||||
case ColorOff:
|
||||
fallthrough
|
||||
case ForceColor:
|
||||
return
|
||||
case AutoColor:
|
||||
fi := l.checkWriterIsFile()
|
||||
isUnixTerm := isatty.IsTerminal(fi.Fd())
|
||||
isCygwinTerm := isatty.IsCygwinTerminal(fi.Fd())
|
||||
isTerm := isUnixTerm || isCygwinTerm
|
||||
if !isTerm {
|
||||
l.writer.color = ColorOff
|
||||
}
|
||||
}
|
||||
}
|
33
vendor/github.com/hashicorp/go-hclog/colorize_windows.go
generated
vendored
Normal file
33
vendor/github.com/hashicorp/go-hclog/colorize_windows.go
generated
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
// +build windows
|
||||
|
||||
package hclog
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
colorable "github.com/mattn/go-colorable"
|
||||
"github.com/mattn/go-isatty"
|
||||
)
|
||||
|
||||
// setColorization will mutate the values of this logger
|
||||
// to approperately configure colorization options. It provides
|
||||
// a wrapper to the output stream on Windows systems.
|
||||
func (l *intLogger) setColorization(opts *LoggerOptions) {
|
||||
switch opts.Color {
|
||||
case ColorOff:
|
||||
return
|
||||
case ForceColor:
|
||||
fi := l.checkWriterIsFile()
|
||||
l.writer.w = colorable.NewColorable(fi)
|
||||
case AutoColor:
|
||||
fi := l.checkWriterIsFile()
|
||||
isUnixTerm := isatty.IsTerminal(os.Stdout.Fd())
|
||||
isCygwinTerm := isatty.IsCygwinTerminal(os.Stdout.Fd())
|
||||
isTerm := isUnixTerm || isCygwinTerm
|
||||
if !isTerm {
|
||||
l.writer.color = ColorOff
|
||||
return
|
||||
}
|
||||
l.writer.w = colorable.NewColorable(fi)
|
||||
}
|
||||
}
|
38
vendor/github.com/hashicorp/go-hclog/context.go
generated
vendored
Normal file
38
vendor/github.com/hashicorp/go-hclog/context.go
generated
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
package hclog
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
// WithContext inserts a logger into the context and is retrievable
|
||||
// with FromContext. The optional args can be set with the same syntax as
|
||||
// Logger.With to set fields on the inserted logger. This will not modify
|
||||
// the logger argument in-place.
|
||||
func WithContext(ctx context.Context, logger Logger, args ...interface{}) context.Context {
|
||||
// While we could call logger.With even with zero args, we have this
|
||||
// check to avoid unnecessary allocations around creating a copy of a
|
||||
// logger.
|
||||
if len(args) > 0 {
|
||||
logger = logger.With(args...)
|
||||
}
|
||||
|
||||
return context.WithValue(ctx, contextKey, logger)
|
||||
}
|
||||
|
||||
// FromContext returns a logger from the context. This will return L()
|
||||
// (the default logger) if no logger is found in the context. Therefore,
|
||||
// this will never return a nil value.
|
||||
func FromContext(ctx context.Context) Logger {
|
||||
logger, _ := ctx.Value(contextKey).(Logger)
|
||||
if logger == nil {
|
||||
return L()
|
||||
}
|
||||
|
||||
return logger
|
||||
}
|
||||
|
||||
// Unexported new type so that our context key never collides with another.
|
||||
type contextKeyType struct{}
|
||||
|
||||
// contextKey is the key used for the context to store the logger.
|
||||
var contextKey = contextKeyType{}
|
71
vendor/github.com/hashicorp/go-hclog/exclude.go
generated
vendored
Normal file
71
vendor/github.com/hashicorp/go-hclog/exclude.go
generated
vendored
Normal file
@ -0,0 +1,71 @@
|
||||
package hclog
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ExcludeByMessage provides a simple way to build a list of log messages that
|
||||
// can be queried and matched. This is meant to be used with the Exclude
|
||||
// option on Options to suppress log messages. This does not hold any mutexs
|
||||
// within itself, so normal usage would be to Add entries at setup and none after
|
||||
// Exclude is going to be called. Exclude is called with a mutex held within
|
||||
// the Logger, so that doesn't need to use a mutex. Example usage:
|
||||
//
|
||||
// f := new(ExcludeByMessage)
|
||||
// f.Add("Noisy log message text")
|
||||
// appLogger.Exclude = f.Exclude
|
||||
type ExcludeByMessage struct {
|
||||
messages map[string]struct{}
|
||||
}
|
||||
|
||||
// Add a message to be filtered. Do not call this after Exclude is to be called
|
||||
// due to concurrency issues.
|
||||
func (f *ExcludeByMessage) Add(msg string) {
|
||||
if f.messages == nil {
|
||||
f.messages = make(map[string]struct{})
|
||||
}
|
||||
|
||||
f.messages[msg] = struct{}{}
|
||||
}
|
||||
|
||||
// Return true if the given message should be included
|
||||
func (f *ExcludeByMessage) Exclude(level Level, msg string, args ...interface{}) bool {
|
||||
_, ok := f.messages[msg]
|
||||
return ok
|
||||
}
|
||||
|
||||
// ExcludeByPrefix is a simple type to match a message string that has a common prefix.
|
||||
type ExcludeByPrefix string
|
||||
|
||||
// Matches an message that starts with the prefix.
|
||||
func (p ExcludeByPrefix) Exclude(level Level, msg string, args ...interface{}) bool {
|
||||
return strings.HasPrefix(msg, string(p))
|
||||
}
|
||||
|
||||
// ExcludeByRegexp takes a regexp and uses it to match a log message string. If it matches
|
||||
// the log entry is excluded.
|
||||
type ExcludeByRegexp struct {
|
||||
Regexp *regexp.Regexp
|
||||
}
|
||||
|
||||
// Exclude the log message if the message string matches the regexp
|
||||
func (e ExcludeByRegexp) Exclude(level Level, msg string, args ...interface{}) bool {
|
||||
return e.Regexp.MatchString(msg)
|
||||
}
|
||||
|
||||
// ExcludeFuncs is a slice of functions that will called to see if a log entry
|
||||
// should be filtered or not. It stops calling functions once at least one returns
|
||||
// true.
|
||||
type ExcludeFuncs []func(level Level, msg string, args ...interface{}) bool
|
||||
|
||||
// Calls each function until one of them returns true
|
||||
func (ff ExcludeFuncs) Exclude(level Level, msg string, args ...interface{}) bool {
|
||||
for _, f := range ff {
|
||||
if f(level, msg, args...) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
62
vendor/github.com/hashicorp/go-hclog/global.go
generated
vendored
Normal file
62
vendor/github.com/hashicorp/go-hclog/global.go
generated
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
package hclog
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
protect sync.Once
|
||||
def Logger
|
||||
|
||||
// DefaultOptions is used to create the Default logger. These are read
|
||||
// only when the Default logger is created, so set them as soon as the
|
||||
// process starts.
|
||||
DefaultOptions = &LoggerOptions{
|
||||
Level: DefaultLevel,
|
||||
Output: DefaultOutput,
|
||||
}
|
||||
)
|
||||
|
||||
// Default returns a globally held logger. This can be a good starting
|
||||
// place, and then you can use .With() and .Name() to create sub-loggers
|
||||
// to be used in more specific contexts.
|
||||
// The value of the Default logger can be set via SetDefault() or by
|
||||
// changing the options in DefaultOptions.
|
||||
//
|
||||
// This method is goroutine safe, returning a global from memory, but
|
||||
// cause should be used if SetDefault() is called it random times
|
||||
// in the program as that may result in race conditions and an unexpected
|
||||
// Logger being returned.
|
||||
func Default() Logger {
|
||||
protect.Do(func() {
|
||||
// If SetDefault was used before Default() was called, we need to
|
||||
// detect that here.
|
||||
if def == nil {
|
||||
def = New(DefaultOptions)
|
||||
}
|
||||
})
|
||||
|
||||
return def
|
||||
}
|
||||
|
||||
// L is a short alias for Default().
|
||||
func L() Logger {
|
||||
return Default()
|
||||
}
|
||||
|
||||
// SetDefault changes the logger to be returned by Default()and L()
|
||||
// to the one given. This allows packages to use the default logger
|
||||
// and have higher level packages change it to match the execution
|
||||
// environment. It returns any old default if there is one.
|
||||
//
|
||||
// NOTE: This is expected to be called early in the program to setup
|
||||
// a default logger. As such, it does not attempt to make itself
|
||||
// not racy with regard to the value of the default logger. Ergo
|
||||
// if it is called in goroutines, you may experience race conditions
|
||||
// with other goroutines retrieving the default logger. Basically,
|
||||
// don't do that.
|
||||
func SetDefault(log Logger) Logger {
|
||||
old := def
|
||||
def = log
|
||||
return old
|
||||
}
|
12
vendor/github.com/hashicorp/go-hclog/go.mod
generated
vendored
Normal file
12
vendor/github.com/hashicorp/go-hclog/go.mod
generated
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
module github.com/hashicorp/go-hclog
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/fatih/color v1.7.0
|
||||
github.com/mattn/go-colorable v0.1.4
|
||||
github.com/mattn/go-isatty v0.0.10
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/stretchr/testify v1.2.2
|
||||
)
|
||||
|
||||
go 1.13
|
18
vendor/github.com/hashicorp/go-hclog/go.sum
generated
vendored
Normal file
18
vendor/github.com/hashicorp/go-hclog/go.sum
generated
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
|
||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.10 h1:qxFzApOv4WsAL965uUPIsXzAKCZxN2p9UqdhFS4ZW10=
|
||||
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20191008105621-543471e840be h1:QAcqgptGM8IQBC9K/RC4o+O9YmqEm0diQn9QmZw/0mU=
|
||||
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
246
vendor/github.com/hashicorp/go-hclog/interceptlogger.go
generated
vendored
Normal file
246
vendor/github.com/hashicorp/go-hclog/interceptlogger.go
generated
vendored
Normal file
@ -0,0 +1,246 @@
|
||||
package hclog
|
||||
|
||||
import (
|
||||
"io"
|
||||
"log"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
var _ Logger = &interceptLogger{}
|
||||
|
||||
type interceptLogger struct {
|
||||
Logger
|
||||
|
||||
mu *sync.Mutex
|
||||
sinkCount *int32
|
||||
Sinks map[SinkAdapter]struct{}
|
||||
}
|
||||
|
||||
func NewInterceptLogger(opts *LoggerOptions) InterceptLogger {
|
||||
intercept := &interceptLogger{
|
||||
Logger: New(opts),
|
||||
mu: new(sync.Mutex),
|
||||
sinkCount: new(int32),
|
||||
Sinks: make(map[SinkAdapter]struct{}),
|
||||
}
|
||||
|
||||
atomic.StoreInt32(intercept.sinkCount, 0)
|
||||
|
||||
return intercept
|
||||
}
|
||||
|
||||
func (i *interceptLogger) Log(level Level, msg string, args ...interface{}) {
|
||||
i.Logger.Log(level, msg, args...)
|
||||
if atomic.LoadInt32(i.sinkCount) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
i.mu.Lock()
|
||||
defer i.mu.Unlock()
|
||||
for s := range i.Sinks {
|
||||
s.Accept(i.Name(), level, msg, i.retrieveImplied(args...)...)
|
||||
}
|
||||
}
|
||||
|
||||
// Emit the message and args at TRACE level to log and sinks
|
||||
func (i *interceptLogger) Trace(msg string, args ...interface{}) {
|
||||
i.Logger.Trace(msg, args...)
|
||||
if atomic.LoadInt32(i.sinkCount) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
i.mu.Lock()
|
||||
defer i.mu.Unlock()
|
||||
for s := range i.Sinks {
|
||||
s.Accept(i.Name(), Trace, msg, i.retrieveImplied(args...)...)
|
||||
}
|
||||
}
|
||||
|
||||
// Emit the message and args at DEBUG level to log and sinks
|
||||
func (i *interceptLogger) Debug(msg string, args ...interface{}) {
|
||||
i.Logger.Debug(msg, args...)
|
||||
if atomic.LoadInt32(i.sinkCount) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
i.mu.Lock()
|
||||
defer i.mu.Unlock()
|
||||
for s := range i.Sinks {
|
||||
s.Accept(i.Name(), Debug, msg, i.retrieveImplied(args...)...)
|
||||
}
|
||||
}
|
||||
|
||||
// Emit the message and args at INFO level to log and sinks
|
||||
func (i *interceptLogger) Info(msg string, args ...interface{}) {
|
||||
i.Logger.Info(msg, args...)
|
||||
if atomic.LoadInt32(i.sinkCount) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
i.mu.Lock()
|
||||
defer i.mu.Unlock()
|
||||
for s := range i.Sinks {
|
||||
s.Accept(i.Name(), Info, msg, i.retrieveImplied(args...)...)
|
||||
}
|
||||
}
|
||||
|
||||
// Emit the message and args at WARN level to log and sinks
|
||||
func (i *interceptLogger) Warn(msg string, args ...interface{}) {
|
||||
i.Logger.Warn(msg, args...)
|
||||
if atomic.LoadInt32(i.sinkCount) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
i.mu.Lock()
|
||||
defer i.mu.Unlock()
|
||||
for s := range i.Sinks {
|
||||
s.Accept(i.Name(), Warn, msg, i.retrieveImplied(args...)...)
|
||||
}
|
||||
}
|
||||
|
||||
// Emit the message and args at ERROR level to log and sinks
|
||||
func (i *interceptLogger) Error(msg string, args ...interface{}) {
|
||||
i.Logger.Error(msg, args...)
|
||||
if atomic.LoadInt32(i.sinkCount) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
i.mu.Lock()
|
||||
defer i.mu.Unlock()
|
||||
for s := range i.Sinks {
|
||||
s.Accept(i.Name(), Error, msg, i.retrieveImplied(args...)...)
|
||||
}
|
||||
}
|
||||
|
||||
func (i *interceptLogger) retrieveImplied(args ...interface{}) []interface{} {
|
||||
top := i.Logger.ImpliedArgs()
|
||||
|
||||
cp := make([]interface{}, len(top)+len(args))
|
||||
copy(cp, top)
|
||||
copy(cp[len(top):], args)
|
||||
|
||||
return cp
|
||||
}
|
||||
|
||||
// Create a new sub-Logger that a name decending from the current name.
|
||||
// This is used to create a subsystem specific Logger.
|
||||
// Registered sinks will subscribe to these messages as well.
|
||||
func (i *interceptLogger) Named(name string) Logger {
|
||||
var sub interceptLogger
|
||||
|
||||
sub = *i
|
||||
|
||||
sub.Logger = i.Logger.Named(name)
|
||||
|
||||
return &sub
|
||||
}
|
||||
|
||||
// Create a new sub-Logger with an explicit name. This ignores the current
|
||||
// name. This is used to create a standalone logger that doesn't fall
|
||||
// within the normal hierarchy. Registered sinks will subscribe
|
||||
// to these messages as well.
|
||||
func (i *interceptLogger) ResetNamed(name string) Logger {
|
||||
var sub interceptLogger
|
||||
|
||||
sub = *i
|
||||
|
||||
sub.Logger = i.Logger.ResetNamed(name)
|
||||
|
||||
return &sub
|
||||
}
|
||||
|
||||
// Create a new sub-Logger that a name decending from the current name.
|
||||
// This is used to create a subsystem specific Logger.
|
||||
// Registered sinks will subscribe to these messages as well.
|
||||
func (i *interceptLogger) NamedIntercept(name string) InterceptLogger {
|
||||
var sub interceptLogger
|
||||
|
||||
sub = *i
|
||||
|
||||
sub.Logger = i.Logger.Named(name)
|
||||
|
||||
return &sub
|
||||
}
|
||||
|
||||
// Create a new sub-Logger with an explicit name. This ignores the current
|
||||
// name. This is used to create a standalone logger that doesn't fall
|
||||
// within the normal hierarchy. Registered sinks will subscribe
|
||||
// to these messages as well.
|
||||
func (i *interceptLogger) ResetNamedIntercept(name string) InterceptLogger {
|
||||
var sub interceptLogger
|
||||
|
||||
sub = *i
|
||||
|
||||
sub.Logger = i.Logger.ResetNamed(name)
|
||||
|
||||
return &sub
|
||||
}
|
||||
|
||||
// Return a sub-Logger for which every emitted log message will contain
|
||||
// the given key/value pairs. This is used to create a context specific
|
||||
// Logger.
|
||||
func (i *interceptLogger) With(args ...interface{}) Logger {
|
||||
var sub interceptLogger
|
||||
|
||||
sub = *i
|
||||
|
||||
sub.Logger = i.Logger.With(args...)
|
||||
|
||||
return &sub
|
||||
}
|
||||
|
||||
// RegisterSink attaches a SinkAdapter to interceptLoggers sinks.
|
||||
func (i *interceptLogger) RegisterSink(sink SinkAdapter) {
|
||||
i.mu.Lock()
|
||||
defer i.mu.Unlock()
|
||||
|
||||
i.Sinks[sink] = struct{}{}
|
||||
|
||||
atomic.AddInt32(i.sinkCount, 1)
|
||||
}
|
||||
|
||||
// DeregisterSink removes a SinkAdapter from interceptLoggers sinks.
|
||||
func (i *interceptLogger) DeregisterSink(sink SinkAdapter) {
|
||||
i.mu.Lock()
|
||||
defer i.mu.Unlock()
|
||||
|
||||
delete(i.Sinks, sink)
|
||||
|
||||
atomic.AddInt32(i.sinkCount, -1)
|
||||
}
|
||||
|
||||
// Create a *log.Logger that will send it's data through this Logger. This
|
||||
// allows packages that expect to be using the standard library to log to
|
||||
// actually use this logger, which will also send to any registered sinks.
|
||||
func (i *interceptLogger) StandardLoggerIntercept(opts *StandardLoggerOptions) *log.Logger {
|
||||
if opts == nil {
|
||||
opts = &StandardLoggerOptions{}
|
||||
}
|
||||
|
||||
return log.New(i.StandardWriterIntercept(opts), "", 0)
|
||||
}
|
||||
|
||||
func (i *interceptLogger) StandardWriterIntercept(opts *StandardLoggerOptions) io.Writer {
|
||||
return &stdlogAdapter{
|
||||
log: i,
|
||||
inferLevels: opts.InferLevels,
|
||||
forceLevel: opts.ForceLevel,
|
||||
}
|
||||
}
|
||||
|
||||
func (i *interceptLogger) ResetOutput(opts *LoggerOptions) error {
|
||||
if or, ok := i.Logger.(OutputResettable); ok {
|
||||
return or.ResetOutput(opts)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (i *interceptLogger) ResetOutputWithFlush(opts *LoggerOptions, flushable Flushable) error {
|
||||
if or, ok := i.Logger.(OutputResettable); ok {
|
||||
return or.ResetOutputWithFlush(opts, flushable)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
665
vendor/github.com/hashicorp/go-hclog/intlogger.go
generated
vendored
Normal file
665
vendor/github.com/hashicorp/go-hclog/intlogger.go
generated
vendored
Normal file
@ -0,0 +1,665 @@
|
||||
package hclog
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/fatih/color"
|
||||
)
|
||||
|
||||
// TimeFormat to use for logging. This is a version of RFC3339 that contains
|
||||
// contains millisecond precision
|
||||
const TimeFormat = "2006-01-02T15:04:05.000Z0700"
|
||||
|
||||
// errJsonUnsupportedTypeMsg is included in log json entries, if an arg cannot be serialized to json
|
||||
const errJsonUnsupportedTypeMsg = "logging contained values that don't serialize to json"
|
||||
|
||||
var (
|
||||
_levelToBracket = map[Level]string{
|
||||
Debug: "[DEBUG]",
|
||||
Trace: "[TRACE]",
|
||||
Info: "[INFO] ",
|
||||
Warn: "[WARN] ",
|
||||
Error: "[ERROR]",
|
||||
}
|
||||
|
||||
_levelToColor = map[Level]*color.Color{
|
||||
Debug: color.New(color.FgHiWhite),
|
||||
Trace: color.New(color.FgHiGreen),
|
||||
Info: color.New(color.FgHiBlue),
|
||||
Warn: color.New(color.FgHiYellow),
|
||||
Error: color.New(color.FgHiRed),
|
||||
}
|
||||
)
|
||||
|
||||
// Make sure that intLogger is a Logger
|
||||
var _ Logger = &intLogger{}
|
||||
|
||||
// intLogger is an internal logger implementation. Internal in that it is
|
||||
// defined entirely by this package.
|
||||
type intLogger struct {
|
||||
json bool
|
||||
caller bool
|
||||
name string
|
||||
timeFormat string
|
||||
|
||||
// This is an interface so that it's shared by any derived loggers, since
|
||||
// those derived loggers share the bufio.Writer as well.
|
||||
mutex Locker
|
||||
writer *writer
|
||||
level *int32
|
||||
|
||||
implied []interface{}
|
||||
|
||||
exclude func(level Level, msg string, args ...interface{}) bool
|
||||
}
|
||||
|
||||
// New returns a configured logger.
|
||||
func New(opts *LoggerOptions) Logger {
|
||||
return newLogger(opts)
|
||||
}
|
||||
|
||||
// NewSinkAdapter returns a SinkAdapter with configured settings
|
||||
// defined by LoggerOptions
|
||||
func NewSinkAdapter(opts *LoggerOptions) SinkAdapter {
|
||||
return newLogger(opts)
|
||||
}
|
||||
|
||||
func newLogger(opts *LoggerOptions) *intLogger {
|
||||
if opts == nil {
|
||||
opts = &LoggerOptions{}
|
||||
}
|
||||
|
||||
output := opts.Output
|
||||
if output == nil {
|
||||
output = DefaultOutput
|
||||
}
|
||||
|
||||
level := opts.Level
|
||||
if level == NoLevel {
|
||||
level = DefaultLevel
|
||||
}
|
||||
|
||||
mutex := opts.Mutex
|
||||
if mutex == nil {
|
||||
mutex = new(sync.Mutex)
|
||||
}
|
||||
|
||||
l := &intLogger{
|
||||
json: opts.JSONFormat,
|
||||
caller: opts.IncludeLocation,
|
||||
name: opts.Name,
|
||||
timeFormat: TimeFormat,
|
||||
mutex: mutex,
|
||||
writer: newWriter(output, opts.Color),
|
||||
level: new(int32),
|
||||
exclude: opts.Exclude,
|
||||
}
|
||||
|
||||
l.setColorization(opts)
|
||||
|
||||
if opts.DisableTime {
|
||||
l.timeFormat = ""
|
||||
} else if opts.TimeFormat != "" {
|
||||
l.timeFormat = opts.TimeFormat
|
||||
}
|
||||
|
||||
atomic.StoreInt32(l.level, int32(level))
|
||||
|
||||
return l
|
||||
}
|
||||
|
||||
// Log a message and a set of key/value pairs if the given level is at
|
||||
// or more severe that the threshold configured in the Logger.
|
||||
func (l *intLogger) log(name string, level Level, msg string, args ...interface{}) {
|
||||
if level < Level(atomic.LoadInt32(l.level)) {
|
||||
return
|
||||
}
|
||||
|
||||
t := time.Now()
|
||||
|
||||
l.mutex.Lock()
|
||||
defer l.mutex.Unlock()
|
||||
|
||||
if l.exclude != nil && l.exclude(level, msg, args...) {
|
||||
return
|
||||
}
|
||||
|
||||
if l.json {
|
||||
l.logJSON(t, name, level, msg, args...)
|
||||
} else {
|
||||
l.logPlain(t, name, level, msg, args...)
|
||||
}
|
||||
|
||||
l.writer.Flush(level)
|
||||
}
|
||||
|
||||
// Cleanup a path by returning the last 2 segments of the path only.
|
||||
func trimCallerPath(path string) string {
|
||||
// lovely borrowed from zap
|
||||
// nb. To make sure we trim the path correctly on Windows too, we
|
||||
// counter-intuitively need to use '/' and *not* os.PathSeparator here,
|
||||
// because the path given originates from Go stdlib, specifically
|
||||
// runtime.Caller() which (as of Mar/17) returns forward slashes even on
|
||||
// Windows.
|
||||
//
|
||||
// See https://github.com/golang/go/issues/3335
|
||||
// and https://github.com/golang/go/issues/18151
|
||||
//
|
||||
// for discussion on the issue on Go side.
|
||||
|
||||
// Find the last separator.
|
||||
idx := strings.LastIndexByte(path, '/')
|
||||
if idx == -1 {
|
||||
return path
|
||||
}
|
||||
|
||||
// Find the penultimate separator.
|
||||
idx = strings.LastIndexByte(path[:idx], '/')
|
||||
if idx == -1 {
|
||||
return path
|
||||
}
|
||||
|
||||
return path[idx+1:]
|
||||
}
|
||||
|
||||
var logImplFile = regexp.MustCompile(`.+intlogger.go|.+interceptlogger.go$`)
|
||||
|
||||
// Non-JSON logging format function
|
||||
func (l *intLogger) logPlain(t time.Time, name string, level Level, msg string, args ...interface{}) {
|
||||
if len(l.timeFormat) > 0 {
|
||||
l.writer.WriteString(t.Format(l.timeFormat))
|
||||
l.writer.WriteByte(' ')
|
||||
}
|
||||
|
||||
s, ok := _levelToBracket[level]
|
||||
if ok {
|
||||
l.writer.WriteString(s)
|
||||
} else {
|
||||
l.writer.WriteString("[?????]")
|
||||
}
|
||||
|
||||
offset := 3
|
||||
if l.caller {
|
||||
// Check if the caller is inside our package and inside
|
||||
// a logger implementation file
|
||||
if _, file, _, ok := runtime.Caller(3); ok {
|
||||
match := logImplFile.MatchString(file)
|
||||
if match {
|
||||
offset = 4
|
||||
}
|
||||
}
|
||||
|
||||
if _, file, line, ok := runtime.Caller(offset); ok {
|
||||
l.writer.WriteByte(' ')
|
||||
l.writer.WriteString(trimCallerPath(file))
|
||||
l.writer.WriteByte(':')
|
||||
l.writer.WriteString(strconv.Itoa(line))
|
||||
l.writer.WriteByte(':')
|
||||
}
|
||||
}
|
||||
|
||||
l.writer.WriteByte(' ')
|
||||
|
||||
if name != "" {
|
||||
l.writer.WriteString(name)
|
||||
l.writer.WriteString(": ")
|
||||
}
|
||||
|
||||
l.writer.WriteString(msg)
|
||||
|
||||
args = append(l.implied, args...)
|
||||
|
||||
var stacktrace CapturedStacktrace
|
||||
|
||||
if args != nil && len(args) > 0 {
|
||||
if len(args)%2 != 0 {
|
||||
cs, ok := args[len(args)-1].(CapturedStacktrace)
|
||||
if ok {
|
||||
args = args[:len(args)-1]
|
||||
stacktrace = cs
|
||||
} else {
|
||||
extra := args[len(args)-1]
|
||||
args = append(args[:len(args)-1], MissingKey, extra)
|
||||
}
|
||||
}
|
||||
|
||||
l.writer.WriteByte(':')
|
||||
|
||||
FOR:
|
||||
for i := 0; i < len(args); i = i + 2 {
|
||||
var (
|
||||
val string
|
||||
raw bool
|
||||
)
|
||||
|
||||
switch st := args[i+1].(type) {
|
||||
case string:
|
||||
val = st
|
||||
case int:
|
||||
val = strconv.FormatInt(int64(st), 10)
|
||||
case int64:
|
||||
val = strconv.FormatInt(int64(st), 10)
|
||||
case int32:
|
||||
val = strconv.FormatInt(int64(st), 10)
|
||||
case int16:
|
||||
val = strconv.FormatInt(int64(st), 10)
|
||||
case int8:
|
||||
val = strconv.FormatInt(int64(st), 10)
|
||||
case uint:
|
||||
val = strconv.FormatUint(uint64(st), 10)
|
||||
case uint64:
|
||||
val = strconv.FormatUint(uint64(st), 10)
|
||||
case uint32:
|
||||
val = strconv.FormatUint(uint64(st), 10)
|
||||
case uint16:
|
||||
val = strconv.FormatUint(uint64(st), 10)
|
||||
case uint8:
|
||||
val = strconv.FormatUint(uint64(st), 10)
|
||||
case Hex:
|
||||
val = "0x" + strconv.FormatUint(uint64(st), 16)
|
||||
case Octal:
|
||||
val = "0" + strconv.FormatUint(uint64(st), 8)
|
||||
case Binary:
|
||||
val = "0b" + strconv.FormatUint(uint64(st), 2)
|
||||
case CapturedStacktrace:
|
||||
stacktrace = st
|
||||
continue FOR
|
||||
case Format:
|
||||
val = fmt.Sprintf(st[0].(string), st[1:]...)
|
||||
default:
|
||||
v := reflect.ValueOf(st)
|
||||
if v.Kind() == reflect.Slice {
|
||||
val = l.renderSlice(v)
|
||||
raw = true
|
||||
} else {
|
||||
val = fmt.Sprintf("%v", st)
|
||||
}
|
||||
}
|
||||
|
||||
l.writer.WriteByte(' ')
|
||||
switch st := args[i].(type) {
|
||||
case string:
|
||||
l.writer.WriteString(st)
|
||||
default:
|
||||
l.writer.WriteString(fmt.Sprintf("%s", st))
|
||||
}
|
||||
l.writer.WriteByte('=')
|
||||
|
||||
if !raw && strings.ContainsAny(val, " \t\n\r") {
|
||||
l.writer.WriteByte('"')
|
||||
l.writer.WriteString(val)
|
||||
l.writer.WriteByte('"')
|
||||
} else {
|
||||
l.writer.WriteString(val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
l.writer.WriteString("\n")
|
||||
|
||||
if stacktrace != "" {
|
||||
l.writer.WriteString(string(stacktrace))
|
||||
}
|
||||
}
|
||||
|
||||
func (l *intLogger) renderSlice(v reflect.Value) string {
|
||||
var buf bytes.Buffer
|
||||
|
||||
buf.WriteRune('[')
|
||||
|
||||
for i := 0; i < v.Len(); i++ {
|
||||
if i > 0 {
|
||||
buf.WriteString(", ")
|
||||
}
|
||||
|
||||
sv := v.Index(i)
|
||||
|
||||
var val string
|
||||
|
||||
switch sv.Kind() {
|
||||
case reflect.String:
|
||||
val = sv.String()
|
||||
case reflect.Int, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
val = strconv.FormatInt(sv.Int(), 10)
|
||||
case reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
val = strconv.FormatUint(sv.Uint(), 10)
|
||||
default:
|
||||
val = fmt.Sprintf("%v", sv.Interface())
|
||||
}
|
||||
|
||||
if strings.ContainsAny(val, " \t\n\r") {
|
||||
buf.WriteByte('"')
|
||||
buf.WriteString(val)
|
||||
buf.WriteByte('"')
|
||||
} else {
|
||||
buf.WriteString(val)
|
||||
}
|
||||
}
|
||||
|
||||
buf.WriteRune(']')
|
||||
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// JSON logging function
|
||||
func (l *intLogger) logJSON(t time.Time, name string, level Level, msg string, args ...interface{}) {
|
||||
vals := l.jsonMapEntry(t, name, level, msg)
|
||||
args = append(l.implied, args...)
|
||||
|
||||
if args != nil && len(args) > 0 {
|
||||
if len(args)%2 != 0 {
|
||||
cs, ok := args[len(args)-1].(CapturedStacktrace)
|
||||
if ok {
|
||||
args = args[:len(args)-1]
|
||||
vals["stacktrace"] = cs
|
||||
} else {
|
||||
extra := args[len(args)-1]
|
||||
args = append(args[:len(args)-1], MissingKey, extra)
|
||||
}
|
||||
}
|
||||
|
||||
for i := 0; i < len(args); i = i + 2 {
|
||||
val := args[i+1]
|
||||
switch sv := val.(type) {
|
||||
case error:
|
||||
// Check if val is of type error. If error type doesn't
|
||||
// implement json.Marshaler or encoding.TextMarshaler
|
||||
// then set val to err.Error() so that it gets marshaled
|
||||
switch sv.(type) {
|
||||
case json.Marshaler, encoding.TextMarshaler:
|
||||
default:
|
||||
val = sv.Error()
|
||||
}
|
||||
case Format:
|
||||
val = fmt.Sprintf(sv[0].(string), sv[1:]...)
|
||||
}
|
||||
|
||||
var key string
|
||||
|
||||
switch st := args[i].(type) {
|
||||
case string:
|
||||
key = st
|
||||
default:
|
||||
key = fmt.Sprintf("%s", st)
|
||||
}
|
||||
vals[key] = val
|
||||
}
|
||||
}
|
||||
|
||||
err := json.NewEncoder(l.writer).Encode(vals)
|
||||
if err != nil {
|
||||
if _, ok := err.(*json.UnsupportedTypeError); ok {
|
||||
plainVal := l.jsonMapEntry(t, name, level, msg)
|
||||
plainVal["@warn"] = errJsonUnsupportedTypeMsg
|
||||
|
||||
json.NewEncoder(l.writer).Encode(plainVal)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (l intLogger) jsonMapEntry(t time.Time, name string, level Level, msg string) map[string]interface{} {
|
||||
vals := map[string]interface{}{
|
||||
"@message": msg,
|
||||
"@timestamp": t.Format("2006-01-02T15:04:05.000000Z07:00"),
|
||||
}
|
||||
|
||||
var levelStr string
|
||||
switch level {
|
||||
case Error:
|
||||
levelStr = "error"
|
||||
case Warn:
|
||||
levelStr = "warn"
|
||||
case Info:
|
||||
levelStr = "info"
|
||||
case Debug:
|
||||
levelStr = "debug"
|
||||
case Trace:
|
||||
levelStr = "trace"
|
||||
default:
|
||||
levelStr = "all"
|
||||
}
|
||||
|
||||
vals["@level"] = levelStr
|
||||
|
||||
if name != "" {
|
||||
vals["@module"] = name
|
||||
}
|
||||
|
||||
if l.caller {
|
||||
if _, file, line, ok := runtime.Caller(4); ok {
|
||||
vals["@caller"] = fmt.Sprintf("%s:%d", file, line)
|
||||
}
|
||||
}
|
||||
return vals
|
||||
}
|
||||
|
||||
// Emit the message and args at the provided level
|
||||
func (l *intLogger) Log(level Level, msg string, args ...interface{}) {
|
||||
l.log(l.Name(), level, msg, args...)
|
||||
}
|
||||
|
||||
// Emit the message and args at DEBUG level
|
||||
func (l *intLogger) Debug(msg string, args ...interface{}) {
|
||||
l.log(l.Name(), Debug, msg, args...)
|
||||
}
|
||||
|
||||
// Emit the message and args at TRACE level
|
||||
func (l *intLogger) Trace(msg string, args ...interface{}) {
|
||||
l.log(l.Name(), Trace, msg, args...)
|
||||
}
|
||||
|
||||
// Emit the message and args at INFO level
|
||||
func (l *intLogger) Info(msg string, args ...interface{}) {
|
||||
l.log(l.Name(), Info, msg, args...)
|
||||
}
|
||||
|
||||
// Emit the message and args at WARN level
|
||||
func (l *intLogger) Warn(msg string, args ...interface{}) {
|
||||
l.log(l.Name(), Warn, msg, args...)
|
||||
}
|
||||
|
||||
// Emit the message and args at ERROR level
|
||||
func (l *intLogger) Error(msg string, args ...interface{}) {
|
||||
l.log(l.Name(), Error, msg, args...)
|
||||
}
|
||||
|
||||
// Indicate that the logger would emit TRACE level logs
|
||||
func (l *intLogger) IsTrace() bool {
|
||||
return Level(atomic.LoadInt32(l.level)) == Trace
|
||||
}
|
||||
|
||||
// Indicate that the logger would emit DEBUG level logs
|
||||
func (l *intLogger) IsDebug() bool {
|
||||
return Level(atomic.LoadInt32(l.level)) <= Debug
|
||||
}
|
||||
|
||||
// Indicate that the logger would emit INFO level logs
|
||||
func (l *intLogger) IsInfo() bool {
|
||||
return Level(atomic.LoadInt32(l.level)) <= Info
|
||||
}
|
||||
|
||||
// Indicate that the logger would emit WARN level logs
|
||||
func (l *intLogger) IsWarn() bool {
|
||||
return Level(atomic.LoadInt32(l.level)) <= Warn
|
||||
}
|
||||
|
||||
// Indicate that the logger would emit ERROR level logs
|
||||
func (l *intLogger) IsError() bool {
|
||||
return Level(atomic.LoadInt32(l.level)) <= Error
|
||||
}
|
||||
|
||||
const MissingKey = "EXTRA_VALUE_AT_END"
|
||||
|
||||
// Return a sub-Logger for which every emitted log message will contain
|
||||
// the given key/value pairs. This is used to create a context specific
|
||||
// Logger.
|
||||
func (l *intLogger) With(args ...interface{}) Logger {
|
||||
var extra interface{}
|
||||
|
||||
if len(args)%2 != 0 {
|
||||
extra = args[len(args)-1]
|
||||
args = args[:len(args)-1]
|
||||
}
|
||||
|
||||
sl := *l
|
||||
|
||||
result := make(map[string]interface{}, len(l.implied)+len(args))
|
||||
keys := make([]string, 0, len(l.implied)+len(args))
|
||||
|
||||
// Read existing args, store map and key for consistent sorting
|
||||
for i := 0; i < len(l.implied); i += 2 {
|
||||
key := l.implied[i].(string)
|
||||
keys = append(keys, key)
|
||||
result[key] = l.implied[i+1]
|
||||
}
|
||||
// Read new args, store map and key for consistent sorting
|
||||
for i := 0; i < len(args); i += 2 {
|
||||
key := args[i].(string)
|
||||
_, exists := result[key]
|
||||
if !exists {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
result[key] = args[i+1]
|
||||
}
|
||||
|
||||
// Sort keys to be consistent
|
||||
sort.Strings(keys)
|
||||
|
||||
sl.implied = make([]interface{}, 0, len(l.implied)+len(args))
|
||||
for _, k := range keys {
|
||||
sl.implied = append(sl.implied, k)
|
||||
sl.implied = append(sl.implied, result[k])
|
||||
}
|
||||
|
||||
if extra != nil {
|
||||
sl.implied = append(sl.implied, MissingKey, extra)
|
||||
}
|
||||
|
||||
return &sl
|
||||
}
|
||||
|
||||
// Create a new sub-Logger that a name decending from the current name.
|
||||
// This is used to create a subsystem specific Logger.
|
||||
func (l *intLogger) Named(name string) Logger {
|
||||
sl := *l
|
||||
|
||||
if sl.name != "" {
|
||||
sl.name = sl.name + "." + name
|
||||
} else {
|
||||
sl.name = name
|
||||
}
|
||||
|
||||
return &sl
|
||||
}
|
||||
|
||||
// Create a new sub-Logger with an explicit name. This ignores the current
|
||||
// name. This is used to create a standalone logger that doesn't fall
|
||||
// within the normal hierarchy.
|
||||
func (l *intLogger) ResetNamed(name string) Logger {
|
||||
sl := *l
|
||||
|
||||
sl.name = name
|
||||
|
||||
return &sl
|
||||
}
|
||||
|
||||
func (l *intLogger) ResetOutput(opts *LoggerOptions) error {
|
||||
if opts.Output == nil {
|
||||
return errors.New("given output is nil")
|
||||
}
|
||||
|
||||
l.mutex.Lock()
|
||||
defer l.mutex.Unlock()
|
||||
|
||||
return l.resetOutput(opts)
|
||||
}
|
||||
|
||||
func (l *intLogger) ResetOutputWithFlush(opts *LoggerOptions, flushable Flushable) error {
|
||||
if opts.Output == nil {
|
||||
return errors.New("given output is nil")
|
||||
}
|
||||
if flushable == nil {
|
||||
return errors.New("flushable is nil")
|
||||
}
|
||||
|
||||
l.mutex.Lock()
|
||||
defer l.mutex.Unlock()
|
||||
|
||||
if err := flushable.Flush(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return l.resetOutput(opts)
|
||||
}
|
||||
|
||||
func (l *intLogger) resetOutput(opts *LoggerOptions) error {
|
||||
l.writer = newWriter(opts.Output, opts.Color)
|
||||
l.setColorization(opts)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Update the logging level on-the-fly. This will affect all subloggers as
|
||||
// well.
|
||||
func (l *intLogger) SetLevel(level Level) {
|
||||
atomic.StoreInt32(l.level, int32(level))
|
||||
}
|
||||
|
||||
// Create a *log.Logger that will send it's data through this Logger. This
|
||||
// allows packages that expect to be using the standard library log to actually
|
||||
// use this logger.
|
||||
func (l *intLogger) StandardLogger(opts *StandardLoggerOptions) *log.Logger {
|
||||
if opts == nil {
|
||||
opts = &StandardLoggerOptions{}
|
||||
}
|
||||
|
||||
return log.New(l.StandardWriter(opts), "", 0)
|
||||
}
|
||||
|
||||
func (l *intLogger) StandardWriter(opts *StandardLoggerOptions) io.Writer {
|
||||
return &stdlogAdapter{
|
||||
log: l,
|
||||
inferLevels: opts.InferLevels,
|
||||
forceLevel: opts.ForceLevel,
|
||||
}
|
||||
}
|
||||
|
||||
// checks if the underlying io.Writer is a file, and
|
||||
// panics if not. For use by colorization.
|
||||
func (l *intLogger) checkWriterIsFile() *os.File {
|
||||
fi, ok := l.writer.w.(*os.File)
|
||||
if !ok {
|
||||
panic("Cannot enable coloring of non-file Writers")
|
||||
}
|
||||
return fi
|
||||
}
|
||||
|
||||
// Accept implements the SinkAdapter interface
|
||||
func (i *intLogger) Accept(name string, level Level, msg string, args ...interface{}) {
|
||||
i.log(name, level, msg, args...)
|
||||
}
|
||||
|
||||
// ImpliedArgs returns the loggers implied args
|
||||
func (i *intLogger) ImpliedArgs() []interface{} {
|
||||
return i.implied
|
||||
}
|
||||
|
||||
// Name returns the loggers name
|
||||
func (i *intLogger) Name() string {
|
||||
return i.name
|
||||
}
|
327
vendor/github.com/hashicorp/go-hclog/logger.go
generated
vendored
Normal file
327
vendor/github.com/hashicorp/go-hclog/logger.go
generated
vendored
Normal file
@ -0,0 +1,327 @@
|
||||
package hclog
|
||||
|
||||
import (
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
//DefaultOutput is used as the default log output.
|
||||
DefaultOutput io.Writer = os.Stderr
|
||||
|
||||
// DefaultLevel is used as the default log level.
|
||||
DefaultLevel = Info
|
||||
)
|
||||
|
||||
// Level represents a log level.
|
||||
type Level int32
|
||||
|
||||
const (
|
||||
// NoLevel is a special level used to indicate that no level has been
|
||||
// set and allow for a default to be used.
|
||||
NoLevel Level = 0
|
||||
|
||||
// Trace is the most verbose level. Intended to be used for the tracing
|
||||
// of actions in code, such as function enters/exits, etc.
|
||||
Trace Level = 1
|
||||
|
||||
// Debug information for programmer lowlevel analysis.
|
||||
Debug Level = 2
|
||||
|
||||
// Info information about steady state operations.
|
||||
Info Level = 3
|
||||
|
||||
// Warn information about rare but handled events.
|
||||
Warn Level = 4
|
||||
|
||||
// Error information about unrecoverable events.
|
||||
Error Level = 5
|
||||
)
|
||||
|
||||
// Format is a simple convience type for when formatting is required. When
|
||||
// processing a value of this type, the logger automatically treats the first
|
||||
// argument as a Printf formatting string and passes the rest as the values
|
||||
// to be formatted. For example: L.Info(Fmt{"%d beans/day", beans}).
|
||||
type Format []interface{}
|
||||
|
||||
// Fmt returns a Format type. This is a convience function for creating a Format
|
||||
// type.
|
||||
func Fmt(str string, args ...interface{}) Format {
|
||||
return append(Format{str}, args...)
|
||||
}
|
||||
|
||||
// A simple shortcut to format numbers in hex when displayed with the normal
|
||||
// text output. For example: L.Info("header value", Hex(17))
|
||||
type Hex int
|
||||
|
||||
// A simple shortcut to format numbers in octal when displayed with the normal
|
||||
// text output. For example: L.Info("perms", Octal(17))
|
||||
type Octal int
|
||||
|
||||
// A simple shortcut to format numbers in binary when displayed with the normal
|
||||
// text output. For example: L.Info("bits", Binary(17))
|
||||
type Binary int
|
||||
|
||||
// ColorOption expresses how the output should be colored, if at all.
|
||||
type ColorOption uint8
|
||||
|
||||
const (
|
||||
// ColorOff is the default coloration, and does not
|
||||
// inject color codes into the io.Writer.
|
||||
ColorOff ColorOption = iota
|
||||
// AutoColor checks if the io.Writer is a tty,
|
||||
// and if so enables coloring.
|
||||
AutoColor
|
||||
// ForceColor will enable coloring, regardless of whether
|
||||
// the io.Writer is a tty or not.
|
||||
ForceColor
|
||||
)
|
||||
|
||||
// LevelFromString returns a Level type for the named log level, or "NoLevel" if
|
||||
// the level string is invalid. This facilitates setting the log level via
|
||||
// config or environment variable by name in a predictable way.
|
||||
func LevelFromString(levelStr string) Level {
|
||||
// We don't care about case. Accept both "INFO" and "info".
|
||||
levelStr = strings.ToLower(strings.TrimSpace(levelStr))
|
||||
switch levelStr {
|
||||
case "trace":
|
||||
return Trace
|
||||
case "debug":
|
||||
return Debug
|
||||
case "info":
|
||||
return Info
|
||||
case "warn":
|
||||
return Warn
|
||||
case "error":
|
||||
return Error
|
||||
default:
|
||||
return NoLevel
|
||||
}
|
||||
}
|
||||
|
||||
func (l Level) String() string {
|
||||
switch l {
|
||||
case Trace:
|
||||
return "trace"
|
||||
case Debug:
|
||||
return "debug"
|
||||
case Info:
|
||||
return "info"
|
||||
case Warn:
|
||||
return "warn"
|
||||
case Error:
|
||||
return "error"
|
||||
case NoLevel:
|
||||
return "none"
|
||||
default:
|
||||
return "unknown"
|
||||
}
|
||||
}
|
||||
|
||||
// Logger describes the interface that must be implemeted by all loggers.
|
||||
type Logger interface {
|
||||
// Args are alternating key, val pairs
|
||||
// keys must be strings
|
||||
// vals can be any type, but display is implementation specific
|
||||
// Emit a message and key/value pairs at a provided log level
|
||||
Log(level Level, msg string, args ...interface{})
|
||||
|
||||
// Emit a message and key/value pairs at the TRACE level
|
||||
Trace(msg string, args ...interface{})
|
||||
|
||||
// Emit a message and key/value pairs at the DEBUG level
|
||||
Debug(msg string, args ...interface{})
|
||||
|
||||
// Emit a message and key/value pairs at the INFO level
|
||||
Info(msg string, args ...interface{})
|
||||
|
||||
// Emit a message and key/value pairs at the WARN level
|
||||
Warn(msg string, args ...interface{})
|
||||
|
||||
// Emit a message and key/value pairs at the ERROR level
|
||||
Error(msg string, args ...interface{})
|
||||
|
||||
// Indicate if TRACE logs would be emitted. This and the other Is* guards
|
||||
// are used to elide expensive logging code based on the current level.
|
||||
IsTrace() bool
|
||||
|
||||
// Indicate if DEBUG logs would be emitted. This and the other Is* guards
|
||||
IsDebug() bool
|
||||
|
||||
// Indicate if INFO logs would be emitted. This and the other Is* guards
|
||||
IsInfo() bool
|
||||
|
||||
// Indicate if WARN logs would be emitted. This and the other Is* guards
|
||||
IsWarn() bool
|
||||
|
||||
// Indicate if ERROR logs would be emitted. This and the other Is* guards
|
||||
IsError() bool
|
||||
|
||||
// ImpliedArgs returns With key/value pairs
|
||||
ImpliedArgs() []interface{}
|
||||
|
||||
// Creates a sublogger that will always have the given key/value pairs
|
||||
With(args ...interface{}) Logger
|
||||
|
||||
// Returns the Name of the logger
|
||||
Name() string
|
||||
|
||||
// Create a logger that will prepend the name string on the front of all messages.
|
||||
// If the logger already has a name, the new value will be appended to the current
|
||||
// name. That way, a major subsystem can use this to decorate all it's own logs
|
||||
// without losing context.
|
||||
Named(name string) Logger
|
||||
|
||||
// Create a logger that will prepend the name string on the front of all messages.
|
||||
// This sets the name of the logger to the value directly, unlike Named which honor
|
||||
// the current name as well.
|
||||
ResetNamed(name string) Logger
|
||||
|
||||
// Updates the level. This should affect all sub-loggers as well. If an
|
||||
// implementation cannot update the level on the fly, it should no-op.
|
||||
SetLevel(level Level)
|
||||
|
||||
// Return a value that conforms to the stdlib log.Logger interface
|
||||
StandardLogger(opts *StandardLoggerOptions) *log.Logger
|
||||
|
||||
// Return a value that conforms to io.Writer, which can be passed into log.SetOutput()
|
||||
StandardWriter(opts *StandardLoggerOptions) io.Writer
|
||||
}
|
||||
|
||||
// StandardLoggerOptions can be used to configure a new standard logger.
|
||||
type StandardLoggerOptions struct {
|
||||
// Indicate that some minimal parsing should be done on strings to try
|
||||
// and detect their level and re-emit them.
|
||||
// This supports the strings like [ERROR], [ERR] [TRACE], [WARN], [INFO],
|
||||
// [DEBUG] and strip it off before reapplying it.
|
||||
InferLevels bool
|
||||
|
||||
// ForceLevel is used to force all output from the standard logger to be at
|
||||
// the specified level. Similar to InferLevels, this will strip any level
|
||||
// prefix contained in the logged string before applying the forced level.
|
||||
// If set, this override InferLevels.
|
||||
ForceLevel Level
|
||||
}
|
||||
|
||||
// LoggerOptions can be used to configure a new logger.
|
||||
type LoggerOptions struct {
|
||||
// Name of the subsystem to prefix logs with
|
||||
Name string
|
||||
|
||||
// The threshold for the logger. Anything less severe is supressed
|
||||
Level Level
|
||||
|
||||
// Where to write the logs to. Defaults to os.Stderr if nil
|
||||
Output io.Writer
|
||||
|
||||
// An optional Locker in case Output is shared. This can be a sync.Mutex or
|
||||
// a NoopLocker if the caller wants control over output, e.g. for batching
|
||||
// log lines.
|
||||
Mutex Locker
|
||||
|
||||
// Control if the output should be in JSON.
|
||||
JSONFormat bool
|
||||
|
||||
// Include file and line information in each log line
|
||||
IncludeLocation bool
|
||||
|
||||
// The time format to use instead of the default
|
||||
TimeFormat string
|
||||
|
||||
// Control whether or not to display the time at all. This is required
|
||||
// because setting TimeFormat to empty assumes the default format.
|
||||
DisableTime bool
|
||||
|
||||
// Color the output. On Windows, colored logs are only avaiable for io.Writers that
|
||||
// are concretely instances of *os.File.
|
||||
Color ColorOption
|
||||
|
||||
// A function which is called with the log information and if it returns true the value
|
||||
// should not be logged.
|
||||
// This is useful when interacting with a system that you wish to suppress the log
|
||||
// message for (because it's too noisy, etc)
|
||||
Exclude func(level Level, msg string, args ...interface{}) bool
|
||||
}
|
||||
|
||||
// InterceptLogger describes the interface for using a logger
|
||||
// that can register different output sinks.
|
||||
// This is useful for sending lower level log messages
|
||||
// to a different output while keeping the root logger
|
||||
// at a higher one.
|
||||
type InterceptLogger interface {
|
||||
// Logger is the root logger for an InterceptLogger
|
||||
Logger
|
||||
|
||||
// RegisterSink adds a SinkAdapter to the InterceptLogger
|
||||
RegisterSink(sink SinkAdapter)
|
||||
|
||||
// DeregisterSink removes a SinkAdapter from the InterceptLogger
|
||||
DeregisterSink(sink SinkAdapter)
|
||||
|
||||
// Create a interceptlogger that will prepend the name string on the front of all messages.
|
||||
// If the logger already has a name, the new value will be appended to the current
|
||||
// name. That way, a major subsystem can use this to decorate all it's own logs
|
||||
// without losing context.
|
||||
NamedIntercept(name string) InterceptLogger
|
||||
|
||||
// Create a interceptlogger that will prepend the name string on the front of all messages.
|
||||
// This sets the name of the logger to the value directly, unlike Named which honor
|
||||
// the current name as well.
|
||||
ResetNamedIntercept(name string) InterceptLogger
|
||||
|
||||
// Return a value that conforms to the stdlib log.Logger interface
|
||||
StandardLoggerIntercept(opts *StandardLoggerOptions) *log.Logger
|
||||
|
||||
// Return a value that conforms to io.Writer, which can be passed into log.SetOutput()
|
||||
StandardWriterIntercept(opts *StandardLoggerOptions) io.Writer
|
||||
}
|
||||
|
||||
// SinkAdapter describes the interface that must be implemented
|
||||
// in order to Register a new sink to an InterceptLogger
|
||||
type SinkAdapter interface {
|
||||
Accept(name string, level Level, msg string, args ...interface{})
|
||||
}
|
||||
|
||||
// Flushable represents a method for flushing an output buffer. It can be used
|
||||
// if Resetting the log to use a new output, in order to flush the writes to
|
||||
// the existing output beforehand.
|
||||
type Flushable interface {
|
||||
Flush() error
|
||||
}
|
||||
|
||||
// OutputResettable provides ways to swap the output in use at runtime
|
||||
type OutputResettable interface {
|
||||
// ResetOutput swaps the current output writer with the one given in the
|
||||
// opts. Color options given in opts will be used for the new output.
|
||||
ResetOutput(opts *LoggerOptions) error
|
||||
|
||||
// ResetOutputWithFlush swaps the current output writer with the one given
|
||||
// in the opts, first calling Flush on the given Flushable. Color options
|
||||
// given in opts will be used for the new output.
|
||||
ResetOutputWithFlush(opts *LoggerOptions, flushable Flushable) error
|
||||
}
|
||||
|
||||
// Locker is used for locking output. If not set when creating a logger, a
|
||||
// sync.Mutex will be used internally.
|
||||
type Locker interface {
|
||||
// Lock is called when the output is going to be changed or written to
|
||||
Lock()
|
||||
|
||||
// Unlock is called when the operation that called Lock() completes
|
||||
Unlock()
|
||||
}
|
||||
|
||||
// NoopLocker implements locker but does nothing. This is useful if the client
|
||||
// wants tight control over locking, in order to provide grouping of log
|
||||
// entries or other functionality.
|
||||
type NoopLocker struct{}
|
||||
|
||||
// Lock does nothing
|
||||
func (n NoopLocker) Lock() {}
|
||||
|
||||
// Unlock does nothing
|
||||
func (n NoopLocker) Unlock() {}
|
||||
|
||||
var _ Locker = (*NoopLocker)(nil)
|
58
vendor/github.com/hashicorp/go-hclog/nulllogger.go
generated
vendored
Normal file
58
vendor/github.com/hashicorp/go-hclog/nulllogger.go
generated
vendored
Normal file
@ -0,0 +1,58 @@
|
||||
package hclog
|
||||
|
||||
import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
)
|
||||
|
||||
// NewNullLogger instantiates a Logger for which all calls
|
||||
// will succeed without doing anything.
|
||||
// Useful for testing purposes.
|
||||
func NewNullLogger() Logger {
|
||||
return &nullLogger{}
|
||||
}
|
||||
|
||||
type nullLogger struct{}
|
||||
|
||||
func (l *nullLogger) Log(level Level, msg string, args ...interface{}) {}
|
||||
|
||||
func (l *nullLogger) Trace(msg string, args ...interface{}) {}
|
||||
|
||||
func (l *nullLogger) Debug(msg string, args ...interface{}) {}
|
||||
|
||||
func (l *nullLogger) Info(msg string, args ...interface{}) {}
|
||||
|
||||
func (l *nullLogger) Warn(msg string, args ...interface{}) {}
|
||||
|
||||
func (l *nullLogger) Error(msg string, args ...interface{}) {}
|
||||
|
||||
func (l *nullLogger) IsTrace() bool { return false }
|
||||
|
||||
func (l *nullLogger) IsDebug() bool { return false }
|
||||
|
||||
func (l *nullLogger) IsInfo() bool { return false }
|
||||
|
||||
func (l *nullLogger) IsWarn() bool { return false }
|
||||
|
||||
func (l *nullLogger) IsError() bool { return false }
|
||||
|
||||
func (l *nullLogger) ImpliedArgs() []interface{} { return []interface{}{} }
|
||||
|
||||
func (l *nullLogger) With(args ...interface{}) Logger { return l }
|
||||
|
||||
func (l *nullLogger) Name() string { return "" }
|
||||
|
||||
func (l *nullLogger) Named(name string) Logger { return l }
|
||||
|
||||
func (l *nullLogger) ResetNamed(name string) Logger { return l }
|
||||
|
||||
func (l *nullLogger) SetLevel(level Level) {}
|
||||
|
||||
func (l *nullLogger) StandardLogger(opts *StandardLoggerOptions) *log.Logger {
|
||||
return log.New(l.StandardWriter(opts), "", log.LstdFlags)
|
||||
}
|
||||
|
||||
func (l *nullLogger) StandardWriter(opts *StandardLoggerOptions) io.Writer {
|
||||
return ioutil.Discard
|
||||
}
|
109
vendor/github.com/hashicorp/go-hclog/stacktrace.go
generated
vendored
Normal file
109
vendor/github.com/hashicorp/go-hclog/stacktrace.go
generated
vendored
Normal file
@ -0,0 +1,109 @@
|
||||
// Copyright (c) 2016 Uber Technologies, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
package hclog
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
_stacktraceIgnorePrefixes = []string{
|
||||
"runtime.goexit",
|
||||
"runtime.main",
|
||||
}
|
||||
_stacktracePool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return newProgramCounters(64)
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
// CapturedStacktrace represents a stacktrace captured by a previous call
|
||||
// to log.Stacktrace. If passed to a logging function, the stacktrace
|
||||
// will be appended.
|
||||
type CapturedStacktrace string
|
||||
|
||||
// Stacktrace captures a stacktrace of the current goroutine and returns
|
||||
// it to be passed to a logging function.
|
||||
func Stacktrace() CapturedStacktrace {
|
||||
return CapturedStacktrace(takeStacktrace())
|
||||
}
|
||||
|
||||
func takeStacktrace() string {
|
||||
programCounters := _stacktracePool.Get().(*programCounters)
|
||||
defer _stacktracePool.Put(programCounters)
|
||||
|
||||
var buffer bytes.Buffer
|
||||
|
||||
for {
|
||||
// Skip the call to runtime.Counters and takeStacktrace so that the
|
||||
// program counters start at the caller of takeStacktrace.
|
||||
n := runtime.Callers(2, programCounters.pcs)
|
||||
if n < cap(programCounters.pcs) {
|
||||
programCounters.pcs = programCounters.pcs[:n]
|
||||
break
|
||||
}
|
||||
// Don't put the too-short counter slice back into the pool; this lets
|
||||
// the pool adjust if we consistently take deep stacktraces.
|
||||
programCounters = newProgramCounters(len(programCounters.pcs) * 2)
|
||||
}
|
||||
|
||||
i := 0
|
||||
frames := runtime.CallersFrames(programCounters.pcs)
|
||||
for frame, more := frames.Next(); more; frame, more = frames.Next() {
|
||||
if shouldIgnoreStacktraceFunction(frame.Function) {
|
||||
continue
|
||||
}
|
||||
if i != 0 {
|
||||
buffer.WriteByte('\n')
|
||||
}
|
||||
i++
|
||||
buffer.WriteString(frame.Function)
|
||||
buffer.WriteByte('\n')
|
||||
buffer.WriteByte('\t')
|
||||
buffer.WriteString(frame.File)
|
||||
buffer.WriteByte(':')
|
||||
buffer.WriteString(strconv.Itoa(int(frame.Line)))
|
||||
}
|
||||
|
||||
return buffer.String()
|
||||
}
|
||||
|
||||
func shouldIgnoreStacktraceFunction(function string) bool {
|
||||
for _, prefix := range _stacktraceIgnorePrefixes {
|
||||
if strings.HasPrefix(function, prefix) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type programCounters struct {
|
||||
pcs []uintptr
|
||||
}
|
||||
|
||||
func newProgramCounters(size int) *programCounters {
|
||||
return &programCounters{make([]uintptr, size)}
|
||||
}
|
95
vendor/github.com/hashicorp/go-hclog/stdlog.go
generated
vendored
Normal file
95
vendor/github.com/hashicorp/go-hclog/stdlog.go
generated
vendored
Normal file
@ -0,0 +1,95 @@
|
||||
package hclog
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"log"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Provides a io.Writer to shim the data out of *log.Logger
|
||||
// and back into our Logger. This is basically the only way to
|
||||
// build upon *log.Logger.
|
||||
type stdlogAdapter struct {
|
||||
log Logger
|
||||
inferLevels bool
|
||||
forceLevel Level
|
||||
}
|
||||
|
||||
// Take the data, infer the levels if configured, and send it through
|
||||
// a regular Logger.
|
||||
func (s *stdlogAdapter) Write(data []byte) (int, error) {
|
||||
str := string(bytes.TrimRight(data, " \t\n"))
|
||||
|
||||
if s.forceLevel != NoLevel {
|
||||
// Use pickLevel to strip log levels included in the line since we are
|
||||
// forcing the level
|
||||
_, str := s.pickLevel(str)
|
||||
|
||||
// Log at the forced level
|
||||
s.dispatch(str, s.forceLevel)
|
||||
} else if s.inferLevels {
|
||||
level, str := s.pickLevel(str)
|
||||
s.dispatch(str, level)
|
||||
} else {
|
||||
s.log.Info(str)
|
||||
}
|
||||
|
||||
return len(data), nil
|
||||
}
|
||||
|
||||
func (s *stdlogAdapter) dispatch(str string, level Level) {
|
||||
switch level {
|
||||
case Trace:
|
||||
s.log.Trace(str)
|
||||
case Debug:
|
||||
s.log.Debug(str)
|
||||
case Info:
|
||||
s.log.Info(str)
|
||||
case Warn:
|
||||
s.log.Warn(str)
|
||||
case Error:
|
||||
s.log.Error(str)
|
||||
default:
|
||||
s.log.Info(str)
|
||||
}
|
||||
}
|
||||
|
||||
// Detect, based on conventions, what log level this is.
|
||||
func (s *stdlogAdapter) pickLevel(str string) (Level, string) {
|
||||
switch {
|
||||
case strings.HasPrefix(str, "[DEBUG]"):
|
||||
return Debug, strings.TrimSpace(str[7:])
|
||||
case strings.HasPrefix(str, "[TRACE]"):
|
||||
return Trace, strings.TrimSpace(str[7:])
|
||||
case strings.HasPrefix(str, "[INFO]"):
|
||||
return Info, strings.TrimSpace(str[6:])
|
||||
case strings.HasPrefix(str, "[WARN]"):
|
||||
return Warn, strings.TrimSpace(str[7:])
|
||||
case strings.HasPrefix(str, "[ERROR]"):
|
||||
return Error, strings.TrimSpace(str[7:])
|
||||
case strings.HasPrefix(str, "[ERR]"):
|
||||
return Error, strings.TrimSpace(str[5:])
|
||||
default:
|
||||
return Info, str
|
||||
}
|
||||
}
|
||||
|
||||
type logWriter struct {
|
||||
l *log.Logger
|
||||
}
|
||||
|
||||
func (l *logWriter) Write(b []byte) (int, error) {
|
||||
l.l.Println(string(bytes.TrimRight(b, " \n\t")))
|
||||
return len(b), nil
|
||||
}
|
||||
|
||||
// Takes a standard library logger and returns a Logger that will write to it
|
||||
func FromStandardLogger(l *log.Logger, opts *LoggerOptions) Logger {
|
||||
var dl LoggerOptions = *opts
|
||||
|
||||
// Use the time format that log.Logger uses
|
||||
dl.DisableTime = true
|
||||
dl.Output = &logWriter{l}
|
||||
|
||||
return New(&dl)
|
||||
}
|
82
vendor/github.com/hashicorp/go-hclog/writer.go
generated
vendored
Normal file
82
vendor/github.com/hashicorp/go-hclog/writer.go
generated
vendored
Normal file
@ -0,0 +1,82 @@
|
||||
package hclog
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
)
|
||||
|
||||
type writer struct {
|
||||
b bytes.Buffer
|
||||
w io.Writer
|
||||
color ColorOption
|
||||
}
|
||||
|
||||
func newWriter(w io.Writer, color ColorOption) *writer {
|
||||
return &writer{w: w, color: color}
|
||||
}
|
||||
|
||||
func (w *writer) Flush(level Level) (err error) {
|
||||
var unwritten = w.b.Bytes()
|
||||
|
||||
if w.color != ColorOff {
|
||||
color := _levelToColor[level]
|
||||
unwritten = []byte(color.Sprintf("%s", unwritten))
|
||||
}
|
||||
|
||||
if lw, ok := w.w.(LevelWriter); ok {
|
||||
_, err = lw.LevelWrite(level, unwritten)
|
||||
} else {
|
||||
_, err = w.w.Write(unwritten)
|
||||
}
|
||||
w.b.Reset()
|
||||
return err
|
||||
}
|
||||
|
||||
func (w *writer) Write(p []byte) (int, error) {
|
||||
return w.b.Write(p)
|
||||
}
|
||||
|
||||
func (w *writer) WriteByte(c byte) error {
|
||||
return w.b.WriteByte(c)
|
||||
}
|
||||
|
||||
func (w *writer) WriteString(s string) (int, error) {
|
||||
return w.b.WriteString(s)
|
||||
}
|
||||
|
||||
// LevelWriter is the interface that wraps the LevelWrite method.
|
||||
type LevelWriter interface {
|
||||
LevelWrite(level Level, p []byte) (n int, err error)
|
||||
}
|
||||
|
||||
// LeveledWriter writes all log messages to the standard writer,
|
||||
// except for log levels that are defined in the overrides map.
|
||||
type LeveledWriter struct {
|
||||
standard io.Writer
|
||||
overrides map[Level]io.Writer
|
||||
}
|
||||
|
||||
// NewLeveledWriter returns an initialized LeveledWriter.
|
||||
//
|
||||
// standard will be used as the default writer for all log levels,
|
||||
// except for log levels that are defined in the overrides map.
|
||||
func NewLeveledWriter(standard io.Writer, overrides map[Level]io.Writer) *LeveledWriter {
|
||||
return &LeveledWriter{
|
||||
standard: standard,
|
||||
overrides: overrides,
|
||||
}
|
||||
}
|
||||
|
||||
// Write implements io.Writer.
|
||||
func (lw *LeveledWriter) Write(p []byte) (int, error) {
|
||||
return lw.standard.Write(p)
|
||||
}
|
||||
|
||||
// LevelWrite implements LevelWriter.
|
||||
func (lw *LeveledWriter) LevelWrite(level Level, p []byte) (int, error) {
|
||||
w, ok := lw.overrides[level]
|
||||
if !ok {
|
||||
w = lw.standard
|
||||
}
|
||||
return w.Write(p)
|
||||
}
|
12
vendor/github.com/hashicorp/go-multierror/.travis.yml
generated
vendored
Normal file
12
vendor/github.com/hashicorp/go-multierror/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
sudo: false
|
||||
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.x
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
|
||||
script: env GO111MODULE=on make test testrace
|
353
vendor/github.com/hashicorp/go-multierror/LICENSE
generated
vendored
Normal file
353
vendor/github.com/hashicorp/go-multierror/LICENSE
generated
vendored
Normal file
@ -0,0 +1,353 @@
|
||||
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.
|
31
vendor/github.com/hashicorp/go-multierror/Makefile
generated
vendored
Normal file
31
vendor/github.com/hashicorp/go-multierror/Makefile
generated
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
TEST?=./...
|
||||
|
||||
default: test
|
||||
|
||||
# test runs the test suite and vets the code.
|
||||
test: generate
|
||||
@echo "==> Running tests..."
|
||||
@go list $(TEST) \
|
||||
| grep -v "/vendor/" \
|
||||
| xargs -n1 go test -timeout=60s -parallel=10 ${TESTARGS}
|
||||
|
||||
# testrace runs the race checker
|
||||
testrace: generate
|
||||
@echo "==> Running tests (race)..."
|
||||
@go list $(TEST) \
|
||||
| grep -v "/vendor/" \
|
||||
| xargs -n1 go test -timeout=60s -race ${TESTARGS}
|
||||
|
||||
# updatedeps installs all the dependencies needed to run and build.
|
||||
updatedeps:
|
||||
@sh -c "'${CURDIR}/scripts/deps.sh' '${NAME}'"
|
||||
|
||||
# generate runs `go generate` to build the dynamically generated source files.
|
||||
generate:
|
||||
@echo "==> Generating..."
|
||||
@find . -type f -name '.DS_Store' -delete
|
||||
@go list ./... \
|
||||
| grep -v "/vendor/" \
|
||||
| xargs -n1 go generate
|
||||
|
||||
.PHONY: default test testrace updatedeps generate
|
131
vendor/github.com/hashicorp/go-multierror/README.md
generated
vendored
Normal file
131
vendor/github.com/hashicorp/go-multierror/README.md
generated
vendored
Normal file
@ -0,0 +1,131 @@
|
||||
# go-multierror
|
||||
|
||||
[][travis]
|
||||
[][godocs]
|
||||
|
||||
[travis]: https://travis-ci.org/hashicorp/go-multierror
|
||||
[godocs]: https://godoc.org/github.com/hashicorp/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` is fully compatible with the Go standard library
|
||||
[errors](https://golang.org/pkg/errors/) package, including the
|
||||
functions `As`, `Is`, and `Unwrap`. This provides a standardized approach
|
||||
for introspecting on error values.
|
||||
|
||||
## 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
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
You can also use the standard [`errors.Unwrap`](https://golang.org/pkg/errors/#Unwrap)
|
||||
function. This will continue to unwrap into subsequent errors until none exist.
|
||||
|
||||
**Extracting an error**
|
||||
|
||||
The standard library [`errors.As`](https://golang.org/pkg/errors/#As)
|
||||
function can be used directly with a multierror to extract a specific error:
|
||||
|
||||
```go
|
||||
// Assume err is a multierror value
|
||||
err := somefunc()
|
||||
|
||||
// We want to know if "err" has a "RichErrorType" in it and extract it.
|
||||
var errRich RichErrorType
|
||||
if errors.As(err, &errRich) {
|
||||
// It has it, and now errRich is populated.
|
||||
}
|
||||
```
|
||||
|
||||
**Checking for an exact error value**
|
||||
|
||||
Some errors are returned as exact errors such as the [`ErrNotExist`](https://golang.org/pkg/os/#pkg-variables)
|
||||
error in the `os` package. You can check if this error is present by using
|
||||
the standard [`errors.Is`](https://golang.org/pkg/errors/#Is) function.
|
||||
|
||||
```go
|
||||
// Assume err is a multierror value
|
||||
err := somefunc()
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
// err contains os.ErrNotExist
|
||||
}
|
||||
```
|
||||
|
||||
**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()
|
||||
```
|
41
vendor/github.com/hashicorp/go-multierror/append.go
generated
vendored
Normal file
41
vendor/github.com/hashicorp/go-multierror/append.go
generated
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
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:
|
||||
if e != nil {
|
||||
err.Errors = append(err.Errors, e.Errors...)
|
||||
}
|
||||
default:
|
||||
if e != nil {
|
||||
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
Normal file
26
vendor/github.com/hashicorp/go-multierror/flatten.go
generated
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
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)
|
||||
}
|
||||
}
|
27
vendor/github.com/hashicorp/go-multierror/format.go
generated
vendored
Normal file
27
vendor/github.com/hashicorp/go-multierror/format.go
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
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 {
|
||||
if len(es) == 1 {
|
||||
return fmt.Sprintf("1 error occurred:\n\t* %s\n\n", es[0])
|
||||
}
|
||||
|
||||
points := make([]string, len(es))
|
||||
for i, err := range es {
|
||||
points[i] = fmt.Sprintf("* %s", err)
|
||||
}
|
||||
|
||||
return fmt.Sprintf(
|
||||
"%d errors occurred:\n\t%s\n\n",
|
||||
len(es), strings.Join(points, "\n\t"))
|
||||
}
|
5
vendor/github.com/hashicorp/go-multierror/go.mod
generated
vendored
Normal file
5
vendor/github.com/hashicorp/go-multierror/go.mod
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
module github.com/hashicorp/go-multierror
|
||||
|
||||
go 1.14
|
||||
|
||||
require github.com/hashicorp/errwrap v1.0.0
|
2
vendor/github.com/hashicorp/go-multierror/go.sum
generated
vendored
Normal file
2
vendor/github.com/hashicorp/go-multierror/go.sum
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
38
vendor/github.com/hashicorp/go-multierror/group.go
generated
vendored
Normal file
38
vendor/github.com/hashicorp/go-multierror/group.go
generated
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
package multierror
|
||||
|
||||
import "sync"
|
||||
|
||||
// Group is a collection of goroutines which return errors that need to be
|
||||
// coalesced.
|
||||
type Group struct {
|
||||
mutex sync.Mutex
|
||||
err *Error
|
||||
wg sync.WaitGroup
|
||||
}
|
||||
|
||||
// Go calls the given function in a new goroutine.
|
||||
//
|
||||
// If the function returns an error it is added to the group multierror which
|
||||
// is returned by Wait.
|
||||
func (g *Group) Go(f func() error) {
|
||||
g.wg.Add(1)
|
||||
|
||||
go func() {
|
||||
defer g.wg.Done()
|
||||
|
||||
if err := f(); err != nil {
|
||||
g.mutex.Lock()
|
||||
g.err = Append(g.err, err)
|
||||
g.mutex.Unlock()
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// Wait blocks until all function calls from the Go method have returned, then
|
||||
// returns the multierror.
|
||||
func (g *Group) Wait() *Error {
|
||||
g.wg.Wait()
|
||||
g.mutex.Lock()
|
||||
defer g.mutex.Unlock()
|
||||
return g.err
|
||||
}
|
118
vendor/github.com/hashicorp/go-multierror/multierror.go
generated
vendored
Normal file
118
vendor/github.com/hashicorp/go-multierror/multierror.go
generated
vendored
Normal file
@ -0,0 +1,118 @@
|
||||
package multierror
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"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 implementation 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 implemented only to
|
||||
// satisfy the errwrap.Wrapper interface.
|
||||
func (e *Error) WrappedErrors() []error {
|
||||
return e.Errors
|
||||
}
|
||||
|
||||
// Unwrap returns an error from Error (or nil if there are no errors).
|
||||
// This error returned will further support Unwrap to get the next error,
|
||||
// etc. The order will match the order of Errors in the multierror.Error
|
||||
// at the time of calling.
|
||||
//
|
||||
// The resulting error supports errors.As/Is/Unwrap so you can continue
|
||||
// to use the stdlib errors package to introspect further.
|
||||
//
|
||||
// This will perform a shallow copy of the errors slice. Any errors appended
|
||||
// to this error after calling Unwrap will not be available until a new
|
||||
// Unwrap is called on the multierror.Error.
|
||||
func (e *Error) Unwrap() error {
|
||||
// If we have no errors then we do nothing
|
||||
if e == nil || len(e.Errors) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// If we have exactly one error, we can just return that directly.
|
||||
if len(e.Errors) == 1 {
|
||||
return e.Errors[0]
|
||||
}
|
||||
|
||||
// Shallow copy the slice
|
||||
errs := make([]error, len(e.Errors))
|
||||
copy(errs, e.Errors)
|
||||
return chain(errs)
|
||||
}
|
||||
|
||||
// chain implements the interfaces necessary for errors.Is/As/Unwrap to
|
||||
// work in a deterministic way with multierror. A chain tracks a list of
|
||||
// errors while accounting for the current represented error. This lets
|
||||
// Is/As be meaningful.
|
||||
//
|
||||
// Unwrap returns the next error. In the cleanest form, Unwrap would return
|
||||
// the wrapped error here but we can't do that if we want to properly
|
||||
// get access to all the errors. Instead, users are recommended to use
|
||||
// Is/As to get the correct error type out.
|
||||
//
|
||||
// Precondition: []error is non-empty (len > 0)
|
||||
type chain []error
|
||||
|
||||
// Error implements the error interface
|
||||
func (e chain) Error() string {
|
||||
return e[0].Error()
|
||||
}
|
||||
|
||||
// Unwrap implements errors.Unwrap by returning the next error in the
|
||||
// chain or nil if there are no more errors.
|
||||
func (e chain) Unwrap() error {
|
||||
if len(e) == 1 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return e[1:]
|
||||
}
|
||||
|
||||
// As implements errors.As by attempting to map to the current value.
|
||||
func (e chain) As(target interface{}) bool {
|
||||
return errors.As(e[0], target)
|
||||
}
|
||||
|
||||
// Is implements errors.Is by comparing the current value directly.
|
||||
func (e chain) Is(target error) bool {
|
||||
return errors.Is(e[0], target)
|
||||
}
|
37
vendor/github.com/hashicorp/go-multierror/prefix.go
generated
vendored
Normal file
37
vendor/github.com/hashicorp/go-multierror/prefix.go
generated
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
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)
|
||||
}
|
||||
}
|
16
vendor/github.com/hashicorp/go-multierror/sort.go
generated
vendored
Normal file
16
vendor/github.com/hashicorp/go-multierror/sort.go
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
package multierror
|
||||
|
||||
// Len implements sort.Interface function for length
|
||||
func (err Error) Len() int {
|
||||
return len(err.Errors)
|
||||
}
|
||||
|
||||
// Swap implements sort.Interface function for swapping elements
|
||||
func (err Error) Swap(i, j int) {
|
||||
err.Errors[i], err.Errors[j] = err.Errors[j], err.Errors[i]
|
||||
}
|
||||
|
||||
// Less implements sort.Interface function for determining order
|
||||
func (err Error) Less(i, j int) bool {
|
||||
return err.Errors[i].Error() < err.Errors[j].Error()
|
||||
}
|
4
vendor/github.com/hashicorp/go-retryablehttp/.gitignore
generated
vendored
Normal file
4
vendor/github.com/hashicorp/go-retryablehttp/.gitignore
generated
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
.idea/
|
||||
*.iml
|
||||
*.test
|
||||
.vscode/
|
12
vendor/github.com/hashicorp/go-retryablehttp/.travis.yml
generated
vendored
Normal file
12
vendor/github.com/hashicorp/go-retryablehttp/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
sudo: false
|
||||
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.12.4
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
|
||||
script: make updatedeps test
|
363
vendor/github.com/hashicorp/go-retryablehttp/LICENSE
generated
vendored
Normal file
363
vendor/github.com/hashicorp/go-retryablehttp/LICENSE
generated
vendored
Normal file
@ -0,0 +1,363 @@
|
||||
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.
|
||||
|
11
vendor/github.com/hashicorp/go-retryablehttp/Makefile
generated
vendored
Normal file
11
vendor/github.com/hashicorp/go-retryablehttp/Makefile
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
default: test
|
||||
|
||||
test:
|
||||
go vet ./...
|
||||
go test -race ./...
|
||||
|
||||
updatedeps:
|
||||
go get -f -t -u ./...
|
||||
go get -f -u ./...
|
||||
|
||||
.PHONY: default test updatedeps
|
61
vendor/github.com/hashicorp/go-retryablehttp/README.md
generated
vendored
Normal file
61
vendor/github.com/hashicorp/go-retryablehttp/README.md
generated
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
go-retryablehttp
|
||||
================
|
||||
|
||||
[][travis]
|
||||
[][godocs]
|
||||
|
||||
[travis]: http://travis-ci.org/hashicorp/go-retryablehttp
|
||||
[godocs]: http://godoc.org/github.com/hashicorp/go-retryablehttp
|
||||
|
||||
The `retryablehttp` package provides a familiar HTTP client interface with
|
||||
automatic retries and exponential backoff. It is a thin wrapper over the
|
||||
standard `net/http` client library and exposes nearly the same public API. This
|
||||
makes `retryablehttp` very easy to drop into existing programs.
|
||||
|
||||
`retryablehttp` performs automatic retries under certain conditions. Mainly, if
|
||||
an error is returned by the client (connection errors, etc.), or if a 500-range
|
||||
response code is received (except 501), then a retry is invoked after a wait
|
||||
period. Otherwise, the response is returned and left to the caller to
|
||||
interpret.
|
||||
|
||||
The main difference from `net/http` is that requests which take a request body
|
||||
(POST/PUT et. al) can have the body provided in a number of ways (some more or
|
||||
less efficient) that allow "rewinding" the request body if the initial request
|
||||
fails so that the full request can be attempted again. See the
|
||||
[godoc](http://godoc.org/github.com/hashicorp/go-retryablehttp) for more
|
||||
details.
|
||||
|
||||
Version 0.6.0 and before are compatible with Go prior to 1.12. From 0.6.1 onward, Go 1.12+ is required.
|
||||
|
||||
Example Use
|
||||
===========
|
||||
|
||||
Using this library should look almost identical to what you would do with
|
||||
`net/http`. The most simple example of a GET request is shown below:
|
||||
|
||||
```go
|
||||
resp, err := retryablehttp.Get("/foo")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
```
|
||||
|
||||
The returned response object is an `*http.Response`, the same thing you would
|
||||
usually get from `net/http`. Had the request failed one or more times, the above
|
||||
call would block and retry with exponential backoff.
|
||||
|
||||
## Getting a stdlib `*http.Client` with retries
|
||||
|
||||
It's possible to convert a `*retryablehttp.Client` directly to a `*http.Client`.
|
||||
This makes use of retryablehttp broadly applicable with minimal effort. Simply
|
||||
configure a `*retryablehttp.Client` as you wish, and then call `StandardClient()`:
|
||||
|
||||
```go
|
||||
retryClient := retryablehttp.NewClient()
|
||||
retryClient.RetryMax = 10
|
||||
|
||||
standardClient := retryClient.StandardClient() // *http.Client
|
||||
```
|
||||
|
||||
For more usage and examples see the
|
||||
[godoc](http://godoc.org/github.com/hashicorp/go-retryablehttp).
|
705
vendor/github.com/hashicorp/go-retryablehttp/client.go
generated
vendored
Normal file
705
vendor/github.com/hashicorp/go-retryablehttp/client.go
generated
vendored
Normal file
@ -0,0 +1,705 @@
|
||||
// Package retryablehttp provides a familiar HTTP client interface with
|
||||
// automatic retries and exponential backoff. It is a thin wrapper over the
|
||||
// standard net/http client library and exposes nearly the same public API.
|
||||
// This makes retryablehttp very easy to drop into existing programs.
|
||||
//
|
||||
// retryablehttp performs automatic retries under certain conditions. Mainly, if
|
||||
// an error is returned by the client (connection errors etc), or if a 500-range
|
||||
// response is received, then a retry is invoked. Otherwise, the response is
|
||||
// returned and left to the caller to interpret.
|
||||
//
|
||||
// Requests which take a request body should provide a non-nil function
|
||||
// parameter. The best choice is to provide either a function satisfying
|
||||
// ReaderFunc which provides multiple io.Readers in an efficient manner, a
|
||||
// *bytes.Buffer (the underlying raw byte slice will be used) or a raw byte
|
||||
// slice. As it is a reference type, and we will wrap it as needed by readers,
|
||||
// we can efficiently re-use the request body without needing to copy it. If an
|
||||
// io.Reader (such as a *bytes.Reader) is provided, the full body will be read
|
||||
// prior to the first request, and will be efficiently re-used for any retries.
|
||||
// ReadSeeker can be used, but some users have observed occasional data races
|
||||
// between the net/http library and the Seek functionality of some
|
||||
// implementations of ReadSeeker, so should be avoided if possible.
|
||||
package retryablehttp
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"math"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/go-cleanhttp"
|
||||
)
|
||||
|
||||
var (
|
||||
// Default retry configuration
|
||||
defaultRetryWaitMin = 1 * time.Second
|
||||
defaultRetryWaitMax = 30 * time.Second
|
||||
defaultRetryMax = 4
|
||||
|
||||
// defaultLogger is the logger provided with defaultClient
|
||||
defaultLogger = log.New(os.Stderr, "", log.LstdFlags)
|
||||
|
||||
// defaultClient is used for performing requests without explicitly making
|
||||
// a new client. It is purposely private to avoid modifications.
|
||||
defaultClient = NewClient()
|
||||
|
||||
// We need to consume response bodies to maintain http connections, but
|
||||
// limit the size we consume to respReadLimit.
|
||||
respReadLimit = int64(4096)
|
||||
|
||||
// A regular expression to match the error returned by net/http when the
|
||||
// configured number of redirects is exhausted. This error isn't typed
|
||||
// specifically so we resort to matching on the error string.
|
||||
redirectsErrorRe = regexp.MustCompile(`stopped after \d+ redirects\z`)
|
||||
|
||||
// A regular expression to match the error returned by net/http when the
|
||||
// scheme specified in the URL is invalid. This error isn't typed
|
||||
// specifically so we resort to matching on the error string.
|
||||
schemeErrorRe = regexp.MustCompile(`unsupported protocol scheme`)
|
||||
)
|
||||
|
||||
// ReaderFunc is the type of function that can be given natively to NewRequest
|
||||
type ReaderFunc func() (io.Reader, error)
|
||||
|
||||
// LenReader is an interface implemented by many in-memory io.Reader's. Used
|
||||
// for automatically sending the right Content-Length header when possible.
|
||||
type LenReader interface {
|
||||
Len() int
|
||||
}
|
||||
|
||||
// Request wraps the metadata needed to create HTTP requests.
|
||||
type Request struct {
|
||||
// body is a seekable reader over the request body payload. This is
|
||||
// used to rewind the request data in between retries.
|
||||
body ReaderFunc
|
||||
|
||||
// Embed an HTTP request directly. This makes a *Request act exactly
|
||||
// like an *http.Request so that all meta methods are supported.
|
||||
*http.Request
|
||||
}
|
||||
|
||||
// WithContext returns wrapped Request with a shallow copy of underlying *http.Request
|
||||
// with its context changed to ctx. The provided ctx must be non-nil.
|
||||
func (r *Request) WithContext(ctx context.Context) *Request {
|
||||
r.Request = r.Request.WithContext(ctx)
|
||||
return r
|
||||
}
|
||||
|
||||
// BodyBytes allows accessing the request body. It is an analogue to
|
||||
// http.Request's Body variable, but it returns a copy of the underlying data
|
||||
// rather than consuming it.
|
||||
//
|
||||
// This function is not thread-safe; do not call it at the same time as another
|
||||
// call, or at the same time this request is being used with Client.Do.
|
||||
func (r *Request) BodyBytes() ([]byte, error) {
|
||||
if r.body == nil {
|
||||
return nil, nil
|
||||
}
|
||||
body, err := r.body()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
buf := new(bytes.Buffer)
|
||||
_, err = buf.ReadFrom(body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
// SetBody allows setting the request body.
|
||||
//
|
||||
// It is useful if a new body needs to be set without constructing a new Request.
|
||||
func (r *Request) SetBody(rawBody interface{}) error {
|
||||
bodyReader, contentLength, err := getBodyReaderAndContentLength(rawBody)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r.body = bodyReader
|
||||
r.ContentLength = contentLength
|
||||
return nil
|
||||
}
|
||||
|
||||
// WriteTo allows copying the request body into a writer.
|
||||
//
|
||||
// It writes data to w until there's no more data to write or
|
||||
// when an error occurs. The return int64 value is the number of bytes
|
||||
// written. Any error encountered during the write is also returned.
|
||||
// The signature matches io.WriterTo interface.
|
||||
func (r *Request) WriteTo(w io.Writer) (int64, error) {
|
||||
body, err := r.body()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if c, ok := body.(io.Closer); ok {
|
||||
defer c.Close()
|
||||
}
|
||||
return io.Copy(w, body)
|
||||
}
|
||||
|
||||
func getBodyReaderAndContentLength(rawBody interface{}) (ReaderFunc, int64, error) {
|
||||
var bodyReader ReaderFunc
|
||||
var contentLength int64
|
||||
|
||||
switch body := rawBody.(type) {
|
||||
// If they gave us a function already, great! Use it.
|
||||
case ReaderFunc:
|
||||
bodyReader = body
|
||||
tmp, err := body()
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
if lr, ok := tmp.(LenReader); ok {
|
||||
contentLength = int64(lr.Len())
|
||||
}
|
||||
if c, ok := tmp.(io.Closer); ok {
|
||||
c.Close()
|
||||
}
|
||||
|
||||
case func() (io.Reader, error):
|
||||
bodyReader = body
|
||||
tmp, err := body()
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
if lr, ok := tmp.(LenReader); ok {
|
||||
contentLength = int64(lr.Len())
|
||||
}
|
||||
if c, ok := tmp.(io.Closer); ok {
|
||||
c.Close()
|
||||
}
|
||||
|
||||
// If a regular byte slice, we can read it over and over via new
|
||||
// readers
|
||||
case []byte:
|
||||
buf := body
|
||||
bodyReader = func() (io.Reader, error) {
|
||||
return bytes.NewReader(buf), nil
|
||||
}
|
||||
contentLength = int64(len(buf))
|
||||
|
||||
// If a bytes.Buffer we can read the underlying byte slice over and
|
||||
// over
|
||||
case *bytes.Buffer:
|
||||
buf := body
|
||||
bodyReader = func() (io.Reader, error) {
|
||||
return bytes.NewReader(buf.Bytes()), nil
|
||||
}
|
||||
contentLength = int64(buf.Len())
|
||||
|
||||
// We prioritize *bytes.Reader here because we don't really want to
|
||||
// deal with it seeking so want it to match here instead of the
|
||||
// io.ReadSeeker case.
|
||||
case *bytes.Reader:
|
||||
buf, err := ioutil.ReadAll(body)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
bodyReader = func() (io.Reader, error) {
|
||||
return bytes.NewReader(buf), nil
|
||||
}
|
||||
contentLength = int64(len(buf))
|
||||
|
||||
// Compat case
|
||||
case io.ReadSeeker:
|
||||
raw := body
|
||||
bodyReader = func() (io.Reader, error) {
|
||||
_, err := raw.Seek(0, 0)
|
||||
return ioutil.NopCloser(raw), err
|
||||
}
|
||||
if lr, ok := raw.(LenReader); ok {
|
||||
contentLength = int64(lr.Len())
|
||||
}
|
||||
|
||||
// Read all in so we can reset
|
||||
case io.Reader:
|
||||
buf, err := ioutil.ReadAll(body)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
bodyReader = func() (io.Reader, error) {
|
||||
return bytes.NewReader(buf), nil
|
||||
}
|
||||
contentLength = int64(len(buf))
|
||||
|
||||
// No body provided, nothing to do
|
||||
case nil:
|
||||
|
||||
// Unrecognized type
|
||||
default:
|
||||
return nil, 0, fmt.Errorf("cannot handle type %T", rawBody)
|
||||
}
|
||||
return bodyReader, contentLength, nil
|
||||
}
|
||||
|
||||
// FromRequest wraps an http.Request in a retryablehttp.Request
|
||||
func FromRequest(r *http.Request) (*Request, error) {
|
||||
bodyReader, _, err := getBodyReaderAndContentLength(r.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Could assert contentLength == r.ContentLength
|
||||
return &Request{bodyReader, r}, nil
|
||||
}
|
||||
|
||||
// NewRequest creates a new wrapped request.
|
||||
func NewRequest(method, url string, rawBody interface{}) (*Request, error) {
|
||||
bodyReader, contentLength, err := getBodyReaderAndContentLength(rawBody)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
httpReq, err := http.NewRequest(method, url, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
httpReq.ContentLength = contentLength
|
||||
|
||||
return &Request{bodyReader, httpReq}, nil
|
||||
}
|
||||
|
||||
// Logger interface allows to use other loggers than
|
||||
// standard log.Logger.
|
||||
type Logger interface {
|
||||
Printf(string, ...interface{})
|
||||
}
|
||||
|
||||
// LeveledLogger interface implements the basic methods that a logger library needs
|
||||
type LeveledLogger interface {
|
||||
Error(string, ...interface{})
|
||||
Info(string, ...interface{})
|
||||
Debug(string, ...interface{})
|
||||
Warn(string, ...interface{})
|
||||
}
|
||||
|
||||
// hookLogger adapts an LeveledLogger to Logger for use by the existing hook functions
|
||||
// without changing the API.
|
||||
type hookLogger struct {
|
||||
LeveledLogger
|
||||
}
|
||||
|
||||
func (h hookLogger) Printf(s string, args ...interface{}) {
|
||||
h.Info(fmt.Sprintf(s, args...))
|
||||
}
|
||||
|
||||
// RequestLogHook allows a function to run before each retry. The HTTP
|
||||
// request which will be made, and the retry number (0 for the initial
|
||||
// request) are available to users. The internal logger is exposed to
|
||||
// consumers.
|
||||
type RequestLogHook func(Logger, *http.Request, int)
|
||||
|
||||
// ResponseLogHook is like RequestLogHook, but allows running a function
|
||||
// on each HTTP response. This function will be invoked at the end of
|
||||
// every HTTP request executed, regardless of whether a subsequent retry
|
||||
// needs to be performed or not. If the response body is read or closed
|
||||
// from this method, this will affect the response returned from Do().
|
||||
type ResponseLogHook func(Logger, *http.Response)
|
||||
|
||||
// CheckRetry specifies a policy for handling retries. It is called
|
||||
// following each request with the response and error values returned by
|
||||
// the http.Client. If CheckRetry returns false, the Client stops retrying
|
||||
// and returns the response to the caller. If CheckRetry returns an error,
|
||||
// that error value is returned in lieu of the error from the request. The
|
||||
// Client will close any response body when retrying, but if the retry is
|
||||
// aborted it is up to the CheckRetry callback to properly close any
|
||||
// response body before returning.
|
||||
type CheckRetry func(ctx context.Context, resp *http.Response, err error) (bool, error)
|
||||
|
||||
// Backoff specifies a policy for how long to wait between retries.
|
||||
// It is called after a failing request to determine the amount of time
|
||||
// that should pass before trying again.
|
||||
type Backoff func(min, max time.Duration, attemptNum int, resp *http.Response) time.Duration
|
||||
|
||||
// ErrorHandler is called if retries are expired, containing the last status
|
||||
// from the http library. If not specified, default behavior for the library is
|
||||
// to close the body and return an error indicating how many tries were
|
||||
// attempted. If overriding this, be sure to close the body if needed.
|
||||
type ErrorHandler func(resp *http.Response, err error, numTries int) (*http.Response, error)
|
||||
|
||||
// Client is used to make HTTP requests. It adds additional functionality
|
||||
// like automatic retries to tolerate minor outages.
|
||||
type Client struct {
|
||||
HTTPClient *http.Client // Internal HTTP client.
|
||||
Logger interface{} // Customer logger instance. Can be either Logger or LeveledLogger
|
||||
|
||||
RetryWaitMin time.Duration // Minimum time to wait
|
||||
RetryWaitMax time.Duration // Maximum time to wait
|
||||
RetryMax int // Maximum number of retries
|
||||
|
||||
// RequestLogHook allows a user-supplied function to be called
|
||||
// before each retry.
|
||||
RequestLogHook RequestLogHook
|
||||
|
||||
// ResponseLogHook allows a user-supplied function to be called
|
||||
// with the response from each HTTP request executed.
|
||||
ResponseLogHook ResponseLogHook
|
||||
|
||||
// CheckRetry specifies the policy for handling retries, and is called
|
||||
// after each request. The default policy is DefaultRetryPolicy.
|
||||
CheckRetry CheckRetry
|
||||
|
||||
// Backoff specifies the policy for how long to wait between retries
|
||||
Backoff Backoff
|
||||
|
||||
// ErrorHandler specifies the custom error handler to use, if any
|
||||
ErrorHandler ErrorHandler
|
||||
|
||||
loggerInit sync.Once
|
||||
}
|
||||
|
||||
// NewClient creates a new Client with default settings.
|
||||
func NewClient() *Client {
|
||||
return &Client{
|
||||
HTTPClient: cleanhttp.DefaultPooledClient(),
|
||||
Logger: defaultLogger,
|
||||
RetryWaitMin: defaultRetryWaitMin,
|
||||
RetryWaitMax: defaultRetryWaitMax,
|
||||
RetryMax: defaultRetryMax,
|
||||
CheckRetry: DefaultRetryPolicy,
|
||||
Backoff: DefaultBackoff,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) logger() interface{} {
|
||||
c.loggerInit.Do(func() {
|
||||
if c.Logger == nil {
|
||||
return
|
||||
}
|
||||
|
||||
switch c.Logger.(type) {
|
||||
case Logger, LeveledLogger:
|
||||
// ok
|
||||
default:
|
||||
// This should happen in dev when they are setting Logger and work on code, not in prod.
|
||||
panic(fmt.Sprintf("invalid logger type passed, must be Logger or LeveledLogger, was %T", c.Logger))
|
||||
}
|
||||
})
|
||||
|
||||
return c.Logger
|
||||
}
|
||||
|
||||
// DefaultRetryPolicy provides a default callback for Client.CheckRetry, which
|
||||
// will retry on connection errors and server errors.
|
||||
func DefaultRetryPolicy(ctx context.Context, resp *http.Response, err error) (bool, error) {
|
||||
// do not retry on context.Canceled or context.DeadlineExceeded
|
||||
if ctx.Err() != nil {
|
||||
return false, ctx.Err()
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
if v, ok := err.(*url.Error); ok {
|
||||
// Don't retry if the error was due to too many redirects.
|
||||
if redirectsErrorRe.MatchString(v.Error()) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// Don't retry if the error was due to an invalid protocol scheme.
|
||||
if schemeErrorRe.MatchString(v.Error()) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// Don't retry if the error was due to TLS cert verification failure.
|
||||
if _, ok := v.Err.(x509.UnknownAuthorityError); ok {
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
|
||||
// The error is likely recoverable so retry.
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// Check the response code. We retry on 500-range responses to allow
|
||||
// the server time to recover, as 500's are typically not permanent
|
||||
// errors and may relate to outages on the server side. This will catch
|
||||
// invalid response codes as well, like 0 and 999.
|
||||
if resp.StatusCode == 0 || (resp.StatusCode >= 500 && resp.StatusCode != 501) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// DefaultBackoff provides a default callback for Client.Backoff which
|
||||
// will perform exponential backoff based on the attempt number and limited
|
||||
// by the provided minimum and maximum durations.
|
||||
func DefaultBackoff(min, max time.Duration, attemptNum int, resp *http.Response) time.Duration {
|
||||
mult := math.Pow(2, float64(attemptNum)) * float64(min)
|
||||
sleep := time.Duration(mult)
|
||||
if float64(sleep) != mult || sleep > max {
|
||||
sleep = max
|
||||
}
|
||||
return sleep
|
||||
}
|
||||
|
||||
// LinearJitterBackoff provides a callback for Client.Backoff which will
|
||||
// perform linear backoff based on the attempt number and with jitter to
|
||||
// prevent a thundering herd.
|
||||
//
|
||||
// min and max here are *not* absolute values. The number to be multiplied by
|
||||
// the attempt number will be chosen at random from between them, thus they are
|
||||
// bounding the jitter.
|
||||
//
|
||||
// For instance:
|
||||
// * To get strictly linear backoff of one second increasing each retry, set
|
||||
// both to one second (1s, 2s, 3s, 4s, ...)
|
||||
// * To get a small amount of jitter centered around one second increasing each
|
||||
// retry, set to around one second, such as a min of 800ms and max of 1200ms
|
||||
// (892ms, 2102ms, 2945ms, 4312ms, ...)
|
||||
// * To get extreme jitter, set to a very wide spread, such as a min of 100ms
|
||||
// and a max of 20s (15382ms, 292ms, 51321ms, 35234ms, ...)
|
||||
func LinearJitterBackoff(min, max time.Duration, attemptNum int, resp *http.Response) time.Duration {
|
||||
// attemptNum always starts at zero but we want to start at 1 for multiplication
|
||||
attemptNum++
|
||||
|
||||
if max <= min {
|
||||
// Unclear what to do here, or they are the same, so return min *
|
||||
// attemptNum
|
||||
return min * time.Duration(attemptNum)
|
||||
}
|
||||
|
||||
// Seed rand; doing this every time is fine
|
||||
rand := rand.New(rand.NewSource(int64(time.Now().Nanosecond())))
|
||||
|
||||
// Pick a random number that lies somewhere between the min and max and
|
||||
// multiply by the attemptNum. attemptNum starts at zero so we always
|
||||
// increment here. We first get a random percentage, then apply that to the
|
||||
// difference between min and max, and add to min.
|
||||
jitter := rand.Float64() * float64(max-min)
|
||||
jitterMin := int64(jitter) + int64(min)
|
||||
return time.Duration(jitterMin * int64(attemptNum))
|
||||
}
|
||||
|
||||
// PassthroughErrorHandler is an ErrorHandler that directly passes through the
|
||||
// values from the net/http library for the final request. The body is not
|
||||
// closed.
|
||||
func PassthroughErrorHandler(resp *http.Response, err error, _ int) (*http.Response, error) {
|
||||
return resp, err
|
||||
}
|
||||
|
||||
// Do wraps calling an HTTP method with retries.
|
||||
func (c *Client) Do(req *Request) (*http.Response, error) {
|
||||
if c.HTTPClient == nil {
|
||||
c.HTTPClient = cleanhttp.DefaultPooledClient()
|
||||
}
|
||||
|
||||
logger := c.logger()
|
||||
|
||||
if logger != nil {
|
||||
switch v := logger.(type) {
|
||||
case Logger:
|
||||
v.Printf("[DEBUG] %s %s", req.Method, req.URL)
|
||||
case LeveledLogger:
|
||||
v.Debug("performing request", "method", req.Method, "url", req.URL)
|
||||
}
|
||||
}
|
||||
|
||||
var resp *http.Response
|
||||
var err error
|
||||
|
||||
for i := 0; ; i++ {
|
||||
var code int // HTTP response code
|
||||
|
||||
// Always rewind the request body when non-nil.
|
||||
if req.body != nil {
|
||||
body, err := req.body()
|
||||
if err != nil {
|
||||
c.HTTPClient.CloseIdleConnections()
|
||||
return resp, err
|
||||
}
|
||||
if c, ok := body.(io.ReadCloser); ok {
|
||||
req.Body = c
|
||||
} else {
|
||||
req.Body = ioutil.NopCloser(body)
|
||||
}
|
||||
}
|
||||
|
||||
if c.RequestLogHook != nil {
|
||||
switch v := logger.(type) {
|
||||
case Logger:
|
||||
c.RequestLogHook(v, req.Request, i)
|
||||
case LeveledLogger:
|
||||
c.RequestLogHook(hookLogger{v}, req.Request, i)
|
||||
default:
|
||||
c.RequestLogHook(nil, req.Request, i)
|
||||
}
|
||||
}
|
||||
|
||||
// Attempt the request
|
||||
resp, err = c.HTTPClient.Do(req.Request)
|
||||
if resp != nil {
|
||||
code = resp.StatusCode
|
||||
}
|
||||
|
||||
// Check if we should continue with retries.
|
||||
checkOK, checkErr := c.CheckRetry(req.Context(), resp, err)
|
||||
|
||||
if err != nil {
|
||||
switch v := logger.(type) {
|
||||
case Logger:
|
||||
v.Printf("[ERR] %s %s request failed: %v", req.Method, req.URL, err)
|
||||
case LeveledLogger:
|
||||
v.Error("request failed", "error", err, "method", req.Method, "url", req.URL)
|
||||
}
|
||||
} else {
|
||||
// Call this here to maintain the behavior of logging all requests,
|
||||
// even if CheckRetry signals to stop.
|
||||
if c.ResponseLogHook != nil {
|
||||
// Call the response logger function if provided.
|
||||
switch v := logger.(type) {
|
||||
case Logger:
|
||||
c.ResponseLogHook(v, resp)
|
||||
case LeveledLogger:
|
||||
c.ResponseLogHook(hookLogger{v}, resp)
|
||||
default:
|
||||
c.ResponseLogHook(nil, resp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now decide if we should continue.
|
||||
if !checkOK {
|
||||
if checkErr != nil {
|
||||
err = checkErr
|
||||
}
|
||||
c.HTTPClient.CloseIdleConnections()
|
||||
return resp, err
|
||||
}
|
||||
|
||||
// We do this before drainBody because there's no need for the I/O if
|
||||
// we're breaking out
|
||||
remain := c.RetryMax - i
|
||||
if remain <= 0 {
|
||||
break
|
||||
}
|
||||
|
||||
// We're going to retry, consume any response to reuse the connection.
|
||||
if err == nil && resp != nil {
|
||||
c.drainBody(resp.Body)
|
||||
}
|
||||
|
||||
wait := c.Backoff(c.RetryWaitMin, c.RetryWaitMax, i, resp)
|
||||
desc := fmt.Sprintf("%s %s", req.Method, req.URL)
|
||||
if code > 0 {
|
||||
desc = fmt.Sprintf("%s (status: %d)", desc, code)
|
||||
}
|
||||
if logger != nil {
|
||||
switch v := logger.(type) {
|
||||
case Logger:
|
||||
v.Printf("[DEBUG] %s: retrying in %s (%d left)", desc, wait, remain)
|
||||
case LeveledLogger:
|
||||
v.Debug("retrying request", "request", desc, "timeout", wait, "remaining", remain)
|
||||
}
|
||||
}
|
||||
select {
|
||||
case <-req.Context().Done():
|
||||
c.HTTPClient.CloseIdleConnections()
|
||||
return nil, req.Context().Err()
|
||||
case <-time.After(wait):
|
||||
}
|
||||
}
|
||||
|
||||
if c.ErrorHandler != nil {
|
||||
c.HTTPClient.CloseIdleConnections()
|
||||
return c.ErrorHandler(resp, err, c.RetryMax+1)
|
||||
}
|
||||
|
||||
// By default, we close the response body and return an error without
|
||||
// returning the response
|
||||
if resp != nil {
|
||||
resp.Body.Close()
|
||||
}
|
||||
c.HTTPClient.CloseIdleConnections()
|
||||
return nil, fmt.Errorf("%s %s giving up after %d attempts",
|
||||
req.Method, req.URL, c.RetryMax+1)
|
||||
}
|
||||
|
||||
// Try to read the response body so we can reuse this connection.
|
||||
func (c *Client) drainBody(body io.ReadCloser) {
|
||||
defer body.Close()
|
||||
_, err := io.Copy(ioutil.Discard, io.LimitReader(body, respReadLimit))
|
||||
if err != nil {
|
||||
if c.logger() != nil {
|
||||
switch v := c.logger().(type) {
|
||||
case Logger:
|
||||
v.Printf("[ERR] error reading response body: %v", err)
|
||||
case LeveledLogger:
|
||||
v.Error("error reading response body", "error", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get is a shortcut for doing a GET request without making a new client.
|
||||
func Get(url string) (*http.Response, error) {
|
||||
return defaultClient.Get(url)
|
||||
}
|
||||
|
||||
// Get is a convenience helper for doing simple GET requests.
|
||||
func (c *Client) Get(url string) (*http.Response, error) {
|
||||
req, err := NewRequest("GET", url, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c.Do(req)
|
||||
}
|
||||
|
||||
// Head is a shortcut for doing a HEAD request without making a new client.
|
||||
func Head(url string) (*http.Response, error) {
|
||||
return defaultClient.Head(url)
|
||||
}
|
||||
|
||||
// Head is a convenience method for doing simple HEAD requests.
|
||||
func (c *Client) Head(url string) (*http.Response, error) {
|
||||
req, err := NewRequest("HEAD", url, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c.Do(req)
|
||||
}
|
||||
|
||||
// Post is a shortcut for doing a POST request without making a new client.
|
||||
func Post(url, bodyType string, body interface{}) (*http.Response, error) {
|
||||
return defaultClient.Post(url, bodyType, body)
|
||||
}
|
||||
|
||||
// Post is a convenience method for doing simple POST requests.
|
||||
func (c *Client) Post(url, bodyType string, body interface{}) (*http.Response, error) {
|
||||
req, err := NewRequest("POST", url, body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Header.Set("Content-Type", bodyType)
|
||||
return c.Do(req)
|
||||
}
|
||||
|
||||
// PostForm is a shortcut to perform a POST with form data without creating
|
||||
// a new client.
|
||||
func PostForm(url string, data url.Values) (*http.Response, error) {
|
||||
return defaultClient.PostForm(url, data)
|
||||
}
|
||||
|
||||
// PostForm is a convenience method for doing simple POST operations using
|
||||
// pre-filled url.Values form data.
|
||||
func (c *Client) PostForm(url string, data url.Values) (*http.Response, error) {
|
||||
return c.Post(url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode()))
|
||||
}
|
||||
|
||||
// StandardClient returns a stdlib *http.Client with a custom Transport, which
|
||||
// shims in a *retryablehttp.Client for added retries.
|
||||
func (c *Client) StandardClient() *http.Client {
|
||||
return &http.Client{
|
||||
Transport: &RoundTripper{Client: c},
|
||||
}
|
||||
}
|
8
vendor/github.com/hashicorp/go-retryablehttp/go.mod
generated
vendored
Normal file
8
vendor/github.com/hashicorp/go-retryablehttp/go.mod
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
module github.com/hashicorp/go-retryablehttp
|
||||
|
||||
require (
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1
|
||||
github.com/hashicorp/go-hclog v0.9.2
|
||||
)
|
||||
|
||||
go 1.13
|
10
vendor/github.com/hashicorp/go-retryablehttp/go.sum
generated
vendored
Normal file
10
vendor/github.com/hashicorp/go-retryablehttp/go.sum
generated
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxCsHI=
|
||||
github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
43
vendor/github.com/hashicorp/go-retryablehttp/roundtripper.go
generated
vendored
Normal file
43
vendor/github.com/hashicorp/go-retryablehttp/roundtripper.go
generated
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
package retryablehttp
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// RoundTripper implements the http.RoundTripper interface, using a retrying
|
||||
// HTTP client to execute requests.
|
||||
//
|
||||
// It is important to note that retryablehttp doesn't always act exactly as a
|
||||
// RoundTripper should. This is highly dependent on the retryable client's
|
||||
// configuration.
|
||||
type RoundTripper struct {
|
||||
// The client to use during requests. If nil, the default retryablehttp
|
||||
// client and settings will be used.
|
||||
Client *Client
|
||||
|
||||
// once ensures that the logic to initialize the default client runs at
|
||||
// most once, in a single thread.
|
||||
once sync.Once
|
||||
}
|
||||
|
||||
// init initializes the underlying retryable client.
|
||||
func (rt *RoundTripper) init() {
|
||||
if rt.Client == nil {
|
||||
rt.Client = NewClient()
|
||||
}
|
||||
}
|
||||
|
||||
// RoundTrip satisfies the http.RoundTripper interface.
|
||||
func (rt *RoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
rt.once.Do(rt.init)
|
||||
|
||||
// Convert the request to be retryable.
|
||||
retryableReq, err := FromRequest(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Execute the request.
|
||||
return rt.Client.Do(retryableReq)
|
||||
}
|
12
vendor/github.com/hashicorp/go-rootcerts/.travis.yml
generated
vendored
Normal file
12
vendor/github.com/hashicorp/go-rootcerts/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
sudo: false
|
||||
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.6
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
|
||||
script: make test
|
363
vendor/github.com/hashicorp/go-rootcerts/LICENSE
generated
vendored
Normal file
363
vendor/github.com/hashicorp/go-rootcerts/LICENSE
generated
vendored
Normal file
@ -0,0 +1,363 @@
|
||||
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
Normal file
8
vendor/github.com/hashicorp/go-rootcerts/Makefile
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
TEST?=./...
|
||||
|
||||
test:
|
||||
go test $(TEST) $(TESTARGS) -timeout=3s -parallel=4
|
||||
go vet $(TEST)
|
||||
go test $(TEST) -race
|
||||
|
||||
.PHONY: test
|
44
vendor/github.com/hashicorp/go-rootcerts/README.md
generated
vendored
Normal file
44
vendor/github.com/hashicorp/go-rootcerts/README.md
generated
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
# 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"),
|
||||
Certificate: os.Getenv("MYAPP_CERTIFICATE"),
|
||||
})
|
||||
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
Normal file
9
vendor/github.com/hashicorp/go-rootcerts/doc.go
generated
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
// 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
|
5
vendor/github.com/hashicorp/go-rootcerts/go.mod
generated
vendored
Normal file
5
vendor/github.com/hashicorp/go-rootcerts/go.mod
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
module github.com/hashicorp/go-rootcerts
|
||||
|
||||
go 1.12
|
||||
|
||||
require github.com/mitchellh/go-homedir v1.1.0
|
2
vendor/github.com/hashicorp/go-rootcerts/go.sum
generated
vendored
Normal file
2
vendor/github.com/hashicorp/go-rootcerts/go.sum
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
123
vendor/github.com/hashicorp/go-rootcerts/rootcerts.go
generated
vendored
Normal file
123
vendor/github.com/hashicorp/go-rootcerts/rootcerts.go
generated
vendored
Normal file
@ -0,0 +1,123 @@
|
||||
package rootcerts
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// Config determines where LoadCACerts will load certificates from. When CAFile,
|
||||
// CACertificate 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 CACertificate and CAPath.
|
||||
CAFile string
|
||||
|
||||
// CACertificate is a PEM-encoded certificate or bundle. Takes precedence
|
||||
// over CAPath.
|
||||
CACertificate []byte
|
||||
|
||||
// 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 len(c.CACertificate) != 0 {
|
||||
return AppendCertificate(c.CACertificate)
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
// AppendCertificate appends an in-memory PEM-encoded certificate or bundle and returns a pool.
|
||||
func AppendCertificate(ca []byte) (*x509.CertPool, error) {
|
||||
pool := x509.NewCertPool()
|
||||
|
||||
ok := pool.AppendCertsFromPEM(ca)
|
||||
if !ok {
|
||||
return nil, errors.New("Error appending CA: Couldn't parse PEM")
|
||||
}
|
||||
|
||||
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
Normal file
12
vendor/github.com/hashicorp/go-rootcerts/rootcerts_base.go
generated
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
// +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
Normal file
48
vendor/github.com/hashicorp/go-rootcerts/rootcerts_darwin.go
generated
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
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
|
||||
}
|
26
vendor/github.com/hashicorp/go-sockaddr/.gitignore
generated
vendored
Normal file
26
vendor/github.com/hashicorp/go-sockaddr/.gitignore
generated
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
# 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
|
||||
*.prof
|
||||
.cover.out*
|
||||
coverage.html
|
65
vendor/github.com/hashicorp/go-sockaddr/GNUmakefile
generated
vendored
Normal file
65
vendor/github.com/hashicorp/go-sockaddr/GNUmakefile
generated
vendored
Normal file
@ -0,0 +1,65 @@
|
||||
TOOLS= golang.org/x/tools/cover
|
||||
GOCOVER_TMPFILE?= $(GOCOVER_FILE).tmp
|
||||
GOCOVER_FILE?= .cover.out
|
||||
GOCOVERHTML?= coverage.html
|
||||
FIND=`/usr/bin/which 2> /dev/null gfind find | /usr/bin/grep -v ^no | /usr/bin/head -n 1`
|
||||
XARGS=`/usr/bin/which 2> /dev/null gxargs xargs | /usr/bin/grep -v ^no | /usr/bin/head -n 1`
|
||||
|
||||
test:: $(GOCOVER_FILE)
|
||||
@$(MAKE) -C cmd/sockaddr test
|
||||
|
||||
cover:: coverage_report
|
||||
|
||||
$(GOCOVER_FILE)::
|
||||
@${FIND} . -type d ! -path '*cmd*' ! -path '*.git*' -print0 | ${XARGS} -0 -I % sh -ec "cd % && rm -f $(GOCOVER_TMPFILE) && go test -coverprofile=$(GOCOVER_TMPFILE)"
|
||||
|
||||
@echo 'mode: set' > $(GOCOVER_FILE)
|
||||
@${FIND} . -type f ! -path '*cmd*' ! -path '*.git*' -name "$(GOCOVER_TMPFILE)" -print0 | ${XARGS} -0 -n1 cat $(GOCOVER_TMPFILE) | grep -v '^mode: ' >> ${PWD}/$(GOCOVER_FILE)
|
||||
|
||||
$(GOCOVERHTML): $(GOCOVER_FILE)
|
||||
go tool cover -html=$(GOCOVER_FILE) -o $(GOCOVERHTML)
|
||||
|
||||
coverage_report:: $(GOCOVER_FILE)
|
||||
go tool cover -html=$(GOCOVER_FILE)
|
||||
|
||||
audit_tools::
|
||||
@go get -u github.com/golang/lint/golint && echo "Installed golint:"
|
||||
@go get -u github.com/fzipp/gocyclo && echo "Installed gocyclo:"
|
||||
@go get -u github.com/remyoudompheng/go-misc/deadcode && echo "Installed deadcode:"
|
||||
@go get -u github.com/client9/misspell/cmd/misspell && echo "Installed misspell:"
|
||||
@go get -u github.com/gordonklaus/ineffassign && echo "Installed ineffassign:"
|
||||
|
||||
audit::
|
||||
deadcode
|
||||
go tool vet -all *.go
|
||||
go tool vet -shadow=true *.go
|
||||
golint *.go
|
||||
ineffassign .
|
||||
gocyclo -over 65 *.go
|
||||
misspell *.go
|
||||
|
||||
clean::
|
||||
rm -f $(GOCOVER_FILE) $(GOCOVERHTML)
|
||||
|
||||
dev::
|
||||
@go build
|
||||
@$(MAKE) -B -C cmd/sockaddr sockaddr
|
||||
|
||||
install::
|
||||
@go install
|
||||
@$(MAKE) -C cmd/sockaddr install
|
||||
|
||||
doc::
|
||||
@echo Visit: http://127.0.0.1:6161/pkg/github.com/hashicorp/go-sockaddr/
|
||||
godoc -http=:6161 -goroot $GOROOT
|
||||
|
||||
world::
|
||||
@set -e; \
|
||||
for os in solaris darwin freebsd linux windows android; do \
|
||||
for arch in amd64; do \
|
||||
printf "Building on %s-%s\n" "$${os}" "$${arch}" ; \
|
||||
env GOOS="$${os}" GOARCH="$${arch}" go build -o /dev/null; \
|
||||
done; \
|
||||
done
|
||||
|
||||
$(MAKE) -C cmd/sockaddr world
|
373
vendor/github.com/hashicorp/go-sockaddr/LICENSE
generated
vendored
Normal file
373
vendor/github.com/hashicorp/go-sockaddr/LICENSE
generated
vendored
Normal file
@ -0,0 +1,373 @@
|
||||
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.
|
118
vendor/github.com/hashicorp/go-sockaddr/README.md
generated
vendored
Normal file
118
vendor/github.com/hashicorp/go-sockaddr/README.md
generated
vendored
Normal file
@ -0,0 +1,118 @@
|
||||
# go-sockaddr
|
||||
|
||||
## `sockaddr` Library
|
||||
|
||||
Socket address convenience functions for Go. `go-sockaddr` is a convenience
|
||||
library that makes doing the right thing with IP addresses easy. `go-sockaddr`
|
||||
is loosely modeled after the UNIX `sockaddr_t` and creates a union of the family
|
||||
of `sockaddr_t` types (see below for an ascii diagram). Library documentation
|
||||
is available
|
||||
at
|
||||
[https://godoc.org/github.com/hashicorp/go-sockaddr](https://godoc.org/github.com/hashicorp/go-sockaddr).
|
||||
The primary intent of the library was to make it possible to define heuristics
|
||||
for selecting the correct IP addresses when a configuration is evaluated at
|
||||
runtime. See
|
||||
the
|
||||
[docs](https://godoc.org/github.com/hashicorp/go-sockaddr),
|
||||
[`template` package](https://godoc.org/github.com/hashicorp/go-sockaddr/template),
|
||||
tests,
|
||||
and
|
||||
[CLI utility](https://github.com/hashicorp/go-sockaddr/tree/master/cmd/sockaddr)
|
||||
for details and hints as to how to use this library.
|
||||
|
||||
For example, with this library it is possible to find an IP address that:
|
||||
|
||||
* is attached to a default route
|
||||
([`GetDefaultInterfaces()`](https://godoc.org/github.com/hashicorp/go-sockaddr#GetDefaultInterfaces))
|
||||
* is contained within a CIDR block ([`IfByNetwork()`](https://godoc.org/github.com/hashicorp/go-sockaddr#IfByNetwork))
|
||||
* is an RFC1918 address
|
||||
([`IfByRFC("1918")`](https://godoc.org/github.com/hashicorp/go-sockaddr#IfByRFC))
|
||||
* is ordered
|
||||
([`OrderedIfAddrBy(args)`](https://godoc.org/github.com/hashicorp/go-sockaddr#OrderedIfAddrBy) where
|
||||
`args` includes, but is not limited
|
||||
to,
|
||||
[`AscIfType`](https://godoc.org/github.com/hashicorp/go-sockaddr#AscIfType),
|
||||
[`AscNetworkSize`](https://godoc.org/github.com/hashicorp/go-sockaddr#AscNetworkSize))
|
||||
* excludes all IPv6 addresses
|
||||
([`IfByType("^(IPv4)$")`](https://godoc.org/github.com/hashicorp/go-sockaddr#IfByType))
|
||||
* is larger than a `/32`
|
||||
([`IfByMaskSize(32)`](https://godoc.org/github.com/hashicorp/go-sockaddr#IfByMaskSize))
|
||||
* is not on a `down` interface
|
||||
([`ExcludeIfs("flags", "down")`](https://godoc.org/github.com/hashicorp/go-sockaddr#ExcludeIfs))
|
||||
* preferences an IPv6 address over an IPv4 address
|
||||
([`SortIfByType()`](https://godoc.org/github.com/hashicorp/go-sockaddr#SortIfByType) +
|
||||
[`ReverseIfAddrs()`](https://godoc.org/github.com/hashicorp/go-sockaddr#ReverseIfAddrs)); and
|
||||
* excludes any IP in RFC6890 address
|
||||
([`IfByRFC("6890")`](https://godoc.org/github.com/hashicorp/go-sockaddr#IfByRFC))
|
||||
|
||||
Or any combination or variation therein.
|
||||
|
||||
There are also a few simple helper functions such as `GetPublicIP` and
|
||||
`GetPrivateIP` which both return strings and select the first public or private
|
||||
IP address on the default interface, respectively. Similarly, there is also a
|
||||
helper function called `GetInterfaceIP` which returns the first usable IP
|
||||
address on the named interface.
|
||||
|
||||
## `sockaddr` CLI
|
||||
|
||||
Given the possible complexity of the `sockaddr` library, there is a CLI utility
|
||||
that accompanies the library, also
|
||||
called
|
||||
[`sockaddr`](https://github.com/hashicorp/go-sockaddr/tree/master/cmd/sockaddr).
|
||||
The
|
||||
[`sockaddr`](https://github.com/hashicorp/go-sockaddr/tree/master/cmd/sockaddr)
|
||||
utility exposes nearly all of the functionality of the library and can be used
|
||||
either as an administrative tool or testing tool. To install
|
||||
the
|
||||
[`sockaddr`](https://github.com/hashicorp/go-sockaddr/tree/master/cmd/sockaddr),
|
||||
run:
|
||||
|
||||
```text
|
||||
$ go get -u github.com/hashicorp/go-sockaddr/cmd/sockaddr
|
||||
```
|
||||
|
||||
If you're familiar with UNIX's `sockaddr` struct's, the following diagram
|
||||
mapping the C `sockaddr` (top) to `go-sockaddr` structs (bottom) and
|
||||
interfaces will be helpful:
|
||||
|
||||
```
|
||||
+-------------------------------------------------------+
|
||||
| |
|
||||
| sockaddr |
|
||||
| SockAddr |
|
||||
| |
|
||||
| +--------------+ +----------------------------------+ |
|
||||
| | sockaddr_un | | | |
|
||||
| | SockAddrUnix | | sockaddr_in{,6} | |
|
||||
| +--------------+ | IPAddr | |
|
||||
| | | |
|
||||
| | +-------------+ +--------------+ | |
|
||||
| | | sockaddr_in | | sockaddr_in6 | | |
|
||||
| | | IPv4Addr | | IPv6Addr | | |
|
||||
| | +-------------+ +--------------+ | |
|
||||
| | | |
|
||||
| +----------------------------------+ |
|
||||
| |
|
||||
+-------------------------------------------------------+
|
||||
```
|
||||
|
||||
## Inspiration and Design
|
||||
|
||||
There were many subtle inspirations that led to this design, but the most direct
|
||||
inspiration for the filtering syntax was
|
||||
OpenBSD's
|
||||
[`pf.conf(5)`](https://www.freebsd.org/cgi/man.cgi?query=pf.conf&apropos=0&sektion=0&arch=default&format=html#PARAMETERS) firewall
|
||||
syntax that lets you select the first IP address on a given named interface.
|
||||
The original problem stemmed from:
|
||||
|
||||
* needing to create immutable images using [Packer](https://www.packer.io) that
|
||||
ran the [Consul](https://www.consul.io) process (Consul can only use one IP
|
||||
address at a time);
|
||||
* images that may or may not have multiple interfaces or IP addresses at
|
||||
runtime; and
|
||||
* we didn't want to rely on configuration management to render out the correct
|
||||
IP address if the VM image was being used in an auto-scaling group.
|
||||
|
||||
Instead we needed some way to codify a heuristic that would correctly select the
|
||||
right IP address but the input parameters were not known when the image was
|
||||
created.
|
5
vendor/github.com/hashicorp/go-sockaddr/doc.go
generated
vendored
Normal file
5
vendor/github.com/hashicorp/go-sockaddr/doc.go
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
/*
|
||||
Package sockaddr is a Go implementation of the UNIX socket family data types and
|
||||
related helper functions.
|
||||
*/
|
||||
package sockaddr
|
8
vendor/github.com/hashicorp/go-sockaddr/go.mod
generated
vendored
Normal file
8
vendor/github.com/hashicorp/go-sockaddr/go.mod
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
module github.com/hashicorp/go-sockaddr
|
||||
|
||||
require (
|
||||
github.com/hashicorp/errwrap v1.0.0
|
||||
github.com/mitchellh/cli v1.0.0
|
||||
github.com/mitchellh/go-wordwrap v1.0.0
|
||||
github.com/ryanuber/columnize v2.1.0+incompatible
|
||||
)
|
24
vendor/github.com/hashicorp/go-sockaddr/go.sum
generated
vendored
Normal file
24
vendor/github.com/hashicorp/go-sockaddr/go.sum
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310 h1:BUAU3CGlLvorLI26FmByPp2eC2qla6E1Tw+scpcg/to=
|
||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY=
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o=
|
||||
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
||||
github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-isatty v0.0.3 h1:ns/ykhmWi7G9O+8a448SecJU3nSMBXJfqQkl0upE1jI=
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mitchellh/cli v1.0.0 h1:iGBIsUe3+HZ/AD/Vd7DErOt5sU9fa8Uj7A2s1aggv1Y=
|
||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||
github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4=
|
||||
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
|
||||
github.com/posener/complete v1.1.1 h1:ccV59UEOTzVDnDUEFdT95ZzHVZ+5+158q8+SJb2QV5w=
|
||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||
github.com/ryanuber/columnize v2.1.0+incompatible h1:j1Wcmh8OrK4Q7GXY+V7SVSY8nUWQxHW5TkBe7YUl+2s=
|
||||
github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc h1:MeuS1UDyZyFH++6vVy44PuufTeFF0d0nfI6XB87YGSk=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
254
vendor/github.com/hashicorp/go-sockaddr/ifaddr.go
generated
vendored
Normal file
254
vendor/github.com/hashicorp/go-sockaddr/ifaddr.go
generated
vendored
Normal file
@ -0,0 +1,254 @@
|
||||
package sockaddr
|
||||
|
||||
import "strings"
|
||||
|
||||
// ifAddrAttrMap is a map of the IfAddr type-specific attributes.
|
||||
var ifAddrAttrMap map[AttrName]func(IfAddr) string
|
||||
var ifAddrAttrs []AttrName
|
||||
|
||||
func init() {
|
||||
ifAddrAttrInit()
|
||||
}
|
||||
|
||||
// GetPrivateIP returns a string with a single IP address that is part of RFC
|
||||
// 6890 and has a default route. If the system can't determine its IP address
|
||||
// or find an RFC 6890 IP address, an empty string will be returned instead.
|
||||
// This function is the `eval` equivalent of:
|
||||
//
|
||||
// ```
|
||||
// $ sockaddr eval -r '{{GetPrivateInterfaces | attr "address"}}'
|
||||
/// ```
|
||||
func GetPrivateIP() (string, error) {
|
||||
privateIfs, err := GetPrivateInterfaces()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(privateIfs) < 1 {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
ifAddr := privateIfs[0]
|
||||
ip := *ToIPAddr(ifAddr.SockAddr)
|
||||
return ip.NetIP().String(), nil
|
||||
}
|
||||
|
||||
// GetPrivateIPs returns a string with all IP addresses that are part of RFC
|
||||
// 6890 (regardless of whether or not there is a default route, unlike
|
||||
// GetPublicIP). If the system can't find any RFC 6890 IP addresses, an empty
|
||||
// string will be returned instead. This function is the `eval` equivalent of:
|
||||
//
|
||||
// ```
|
||||
// $ sockaddr eval -r '{{GetAllInterfaces | include "RFC" "6890" | join "address" " "}}'
|
||||
/// ```
|
||||
func GetPrivateIPs() (string, error) {
|
||||
ifAddrs, err := GetAllInterfaces()
|
||||
if err != nil {
|
||||
return "", err
|
||||
} else if len(ifAddrs) < 1 {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
ifAddrs, _ = FilterIfByType(ifAddrs, TypeIP)
|
||||
if len(ifAddrs) == 0 {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
OrderedIfAddrBy(AscIfType, AscIfNetworkSize).Sort(ifAddrs)
|
||||
|
||||
ifAddrs, _, err = IfByRFC("6890", ifAddrs)
|
||||
if err != nil {
|
||||
return "", err
|
||||
} else if len(ifAddrs) == 0 {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
_, ifAddrs, err = IfByRFC(ForwardingBlacklistRFC, ifAddrs)
|
||||
if err != nil {
|
||||
return "", err
|
||||
} else if len(ifAddrs) == 0 {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
ips := make([]string, 0, len(ifAddrs))
|
||||
for _, ifAddr := range ifAddrs {
|
||||
ip := *ToIPAddr(ifAddr.SockAddr)
|
||||
s := ip.NetIP().String()
|
||||
ips = append(ips, s)
|
||||
}
|
||||
|
||||
return strings.Join(ips, " "), nil
|
||||
}
|
||||
|
||||
// GetPublicIP returns a string with a single IP address that is NOT part of RFC
|
||||
// 6890 and has a default route. If the system can't determine its IP address
|
||||
// or find a non RFC 6890 IP address, an empty string will be returned instead.
|
||||
// This function is the `eval` equivalent of:
|
||||
//
|
||||
// ```
|
||||
// $ sockaddr eval -r '{{GetPublicInterfaces | attr "address"}}'
|
||||
/// ```
|
||||
func GetPublicIP() (string, error) {
|
||||
publicIfs, err := GetPublicInterfaces()
|
||||
if err != nil {
|
||||
return "", err
|
||||
} else if len(publicIfs) < 1 {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
ifAddr := publicIfs[0]
|
||||
ip := *ToIPAddr(ifAddr.SockAddr)
|
||||
return ip.NetIP().String(), nil
|
||||
}
|
||||
|
||||
// GetPublicIPs returns a string with all IP addresses that are NOT part of RFC
|
||||
// 6890 (regardless of whether or not there is a default route, unlike
|
||||
// GetPublicIP). If the system can't find any non RFC 6890 IP addresses, an
|
||||
// empty string will be returned instead. This function is the `eval`
|
||||
// equivalent of:
|
||||
//
|
||||
// ```
|
||||
// $ sockaddr eval -r '{{GetAllInterfaces | exclude "RFC" "6890" | join "address" " "}}'
|
||||
/// ```
|
||||
func GetPublicIPs() (string, error) {
|
||||
ifAddrs, err := GetAllInterfaces()
|
||||
if err != nil {
|
||||
return "", err
|
||||
} else if len(ifAddrs) < 1 {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
ifAddrs, _ = FilterIfByType(ifAddrs, TypeIP)
|
||||
if len(ifAddrs) == 0 {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
OrderedIfAddrBy(AscIfType, AscIfNetworkSize).Sort(ifAddrs)
|
||||
|
||||
_, ifAddrs, err = IfByRFC("6890", ifAddrs)
|
||||
if err != nil {
|
||||
return "", err
|
||||
} else if len(ifAddrs) == 0 {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
ips := make([]string, 0, len(ifAddrs))
|
||||
for _, ifAddr := range ifAddrs {
|
||||
ip := *ToIPAddr(ifAddr.SockAddr)
|
||||
s := ip.NetIP().String()
|
||||
ips = append(ips, s)
|
||||
}
|
||||
|
||||
return strings.Join(ips, " "), nil
|
||||
}
|
||||
|
||||
// GetInterfaceIP returns a string with a single IP address sorted by the size
|
||||
// of the network (i.e. IP addresses with a smaller netmask, larger network
|
||||
// size, are sorted first). This function is the `eval` equivalent of:
|
||||
//
|
||||
// ```
|
||||
// $ sockaddr eval -r '{{GetAllInterfaces | include "name" <<ARG>> | sort "type,size" | include "flag" "forwardable" | attr "address" }}'
|
||||
/// ```
|
||||
func GetInterfaceIP(namedIfRE string) (string, error) {
|
||||
ifAddrs, err := GetAllInterfaces()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
ifAddrs, _, err = IfByName(namedIfRE, ifAddrs)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
ifAddrs, _, err = IfByFlag("forwardable", ifAddrs)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
ifAddrs, err = SortIfBy("+type,+size", ifAddrs)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if len(ifAddrs) == 0 {
|
||||
return "", err
|
||||
}
|
||||
|
||||
ip := ToIPAddr(ifAddrs[0].SockAddr)
|
||||
if ip == nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return IPAddrAttr(*ip, "address"), nil
|
||||
}
|
||||
|
||||
// GetInterfaceIPs returns a string with all IPs, sorted by the size of the
|
||||
// network (i.e. IP addresses with a smaller netmask, larger network size, are
|
||||
// sorted first), on a named interface. This function is the `eval` equivalent
|
||||
// of:
|
||||
//
|
||||
// ```
|
||||
// $ sockaddr eval -r '{{GetAllInterfaces | include "name" <<ARG>> | sort "type,size" | join "address" " "}}'
|
||||
/// ```
|
||||
func GetInterfaceIPs(namedIfRE string) (string, error) {
|
||||
ifAddrs, err := GetAllInterfaces()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
ifAddrs, _, err = IfByName(namedIfRE, ifAddrs)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
ifAddrs, err = SortIfBy("+type,+size", ifAddrs)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if len(ifAddrs) == 0 {
|
||||
return "", err
|
||||
}
|
||||
|
||||
ips := make([]string, 0, len(ifAddrs))
|
||||
for _, ifAddr := range ifAddrs {
|
||||
ip := *ToIPAddr(ifAddr.SockAddr)
|
||||
s := ip.NetIP().String()
|
||||
ips = append(ips, s)
|
||||
}
|
||||
|
||||
return strings.Join(ips, " "), nil
|
||||
}
|
||||
|
||||
// IfAddrAttrs returns a list of attributes supported by the IfAddr type
|
||||
func IfAddrAttrs() []AttrName {
|
||||
return ifAddrAttrs
|
||||
}
|
||||
|
||||
// IfAddrAttr returns a string representation of an attribute for the given
|
||||
// IfAddr.
|
||||
func IfAddrAttr(ifAddr IfAddr, attrName AttrName) string {
|
||||
fn, found := ifAddrAttrMap[attrName]
|
||||
if !found {
|
||||
return ""
|
||||
}
|
||||
|
||||
return fn(ifAddr)
|
||||
}
|
||||
|
||||
// ifAddrAttrInit is called once at init()
|
||||
func ifAddrAttrInit() {
|
||||
// Sorted for human readability
|
||||
ifAddrAttrs = []AttrName{
|
||||
"flags",
|
||||
"name",
|
||||
}
|
||||
|
||||
ifAddrAttrMap = map[AttrName]func(ifAddr IfAddr) string{
|
||||
"flags": func(ifAddr IfAddr) string {
|
||||
return ifAddr.Interface.Flags.String()
|
||||
},
|
||||
"name": func(ifAddr IfAddr) string {
|
||||
return ifAddr.Interface.Name
|
||||
},
|
||||
}
|
||||
}
|
1304
vendor/github.com/hashicorp/go-sockaddr/ifaddrs.go
generated
vendored
Normal file
1304
vendor/github.com/hashicorp/go-sockaddr/ifaddrs.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
65
vendor/github.com/hashicorp/go-sockaddr/ifattr.go
generated
vendored
Normal file
65
vendor/github.com/hashicorp/go-sockaddr/ifattr.go
generated
vendored
Normal file
@ -0,0 +1,65 @@
|
||||
package sockaddr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
)
|
||||
|
||||
// IfAddr is a union of a SockAddr and a net.Interface.
|
||||
type IfAddr struct {
|
||||
SockAddr
|
||||
net.Interface
|
||||
}
|
||||
|
||||
// Attr returns the named attribute as a string
|
||||
func (ifAddr IfAddr) Attr(attrName AttrName) (string, error) {
|
||||
val := IfAddrAttr(ifAddr, attrName)
|
||||
if val != "" {
|
||||
return val, nil
|
||||
}
|
||||
|
||||
return Attr(ifAddr.SockAddr, attrName)
|
||||
}
|
||||
|
||||
// Attr returns the named attribute as a string
|
||||
func Attr(sa SockAddr, attrName AttrName) (string, error) {
|
||||
switch sockType := sa.Type(); {
|
||||
case sockType&TypeIP != 0:
|
||||
ip := *ToIPAddr(sa)
|
||||
attrVal := IPAddrAttr(ip, attrName)
|
||||
if attrVal != "" {
|
||||
return attrVal, nil
|
||||
}
|
||||
|
||||
if sockType == TypeIPv4 {
|
||||
ipv4 := *ToIPv4Addr(sa)
|
||||
attrVal := IPv4AddrAttr(ipv4, attrName)
|
||||
if attrVal != "" {
|
||||
return attrVal, nil
|
||||
}
|
||||
} else if sockType == TypeIPv6 {
|
||||
ipv6 := *ToIPv6Addr(sa)
|
||||
attrVal := IPv6AddrAttr(ipv6, attrName)
|
||||
if attrVal != "" {
|
||||
return attrVal, nil
|
||||
}
|
||||
}
|
||||
|
||||
case sockType == TypeUnix:
|
||||
us := *ToUnixSock(sa)
|
||||
attrVal := UnixSockAttr(us, attrName)
|
||||
if attrVal != "" {
|
||||
return attrVal, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Non type-specific attributes
|
||||
switch attrName {
|
||||
case "string":
|
||||
return sa.String(), nil
|
||||
case "type":
|
||||
return sa.Type().String(), nil
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("unsupported attribute name %q", attrName)
|
||||
}
|
169
vendor/github.com/hashicorp/go-sockaddr/ipaddr.go
generated
vendored
Normal file
169
vendor/github.com/hashicorp/go-sockaddr/ipaddr.go
generated
vendored
Normal file
@ -0,0 +1,169 @@
|
||||
package sockaddr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
"net"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Constants for the sizes of IPv3, IPv4, and IPv6 address types.
|
||||
const (
|
||||
IPv3len = 6
|
||||
IPv4len = 4
|
||||
IPv6len = 16
|
||||
)
|
||||
|
||||
// IPAddr is a generic IP address interface for IPv4 and IPv6 addresses,
|
||||
// networks, and socket endpoints.
|
||||
type IPAddr interface {
|
||||
SockAddr
|
||||
AddressBinString() string
|
||||
AddressHexString() string
|
||||
Cmp(SockAddr) int
|
||||
CmpAddress(SockAddr) int
|
||||
CmpPort(SockAddr) int
|
||||
FirstUsable() IPAddr
|
||||
Host() IPAddr
|
||||
IPPort() IPPort
|
||||
LastUsable() IPAddr
|
||||
Maskbits() int
|
||||
NetIP() *net.IP
|
||||
NetIPMask() *net.IPMask
|
||||
NetIPNet() *net.IPNet
|
||||
Network() IPAddr
|
||||
Octets() []int
|
||||
}
|
||||
|
||||
// IPPort is the type for an IP port number for the TCP and UDP IP transports.
|
||||
type IPPort uint16
|
||||
|
||||
// IPPrefixLen is a typed integer representing the prefix length for a given
|
||||
// IPAddr.
|
||||
type IPPrefixLen byte
|
||||
|
||||
// ipAddrAttrMap is a map of the IPAddr type-specific attributes.
|
||||
var ipAddrAttrMap map[AttrName]func(IPAddr) string
|
||||
var ipAddrAttrs []AttrName
|
||||
|
||||
func init() {
|
||||
ipAddrInit()
|
||||
}
|
||||
|
||||
// NewIPAddr creates a new IPAddr from a string. Returns nil if the string is
|
||||
// not an IPv4 or an IPv6 address.
|
||||
func NewIPAddr(addr string) (IPAddr, error) {
|
||||
ipv4Addr, err := NewIPv4Addr(addr)
|
||||
if err == nil {
|
||||
return ipv4Addr, nil
|
||||
}
|
||||
|
||||
ipv6Addr, err := NewIPv6Addr(addr)
|
||||
if err == nil {
|
||||
return ipv6Addr, nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("invalid IPAddr %v", addr)
|
||||
}
|
||||
|
||||
// IPAddrAttr returns a string representation of an attribute for the given
|
||||
// IPAddr.
|
||||
func IPAddrAttr(ip IPAddr, selector AttrName) string {
|
||||
fn, found := ipAddrAttrMap[selector]
|
||||
if !found {
|
||||
return ""
|
||||
}
|
||||
|
||||
return fn(ip)
|
||||
}
|
||||
|
||||
// IPAttrs returns a list of attributes supported by the IPAddr type
|
||||
func IPAttrs() []AttrName {
|
||||
return ipAddrAttrs
|
||||
}
|
||||
|
||||
// MustIPAddr is a helper method that must return an IPAddr or panic on invalid
|
||||
// input.
|
||||
func MustIPAddr(addr string) IPAddr {
|
||||
ip, err := NewIPAddr(addr)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Unable to create an IPAddr from %+q: %v", addr, err))
|
||||
}
|
||||
return ip
|
||||
}
|
||||
|
||||
// ipAddrInit is called once at init()
|
||||
func ipAddrInit() {
|
||||
// Sorted for human readability
|
||||
ipAddrAttrs = []AttrName{
|
||||
"host",
|
||||
"address",
|
||||
"port",
|
||||
"netmask",
|
||||
"network",
|
||||
"mask_bits",
|
||||
"binary",
|
||||
"hex",
|
||||
"first_usable",
|
||||
"last_usable",
|
||||
"octets",
|
||||
}
|
||||
|
||||
ipAddrAttrMap = map[AttrName]func(ip IPAddr) string{
|
||||
"address": func(ip IPAddr) string {
|
||||
return ip.NetIP().String()
|
||||
},
|
||||
"binary": func(ip IPAddr) string {
|
||||
return ip.AddressBinString()
|
||||
},
|
||||
"first_usable": func(ip IPAddr) string {
|
||||
return ip.FirstUsable().String()
|
||||
},
|
||||
"hex": func(ip IPAddr) string {
|
||||
return ip.AddressHexString()
|
||||
},
|
||||
"host": func(ip IPAddr) string {
|
||||
return ip.Host().String()
|
||||
},
|
||||
"last_usable": func(ip IPAddr) string {
|
||||
return ip.LastUsable().String()
|
||||
},
|
||||
"mask_bits": func(ip IPAddr) string {
|
||||
return fmt.Sprintf("%d", ip.Maskbits())
|
||||
},
|
||||
"netmask": func(ip IPAddr) string {
|
||||
switch v := ip.(type) {
|
||||
case IPv4Addr:
|
||||
ipv4Mask := IPv4Addr{
|
||||
Address: IPv4Address(v.Mask),
|
||||
Mask: IPv4HostMask,
|
||||
}
|
||||
return ipv4Mask.String()
|
||||
case IPv6Addr:
|
||||
ipv6Mask := new(big.Int)
|
||||
ipv6Mask.Set(v.Mask)
|
||||
ipv6MaskAddr := IPv6Addr{
|
||||
Address: IPv6Address(ipv6Mask),
|
||||
Mask: ipv6HostMask,
|
||||
}
|
||||
return ipv6MaskAddr.String()
|
||||
default:
|
||||
return fmt.Sprintf("<unsupported type: %T>", ip)
|
||||
}
|
||||
},
|
||||
"network": func(ip IPAddr) string {
|
||||
return ip.Network().NetIP().String()
|
||||
},
|
||||
"octets": func(ip IPAddr) string {
|
||||
octets := ip.Octets()
|
||||
octetStrs := make([]string, 0, len(octets))
|
||||
for _, octet := range octets {
|
||||
octetStrs = append(octetStrs, fmt.Sprintf("%d", octet))
|
||||
}
|
||||
return strings.Join(octetStrs, " ")
|
||||
},
|
||||
"port": func(ip IPAddr) string {
|
||||
return fmt.Sprintf("%d", ip.IPPort())
|
||||
},
|
||||
}
|
||||
}
|
98
vendor/github.com/hashicorp/go-sockaddr/ipaddrs.go
generated
vendored
Normal file
98
vendor/github.com/hashicorp/go-sockaddr/ipaddrs.go
generated
vendored
Normal file
@ -0,0 +1,98 @@
|
||||
package sockaddr
|
||||
|
||||
import "bytes"
|
||||
|
||||
type IPAddrs []IPAddr
|
||||
|
||||
func (s IPAddrs) Len() int { return len(s) }
|
||||
func (s IPAddrs) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||
|
||||
// // SortIPAddrsByCmp is a type that satisfies sort.Interface and can be used
|
||||
// // by the routines in this package. The SortIPAddrsByCmp type is used to
|
||||
// // sort IPAddrs by Cmp()
|
||||
// type SortIPAddrsByCmp struct{ IPAddrs }
|
||||
|
||||
// // Less reports whether the element with index i should sort before the
|
||||
// // element with index j.
|
||||
// func (s SortIPAddrsByCmp) Less(i, j int) bool {
|
||||
// // Sort by Type, then address, then port number.
|
||||
// return Less(s.IPAddrs[i], s.IPAddrs[j])
|
||||
// }
|
||||
|
||||
// SortIPAddrsBySpecificMaskLen is a type that satisfies sort.Interface and
|
||||
// can be used by the routines in this package. The
|
||||
// SortIPAddrsBySpecificMaskLen type is used to sort IPAddrs by smallest
|
||||
// network (most specific to largest network).
|
||||
type SortIPAddrsByNetworkSize struct{ IPAddrs }
|
||||
|
||||
// Less reports whether the element with index i should sort before the
|
||||
// element with index j.
|
||||
func (s SortIPAddrsByNetworkSize) Less(i, j int) bool {
|
||||
// Sort masks with a larger binary value (i.e. fewer hosts per network
|
||||
// prefix) after masks with a smaller value (larger number of hosts per
|
||||
// prefix).
|
||||
switch bytes.Compare([]byte(*s.IPAddrs[i].NetIPMask()), []byte(*s.IPAddrs[j].NetIPMask())) {
|
||||
case 0:
|
||||
// Fall through to the second test if the net.IPMasks are the
|
||||
// same.
|
||||
break
|
||||
case 1:
|
||||
return true
|
||||
case -1:
|
||||
return false
|
||||
default:
|
||||
panic("bad, m'kay?")
|
||||
}
|
||||
|
||||
// Sort IPs based on the length (i.e. prefer IPv4 over IPv6).
|
||||
iLen := len(*s.IPAddrs[i].NetIP())
|
||||
jLen := len(*s.IPAddrs[j].NetIP())
|
||||
if iLen != jLen {
|
||||
return iLen > jLen
|
||||
}
|
||||
|
||||
// Sort IPs based on their network address from lowest to highest.
|
||||
switch bytes.Compare(s.IPAddrs[i].NetIPNet().IP, s.IPAddrs[j].NetIPNet().IP) {
|
||||
case 0:
|
||||
break
|
||||
case 1:
|
||||
return false
|
||||
case -1:
|
||||
return true
|
||||
default:
|
||||
panic("lol wut?")
|
||||
}
|
||||
|
||||
// If a host does not have a port set, it always sorts after hosts
|
||||
// that have a port (e.g. a host with a /32 and port number is more
|
||||
// specific and should sort first over a host with a /32 but no port
|
||||
// set).
|
||||
if s.IPAddrs[i].IPPort() == 0 || s.IPAddrs[j].IPPort() == 0 {
|
||||
return false
|
||||
}
|
||||
return s.IPAddrs[i].IPPort() < s.IPAddrs[j].IPPort()
|
||||
}
|
||||
|
||||
// SortIPAddrsBySpecificMaskLen is a type that satisfies sort.Interface and
|
||||
// can be used by the routines in this package. The
|
||||
// SortIPAddrsBySpecificMaskLen type is used to sort IPAddrs by smallest
|
||||
// network (most specific to largest network).
|
||||
type SortIPAddrsBySpecificMaskLen struct{ IPAddrs }
|
||||
|
||||
// Less reports whether the element with index i should sort before the
|
||||
// element with index j.
|
||||
func (s SortIPAddrsBySpecificMaskLen) Less(i, j int) bool {
|
||||
return s.IPAddrs[i].Maskbits() > s.IPAddrs[j].Maskbits()
|
||||
}
|
||||
|
||||
// SortIPAddrsByBroadMaskLen is a type that satisfies sort.Interface and can
|
||||
// be used by the routines in this package. The SortIPAddrsByBroadMaskLen
|
||||
// type is used to sort IPAddrs by largest network (i.e. largest subnets
|
||||
// first).
|
||||
type SortIPAddrsByBroadMaskLen struct{ IPAddrs }
|
||||
|
||||
// Less reports whether the element with index i should sort before the
|
||||
// element with index j.
|
||||
func (s SortIPAddrsByBroadMaskLen) Less(i, j int) bool {
|
||||
return s.IPAddrs[i].Maskbits() < s.IPAddrs[j].Maskbits()
|
||||
}
|
516
vendor/github.com/hashicorp/go-sockaddr/ipv4addr.go
generated
vendored
Normal file
516
vendor/github.com/hashicorp/go-sockaddr/ipv4addr.go
generated
vendored
Normal file
@ -0,0 +1,516 @@
|
||||
package sockaddr
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"net"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type (
|
||||
// IPv4Address is a named type representing an IPv4 address.
|
||||
IPv4Address uint32
|
||||
|
||||
// IPv4Network is a named type representing an IPv4 network.
|
||||
IPv4Network uint32
|
||||
|
||||
// IPv4Mask is a named type representing an IPv4 network mask.
|
||||
IPv4Mask uint32
|
||||
)
|
||||
|
||||
// IPv4HostMask is a constant represents a /32 IPv4 Address
|
||||
// (i.e. 255.255.255.255).
|
||||
const IPv4HostMask = IPv4Mask(0xffffffff)
|
||||
|
||||
// ipv4AddrAttrMap is a map of the IPv4Addr type-specific attributes.
|
||||
var ipv4AddrAttrMap map[AttrName]func(IPv4Addr) string
|
||||
var ipv4AddrAttrs []AttrName
|
||||
var trailingHexNetmaskRE *regexp.Regexp
|
||||
|
||||
// IPv4Addr implements a convenience wrapper around the union of Go's
|
||||
// built-in net.IP and net.IPNet types. In UNIX-speak, IPv4Addr implements
|
||||
// `sockaddr` when the the address family is set to AF_INET
|
||||
// (i.e. `sockaddr_in`).
|
||||
type IPv4Addr struct {
|
||||
IPAddr
|
||||
Address IPv4Address
|
||||
Mask IPv4Mask
|
||||
Port IPPort
|
||||
}
|
||||
|
||||
func init() {
|
||||
ipv4AddrInit()
|
||||
trailingHexNetmaskRE = regexp.MustCompile(`/([0f]{8})$`)
|
||||
}
|
||||
|
||||
// NewIPv4Addr creates an IPv4Addr from a string. String can be in the form
|
||||
// of either an IPv4:port (e.g. `1.2.3.4:80`, in which case the mask is
|
||||
// assumed to be a `/32`), an IPv4 address (e.g. `1.2.3.4`, also with a `/32`
|
||||
// mask), or an IPv4 CIDR (e.g. `1.2.3.4/24`, which has its IP port
|
||||
// initialized to zero). ipv4Str can not be a hostname.
|
||||
//
|
||||
// NOTE: Many net.*() routines will initialize and return an IPv6 address.
|
||||
// To create uint32 values from net.IP, always test to make sure the address
|
||||
// returned can be converted to a 4 byte array using To4().
|
||||
func NewIPv4Addr(ipv4Str string) (IPv4Addr, error) {
|
||||
// Strip off any bogus hex-encoded netmasks that will be mis-parsed by Go. In
|
||||
// particular, clients with the Barracuda VPN client will see something like:
|
||||
// `192.168.3.51/00ffffff` as their IP address.
|
||||
trailingHexNetmaskRe := trailingHexNetmaskRE.Copy()
|
||||
if match := trailingHexNetmaskRe.FindStringIndex(ipv4Str); match != nil {
|
||||
ipv4Str = ipv4Str[:match[0]]
|
||||
}
|
||||
|
||||
// Parse as an IPv4 CIDR
|
||||
ipAddr, network, err := net.ParseCIDR(ipv4Str)
|
||||
if err == nil {
|
||||
ipv4 := ipAddr.To4()
|
||||
if ipv4 == nil {
|
||||
return IPv4Addr{}, fmt.Errorf("Unable to convert %s to an IPv4 address", ipv4Str)
|
||||
}
|
||||
|
||||
// If we see an IPv6 netmask, convert it to an IPv4 mask.
|
||||
netmaskSepPos := strings.LastIndexByte(ipv4Str, '/')
|
||||
if netmaskSepPos != -1 && netmaskSepPos+1 < len(ipv4Str) {
|
||||
netMask, err := strconv.ParseUint(ipv4Str[netmaskSepPos+1:], 10, 8)
|
||||
if err != nil {
|
||||
return IPv4Addr{}, fmt.Errorf("Unable to convert %s to an IPv4 address: unable to parse CIDR netmask: %v", ipv4Str, err)
|
||||
} else if netMask > 128 {
|
||||
return IPv4Addr{}, fmt.Errorf("Unable to convert %s to an IPv4 address: invalid CIDR netmask", ipv4Str)
|
||||
}
|
||||
|
||||
if netMask >= 96 {
|
||||
// Convert the IPv6 netmask to an IPv4 netmask
|
||||
network.Mask = net.CIDRMask(int(netMask-96), IPv4len*8)
|
||||
}
|
||||
}
|
||||
ipv4Addr := IPv4Addr{
|
||||
Address: IPv4Address(binary.BigEndian.Uint32(ipv4)),
|
||||
Mask: IPv4Mask(binary.BigEndian.Uint32(network.Mask)),
|
||||
}
|
||||
return ipv4Addr, nil
|
||||
}
|
||||
|
||||
// Attempt to parse ipv4Str as a /32 host with a port number.
|
||||
tcpAddr, err := net.ResolveTCPAddr("tcp4", ipv4Str)
|
||||
if err == nil {
|
||||
ipv4 := tcpAddr.IP.To4()
|
||||
if ipv4 == nil {
|
||||
return IPv4Addr{}, fmt.Errorf("Unable to resolve %+q as an IPv4 address", ipv4Str)
|
||||
}
|
||||
|
||||
ipv4Uint32 := binary.BigEndian.Uint32(ipv4)
|
||||
ipv4Addr := IPv4Addr{
|
||||
Address: IPv4Address(ipv4Uint32),
|
||||
Mask: IPv4HostMask,
|
||||
Port: IPPort(tcpAddr.Port),
|
||||
}
|
||||
|
||||
return ipv4Addr, nil
|
||||
}
|
||||
|
||||
// Parse as a naked IPv4 address
|
||||
ip := net.ParseIP(ipv4Str)
|
||||
if ip != nil {
|
||||
ipv4 := ip.To4()
|
||||
if ipv4 == nil {
|
||||
return IPv4Addr{}, fmt.Errorf("Unable to string convert %+q to an IPv4 address", ipv4Str)
|
||||
}
|
||||
|
||||
ipv4Uint32 := binary.BigEndian.Uint32(ipv4)
|
||||
ipv4Addr := IPv4Addr{
|
||||
Address: IPv4Address(ipv4Uint32),
|
||||
Mask: IPv4HostMask,
|
||||
}
|
||||
return ipv4Addr, nil
|
||||
}
|
||||
|
||||
return IPv4Addr{}, fmt.Errorf("Unable to parse %+q to an IPv4 address: %v", ipv4Str, err)
|
||||
}
|
||||
|
||||
// AddressBinString returns a string with the IPv4Addr's Address represented
|
||||
// as a sequence of '0' and '1' characters. This method is useful for
|
||||
// debugging or by operators who want to inspect an address.
|
||||
func (ipv4 IPv4Addr) AddressBinString() string {
|
||||
return fmt.Sprintf("%032s", strconv.FormatUint(uint64(ipv4.Address), 2))
|
||||
}
|
||||
|
||||
// AddressHexString returns a string with the IPv4Addr address represented as
|
||||
// a sequence of hex characters. This method is useful for debugging or by
|
||||
// operators who want to inspect an address.
|
||||
func (ipv4 IPv4Addr) AddressHexString() string {
|
||||
return fmt.Sprintf("%08s", strconv.FormatUint(uint64(ipv4.Address), 16))
|
||||
}
|
||||
|
||||
// Broadcast is an IPv4Addr-only method that returns the broadcast address of
|
||||
// the network.
|
||||
//
|
||||
// NOTE: IPv6 only supports multicast, so this method only exists for
|
||||
// IPv4Addr.
|
||||
func (ipv4 IPv4Addr) Broadcast() IPAddr {
|
||||
// Nothing should listen on a broadcast address.
|
||||
return IPv4Addr{
|
||||
Address: IPv4Address(ipv4.BroadcastAddress()),
|
||||
Mask: IPv4HostMask,
|
||||
}
|
||||
}
|
||||
|
||||
// BroadcastAddress returns a IPv4Network of the IPv4Addr's broadcast
|
||||
// address.
|
||||
func (ipv4 IPv4Addr) BroadcastAddress() IPv4Network {
|
||||
return IPv4Network(uint32(ipv4.Address)&uint32(ipv4.Mask) | ^uint32(ipv4.Mask))
|
||||
}
|
||||
|
||||
// CmpAddress follows the Cmp() standard protocol and returns:
|
||||
//
|
||||
// - -1 If the receiver should sort first because its address is lower than arg
|
||||
// - 0 if the SockAddr arg is equal to the receiving IPv4Addr or the argument is
|
||||
// of a different type.
|
||||
// - 1 If the argument should sort first.
|
||||
func (ipv4 IPv4Addr) CmpAddress(sa SockAddr) int {
|
||||
ipv4b, ok := sa.(IPv4Addr)
|
||||
if !ok {
|
||||
return sortDeferDecision
|
||||
}
|
||||
|
||||
switch {
|
||||
case ipv4.Address == ipv4b.Address:
|
||||
return sortDeferDecision
|
||||
case ipv4.Address < ipv4b.Address:
|
||||
return sortReceiverBeforeArg
|
||||
default:
|
||||
return sortArgBeforeReceiver
|
||||
}
|
||||
}
|
||||
|
||||
// CmpPort follows the Cmp() standard protocol and returns:
|
||||
//
|
||||
// - -1 If the receiver should sort first because its port is lower than arg
|
||||
// - 0 if the SockAddr arg's port number is equal to the receiving IPv4Addr,
|
||||
// regardless of type.
|
||||
// - 1 If the argument should sort first.
|
||||
func (ipv4 IPv4Addr) CmpPort(sa SockAddr) int {
|
||||
var saPort IPPort
|
||||
switch v := sa.(type) {
|
||||
case IPv4Addr:
|
||||
saPort = v.Port
|
||||
case IPv6Addr:
|
||||
saPort = v.Port
|
||||
default:
|
||||
return sortDeferDecision
|
||||
}
|
||||
|
||||
switch {
|
||||
case ipv4.Port == saPort:
|
||||
return sortDeferDecision
|
||||
case ipv4.Port < saPort:
|
||||
return sortReceiverBeforeArg
|
||||
default:
|
||||
return sortArgBeforeReceiver
|
||||
}
|
||||
}
|
||||
|
||||
// CmpRFC follows the Cmp() standard protocol and returns:
|
||||
//
|
||||
// - -1 If the receiver should sort first because it belongs to the RFC and its
|
||||
// arg does not
|
||||
// - 0 if the receiver and arg both belong to the same RFC or neither do.
|
||||
// - 1 If the arg belongs to the RFC but receiver does not.
|
||||
func (ipv4 IPv4Addr) CmpRFC(rfcNum uint, sa SockAddr) int {
|
||||
recvInRFC := IsRFC(rfcNum, ipv4)
|
||||
ipv4b, ok := sa.(IPv4Addr)
|
||||
if !ok {
|
||||
// If the receiver is part of the desired RFC and the SockAddr
|
||||
// argument is not, return -1 so that the receiver sorts before
|
||||
// the non-IPv4 SockAddr. Conversely, if the receiver is not
|
||||
// part of the RFC, punt on sorting and leave it for the next
|
||||
// sorter.
|
||||
if recvInRFC {
|
||||
return sortReceiverBeforeArg
|
||||
} else {
|
||||
return sortDeferDecision
|
||||
}
|
||||
}
|
||||
|
||||
argInRFC := IsRFC(rfcNum, ipv4b)
|
||||
switch {
|
||||
case (recvInRFC && argInRFC), (!recvInRFC && !argInRFC):
|
||||
// If a and b both belong to the RFC, or neither belong to
|
||||
// rfcNum, defer sorting to the next sorter.
|
||||
return sortDeferDecision
|
||||
case recvInRFC && !argInRFC:
|
||||
return sortReceiverBeforeArg
|
||||
default:
|
||||
return sortArgBeforeReceiver
|
||||
}
|
||||
}
|
||||
|
||||
// Contains returns true if the SockAddr is contained within the receiver.
|
||||
func (ipv4 IPv4Addr) Contains(sa SockAddr) bool {
|
||||
ipv4b, ok := sa.(IPv4Addr)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
return ipv4.ContainsNetwork(ipv4b)
|
||||
}
|
||||
|
||||
// ContainsAddress returns true if the IPv4Address is contained within the
|
||||
// receiver.
|
||||
func (ipv4 IPv4Addr) ContainsAddress(x IPv4Address) bool {
|
||||
return IPv4Address(ipv4.NetworkAddress()) <= x &&
|
||||
IPv4Address(ipv4.BroadcastAddress()) >= x
|
||||
}
|
||||
|
||||
// ContainsNetwork returns true if the network from IPv4Addr is contained
|
||||
// within the receiver.
|
||||
func (ipv4 IPv4Addr) ContainsNetwork(x IPv4Addr) bool {
|
||||
return ipv4.NetworkAddress() <= x.NetworkAddress() &&
|
||||
ipv4.BroadcastAddress() >= x.BroadcastAddress()
|
||||
}
|
||||
|
||||
// DialPacketArgs returns the arguments required to be passed to
|
||||
// net.DialUDP(). If the Mask of ipv4 is not a /32 or the Port is 0,
|
||||
// DialPacketArgs() will fail. See Host() to create an IPv4Addr with its
|
||||
// mask set to /32.
|
||||
func (ipv4 IPv4Addr) DialPacketArgs() (network, dialArgs string) {
|
||||
if ipv4.Mask != IPv4HostMask || ipv4.Port == 0 {
|
||||
return "udp4", ""
|
||||
}
|
||||
return "udp4", fmt.Sprintf("%s:%d", ipv4.NetIP().String(), ipv4.Port)
|
||||
}
|
||||
|
||||
// DialStreamArgs returns the arguments required to be passed to
|
||||
// net.DialTCP(). If the Mask of ipv4 is not a /32 or the Port is 0,
|
||||
// DialStreamArgs() will fail. See Host() to create an IPv4Addr with its
|
||||
// mask set to /32.
|
||||
func (ipv4 IPv4Addr) DialStreamArgs() (network, dialArgs string) {
|
||||
if ipv4.Mask != IPv4HostMask || ipv4.Port == 0 {
|
||||
return "tcp4", ""
|
||||
}
|
||||
return "tcp4", fmt.Sprintf("%s:%d", ipv4.NetIP().String(), ipv4.Port)
|
||||
}
|
||||
|
||||
// Equal returns true if a SockAddr is equal to the receiving IPv4Addr.
|
||||
func (ipv4 IPv4Addr) Equal(sa SockAddr) bool {
|
||||
ipv4b, ok := sa.(IPv4Addr)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
if ipv4.Port != ipv4b.Port {
|
||||
return false
|
||||
}
|
||||
|
||||
if ipv4.Address != ipv4b.Address {
|
||||
return false
|
||||
}
|
||||
|
||||
if ipv4.NetIPNet().String() != ipv4b.NetIPNet().String() {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// FirstUsable returns an IPv4Addr set to the first address following the
|
||||
// network prefix. The first usable address in a network is normally the
|
||||
// gateway and should not be used except by devices forwarding packets
|
||||
// between two administratively distinct networks (i.e. a router). This
|
||||
// function does not discriminate against first usable vs "first address that
|
||||
// should be used." For example, FirstUsable() on "192.168.1.10/24" would
|
||||
// return the address "192.168.1.1/24".
|
||||
func (ipv4 IPv4Addr) FirstUsable() IPAddr {
|
||||
addr := ipv4.NetworkAddress()
|
||||
|
||||
// If /32, return the address itself. If /31 assume a point-to-point
|
||||
// link and return the lower address.
|
||||
if ipv4.Maskbits() < 31 {
|
||||
addr++
|
||||
}
|
||||
|
||||
return IPv4Addr{
|
||||
Address: IPv4Address(addr),
|
||||
Mask: IPv4HostMask,
|
||||
}
|
||||
}
|
||||
|
||||
// Host returns a copy of ipv4 with its mask set to /32 so that it can be
|
||||
// used by DialPacketArgs(), DialStreamArgs(), ListenPacketArgs(), or
|
||||
// ListenStreamArgs().
|
||||
func (ipv4 IPv4Addr) Host() IPAddr {
|
||||
// Nothing should listen on a broadcast address.
|
||||
return IPv4Addr{
|
||||
Address: ipv4.Address,
|
||||
Mask: IPv4HostMask,
|
||||
Port: ipv4.Port,
|
||||
}
|
||||
}
|
||||
|
||||
// IPPort returns the Port number attached to the IPv4Addr
|
||||
func (ipv4 IPv4Addr) IPPort() IPPort {
|
||||
return ipv4.Port
|
||||
}
|
||||
|
||||
// LastUsable returns the last address before the broadcast address in a
|
||||
// given network.
|
||||
func (ipv4 IPv4Addr) LastUsable() IPAddr {
|
||||
addr := ipv4.BroadcastAddress()
|
||||
|
||||
// If /32, return the address itself. If /31 assume a point-to-point
|
||||
// link and return the upper address.
|
||||
if ipv4.Maskbits() < 31 {
|
||||
addr--
|
||||
}
|
||||
|
||||
return IPv4Addr{
|
||||
Address: IPv4Address(addr),
|
||||
Mask: IPv4HostMask,
|
||||
}
|
||||
}
|
||||
|
||||
// ListenPacketArgs returns the arguments required to be passed to
|
||||
// net.ListenUDP(). If the Mask of ipv4 is not a /32, ListenPacketArgs()
|
||||
// will fail. See Host() to create an IPv4Addr with its mask set to /32.
|
||||
func (ipv4 IPv4Addr) ListenPacketArgs() (network, listenArgs string) {
|
||||
if ipv4.Mask != IPv4HostMask {
|
||||
return "udp4", ""
|
||||
}
|
||||
return "udp4", fmt.Sprintf("%s:%d", ipv4.NetIP().String(), ipv4.Port)
|
||||
}
|
||||
|
||||
// ListenStreamArgs returns the arguments required to be passed to
|
||||
// net.ListenTCP(). If the Mask of ipv4 is not a /32, ListenStreamArgs()
|
||||
// will fail. See Host() to create an IPv4Addr with its mask set to /32.
|
||||
func (ipv4 IPv4Addr) ListenStreamArgs() (network, listenArgs string) {
|
||||
if ipv4.Mask != IPv4HostMask {
|
||||
return "tcp4", ""
|
||||
}
|
||||
return "tcp4", fmt.Sprintf("%s:%d", ipv4.NetIP().String(), ipv4.Port)
|
||||
}
|
||||
|
||||
// Maskbits returns the number of network mask bits in a given IPv4Addr. For
|
||||
// example, the Maskbits() of "192.168.1.1/24" would return 24.
|
||||
func (ipv4 IPv4Addr) Maskbits() int {
|
||||
mask := make(net.IPMask, IPv4len)
|
||||
binary.BigEndian.PutUint32(mask, uint32(ipv4.Mask))
|
||||
maskOnes, _ := mask.Size()
|
||||
return maskOnes
|
||||
}
|
||||
|
||||
// MustIPv4Addr is a helper method that must return an IPv4Addr or panic on
|
||||
// invalid input.
|
||||
func MustIPv4Addr(addr string) IPv4Addr {
|
||||
ipv4, err := NewIPv4Addr(addr)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Unable to create an IPv4Addr from %+q: %v", addr, err))
|
||||
}
|
||||
return ipv4
|
||||
}
|
||||
|
||||
// NetIP returns the address as a net.IP (address is always presized to
|
||||
// IPv4).
|
||||
func (ipv4 IPv4Addr) NetIP() *net.IP {
|
||||
x := make(net.IP, IPv4len)
|
||||
binary.BigEndian.PutUint32(x, uint32(ipv4.Address))
|
||||
return &x
|
||||
}
|
||||
|
||||
// NetIPMask create a new net.IPMask from the IPv4Addr.
|
||||
func (ipv4 IPv4Addr) NetIPMask() *net.IPMask {
|
||||
ipv4Mask := net.IPMask{}
|
||||
ipv4Mask = make(net.IPMask, IPv4len)
|
||||
binary.BigEndian.PutUint32(ipv4Mask, uint32(ipv4.Mask))
|
||||
return &ipv4Mask
|
||||
}
|
||||
|
||||
// NetIPNet create a new net.IPNet from the IPv4Addr.
|
||||
func (ipv4 IPv4Addr) NetIPNet() *net.IPNet {
|
||||
ipv4net := &net.IPNet{}
|
||||
ipv4net.IP = make(net.IP, IPv4len)
|
||||
binary.BigEndian.PutUint32(ipv4net.IP, uint32(ipv4.NetworkAddress()))
|
||||
ipv4net.Mask = *ipv4.NetIPMask()
|
||||
return ipv4net
|
||||
}
|
||||
|
||||
// Network returns the network prefix or network address for a given network.
|
||||
func (ipv4 IPv4Addr) Network() IPAddr {
|
||||
return IPv4Addr{
|
||||
Address: IPv4Address(ipv4.NetworkAddress()),
|
||||
Mask: ipv4.Mask,
|
||||
}
|
||||
}
|
||||
|
||||
// NetworkAddress returns an IPv4Network of the IPv4Addr's network address.
|
||||
func (ipv4 IPv4Addr) NetworkAddress() IPv4Network {
|
||||
return IPv4Network(uint32(ipv4.Address) & uint32(ipv4.Mask))
|
||||
}
|
||||
|
||||
// Octets returns a slice of the four octets in an IPv4Addr's Address. The
|
||||
// order of the bytes is big endian.
|
||||
func (ipv4 IPv4Addr) Octets() []int {
|
||||
return []int{
|
||||
int(ipv4.Address >> 24),
|
||||
int((ipv4.Address >> 16) & 0xff),
|
||||
int((ipv4.Address >> 8) & 0xff),
|
||||
int(ipv4.Address & 0xff),
|
||||
}
|
||||
}
|
||||
|
||||
// String returns a string representation of the IPv4Addr
|
||||
func (ipv4 IPv4Addr) String() string {
|
||||
if ipv4.Port != 0 {
|
||||
return fmt.Sprintf("%s:%d", ipv4.NetIP().String(), ipv4.Port)
|
||||
}
|
||||
|
||||
if ipv4.Maskbits() == 32 {
|
||||
return ipv4.NetIP().String()
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s/%d", ipv4.NetIP().String(), ipv4.Maskbits())
|
||||
}
|
||||
|
||||
// Type is used as a type switch and returns TypeIPv4
|
||||
func (IPv4Addr) Type() SockAddrType {
|
||||
return TypeIPv4
|
||||
}
|
||||
|
||||
// IPv4AddrAttr returns a string representation of an attribute for the given
|
||||
// IPv4Addr.
|
||||
func IPv4AddrAttr(ipv4 IPv4Addr, selector AttrName) string {
|
||||
fn, found := ipv4AddrAttrMap[selector]
|
||||
if !found {
|
||||
return ""
|
||||
}
|
||||
|
||||
return fn(ipv4)
|
||||
}
|
||||
|
||||
// IPv4Attrs returns a list of attributes supported by the IPv4Addr type
|
||||
func IPv4Attrs() []AttrName {
|
||||
return ipv4AddrAttrs
|
||||
}
|
||||
|
||||
// ipv4AddrInit is called once at init()
|
||||
func ipv4AddrInit() {
|
||||
// Sorted for human readability
|
||||
ipv4AddrAttrs = []AttrName{
|
||||
"size", // Same position as in IPv6 for output consistency
|
||||
"broadcast",
|
||||
"uint32",
|
||||
}
|
||||
|
||||
ipv4AddrAttrMap = map[AttrName]func(ipv4 IPv4Addr) string{
|
||||
"broadcast": func(ipv4 IPv4Addr) string {
|
||||
return ipv4.Broadcast().String()
|
||||
},
|
||||
"size": func(ipv4 IPv4Addr) string {
|
||||
return fmt.Sprintf("%d", 1<<uint(IPv4len*8-ipv4.Maskbits()))
|
||||
},
|
||||
"uint32": func(ipv4 IPv4Addr) string {
|
||||
return fmt.Sprintf("%d", uint32(ipv4.Address))
|
||||
},
|
||||
}
|
||||
}
|
591
vendor/github.com/hashicorp/go-sockaddr/ipv6addr.go
generated
vendored
Normal file
591
vendor/github.com/hashicorp/go-sockaddr/ipv6addr.go
generated
vendored
Normal file
@ -0,0 +1,591 @@
|
||||
package sockaddr
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"net"
|
||||
)
|
||||
|
||||
type (
|
||||
// IPv6Address is a named type representing an IPv6 address.
|
||||
IPv6Address *big.Int
|
||||
|
||||
// IPv6Network is a named type representing an IPv6 network.
|
||||
IPv6Network *big.Int
|
||||
|
||||
// IPv6Mask is a named type representing an IPv6 network mask.
|
||||
IPv6Mask *big.Int
|
||||
)
|
||||
|
||||
// IPv6HostPrefix is a constant represents a /128 IPv6 Prefix.
|
||||
const IPv6HostPrefix = IPPrefixLen(128)
|
||||
|
||||
// ipv6HostMask is an unexported big.Int representing a /128 IPv6 address.
|
||||
// This value must be a constant and always set to all ones.
|
||||
var ipv6HostMask IPv6Mask
|
||||
|
||||
// ipv6AddrAttrMap is a map of the IPv6Addr type-specific attributes.
|
||||
var ipv6AddrAttrMap map[AttrName]func(IPv6Addr) string
|
||||
var ipv6AddrAttrs []AttrName
|
||||
|
||||
func init() {
|
||||
biMask := new(big.Int)
|
||||
biMask.SetBytes([]byte{
|
||||
0xff, 0xff,
|
||||
0xff, 0xff,
|
||||
0xff, 0xff,
|
||||
0xff, 0xff,
|
||||
0xff, 0xff,
|
||||
0xff, 0xff,
|
||||
0xff, 0xff,
|
||||
0xff, 0xff,
|
||||
},
|
||||
)
|
||||
ipv6HostMask = IPv6Mask(biMask)
|
||||
|
||||
ipv6AddrInit()
|
||||
}
|
||||
|
||||
// IPv6Addr implements a convenience wrapper around the union of Go's
|
||||
// built-in net.IP and net.IPNet types. In UNIX-speak, IPv6Addr implements
|
||||
// `sockaddr` when the the address family is set to AF_INET6
|
||||
// (i.e. `sockaddr_in6`).
|
||||
type IPv6Addr struct {
|
||||
IPAddr
|
||||
Address IPv6Address
|
||||
Mask IPv6Mask
|
||||
Port IPPort
|
||||
}
|
||||
|
||||
// NewIPv6Addr creates an IPv6Addr from a string. String can be in the form of
|
||||
// an an IPv6:port (e.g. `[2001:4860:0:2001::68]:80`, in which case the mask is
|
||||
// assumed to be a /128), an IPv6 address (e.g. `2001:4860:0:2001::68`, also
|
||||
// with a `/128` mask), an IPv6 CIDR (e.g. `2001:4860:0:2001::68/64`, which has
|
||||
// its IP port initialized to zero). ipv6Str can not be a hostname.
|
||||
//
|
||||
// NOTE: Many net.*() routines will initialize and return an IPv4 address.
|
||||
// Always test to make sure the address returned cannot be converted to a 4 byte
|
||||
// array using To4().
|
||||
func NewIPv6Addr(ipv6Str string) (IPv6Addr, error) {
|
||||
v6Addr := false
|
||||
LOOP:
|
||||
for i := 0; i < len(ipv6Str); i++ {
|
||||
switch ipv6Str[i] {
|
||||
case '.':
|
||||
break LOOP
|
||||
case ':':
|
||||
v6Addr = true
|
||||
break LOOP
|
||||
}
|
||||
}
|
||||
|
||||
if !v6Addr {
|
||||
return IPv6Addr{}, fmt.Errorf("Unable to resolve %+q as an IPv6 address, appears to be an IPv4 address", ipv6Str)
|
||||
}
|
||||
|
||||
// Attempt to parse ipv6Str as a /128 host with a port number.
|
||||
tcpAddr, err := net.ResolveTCPAddr("tcp6", ipv6Str)
|
||||
if err == nil {
|
||||
ipv6 := tcpAddr.IP.To16()
|
||||
if ipv6 == nil {
|
||||
return IPv6Addr{}, fmt.Errorf("Unable to resolve %+q as a 16byte IPv6 address", ipv6Str)
|
||||
}
|
||||
|
||||
ipv6BigIntAddr := new(big.Int)
|
||||
ipv6BigIntAddr.SetBytes(ipv6)
|
||||
|
||||
ipv6BigIntMask := new(big.Int)
|
||||
ipv6BigIntMask.Set(ipv6HostMask)
|
||||
|
||||
ipv6Addr := IPv6Addr{
|
||||
Address: IPv6Address(ipv6BigIntAddr),
|
||||
Mask: IPv6Mask(ipv6BigIntMask),
|
||||
Port: IPPort(tcpAddr.Port),
|
||||
}
|
||||
|
||||
return ipv6Addr, nil
|
||||
}
|
||||
|
||||
// Parse as a naked IPv6 address. Trim square brackets if present.
|
||||
if len(ipv6Str) > 2 && ipv6Str[0] == '[' && ipv6Str[len(ipv6Str)-1] == ']' {
|
||||
ipv6Str = ipv6Str[1 : len(ipv6Str)-1]
|
||||
}
|
||||
ip := net.ParseIP(ipv6Str)
|
||||
if ip != nil {
|
||||
ipv6 := ip.To16()
|
||||
if ipv6 == nil {
|
||||
return IPv6Addr{}, fmt.Errorf("Unable to string convert %+q to a 16byte IPv6 address", ipv6Str)
|
||||
}
|
||||
|
||||
ipv6BigIntAddr := new(big.Int)
|
||||
ipv6BigIntAddr.SetBytes(ipv6)
|
||||
|
||||
ipv6BigIntMask := new(big.Int)
|
||||
ipv6BigIntMask.Set(ipv6HostMask)
|
||||
|
||||
return IPv6Addr{
|
||||
Address: IPv6Address(ipv6BigIntAddr),
|
||||
Mask: IPv6Mask(ipv6BigIntMask),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Parse as an IPv6 CIDR
|
||||
ipAddr, network, err := net.ParseCIDR(ipv6Str)
|
||||
if err == nil {
|
||||
ipv6 := ipAddr.To16()
|
||||
if ipv6 == nil {
|
||||
return IPv6Addr{}, fmt.Errorf("Unable to convert %+q to a 16byte IPv6 address", ipv6Str)
|
||||
}
|
||||
|
||||
ipv6BigIntAddr := new(big.Int)
|
||||
ipv6BigIntAddr.SetBytes(ipv6)
|
||||
|
||||
ipv6BigIntMask := new(big.Int)
|
||||
ipv6BigIntMask.SetBytes(network.Mask)
|
||||
|
||||
ipv6Addr := IPv6Addr{
|
||||
Address: IPv6Address(ipv6BigIntAddr),
|
||||
Mask: IPv6Mask(ipv6BigIntMask),
|
||||
}
|
||||
return ipv6Addr, nil
|
||||
}
|
||||
|
||||
return IPv6Addr{}, fmt.Errorf("Unable to parse %+q to an IPv6 address: %v", ipv6Str, err)
|
||||
}
|
||||
|
||||
// AddressBinString returns a string with the IPv6Addr's Address represented
|
||||
// as a sequence of '0' and '1' characters. This method is useful for
|
||||
// debugging or by operators who want to inspect an address.
|
||||
func (ipv6 IPv6Addr) AddressBinString() string {
|
||||
bi := big.Int(*ipv6.Address)
|
||||
return fmt.Sprintf("%0128s", bi.Text(2))
|
||||
}
|
||||
|
||||
// AddressHexString returns a string with the IPv6Addr address represented as
|
||||
// a sequence of hex characters. This method is useful for debugging or by
|
||||
// operators who want to inspect an address.
|
||||
func (ipv6 IPv6Addr) AddressHexString() string {
|
||||
bi := big.Int(*ipv6.Address)
|
||||
return fmt.Sprintf("%032s", bi.Text(16))
|
||||
}
|
||||
|
||||
// CmpAddress follows the Cmp() standard protocol and returns:
|
||||
//
|
||||
// - -1 If the receiver should sort first because its address is lower than arg
|
||||
// - 0 if the SockAddr arg equal to the receiving IPv6Addr or the argument is of a
|
||||
// different type.
|
||||
// - 1 If the argument should sort first.
|
||||
func (ipv6 IPv6Addr) CmpAddress(sa SockAddr) int {
|
||||
ipv6b, ok := sa.(IPv6Addr)
|
||||
if !ok {
|
||||
return sortDeferDecision
|
||||
}
|
||||
|
||||
ipv6aBigInt := new(big.Int)
|
||||
ipv6aBigInt.Set(ipv6.Address)
|
||||
ipv6bBigInt := new(big.Int)
|
||||
ipv6bBigInt.Set(ipv6b.Address)
|
||||
|
||||
return ipv6aBigInt.Cmp(ipv6bBigInt)
|
||||
}
|
||||
|
||||
// CmpPort follows the Cmp() standard protocol and returns:
|
||||
//
|
||||
// - -1 If the receiver should sort first because its port is lower than arg
|
||||
// - 0 if the SockAddr arg's port number is equal to the receiving IPv6Addr,
|
||||
// regardless of type.
|
||||
// - 1 If the argument should sort first.
|
||||
func (ipv6 IPv6Addr) CmpPort(sa SockAddr) int {
|
||||
var saPort IPPort
|
||||
switch v := sa.(type) {
|
||||
case IPv4Addr:
|
||||
saPort = v.Port
|
||||
case IPv6Addr:
|
||||
saPort = v.Port
|
||||
default:
|
||||
return sortDeferDecision
|
||||
}
|
||||
|
||||
switch {
|
||||
case ipv6.Port == saPort:
|
||||
return sortDeferDecision
|
||||
case ipv6.Port < saPort:
|
||||
return sortReceiverBeforeArg
|
||||
default:
|
||||
return sortArgBeforeReceiver
|
||||
}
|
||||
}
|
||||
|
||||
// CmpRFC follows the Cmp() standard protocol and returns:
|
||||
//
|
||||
// - -1 If the receiver should sort first because it belongs to the RFC and its
|
||||
// arg does not
|
||||
// - 0 if the receiver and arg both belong to the same RFC or neither do.
|
||||
// - 1 If the arg belongs to the RFC but receiver does not.
|
||||
func (ipv6 IPv6Addr) CmpRFC(rfcNum uint, sa SockAddr) int {
|
||||
recvInRFC := IsRFC(rfcNum, ipv6)
|
||||
ipv6b, ok := sa.(IPv6Addr)
|
||||
if !ok {
|
||||
// If the receiver is part of the desired RFC and the SockAddr
|
||||
// argument is not, sort receiver before the non-IPv6 SockAddr.
|
||||
// Conversely, if the receiver is not part of the RFC, punt on
|
||||
// sorting and leave it for the next sorter.
|
||||
if recvInRFC {
|
||||
return sortReceiverBeforeArg
|
||||
} else {
|
||||
return sortDeferDecision
|
||||
}
|
||||
}
|
||||
|
||||
argInRFC := IsRFC(rfcNum, ipv6b)
|
||||
switch {
|
||||
case (recvInRFC && argInRFC), (!recvInRFC && !argInRFC):
|
||||
// If a and b both belong to the RFC, or neither belong to
|
||||
// rfcNum, defer sorting to the next sorter.
|
||||
return sortDeferDecision
|
||||
case recvInRFC && !argInRFC:
|
||||
return sortReceiverBeforeArg
|
||||
default:
|
||||
return sortArgBeforeReceiver
|
||||
}
|
||||
}
|
||||
|
||||
// Contains returns true if the SockAddr is contained within the receiver.
|
||||
func (ipv6 IPv6Addr) Contains(sa SockAddr) bool {
|
||||
ipv6b, ok := sa.(IPv6Addr)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
return ipv6.ContainsNetwork(ipv6b)
|
||||
}
|
||||
|
||||
// ContainsAddress returns true if the IPv6Address is contained within the
|
||||
// receiver.
|
||||
func (ipv6 IPv6Addr) ContainsAddress(x IPv6Address) bool {
|
||||
xAddr := IPv6Addr{
|
||||
Address: x,
|
||||
Mask: ipv6HostMask,
|
||||
}
|
||||
|
||||
{
|
||||
xIPv6 := xAddr.FirstUsable().(IPv6Addr)
|
||||
yIPv6 := ipv6.FirstUsable().(IPv6Addr)
|
||||
if xIPv6.CmpAddress(yIPv6) >= 1 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
xIPv6 := xAddr.LastUsable().(IPv6Addr)
|
||||
yIPv6 := ipv6.LastUsable().(IPv6Addr)
|
||||
if xIPv6.CmpAddress(yIPv6) <= -1 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// ContainsNetwork returns true if the network from IPv6Addr is contained within
|
||||
// the receiver.
|
||||
func (x IPv6Addr) ContainsNetwork(y IPv6Addr) bool {
|
||||
{
|
||||
xIPv6 := x.FirstUsable().(IPv6Addr)
|
||||
yIPv6 := y.FirstUsable().(IPv6Addr)
|
||||
if ret := xIPv6.CmpAddress(yIPv6); ret >= 1 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
xIPv6 := x.LastUsable().(IPv6Addr)
|
||||
yIPv6 := y.LastUsable().(IPv6Addr)
|
||||
if ret := xIPv6.CmpAddress(yIPv6); ret <= -1 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// DialPacketArgs returns the arguments required to be passed to
|
||||
// net.DialUDP(). If the Mask of ipv6 is not a /128 or the Port is 0,
|
||||
// DialPacketArgs() will fail. See Host() to create an IPv6Addr with its
|
||||
// mask set to /128.
|
||||
func (ipv6 IPv6Addr) DialPacketArgs() (network, dialArgs string) {
|
||||
ipv6Mask := big.Int(*ipv6.Mask)
|
||||
if ipv6Mask.Cmp(ipv6HostMask) != 0 || ipv6.Port == 0 {
|
||||
return "udp6", ""
|
||||
}
|
||||
return "udp6", fmt.Sprintf("[%s]:%d", ipv6.NetIP().String(), ipv6.Port)
|
||||
}
|
||||
|
||||
// DialStreamArgs returns the arguments required to be passed to
|
||||
// net.DialTCP(). If the Mask of ipv6 is not a /128 or the Port is 0,
|
||||
// DialStreamArgs() will fail. See Host() to create an IPv6Addr with its
|
||||
// mask set to /128.
|
||||
func (ipv6 IPv6Addr) DialStreamArgs() (network, dialArgs string) {
|
||||
ipv6Mask := big.Int(*ipv6.Mask)
|
||||
if ipv6Mask.Cmp(ipv6HostMask) != 0 || ipv6.Port == 0 {
|
||||
return "tcp6", ""
|
||||
}
|
||||
return "tcp6", fmt.Sprintf("[%s]:%d", ipv6.NetIP().String(), ipv6.Port)
|
||||
}
|
||||
|
||||
// Equal returns true if a SockAddr is equal to the receiving IPv4Addr.
|
||||
func (ipv6a IPv6Addr) Equal(sa SockAddr) bool {
|
||||
ipv6b, ok := sa.(IPv6Addr)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
if ipv6a.NetIP().String() != ipv6b.NetIP().String() {
|
||||
return false
|
||||
}
|
||||
|
||||
if ipv6a.NetIPNet().String() != ipv6b.NetIPNet().String() {
|
||||
return false
|
||||
}
|
||||
|
||||
if ipv6a.Port != ipv6b.Port {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// FirstUsable returns an IPv6Addr set to the first address following the
|
||||
// network prefix. The first usable address in a network is normally the
|
||||
// gateway and should not be used except by devices forwarding packets
|
||||
// between two administratively distinct networks (i.e. a router). This
|
||||
// function does not discriminate against first usable vs "first address that
|
||||
// should be used." For example, FirstUsable() on "2001:0db8::0003/64" would
|
||||
// return "2001:0db8::00011".
|
||||
func (ipv6 IPv6Addr) FirstUsable() IPAddr {
|
||||
return IPv6Addr{
|
||||
Address: IPv6Address(ipv6.NetworkAddress()),
|
||||
Mask: ipv6HostMask,
|
||||
}
|
||||
}
|
||||
|
||||
// Host returns a copy of ipv6 with its mask set to /128 so that it can be
|
||||
// used by DialPacketArgs(), DialStreamArgs(), ListenPacketArgs(), or
|
||||
// ListenStreamArgs().
|
||||
func (ipv6 IPv6Addr) Host() IPAddr {
|
||||
// Nothing should listen on a broadcast address.
|
||||
return IPv6Addr{
|
||||
Address: ipv6.Address,
|
||||
Mask: ipv6HostMask,
|
||||
Port: ipv6.Port,
|
||||
}
|
||||
}
|
||||
|
||||
// IPPort returns the Port number attached to the IPv6Addr
|
||||
func (ipv6 IPv6Addr) IPPort() IPPort {
|
||||
return ipv6.Port
|
||||
}
|
||||
|
||||
// LastUsable returns the last address in a given network.
|
||||
func (ipv6 IPv6Addr) LastUsable() IPAddr {
|
||||
addr := new(big.Int)
|
||||
addr.Set(ipv6.Address)
|
||||
|
||||
mask := new(big.Int)
|
||||
mask.Set(ipv6.Mask)
|
||||
|
||||
negMask := new(big.Int)
|
||||
negMask.Xor(ipv6HostMask, mask)
|
||||
|
||||
lastAddr := new(big.Int)
|
||||
lastAddr.And(addr, mask)
|
||||
lastAddr.Or(lastAddr, negMask)
|
||||
|
||||
return IPv6Addr{
|
||||
Address: IPv6Address(lastAddr),
|
||||
Mask: ipv6HostMask,
|
||||
}
|
||||
}
|
||||
|
||||
// ListenPacketArgs returns the arguments required to be passed to
|
||||
// net.ListenUDP(). If the Mask of ipv6 is not a /128, ListenPacketArgs()
|
||||
// will fail. See Host() to create an IPv6Addr with its mask set to /128.
|
||||
func (ipv6 IPv6Addr) ListenPacketArgs() (network, listenArgs string) {
|
||||
ipv6Mask := big.Int(*ipv6.Mask)
|
||||
if ipv6Mask.Cmp(ipv6HostMask) != 0 {
|
||||
return "udp6", ""
|
||||
}
|
||||
return "udp6", fmt.Sprintf("[%s]:%d", ipv6.NetIP().String(), ipv6.Port)
|
||||
}
|
||||
|
||||
// ListenStreamArgs returns the arguments required to be passed to
|
||||
// net.ListenTCP(). If the Mask of ipv6 is not a /128, ListenStreamArgs()
|
||||
// will fail. See Host() to create an IPv6Addr with its mask set to /128.
|
||||
func (ipv6 IPv6Addr) ListenStreamArgs() (network, listenArgs string) {
|
||||
ipv6Mask := big.Int(*ipv6.Mask)
|
||||
if ipv6Mask.Cmp(ipv6HostMask) != 0 {
|
||||
return "tcp6", ""
|
||||
}
|
||||
return "tcp6", fmt.Sprintf("[%s]:%d", ipv6.NetIP().String(), ipv6.Port)
|
||||
}
|
||||
|
||||
// Maskbits returns the number of network mask bits in a given IPv6Addr. For
|
||||
// example, the Maskbits() of "2001:0db8::0003/64" would return 64.
|
||||
func (ipv6 IPv6Addr) Maskbits() int {
|
||||
maskOnes, _ := ipv6.NetIPNet().Mask.Size()
|
||||
|
||||
return maskOnes
|
||||
}
|
||||
|
||||
// MustIPv6Addr is a helper method that must return an IPv6Addr or panic on
|
||||
// invalid input.
|
||||
func MustIPv6Addr(addr string) IPv6Addr {
|
||||
ipv6, err := NewIPv6Addr(addr)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Unable to create an IPv6Addr from %+q: %v", addr, err))
|
||||
}
|
||||
return ipv6
|
||||
}
|
||||
|
||||
// NetIP returns the address as a net.IP.
|
||||
func (ipv6 IPv6Addr) NetIP() *net.IP {
|
||||
return bigIntToNetIPv6(ipv6.Address)
|
||||
}
|
||||
|
||||
// NetIPMask create a new net.IPMask from the IPv6Addr.
|
||||
func (ipv6 IPv6Addr) NetIPMask() *net.IPMask {
|
||||
ipv6Mask := make(net.IPMask, IPv6len)
|
||||
m := big.Int(*ipv6.Mask)
|
||||
copy(ipv6Mask, m.Bytes())
|
||||
return &ipv6Mask
|
||||
}
|
||||
|
||||
// Network returns a pointer to the net.IPNet within IPv4Addr receiver.
|
||||
func (ipv6 IPv6Addr) NetIPNet() *net.IPNet {
|
||||
ipv6net := &net.IPNet{}
|
||||
ipv6net.IP = make(net.IP, IPv6len)
|
||||
copy(ipv6net.IP, *ipv6.NetIP())
|
||||
ipv6net.Mask = *ipv6.NetIPMask()
|
||||
return ipv6net
|
||||
}
|
||||
|
||||
// Network returns the network prefix or network address for a given network.
|
||||
func (ipv6 IPv6Addr) Network() IPAddr {
|
||||
return IPv6Addr{
|
||||
Address: IPv6Address(ipv6.NetworkAddress()),
|
||||
Mask: ipv6.Mask,
|
||||
}
|
||||
}
|
||||
|
||||
// NetworkAddress returns an IPv6Network of the IPv6Addr's network address.
|
||||
func (ipv6 IPv6Addr) NetworkAddress() IPv6Network {
|
||||
addr := new(big.Int)
|
||||
addr.SetBytes((*ipv6.Address).Bytes())
|
||||
|
||||
mask := new(big.Int)
|
||||
mask.SetBytes(*ipv6.NetIPMask())
|
||||
|
||||
netAddr := new(big.Int)
|
||||
netAddr.And(addr, mask)
|
||||
|
||||
return IPv6Network(netAddr)
|
||||
}
|
||||
|
||||
// Octets returns a slice of the 16 octets in an IPv6Addr's Address. The
|
||||
// order of the bytes is big endian.
|
||||
func (ipv6 IPv6Addr) Octets() []int {
|
||||
x := make([]int, IPv6len)
|
||||
for i, b := range *bigIntToNetIPv6(ipv6.Address) {
|
||||
x[i] = int(b)
|
||||
}
|
||||
|
||||
return x
|
||||
}
|
||||
|
||||
// String returns a string representation of the IPv6Addr
|
||||
func (ipv6 IPv6Addr) String() string {
|
||||
if ipv6.Port != 0 {
|
||||
return fmt.Sprintf("[%s]:%d", ipv6.NetIP().String(), ipv6.Port)
|
||||
}
|
||||
|
||||
if ipv6.Maskbits() == 128 {
|
||||
return ipv6.NetIP().String()
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s/%d", ipv6.NetIP().String(), ipv6.Maskbits())
|
||||
}
|
||||
|
||||
// Type is used as a type switch and returns TypeIPv6
|
||||
func (IPv6Addr) Type() SockAddrType {
|
||||
return TypeIPv6
|
||||
}
|
||||
|
||||
// IPv6Attrs returns a list of attributes supported by the IPv6Addr type
|
||||
func IPv6Attrs() []AttrName {
|
||||
return ipv6AddrAttrs
|
||||
}
|
||||
|
||||
// IPv6AddrAttr returns a string representation of an attribute for the given
|
||||
// IPv6Addr.
|
||||
func IPv6AddrAttr(ipv6 IPv6Addr, selector AttrName) string {
|
||||
fn, found := ipv6AddrAttrMap[selector]
|
||||
if !found {
|
||||
return ""
|
||||
}
|
||||
|
||||
return fn(ipv6)
|
||||
}
|
||||
|
||||
// ipv6AddrInit is called once at init()
|
||||
func ipv6AddrInit() {
|
||||
// Sorted for human readability
|
||||
ipv6AddrAttrs = []AttrName{
|
||||
"size", // Same position as in IPv6 for output consistency
|
||||
"uint128",
|
||||
}
|
||||
|
||||
ipv6AddrAttrMap = map[AttrName]func(ipv6 IPv6Addr) string{
|
||||
"size": func(ipv6 IPv6Addr) string {
|
||||
netSize := big.NewInt(1)
|
||||
netSize = netSize.Lsh(netSize, uint(IPv6len*8-ipv6.Maskbits()))
|
||||
return netSize.Text(10)
|
||||
},
|
||||
"uint128": func(ipv6 IPv6Addr) string {
|
||||
b := big.Int(*ipv6.Address)
|
||||
return b.Text(10)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// bigIntToNetIPv6 is a helper function that correctly returns a net.IP with the
|
||||
// correctly padded values.
|
||||
func bigIntToNetIPv6(bi *big.Int) *net.IP {
|
||||
x := make(net.IP, IPv6len)
|
||||
ipv6Bytes := bi.Bytes()
|
||||
|
||||
// It's possibe for ipv6Bytes to be less than IPv6len bytes in size. If
|
||||
// they are different sizes we to pad the size of response.
|
||||
if len(ipv6Bytes) < IPv6len {
|
||||
buf := new(bytes.Buffer)
|
||||
buf.Grow(IPv6len)
|
||||
|
||||
for i := len(ipv6Bytes); i < IPv6len; i++ {
|
||||
if err := binary.Write(buf, binary.BigEndian, byte(0)); err != nil {
|
||||
panic(fmt.Sprintf("Unable to pad byte %d of input %v: %v", i, bi, err))
|
||||
}
|
||||
}
|
||||
|
||||
for _, b := range ipv6Bytes {
|
||||
if err := binary.Write(buf, binary.BigEndian, b); err != nil {
|
||||
panic(fmt.Sprintf("Unable to preserve endianness of input %v: %v", bi, err))
|
||||
}
|
||||
}
|
||||
|
||||
ipv6Bytes = buf.Bytes()
|
||||
}
|
||||
i := copy(x, ipv6Bytes)
|
||||
if i != IPv6len {
|
||||
panic("IPv6 wrong size")
|
||||
}
|
||||
return &x
|
||||
}
|
948
vendor/github.com/hashicorp/go-sockaddr/rfc.go
generated
vendored
Normal file
948
vendor/github.com/hashicorp/go-sockaddr/rfc.go
generated
vendored
Normal file
@ -0,0 +1,948 @@
|
||||
package sockaddr
|
||||
|
||||
// ForwardingBlacklist is a faux RFC that includes a list of non-forwardable IP
|
||||
// blocks.
|
||||
const ForwardingBlacklist = 4294967295
|
||||
const ForwardingBlacklistRFC = "4294967295"
|
||||
|
||||
// IsRFC tests to see if an SockAddr matches the specified RFC
|
||||
func IsRFC(rfcNum uint, sa SockAddr) bool {
|
||||
rfcNetMap := KnownRFCs()
|
||||
rfcNets, ok := rfcNetMap[rfcNum]
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
var contained bool
|
||||
for _, rfcNet := range rfcNets {
|
||||
if rfcNet.Contains(sa) {
|
||||
contained = true
|
||||
break
|
||||
}
|
||||
}
|
||||
return contained
|
||||
}
|
||||
|
||||
// KnownRFCs returns an initial set of known RFCs.
|
||||
//
|
||||
// NOTE (sean@): As this list evolves over time, please submit patches to keep
|
||||
// this list current. If something isn't right, inquire, as it may just be a
|
||||
// bug on my part. Some of the inclusions were based on my judgement as to what
|
||||
// would be a useful value (e.g. RFC3330).
|
||||
//
|
||||
// Useful resources:
|
||||
//
|
||||
// * https://www.iana.org/assignments/ipv6-address-space/ipv6-address-space.xhtml
|
||||
// * https://www.iana.org/assignments/ipv6-unicast-address-assignments/ipv6-unicast-address-assignments.xhtml
|
||||
// * https://www.iana.org/assignments/ipv6-address-space/ipv6-address-space.xhtml
|
||||
func KnownRFCs() map[uint]SockAddrs {
|
||||
// NOTE(sean@): Multiple SockAddrs per RFC lend themselves well to a
|
||||
// RADIX tree, but `ENOTIME`. Patches welcome.
|
||||
return map[uint]SockAddrs{
|
||||
919: {
|
||||
// [RFC919] Broadcasting Internet Datagrams
|
||||
MustIPv4Addr("255.255.255.255/32"), // [RFC1122], §7 Broadcast IP Addressing - Proposed Standards
|
||||
},
|
||||
1122: {
|
||||
// [RFC1122] Requirements for Internet Hosts -- Communication Layers
|
||||
MustIPv4Addr("0.0.0.0/8"), // [RFC1122], §3.2.1.3
|
||||
MustIPv4Addr("127.0.0.0/8"), // [RFC1122], §3.2.1.3
|
||||
},
|
||||
1112: {
|
||||
// [RFC1112] Host Extensions for IP Multicasting
|
||||
MustIPv4Addr("224.0.0.0/4"), // [RFC1112], §4 Host Group Addresses
|
||||
},
|
||||
1918: {
|
||||
// [RFC1918] Address Allocation for Private Internets
|
||||
MustIPv4Addr("10.0.0.0/8"),
|
||||
MustIPv4Addr("172.16.0.0/12"),
|
||||
MustIPv4Addr("192.168.0.0/16"),
|
||||
},
|
||||
2544: {
|
||||
// [RFC2544] Benchmarking Methodology for Network
|
||||
// Interconnect Devices
|
||||
MustIPv4Addr("198.18.0.0/15"),
|
||||
},
|
||||
2765: {
|
||||
// [RFC2765] Stateless IP/ICMP Translation Algorithm
|
||||
// (SIIT) (obsoleted by RFCs 6145, which itself was
|
||||
// later obsoleted by 7915).
|
||||
|
||||
// [RFC2765], §2.1 Addresses
|
||||
MustIPv6Addr("0:0:0:0:0:ffff:0:0/96"),
|
||||
},
|
||||
2928: {
|
||||
// [RFC2928] Initial IPv6 Sub-TLA ID Assignments
|
||||
MustIPv6Addr("2001::/16"), // Superblock
|
||||
//MustIPv6Addr("2001:0000::/23"), // IANA
|
||||
//MustIPv6Addr("2001:0200::/23"), // APNIC
|
||||
//MustIPv6Addr("2001:0400::/23"), // ARIN
|
||||
//MustIPv6Addr("2001:0600::/23"), // RIPE NCC
|
||||
//MustIPv6Addr("2001:0800::/23"), // (future assignment)
|
||||
// ...
|
||||
//MustIPv6Addr("2001:FE00::/23"), // (future assignment)
|
||||
},
|
||||
3056: { // 6to4 address
|
||||
// [RFC3056] Connection of IPv6 Domains via IPv4 Clouds
|
||||
|
||||
// [RFC3056], §2 IPv6 Prefix Allocation
|
||||
MustIPv6Addr("2002::/16"),
|
||||
},
|
||||
3068: {
|
||||
// [RFC3068] An Anycast Prefix for 6to4 Relay Routers
|
||||
// (obsolete by RFC7526)
|
||||
|
||||
// [RFC3068], § 6to4 Relay anycast address
|
||||
MustIPv4Addr("192.88.99.0/24"),
|
||||
|
||||
// [RFC3068], §2.5 6to4 IPv6 relay anycast address
|
||||
//
|
||||
// NOTE: /120 == 128-(32-24)
|
||||
MustIPv6Addr("2002:c058:6301::/120"),
|
||||
},
|
||||
3171: {
|
||||
// [RFC3171] IANA Guidelines for IPv4 Multicast Address Assignments
|
||||
MustIPv4Addr("224.0.0.0/4"),
|
||||
},
|
||||
3330: {
|
||||
// [RFC3330] Special-Use IPv4 Addresses
|
||||
|
||||
// Addresses in this block refer to source hosts on
|
||||
// "this" network. Address 0.0.0.0/32 may be used as a
|
||||
// source address for this host on this network; other
|
||||
// addresses within 0.0.0.0/8 may be used to refer to
|
||||
// specified hosts on this network [RFC1700, page 4].
|
||||
MustIPv4Addr("0.0.0.0/8"),
|
||||
|
||||
// 10.0.0.0/8 - This block is set aside for use in
|
||||
// private networks. Its intended use is documented in
|
||||
// [RFC1918]. Addresses within this block should not
|
||||
// appear on the public Internet.
|
||||
MustIPv4Addr("10.0.0.0/8"),
|
||||
|
||||
// 14.0.0.0/8 - This block is set aside for assignments
|
||||
// to the international system of Public Data Networks
|
||||
// [RFC1700, page 181]. The registry of assignments
|
||||
// within this block can be accessed from the "Public
|
||||
// Data Network Numbers" link on the web page at
|
||||
// http://www.iana.org/numbers.html. Addresses within
|
||||
// this block are assigned to users and should be
|
||||
// treated as such.
|
||||
|
||||
// 24.0.0.0/8 - This block was allocated in early 1996
|
||||
// for use in provisioning IP service over cable
|
||||
// television systems. Although the IANA initially was
|
||||
// involved in making assignments to cable operators,
|
||||
// this responsibility was transferred to American
|
||||
// Registry for Internet Numbers (ARIN) in May 2001.
|
||||
// Addresses within this block are assigned in the
|
||||
// normal manner and should be treated as such.
|
||||
|
||||
// 39.0.0.0/8 - This block was used in the "Class A
|
||||
// Subnet Experiment" that commenced in May 1995, as
|
||||
// documented in [RFC1797]. The experiment has been
|
||||
// completed and this block has been returned to the
|
||||
// pool of addresses reserved for future allocation or
|
||||
// assignment. This block therefore no longer has a
|
||||
// special use and is subject to allocation to a
|
||||
// Regional Internet Registry for assignment in the
|
||||
// normal manner.
|
||||
|
||||
// 127.0.0.0/8 - This block is assigned for use as the Internet host
|
||||
// loopback address. A datagram sent by a higher level protocol to an
|
||||
// address anywhere within this block should loop back inside the host.
|
||||
// This is ordinarily implemented using only 127.0.0.1/32 for loopback,
|
||||
// but no addresses within this block should ever appear on any network
|
||||
// anywhere [RFC1700, page 5].
|
||||
MustIPv4Addr("127.0.0.0/8"),
|
||||
|
||||
// 128.0.0.0/16 - This block, corresponding to the
|
||||
// numerically lowest of the former Class B addresses,
|
||||
// was initially and is still reserved by the IANA.
|
||||
// Given the present classless nature of the IP address
|
||||
// space, the basis for the reservation no longer
|
||||
// applies and addresses in this block are subject to
|
||||
// future allocation to a Regional Internet Registry for
|
||||
// assignment in the normal manner.
|
||||
|
||||
// 169.254.0.0/16 - This is the "link local" block. It
|
||||
// is allocated for communication between hosts on a
|
||||
// single link. Hosts obtain these addresses by
|
||||
// auto-configuration, such as when a DHCP server may
|
||||
// not be found.
|
||||
MustIPv4Addr("169.254.0.0/16"),
|
||||
|
||||
// 172.16.0.0/12 - This block is set aside for use in
|
||||
// private networks. Its intended use is documented in
|
||||
// [RFC1918]. Addresses within this block should not
|
||||
// appear on the public Internet.
|
||||
MustIPv4Addr("172.16.0.0/12"),
|
||||
|
||||
// 191.255.0.0/16 - This block, corresponding to the numerically highest
|
||||
// to the former Class B addresses, was initially and is still reserved
|
||||
// by the IANA. Given the present classless nature of the IP address
|
||||
// space, the basis for the reservation no longer applies and addresses
|
||||
// in this block are subject to future allocation to a Regional Internet
|
||||
// Registry for assignment in the normal manner.
|
||||
|
||||
// 192.0.0.0/24 - This block, corresponding to the
|
||||
// numerically lowest of the former Class C addresses,
|
||||
// was initially and is still reserved by the IANA.
|
||||
// Given the present classless nature of the IP address
|
||||
// space, the basis for the reservation no longer
|
||||
// applies and addresses in this block are subject to
|
||||
// future allocation to a Regional Internet Registry for
|
||||
// assignment in the normal manner.
|
||||
|
||||
// 192.0.2.0/24 - This block is assigned as "TEST-NET" for use in
|
||||
// documentation and example code. It is often used in conjunction with
|
||||
// domain names example.com or example.net in vendor and protocol
|
||||
// documentation. Addresses within this block should not appear on the
|
||||
// public Internet.
|
||||
MustIPv4Addr("192.0.2.0/24"),
|
||||
|
||||
// 192.88.99.0/24 - This block is allocated for use as 6to4 relay
|
||||
// anycast addresses, according to [RFC3068].
|
||||
MustIPv4Addr("192.88.99.0/24"),
|
||||
|
||||
// 192.168.0.0/16 - This block is set aside for use in private networks.
|
||||
// Its intended use is documented in [RFC1918]. Addresses within this
|
||||
// block should not appear on the public Internet.
|
||||
MustIPv4Addr("192.168.0.0/16"),
|
||||
|
||||
// 198.18.0.0/15 - This block has been allocated for use
|
||||
// in benchmark tests of network interconnect devices.
|
||||
// Its use is documented in [RFC2544].
|
||||
MustIPv4Addr("198.18.0.0/15"),
|
||||
|
||||
// 223.255.255.0/24 - This block, corresponding to the
|
||||
// numerically highest of the former Class C addresses,
|
||||
// was initially and is still reserved by the IANA.
|
||||
// Given the present classless nature of the IP address
|
||||
// space, the basis for the reservation no longer
|
||||
// applies and addresses in this block are subject to
|
||||
// future allocation to a Regional Internet Registry for
|
||||
// assignment in the normal manner.
|
||||
|
||||
// 224.0.0.0/4 - This block, formerly known as the Class
|
||||
// D address space, is allocated for use in IPv4
|
||||
// multicast address assignments. The IANA guidelines
|
||||
// for assignments from this space are described in
|
||||
// [RFC3171].
|
||||
MustIPv4Addr("224.0.0.0/4"),
|
||||
|
||||
// 240.0.0.0/4 - This block, formerly known as the Class E address
|
||||
// space, is reserved. The "limited broadcast" destination address
|
||||
// 255.255.255.255 should never be forwarded outside the (sub-)net of
|
||||
// the source. The remainder of this space is reserved
|
||||
// for future use. [RFC1700, page 4]
|
||||
MustIPv4Addr("240.0.0.0/4"),
|
||||
},
|
||||
3849: {
|
||||
// [RFC3849] IPv6 Address Prefix Reserved for Documentation
|
||||
MustIPv6Addr("2001:db8::/32"), // [RFC3849], §4 IANA Considerations
|
||||
},
|
||||
3927: {
|
||||
// [RFC3927] Dynamic Configuration of IPv4 Link-Local Addresses
|
||||
MustIPv4Addr("169.254.0.0/16"), // [RFC3927], §2.1 Link-Local Address Selection
|
||||
},
|
||||
4038: {
|
||||
// [RFC4038] Application Aspects of IPv6 Transition
|
||||
|
||||
// [RFC4038], §4.2. IPv6 Applications in a Dual-Stack Node
|
||||
MustIPv6Addr("0:0:0:0:0:ffff::/96"),
|
||||
},
|
||||
4193: {
|
||||
// [RFC4193] Unique Local IPv6 Unicast Addresses
|
||||
MustIPv6Addr("fc00::/7"),
|
||||
},
|
||||
4291: {
|
||||
// [RFC4291] IP Version 6 Addressing Architecture
|
||||
|
||||
// [RFC4291], §2.5.2 The Unspecified Address
|
||||
MustIPv6Addr("::/128"),
|
||||
|
||||
// [RFC4291], §2.5.3 The Loopback Address
|
||||
MustIPv6Addr("::1/128"),
|
||||
|
||||
// [RFC4291], §2.5.5.1. IPv4-Compatible IPv6 Address
|
||||
MustIPv6Addr("::/96"),
|
||||
|
||||
// [RFC4291], §2.5.5.2. IPv4-Mapped IPv6 Address
|
||||
MustIPv6Addr("::ffff:0:0/96"),
|
||||
|
||||
// [RFC4291], §2.5.6 Link-Local IPv6 Unicast Addresses
|
||||
MustIPv6Addr("fe80::/10"),
|
||||
|
||||
// [RFC4291], §2.5.7 Site-Local IPv6 Unicast Addresses
|
||||
// (depreciated)
|
||||
MustIPv6Addr("fec0::/10"),
|
||||
|
||||
// [RFC4291], §2.7 Multicast Addresses
|
||||
MustIPv6Addr("ff00::/8"),
|
||||
|
||||
// IPv6 Multicast Information.
|
||||
//
|
||||
// In the following "table" below, `ff0x` is replaced
|
||||
// with the following values depending on the scope of
|
||||
// the query:
|
||||
//
|
||||
// IPv6 Multicast Scopes:
|
||||
// * ff00/9 // reserved
|
||||
// * ff01/9 // interface-local
|
||||
// * ff02/9 // link-local
|
||||
// * ff03/9 // realm-local
|
||||
// * ff04/9 // admin-local
|
||||
// * ff05/9 // site-local
|
||||
// * ff08/9 // organization-local
|
||||
// * ff0e/9 // global
|
||||
// * ff0f/9 // reserved
|
||||
//
|
||||
// IPv6 Multicast Addresses:
|
||||
// * ff0x::2 // All routers
|
||||
// * ff02::5 // OSPFIGP
|
||||
// * ff02::6 // OSPFIGP Designated Routers
|
||||
// * ff02::9 // RIP Routers
|
||||
// * ff02::a // EIGRP Routers
|
||||
// * ff02::d // All PIM Routers
|
||||
// * ff02::1a // All RPL Routers
|
||||
// * ff0x::fb // mDNSv6
|
||||
// * ff0x::101 // All Network Time Protocol (NTP) servers
|
||||
// * ff02::1:1 // Link Name
|
||||
// * ff02::1:2 // All-dhcp-agents
|
||||
// * ff02::1:3 // Link-local Multicast Name Resolution
|
||||
// * ff05::1:3 // All-dhcp-servers
|
||||
// * ff02::1:ff00:0/104 // Solicited-node multicast address.
|
||||
// * ff02::2:ff00:0/104 // Node Information Queries
|
||||
},
|
||||
4380: {
|
||||
// [RFC4380] Teredo: Tunneling IPv6 over UDP through
|
||||
// Network Address Translations (NATs)
|
||||
|
||||
// [RFC4380], §2.6 Global Teredo IPv6 Service Prefix
|
||||
MustIPv6Addr("2001:0000::/32"),
|
||||
},
|
||||
4773: {
|
||||
// [RFC4773] Administration of the IANA Special Purpose IPv6 Address Block
|
||||
MustIPv6Addr("2001:0000::/23"), // IANA
|
||||
},
|
||||
4843: {
|
||||
// [RFC4843] An IPv6 Prefix for Overlay Routable Cryptographic Hash Identifiers (ORCHID)
|
||||
MustIPv6Addr("2001:10::/28"), // [RFC4843], §7 IANA Considerations
|
||||
},
|
||||
5180: {
|
||||
// [RFC5180] IPv6 Benchmarking Methodology for Network Interconnect Devices
|
||||
MustIPv6Addr("2001:0200::/48"), // [RFC5180], §8 IANA Considerations
|
||||
},
|
||||
5735: {
|
||||
// [RFC5735] Special Use IPv4 Addresses
|
||||
MustIPv4Addr("192.0.2.0/24"), // TEST-NET-1
|
||||
MustIPv4Addr("198.51.100.0/24"), // TEST-NET-2
|
||||
MustIPv4Addr("203.0.113.0/24"), // TEST-NET-3
|
||||
MustIPv4Addr("198.18.0.0/15"), // Benchmarks
|
||||
},
|
||||
5737: {
|
||||
// [RFC5737] IPv4 Address Blocks Reserved for Documentation
|
||||
MustIPv4Addr("192.0.2.0/24"), // TEST-NET-1
|
||||
MustIPv4Addr("198.51.100.0/24"), // TEST-NET-2
|
||||
MustIPv4Addr("203.0.113.0/24"), // TEST-NET-3
|
||||
},
|
||||
6052: {
|
||||
// [RFC6052] IPv6 Addressing of IPv4/IPv6 Translators
|
||||
MustIPv6Addr("64:ff9b::/96"), // [RFC6052], §2.1. Well-Known Prefix
|
||||
},
|
||||
6333: {
|
||||
// [RFC6333] Dual-Stack Lite Broadband Deployments Following IPv4 Exhaustion
|
||||
MustIPv4Addr("192.0.0.0/29"), // [RFC6333], §5.7 Well-Known IPv4 Address
|
||||
},
|
||||
6598: {
|
||||
// [RFC6598] IANA-Reserved IPv4 Prefix for Shared Address Space
|
||||
MustIPv4Addr("100.64.0.0/10"),
|
||||
},
|
||||
6666: {
|
||||
// [RFC6666] A Discard Prefix for IPv6
|
||||
MustIPv6Addr("0100::/64"),
|
||||
},
|
||||
6890: {
|
||||
// [RFC6890] Special-Purpose IP Address Registries
|
||||
|
||||
// From "RFC6890 §2.2.1 Information Requirements":
|
||||
/*
|
||||
The IPv4 and IPv6 Special-Purpose Address Registries maintain the
|
||||
following information regarding each entry:
|
||||
|
||||
o Address Block - A block of IPv4 or IPv6 addresses that has been
|
||||
registered for a special purpose.
|
||||
|
||||
o Name - A descriptive name for the special-purpose address block.
|
||||
|
||||
o RFC - The RFC through which the special-purpose address block was
|
||||
requested.
|
||||
|
||||
o Allocation Date - The date upon which the special-purpose address
|
||||
block was allocated.
|
||||
|
||||
o Termination Date - The date upon which the allocation is to be
|
||||
terminated. This field is applicable for limited-use allocations
|
||||
only.
|
||||
|
||||
o Source - A boolean value indicating whether an address from the
|
||||
allocated special-purpose address block is valid when used as the
|
||||
source address of an IP datagram that transits two devices.
|
||||
|
||||
o Destination - A boolean value indicating whether an address from
|
||||
the allocated special-purpose address block is valid when used as
|
||||
the destination address of an IP datagram that transits two
|
||||
devices.
|
||||
|
||||
o Forwardable - A boolean value indicating whether a router may
|
||||
forward an IP datagram whose destination address is drawn from the
|
||||
allocated special-purpose address block between external
|
||||
interfaces.
|
||||
|
||||
o Global - A boolean value indicating whether an IP datagram whose
|
||||
destination address is drawn from the allocated special-purpose
|
||||
address block is forwardable beyond a specified administrative
|
||||
domain.
|
||||
|
||||
o Reserved-by-Protocol - A boolean value indicating whether the
|
||||
special-purpose address block is reserved by IP, itself. This
|
||||
value is "TRUE" if the RFC that created the special-purpose
|
||||
address block requires all compliant IP implementations to behave
|
||||
in a special way when processing packets either to or from
|
||||
addresses contained by the address block.
|
||||
|
||||
If the value of "Destination" is FALSE, the values of "Forwardable"
|
||||
and "Global" must also be false.
|
||||
*/
|
||||
|
||||
/*+----------------------+----------------------------+
|
||||
* | Attribute | Value |
|
||||
* +----------------------+----------------------------+
|
||||
* | Address Block | 0.0.0.0/8 |
|
||||
* | Name | "This host on this network"|
|
||||
* | RFC | [RFC1122], Section 3.2.1.3 |
|
||||
* | Allocation Date | September 1981 |
|
||||
* | Termination Date | N/A |
|
||||
* | Source | True |
|
||||
* | Destination | False |
|
||||
* | Forwardable | False |
|
||||
* | Global | False |
|
||||
* | Reserved-by-Protocol | True |
|
||||
* +----------------------+----------------------------+*/
|
||||
MustIPv4Addr("0.0.0.0/8"),
|
||||
|
||||
/*+----------------------+---------------+
|
||||
* | Attribute | Value |
|
||||
* +----------------------+---------------+
|
||||
* | Address Block | 10.0.0.0/8 |
|
||||
* | Name | Private-Use |
|
||||
* | RFC | [RFC1918] |
|
||||
* | Allocation Date | February 1996 |
|
||||
* | Termination Date | N/A |
|
||||
* | Source | True |
|
||||
* | Destination | True |
|
||||
* | Forwardable | True |
|
||||
* | Global | False |
|
||||
* | Reserved-by-Protocol | False |
|
||||
* +----------------------+---------------+ */
|
||||
MustIPv4Addr("10.0.0.0/8"),
|
||||
|
||||
/*+----------------------+----------------------+
|
||||
| Attribute | Value |
|
||||
+----------------------+----------------------+
|
||||
| Address Block | 100.64.0.0/10 |
|
||||
| Name | Shared Address Space |
|
||||
| RFC | [RFC6598] |
|
||||
| Allocation Date | April 2012 |
|
||||
| Termination Date | N/A |
|
||||
| Source | True |
|
||||
| Destination | True |
|
||||
| Forwardable | True |
|
||||
| Global | False |
|
||||
| Reserved-by-Protocol | False |
|
||||
+----------------------+----------------------+*/
|
||||
MustIPv4Addr("100.64.0.0/10"),
|
||||
|
||||
/*+----------------------+----------------------------+
|
||||
| Attribute | Value |
|
||||
+----------------------+----------------------------+
|
||||
| Address Block | 127.0.0.0/8 |
|
||||
| Name | Loopback |
|
||||
| RFC | [RFC1122], Section 3.2.1.3 |
|
||||
| Allocation Date | September 1981 |
|
||||
| Termination Date | N/A |
|
||||
| Source | False [1] |
|
||||
| Destination | False [1] |
|
||||
| Forwardable | False [1] |
|
||||
| Global | False [1] |
|
||||
| Reserved-by-Protocol | True |
|
||||
+----------------------+----------------------------+*/
|
||||
// [1] Several protocols have been granted exceptions to
|
||||
// this rule. For examples, see [RFC4379] and
|
||||
// [RFC5884].
|
||||
MustIPv4Addr("127.0.0.0/8"),
|
||||
|
||||
/*+----------------------+----------------+
|
||||
| Attribute | Value |
|
||||
+----------------------+----------------+
|
||||
| Address Block | 169.254.0.0/16 |
|
||||
| Name | Link Local |
|
||||
| RFC | [RFC3927] |
|
||||
| Allocation Date | May 2005 |
|
||||
| Termination Date | N/A |
|
||||
| Source | True |
|
||||
| Destination | True |
|
||||
| Forwardable | False |
|
||||
| Global | False |
|
||||
| Reserved-by-Protocol | True |
|
||||
+----------------------+----------------+*/
|
||||
MustIPv4Addr("169.254.0.0/16"),
|
||||
|
||||
/*+----------------------+---------------+
|
||||
| Attribute | Value |
|
||||
+----------------------+---------------+
|
||||
| Address Block | 172.16.0.0/12 |
|
||||
| Name | Private-Use |
|
||||
| RFC | [RFC1918] |
|
||||
| Allocation Date | February 1996 |
|
||||
| Termination Date | N/A |
|
||||
| Source | True |
|
||||
| Destination | True |
|
||||
| Forwardable | True |
|
||||
| Global | False |
|
||||
| Reserved-by-Protocol | False |
|
||||
+----------------------+---------------+*/
|
||||
MustIPv4Addr("172.16.0.0/12"),
|
||||
|
||||
/*+----------------------+---------------------------------+
|
||||
| Attribute | Value |
|
||||
+----------------------+---------------------------------+
|
||||
| Address Block | 192.0.0.0/24 [2] |
|
||||
| Name | IETF Protocol Assignments |
|
||||
| RFC | Section 2.1 of this document |
|
||||
| Allocation Date | January 2010 |
|
||||
| Termination Date | N/A |
|
||||
| Source | False |
|
||||
| Destination | False |
|
||||
| Forwardable | False |
|
||||
| Global | False |
|
||||
| Reserved-by-Protocol | False |
|
||||
+----------------------+---------------------------------+*/
|
||||
// [2] Not usable unless by virtue of a more specific
|
||||
// reservation.
|
||||
MustIPv4Addr("192.0.0.0/24"),
|
||||
|
||||
/*+----------------------+--------------------------------+
|
||||
| Attribute | Value |
|
||||
+----------------------+--------------------------------+
|
||||
| Address Block | 192.0.0.0/29 |
|
||||
| Name | IPv4 Service Continuity Prefix |
|
||||
| RFC | [RFC6333], [RFC7335] |
|
||||
| Allocation Date | June 2011 |
|
||||
| Termination Date | N/A |
|
||||
| Source | True |
|
||||
| Destination | True |
|
||||
| Forwardable | True |
|
||||
| Global | False |
|
||||
| Reserved-by-Protocol | False |
|
||||
+----------------------+--------------------------------+*/
|
||||
MustIPv4Addr("192.0.0.0/29"),
|
||||
|
||||
/*+----------------------+----------------------------+
|
||||
| Attribute | Value |
|
||||
+----------------------+----------------------------+
|
||||
| Address Block | 192.0.2.0/24 |
|
||||
| Name | Documentation (TEST-NET-1) |
|
||||
| RFC | [RFC5737] |
|
||||
| Allocation Date | January 2010 |
|
||||
| Termination Date | N/A |
|
||||
| Source | False |
|
||||
| Destination | False |
|
||||
| Forwardable | False |
|
||||
| Global | False |
|
||||
| Reserved-by-Protocol | False |
|
||||
+----------------------+----------------------------+*/
|
||||
MustIPv4Addr("192.0.2.0/24"),
|
||||
|
||||
/*+----------------------+--------------------+
|
||||
| Attribute | Value |
|
||||
+----------------------+--------------------+
|
||||
| Address Block | 192.88.99.0/24 |
|
||||
| Name | 6to4 Relay Anycast |
|
||||
| RFC | [RFC3068] |
|
||||
| Allocation Date | June 2001 |
|
||||
| Termination Date | N/A |
|
||||
| Source | True |
|
||||
| Destination | True |
|
||||
| Forwardable | True |
|
||||
| Global | True |
|
||||
| Reserved-by-Protocol | False |
|
||||
+----------------------+--------------------+*/
|
||||
MustIPv4Addr("192.88.99.0/24"),
|
||||
|
||||
/*+----------------------+----------------+
|
||||
| Attribute | Value |
|
||||
+----------------------+----------------+
|
||||
| Address Block | 192.168.0.0/16 |
|
||||
| Name | Private-Use |
|
||||
| RFC | [RFC1918] |
|
||||
| Allocation Date | February 1996 |
|
||||
| Termination Date | N/A |
|
||||
| Source | True |
|
||||
| Destination | True |
|
||||
| Forwardable | True |
|
||||
| Global | False |
|
||||
| Reserved-by-Protocol | False |
|
||||
+----------------------+----------------+*/
|
||||
MustIPv4Addr("192.168.0.0/16"),
|
||||
|
||||
/*+----------------------+---------------+
|
||||
| Attribute | Value |
|
||||
+----------------------+---------------+
|
||||
| Address Block | 198.18.0.0/15 |
|
||||
| Name | Benchmarking |
|
||||
| RFC | [RFC2544] |
|
||||
| Allocation Date | March 1999 |
|
||||
| Termination Date | N/A |
|
||||
| Source | True |
|
||||
| Destination | True |
|
||||
| Forwardable | True |
|
||||
| Global | False |
|
||||
| Reserved-by-Protocol | False |
|
||||
+----------------------+---------------+*/
|
||||
MustIPv4Addr("198.18.0.0/15"),
|
||||
|
||||
/*+----------------------+----------------------------+
|
||||
| Attribute | Value |
|
||||
+----------------------+----------------------------+
|
||||
| Address Block | 198.51.100.0/24 |
|
||||
| Name | Documentation (TEST-NET-2) |
|
||||
| RFC | [RFC5737] |
|
||||
| Allocation Date | January 2010 |
|
||||
| Termination Date | N/A |
|
||||
| Source | False |
|
||||
| Destination | False |
|
||||
| Forwardable | False |
|
||||
| Global | False |
|
||||
| Reserved-by-Protocol | False |
|
||||
+----------------------+----------------------------+*/
|
||||
MustIPv4Addr("198.51.100.0/24"),
|
||||
|
||||
/*+----------------------+----------------------------+
|
||||
| Attribute | Value |
|
||||
+----------------------+----------------------------+
|
||||
| Address Block | 203.0.113.0/24 |
|
||||
| Name | Documentation (TEST-NET-3) |
|
||||
| RFC | [RFC5737] |
|
||||
| Allocation Date | January 2010 |
|
||||
| Termination Date | N/A |
|
||||
| Source | False |
|
||||
| Destination | False |
|
||||
| Forwardable | False |
|
||||
| Global | False |
|
||||
| Reserved-by-Protocol | False |
|
||||
+----------------------+----------------------------+*/
|
||||
MustIPv4Addr("203.0.113.0/24"),
|
||||
|
||||
/*+----------------------+----------------------+
|
||||
| Attribute | Value |
|
||||
+----------------------+----------------------+
|
||||
| Address Block | 240.0.0.0/4 |
|
||||
| Name | Reserved |
|
||||
| RFC | [RFC1112], Section 4 |
|
||||
| Allocation Date | August 1989 |
|
||||
| Termination Date | N/A |
|
||||
| Source | False |
|
||||
| Destination | False |
|
||||
| Forwardable | False |
|
||||
| Global | False |
|
||||
| Reserved-by-Protocol | True |
|
||||
+----------------------+----------------------+*/
|
||||
MustIPv4Addr("240.0.0.0/4"),
|
||||
|
||||
/*+----------------------+----------------------+
|
||||
| Attribute | Value |
|
||||
+----------------------+----------------------+
|
||||
| Address Block | 255.255.255.255/32 |
|
||||
| Name | Limited Broadcast |
|
||||
| RFC | [RFC0919], Section 7 |
|
||||
| Allocation Date | October 1984 |
|
||||
| Termination Date | N/A |
|
||||
| Source | False |
|
||||
| Destination | True |
|
||||
| Forwardable | False |
|
||||
| Global | False |
|
||||
| Reserved-by-Protocol | False |
|
||||
+----------------------+----------------------+*/
|
||||
MustIPv4Addr("255.255.255.255/32"),
|
||||
|
||||
/*+----------------------+------------------+
|
||||
| Attribute | Value |
|
||||
+----------------------+------------------+
|
||||
| Address Block | ::1/128 |
|
||||
| Name | Loopback Address |
|
||||
| RFC | [RFC4291] |
|
||||
| Allocation Date | February 2006 |
|
||||
| Termination Date | N/A |
|
||||
| Source | False |
|
||||
| Destination | False |
|
||||
| Forwardable | False |
|
||||
| Global | False |
|
||||
| Reserved-by-Protocol | True |
|
||||
+----------------------+------------------+*/
|
||||
MustIPv6Addr("::1/128"),
|
||||
|
||||
/*+----------------------+---------------------+
|
||||
| Attribute | Value |
|
||||
+----------------------+---------------------+
|
||||
| Address Block | ::/128 |
|
||||
| Name | Unspecified Address |
|
||||
| RFC | [RFC4291] |
|
||||
| Allocation Date | February 2006 |
|
||||
| Termination Date | N/A |
|
||||
| Source | True |
|
||||
| Destination | False |
|
||||
| Forwardable | False |
|
||||
| Global | False |
|
||||
| Reserved-by-Protocol | True |
|
||||
+----------------------+---------------------+*/
|
||||
MustIPv6Addr("::/128"),
|
||||
|
||||
/*+----------------------+---------------------+
|
||||
| Attribute | Value |
|
||||
+----------------------+---------------------+
|
||||
| Address Block | 64:ff9b::/96 |
|
||||
| Name | IPv4-IPv6 Translat. |
|
||||
| RFC | [RFC6052] |
|
||||
| Allocation Date | October 2010 |
|
||||
| Termination Date | N/A |
|
||||
| Source | True |
|
||||
| Destination | True |
|
||||
| Forwardable | True |
|
||||
| Global | True |
|
||||
| Reserved-by-Protocol | False |
|
||||
+----------------------+---------------------+*/
|
||||
MustIPv6Addr("64:ff9b::/96"),
|
||||
|
||||
/*+----------------------+---------------------+
|
||||
| Attribute | Value |
|
||||
+----------------------+---------------------+
|
||||
| Address Block | ::ffff:0:0/96 |
|
||||
| Name | IPv4-mapped Address |
|
||||
| RFC | [RFC4291] |
|
||||
| Allocation Date | February 2006 |
|
||||
| Termination Date | N/A |
|
||||
| Source | False |
|
||||
| Destination | False |
|
||||
| Forwardable | False |
|
||||
| Global | False |
|
||||
| Reserved-by-Protocol | True |
|
||||
+----------------------+---------------------+*/
|
||||
MustIPv6Addr("::ffff:0:0/96"),
|
||||
|
||||
/*+----------------------+----------------------------+
|
||||
| Attribute | Value |
|
||||
+----------------------+----------------------------+
|
||||
| Address Block | 100::/64 |
|
||||
| Name | Discard-Only Address Block |
|
||||
| RFC | [RFC6666] |
|
||||
| Allocation Date | June 2012 |
|
||||
| Termination Date | N/A |
|
||||
| Source | True |
|
||||
| Destination | True |
|
||||
| Forwardable | True |
|
||||
| Global | False |
|
||||
| Reserved-by-Protocol | False |
|
||||
+----------------------+----------------------------+*/
|
||||
MustIPv6Addr("100::/64"),
|
||||
|
||||
/*+----------------------+---------------------------+
|
||||
| Attribute | Value |
|
||||
+----------------------+---------------------------+
|
||||
| Address Block | 2001::/23 |
|
||||
| Name | IETF Protocol Assignments |
|
||||
| RFC | [RFC2928] |
|
||||
| Allocation Date | September 2000 |
|
||||
| Termination Date | N/A |
|
||||
| Source | False[1] |
|
||||
| Destination | False[1] |
|
||||
| Forwardable | False[1] |
|
||||
| Global | False[1] |
|
||||
| Reserved-by-Protocol | False |
|
||||
+----------------------+---------------------------+*/
|
||||
// [1] Unless allowed by a more specific allocation.
|
||||
MustIPv6Addr("2001::/16"),
|
||||
|
||||
/*+----------------------+----------------+
|
||||
| Attribute | Value |
|
||||
+----------------------+----------------+
|
||||
| Address Block | 2001::/32 |
|
||||
| Name | TEREDO |
|
||||
| RFC | [RFC4380] |
|
||||
| Allocation Date | January 2006 |
|
||||
| Termination Date | N/A |
|
||||
| Source | True |
|
||||
| Destination | True |
|
||||
| Forwardable | True |
|
||||
| Global | False |
|
||||
| Reserved-by-Protocol | False |
|
||||
+----------------------+----------------+*/
|
||||
// Covered by previous entry, included for completeness.
|
||||
//
|
||||
// MustIPv6Addr("2001::/16"),
|
||||
|
||||
/*+----------------------+----------------+
|
||||
| Attribute | Value |
|
||||
+----------------------+----------------+
|
||||
| Address Block | 2001:2::/48 |
|
||||
| Name | Benchmarking |
|
||||
| RFC | [RFC5180] |
|
||||
| Allocation Date | April 2008 |
|
||||
| Termination Date | N/A |
|
||||
| Source | True |
|
||||
| Destination | True |
|
||||
| Forwardable | True |
|
||||
| Global | False |
|
||||
| Reserved-by-Protocol | False |
|
||||
+----------------------+----------------+*/
|
||||
// Covered by previous entry, included for completeness.
|
||||
//
|
||||
// MustIPv6Addr("2001:2::/48"),
|
||||
|
||||
/*+----------------------+---------------+
|
||||
| Attribute | Value |
|
||||
+----------------------+---------------+
|
||||
| Address Block | 2001:db8::/32 |
|
||||
| Name | Documentation |
|
||||
| RFC | [RFC3849] |
|
||||
| Allocation Date | July 2004 |
|
||||
| Termination Date | N/A |
|
||||
| Source | False |
|
||||
| Destination | False |
|
||||
| Forwardable | False |
|
||||
| Global | False |
|
||||
| Reserved-by-Protocol | False |
|
||||
+----------------------+---------------+*/
|
||||
// Covered by previous entry, included for completeness.
|
||||
//
|
||||
// MustIPv6Addr("2001:db8::/32"),
|
||||
|
||||
/*+----------------------+--------------+
|
||||
| Attribute | Value |
|
||||
+----------------------+--------------+
|
||||
| Address Block | 2001:10::/28 |
|
||||
| Name | ORCHID |
|
||||
| RFC | [RFC4843] |
|
||||
| Allocation Date | March 2007 |
|
||||
| Termination Date | March 2014 |
|
||||
| Source | False |
|
||||
| Destination | False |
|
||||
| Forwardable | False |
|
||||
| Global | False |
|
||||
| Reserved-by-Protocol | False |
|
||||
+----------------------+--------------+*/
|
||||
// Covered by previous entry, included for completeness.
|
||||
//
|
||||
// MustIPv6Addr("2001:10::/28"),
|
||||
|
||||
/*+----------------------+---------------+
|
||||
| Attribute | Value |
|
||||
+----------------------+---------------+
|
||||
| Address Block | 2002::/16 [2] |
|
||||
| Name | 6to4 |
|
||||
| RFC | [RFC3056] |
|
||||
| Allocation Date | February 2001 |
|
||||
| Termination Date | N/A |
|
||||
| Source | True |
|
||||
| Destination | True |
|
||||
| Forwardable | True |
|
||||
| Global | N/A [2] |
|
||||
| Reserved-by-Protocol | False |
|
||||
+----------------------+---------------+*/
|
||||
// [2] See [RFC3056] for details.
|
||||
MustIPv6Addr("2002::/16"),
|
||||
|
||||
/*+----------------------+--------------+
|
||||
| Attribute | Value |
|
||||
+----------------------+--------------+
|
||||
| Address Block | fc00::/7 |
|
||||
| Name | Unique-Local |
|
||||
| RFC | [RFC4193] |
|
||||
| Allocation Date | October 2005 |
|
||||
| Termination Date | N/A |
|
||||
| Source | True |
|
||||
| Destination | True |
|
||||
| Forwardable | True |
|
||||
| Global | False |
|
||||
| Reserved-by-Protocol | False |
|
||||
+----------------------+--------------+*/
|
||||
MustIPv6Addr("fc00::/7"),
|
||||
|
||||
/*+----------------------+-----------------------+
|
||||
| Attribute | Value |
|
||||
+----------------------+-----------------------+
|
||||
| Address Block | fe80::/10 |
|
||||
| Name | Linked-Scoped Unicast |
|
||||
| RFC | [RFC4291] |
|
||||
| Allocation Date | February 2006 |
|
||||
| Termination Date | N/A |
|
||||
| Source | True |
|
||||
| Destination | True |
|
||||
| Forwardable | False |
|
||||
| Global | False |
|
||||
| Reserved-by-Protocol | True |
|
||||
+----------------------+-----------------------+*/
|
||||
MustIPv6Addr("fe80::/10"),
|
||||
},
|
||||
7335: {
|
||||
// [RFC7335] IPv4 Service Continuity Prefix
|
||||
MustIPv4Addr("192.0.0.0/29"), // [RFC7335], §6 IANA Considerations
|
||||
},
|
||||
ForwardingBlacklist: { // Pseudo-RFC
|
||||
// Blacklist of non-forwardable IP blocks taken from RFC6890
|
||||
//
|
||||
// TODO: the attributes for forwardable should be
|
||||
// searcahble and embedded in the main list of RFCs
|
||||
// above.
|
||||
MustIPv4Addr("0.0.0.0/8"),
|
||||
MustIPv4Addr("127.0.0.0/8"),
|
||||
MustIPv4Addr("169.254.0.0/16"),
|
||||
MustIPv4Addr("192.0.0.0/24"),
|
||||
MustIPv4Addr("192.0.2.0/24"),
|
||||
MustIPv4Addr("198.51.100.0/24"),
|
||||
MustIPv4Addr("203.0.113.0/24"),
|
||||
MustIPv4Addr("240.0.0.0/4"),
|
||||
MustIPv4Addr("255.255.255.255/32"),
|
||||
MustIPv6Addr("::1/128"),
|
||||
MustIPv6Addr("::/128"),
|
||||
MustIPv6Addr("::ffff:0:0/96"),
|
||||
|
||||
// There is no way of expressing a whitelist per RFC2928
|
||||
// atm without creating a negative mask, which I don't
|
||||
// want to do atm.
|
||||
//MustIPv6Addr("2001::/23"),
|
||||
|
||||
MustIPv6Addr("2001:db8::/32"),
|
||||
MustIPv6Addr("2001:10::/28"),
|
||||
MustIPv6Addr("fe80::/10"),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// VisitAllRFCs iterates over all known RFCs and calls the visitor
|
||||
func VisitAllRFCs(fn func(rfcNum uint, sockaddrs SockAddrs)) {
|
||||
rfcNetMap := KnownRFCs()
|
||||
|
||||
// Blacklist of faux-RFCs. Don't show the world that we're abusing the
|
||||
// RFC system in this library.
|
||||
rfcBlacklist := map[uint]struct{}{
|
||||
ForwardingBlacklist: {},
|
||||
}
|
||||
|
||||
for rfcNum, sas := range rfcNetMap {
|
||||
if _, found := rfcBlacklist[rfcNum]; !found {
|
||||
fn(rfcNum, sas)
|
||||
}
|
||||
}
|
||||
}
|
19
vendor/github.com/hashicorp/go-sockaddr/route_info.go
generated
vendored
Normal file
19
vendor/github.com/hashicorp/go-sockaddr/route_info.go
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
package sockaddr
|
||||
|
||||
// RouteInterface specifies an interface for obtaining memoized route table and
|
||||
// network information from a given OS.
|
||||
type RouteInterface interface {
|
||||
// GetDefaultInterfaceName returns the name of the interface that has a
|
||||
// default route or an error and an empty string if a problem was
|
||||
// encountered.
|
||||
GetDefaultInterfaceName() (string, error)
|
||||
}
|
||||
|
||||
// VisitCommands visits each command used by the platform-specific RouteInfo
|
||||
// implementation.
|
||||
func (ri routeInfo) VisitCommands(fn func(name string, cmd []string)) {
|
||||
for k, v := range ri.cmds {
|
||||
cmds := append([]string(nil), v...)
|
||||
fn(k, cmds)
|
||||
}
|
||||
}
|
34
vendor/github.com/hashicorp/go-sockaddr/route_info_android.go
generated
vendored
Normal file
34
vendor/github.com/hashicorp/go-sockaddr/route_info_android.go
generated
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
package sockaddr
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
type routeInfo struct {
|
||||
cmds map[string][]string
|
||||
}
|
||||
|
||||
// NewRouteInfo returns a Android-specific implementation of the RouteInfo
|
||||
// interface.
|
||||
func NewRouteInfo() (routeInfo, error) {
|
||||
return routeInfo{
|
||||
cmds: map[string][]string{"ip": {"/system/bin/ip", "route", "get", "8.8.8.8"}},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetDefaultInterfaceName returns the interface name attached to the default
|
||||
// route on the default interface.
|
||||
func (ri routeInfo) GetDefaultInterfaceName() (string, error) {
|
||||
out, err := exec.Command(ri.cmds["ip"][0], ri.cmds["ip"][1:]...).Output()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
|
||||
var ifName string
|
||||
if ifName, err = parseDefaultIfNameFromIPCmdAndroid(string(out)); err != nil {
|
||||
return "", errors.New("No default interface found")
|
||||
}
|
||||
return ifName, nil
|
||||
}
|
36
vendor/github.com/hashicorp/go-sockaddr/route_info_bsd.go
generated
vendored
Normal file
36
vendor/github.com/hashicorp/go-sockaddr/route_info_bsd.go
generated
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
// +build darwin dragonfly freebsd netbsd openbsd
|
||||
|
||||
package sockaddr
|
||||
|
||||
import "os/exec"
|
||||
|
||||
var cmds map[string][]string = map[string][]string{
|
||||
"route": {"/sbin/route", "-n", "get", "default"},
|
||||
}
|
||||
|
||||
type routeInfo struct {
|
||||
cmds map[string][]string
|
||||
}
|
||||
|
||||
// NewRouteInfo returns a BSD-specific implementation of the RouteInfo
|
||||
// interface.
|
||||
func NewRouteInfo() (routeInfo, error) {
|
||||
return routeInfo{
|
||||
cmds: cmds,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetDefaultInterfaceName returns the interface name attached to the default
|
||||
// route on the default interface.
|
||||
func (ri routeInfo) GetDefaultInterfaceName() (string, error) {
|
||||
out, err := exec.Command(cmds["route"][0], cmds["route"][1:]...).Output()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var ifName string
|
||||
if ifName, err = parseDefaultIfNameFromRoute(string(out)); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return ifName, nil
|
||||
}
|
10
vendor/github.com/hashicorp/go-sockaddr/route_info_default.go
generated
vendored
Normal file
10
vendor/github.com/hashicorp/go-sockaddr/route_info_default.go
generated
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
// +build android nacl plan9
|
||||
|
||||
package sockaddr
|
||||
|
||||
import "errors"
|
||||
|
||||
// getDefaultIfName is the default interface function for unsupported platforms.
|
||||
func getDefaultIfName() (string, error) {
|
||||
return "", errors.New("No default interface found (unsupported platform)")
|
||||
}
|
42
vendor/github.com/hashicorp/go-sockaddr/route_info_linux.go
generated
vendored
Normal file
42
vendor/github.com/hashicorp/go-sockaddr/route_info_linux.go
generated
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
// +build !android
|
||||
|
||||
package sockaddr
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
type routeInfo struct {
|
||||
cmds map[string][]string
|
||||
}
|
||||
|
||||
// NewRouteInfo returns a Linux-specific implementation of the RouteInfo
|
||||
// interface.
|
||||
func NewRouteInfo() (routeInfo, error) {
|
||||
// CoreOS Container Linux moved ip to /usr/bin/ip, so look it up on
|
||||
// $PATH and fallback to /sbin/ip on error.
|
||||
path, _ := exec.LookPath("ip")
|
||||
if path == "" {
|
||||
path = "/sbin/ip"
|
||||
}
|
||||
|
||||
return routeInfo{
|
||||
cmds: map[string][]string{"ip": {path, "route"}},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetDefaultInterfaceName returns the interface name attached to the default
|
||||
// route on the default interface.
|
||||
func (ri routeInfo) GetDefaultInterfaceName() (string, error) {
|
||||
out, err := exec.Command(ri.cmds["ip"][0], ri.cmds["ip"][1:]...).Output()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var ifName string
|
||||
if ifName, err = parseDefaultIfNameFromIPCmd(string(out)); err != nil {
|
||||
return "", errors.New("No default interface found")
|
||||
}
|
||||
return ifName, nil
|
||||
}
|
37
vendor/github.com/hashicorp/go-sockaddr/route_info_solaris.go
generated
vendored
Normal file
37
vendor/github.com/hashicorp/go-sockaddr/route_info_solaris.go
generated
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
package sockaddr
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
var cmds map[string][]string = map[string][]string{
|
||||
"route": {"/usr/sbin/route", "-n", "get", "default"},
|
||||
}
|
||||
|
||||
type routeInfo struct {
|
||||
cmds map[string][]string
|
||||
}
|
||||
|
||||
// NewRouteInfo returns a BSD-specific implementation of the RouteInfo
|
||||
// interface.
|
||||
func NewRouteInfo() (routeInfo, error) {
|
||||
return routeInfo{
|
||||
cmds: cmds,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetDefaultInterfaceName returns the interface name attached to the default
|
||||
// route on the default interface.
|
||||
func (ri routeInfo) GetDefaultInterfaceName() (string, error) {
|
||||
out, err := exec.Command(cmds["route"][0], cmds["route"][1:]...).Output()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var ifName string
|
||||
if ifName, err = parseDefaultIfNameFromRoute(string(out)); err != nil {
|
||||
return "", errors.New("No default interface found")
|
||||
}
|
||||
return ifName, nil
|
||||
}
|
41
vendor/github.com/hashicorp/go-sockaddr/route_info_windows.go
generated
vendored
Normal file
41
vendor/github.com/hashicorp/go-sockaddr/route_info_windows.go
generated
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
package sockaddr
|
||||
|
||||
import "os/exec"
|
||||
|
||||
var cmds map[string][]string = map[string][]string{
|
||||
"netstat": {"netstat", "-rn"},
|
||||
"ipconfig": {"ipconfig"},
|
||||
}
|
||||
|
||||
type routeInfo struct {
|
||||
cmds map[string][]string
|
||||
}
|
||||
|
||||
// NewRouteInfo returns a BSD-specific implementation of the RouteInfo
|
||||
// interface.
|
||||
func NewRouteInfo() (routeInfo, error) {
|
||||
return routeInfo{
|
||||
cmds: cmds,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetDefaultInterfaceName returns the interface name attached to the default
|
||||
// route on the default interface.
|
||||
func (ri routeInfo) GetDefaultInterfaceName() (string, error) {
|
||||
ifNameOut, err := exec.Command(cmds["netstat"][0], cmds["netstat"][1:]...).Output()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
ipconfigOut, err := exec.Command(cmds["ipconfig"][0], cmds["ipconfig"][1:]...).Output()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
ifName, err := parseDefaultIfNameWindows(string(ifNameOut), string(ipconfigOut))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return ifName, nil
|
||||
}
|
206
vendor/github.com/hashicorp/go-sockaddr/sockaddr.go
generated
vendored
Normal file
206
vendor/github.com/hashicorp/go-sockaddr/sockaddr.go
generated
vendored
Normal file
@ -0,0 +1,206 @@
|
||||
package sockaddr
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type SockAddrType int
|
||||
type AttrName string
|
||||
|
||||
const (
|
||||
TypeUnknown SockAddrType = 0x0
|
||||
TypeUnix = 0x1
|
||||
TypeIPv4 = 0x2
|
||||
TypeIPv6 = 0x4
|
||||
|
||||
// TypeIP is the union of TypeIPv4 and TypeIPv6
|
||||
TypeIP = 0x6
|
||||
)
|
||||
|
||||
type SockAddr interface {
|
||||
// CmpRFC returns 0 if SockAddr exactly matches one of the matched RFC
|
||||
// networks, -1 if the receiver is contained within the RFC network, or
|
||||
// 1 if the address is not contained within the RFC.
|
||||
CmpRFC(rfcNum uint, sa SockAddr) int
|
||||
|
||||
// Contains returns true if the SockAddr arg is contained within the
|
||||
// receiver
|
||||
Contains(SockAddr) bool
|
||||
|
||||
// Equal allows for the comparison of two SockAddrs
|
||||
Equal(SockAddr) bool
|
||||
|
||||
DialPacketArgs() (string, string)
|
||||
DialStreamArgs() (string, string)
|
||||
ListenPacketArgs() (string, string)
|
||||
ListenStreamArgs() (string, string)
|
||||
|
||||
// String returns the string representation of SockAddr
|
||||
String() string
|
||||
|
||||
// Type returns the SockAddrType
|
||||
Type() SockAddrType
|
||||
}
|
||||
|
||||
// sockAddrAttrMap is a map of the SockAddr type-specific attributes.
|
||||
var sockAddrAttrMap map[AttrName]func(SockAddr) string
|
||||
var sockAddrAttrs []AttrName
|
||||
|
||||
func init() {
|
||||
sockAddrInit()
|
||||
}
|
||||
|
||||
// New creates a new SockAddr from the string. The order in which New()
|
||||
// attempts to construct a SockAddr is: IPv4Addr, IPv6Addr, SockAddrUnix.
|
||||
//
|
||||
// NOTE: New() relies on the heuristic wherein if the path begins with either a
|
||||
// '.' or '/' character before creating a new UnixSock. For UNIX sockets that
|
||||
// are absolute paths or are nested within a sub-directory, this works as
|
||||
// expected, however if the UNIX socket is contained in the current working
|
||||
// directory, this will fail unless the path begins with "./"
|
||||
// (e.g. "./my-local-socket"). Calls directly to NewUnixSock() do not suffer
|
||||
// this limitation. Invalid IP addresses such as "256.0.0.0/-1" will run afoul
|
||||
// of this heuristic and be assumed to be a valid UNIX socket path (which they
|
||||
// are, but it is probably not what you want and you won't realize it until you
|
||||
// stat(2) the file system to discover it doesn't exist).
|
||||
func NewSockAddr(s string) (SockAddr, error) {
|
||||
ipv4Addr, err := NewIPv4Addr(s)
|
||||
if err == nil {
|
||||
return ipv4Addr, nil
|
||||
}
|
||||
|
||||
ipv6Addr, err := NewIPv6Addr(s)
|
||||
if err == nil {
|
||||
return ipv6Addr, nil
|
||||
}
|
||||
|
||||
// Check to make sure the string begins with either a '.' or '/', or
|
||||
// contains a '/'.
|
||||
if len(s) > 1 && (strings.IndexAny(s[0:1], "./") != -1 || strings.IndexByte(s, '/') != -1) {
|
||||
unixSock, err := NewUnixSock(s)
|
||||
if err == nil {
|
||||
return unixSock, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("Unable to convert %q to an IPv4 or IPv6 address, or a UNIX Socket", s)
|
||||
}
|
||||
|
||||
// ToIPAddr returns an IPAddr type or nil if the type conversion fails.
|
||||
func ToIPAddr(sa SockAddr) *IPAddr {
|
||||
ipa, ok := sa.(IPAddr)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return &ipa
|
||||
}
|
||||
|
||||
// ToIPv4Addr returns an IPv4Addr type or nil if the type conversion fails.
|
||||
func ToIPv4Addr(sa SockAddr) *IPv4Addr {
|
||||
switch v := sa.(type) {
|
||||
case IPv4Addr:
|
||||
return &v
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// ToIPv6Addr returns an IPv6Addr type or nil if the type conversion fails.
|
||||
func ToIPv6Addr(sa SockAddr) *IPv6Addr {
|
||||
switch v := sa.(type) {
|
||||
case IPv6Addr:
|
||||
return &v
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// ToUnixSock returns a UnixSock type or nil if the type conversion fails.
|
||||
func ToUnixSock(sa SockAddr) *UnixSock {
|
||||
switch v := sa.(type) {
|
||||
case UnixSock:
|
||||
return &v
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// SockAddrAttr returns a string representation of an attribute for the given
|
||||
// SockAddr.
|
||||
func SockAddrAttr(sa SockAddr, selector AttrName) string {
|
||||
fn, found := sockAddrAttrMap[selector]
|
||||
if !found {
|
||||
return ""
|
||||
}
|
||||
|
||||
return fn(sa)
|
||||
}
|
||||
|
||||
// String() for SockAddrType returns a string representation of the
|
||||
// SockAddrType (e.g. "IPv4", "IPv6", "UNIX", "IP", or "unknown").
|
||||
func (sat SockAddrType) String() string {
|
||||
switch sat {
|
||||
case TypeIPv4:
|
||||
return "IPv4"
|
||||
case TypeIPv6:
|
||||
return "IPv6"
|
||||
// There is no concrete "IP" type. Leaving here as a reminder.
|
||||
// case TypeIP:
|
||||
// return "IP"
|
||||
case TypeUnix:
|
||||
return "UNIX"
|
||||
default:
|
||||
panic("unsupported type")
|
||||
}
|
||||
}
|
||||
|
||||
// sockAddrInit is called once at init()
|
||||
func sockAddrInit() {
|
||||
sockAddrAttrs = []AttrName{
|
||||
"type", // type should be first
|
||||
"string",
|
||||
}
|
||||
|
||||
sockAddrAttrMap = map[AttrName]func(sa SockAddr) string{
|
||||
"string": func(sa SockAddr) string {
|
||||
return sa.String()
|
||||
},
|
||||
"type": func(sa SockAddr) string {
|
||||
return sa.Type().String()
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// UnixSockAttrs returns a list of attributes supported by the UnixSock type
|
||||
func SockAddrAttrs() []AttrName {
|
||||
return sockAddrAttrs
|
||||
}
|
||||
|
||||
// Although this is pretty trivial to do in a program, having the logic here is
|
||||
// useful all around. Note that this marshals into a *string* -- the underlying
|
||||
// string representation of the sockaddr. If you then unmarshal into this type
|
||||
// in Go, all will work as expected, but externally you can take what comes out
|
||||
// and use the string value directly.
|
||||
type SockAddrMarshaler struct {
|
||||
SockAddr
|
||||
}
|
||||
|
||||
func (s *SockAddrMarshaler) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(s.SockAddr.String())
|
||||
}
|
||||
|
||||
func (s *SockAddrMarshaler) UnmarshalJSON(in []byte) error {
|
||||
var str string
|
||||
err := json.Unmarshal(in, &str)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sa, err := NewSockAddr(str)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.SockAddr = sa
|
||||
return nil
|
||||
}
|
193
vendor/github.com/hashicorp/go-sockaddr/sockaddrs.go
generated
vendored
Normal file
193
vendor/github.com/hashicorp/go-sockaddr/sockaddrs.go
generated
vendored
Normal file
@ -0,0 +1,193 @@
|
||||
package sockaddr
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"sort"
|
||||
)
|
||||
|
||||
// SockAddrs is a slice of SockAddrs
|
||||
type SockAddrs []SockAddr
|
||||
|
||||
func (s SockAddrs) Len() int { return len(s) }
|
||||
func (s SockAddrs) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||
|
||||
// CmpAddrFunc is the function signature that must be met to be used in the
|
||||
// OrderedAddrBy multiAddrSorter
|
||||
type CmpAddrFunc func(p1, p2 *SockAddr) int
|
||||
|
||||
// multiAddrSorter implements the Sort interface, sorting the SockAddrs within.
|
||||
type multiAddrSorter struct {
|
||||
addrs SockAddrs
|
||||
cmp []CmpAddrFunc
|
||||
}
|
||||
|
||||
// Sort sorts the argument slice according to the Cmp functions passed to
|
||||
// OrderedAddrBy.
|
||||
func (ms *multiAddrSorter) Sort(sockAddrs SockAddrs) {
|
||||
ms.addrs = sockAddrs
|
||||
sort.Sort(ms)
|
||||
}
|
||||
|
||||
// OrderedAddrBy sorts SockAddr by the list of sort function pointers.
|
||||
func OrderedAddrBy(cmpFuncs ...CmpAddrFunc) *multiAddrSorter {
|
||||
return &multiAddrSorter{
|
||||
cmp: cmpFuncs,
|
||||
}
|
||||
}
|
||||
|
||||
// Len is part of sort.Interface.
|
||||
func (ms *multiAddrSorter) Len() int {
|
||||
return len(ms.addrs)
|
||||
}
|
||||
|
||||
// Less is part of sort.Interface. It is implemented by looping along the
|
||||
// Cmp() functions until it finds a comparison that is either less than,
|
||||
// equal to, or greater than.
|
||||
func (ms *multiAddrSorter) Less(i, j int) bool {
|
||||
p, q := &ms.addrs[i], &ms.addrs[j]
|
||||
// Try all but the last comparison.
|
||||
var k int
|
||||
for k = 0; k < len(ms.cmp)-1; k++ {
|
||||
cmp := ms.cmp[k]
|
||||
x := cmp(p, q)
|
||||
switch x {
|
||||
case -1:
|
||||
// p < q, so we have a decision.
|
||||
return true
|
||||
case 1:
|
||||
// p > q, so we have a decision.
|
||||
return false
|
||||
}
|
||||
// p == q; try the next comparison.
|
||||
}
|
||||
// All comparisons to here said "equal", so just return whatever the
|
||||
// final comparison reports.
|
||||
switch ms.cmp[k](p, q) {
|
||||
case -1:
|
||||
return true
|
||||
case 1:
|
||||
return false
|
||||
default:
|
||||
// Still a tie! Now what?
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Swap is part of sort.Interface.
|
||||
func (ms *multiAddrSorter) Swap(i, j int) {
|
||||
ms.addrs[i], ms.addrs[j] = ms.addrs[j], ms.addrs[i]
|
||||
}
|
||||
|
||||
const (
|
||||
// NOTE (sean@): These constants are here for code readability only and
|
||||
// are sprucing up the code for readability purposes. Some of the
|
||||
// Cmp*() variants have confusing logic (especially when dealing with
|
||||
// mixed-type comparisons) and this, I think, has made it easier to grok
|
||||
// the code faster.
|
||||
sortReceiverBeforeArg = -1
|
||||
sortDeferDecision = 0
|
||||
sortArgBeforeReceiver = 1
|
||||
)
|
||||
|
||||
// AscAddress is a sorting function to sort SockAddrs by their respective
|
||||
// address type. Non-equal types are deferred in the sort.
|
||||
func AscAddress(p1Ptr, p2Ptr *SockAddr) int {
|
||||
p1 := *p1Ptr
|
||||
p2 := *p2Ptr
|
||||
|
||||
switch v := p1.(type) {
|
||||
case IPv4Addr:
|
||||
return v.CmpAddress(p2)
|
||||
case IPv6Addr:
|
||||
return v.CmpAddress(p2)
|
||||
case UnixSock:
|
||||
return v.CmpAddress(p2)
|
||||
default:
|
||||
return sortDeferDecision
|
||||
}
|
||||
}
|
||||
|
||||
// AscPort is a sorting function to sort SockAddrs by their respective address
|
||||
// type. Non-equal types are deferred in the sort.
|
||||
func AscPort(p1Ptr, p2Ptr *SockAddr) int {
|
||||
p1 := *p1Ptr
|
||||
p2 := *p2Ptr
|
||||
|
||||
switch v := p1.(type) {
|
||||
case IPv4Addr:
|
||||
return v.CmpPort(p2)
|
||||
case IPv6Addr:
|
||||
return v.CmpPort(p2)
|
||||
default:
|
||||
return sortDeferDecision
|
||||
}
|
||||
}
|
||||
|
||||
// AscPrivate is a sorting function to sort "more secure" private values before
|
||||
// "more public" values. Both IPv4 and IPv6 are compared against RFC6890
|
||||
// (RFC6890 includes, and is not limited to, RFC1918 and RFC6598 for IPv4, and
|
||||
// IPv6 includes RFC4193).
|
||||
func AscPrivate(p1Ptr, p2Ptr *SockAddr) int {
|
||||
p1 := *p1Ptr
|
||||
p2 := *p2Ptr
|
||||
|
||||
switch v := p1.(type) {
|
||||
case IPv4Addr, IPv6Addr:
|
||||
return v.CmpRFC(6890, p2)
|
||||
default:
|
||||
return sortDeferDecision
|
||||
}
|
||||
}
|
||||
|
||||
// AscNetworkSize is a sorting function to sort SockAddrs based on their network
|
||||
// size. Non-equal types are deferred in the sort.
|
||||
func AscNetworkSize(p1Ptr, p2Ptr *SockAddr) int {
|
||||
p1 := *p1Ptr
|
||||
p2 := *p2Ptr
|
||||
p1Type := p1.Type()
|
||||
p2Type := p2.Type()
|
||||
|
||||
// Network size operations on non-IP types make no sense
|
||||
if p1Type != p2Type && p1Type != TypeIP {
|
||||
return sortDeferDecision
|
||||
}
|
||||
|
||||
ipA := p1.(IPAddr)
|
||||
ipB := p2.(IPAddr)
|
||||
|
||||
return bytes.Compare([]byte(*ipA.NetIPMask()), []byte(*ipB.NetIPMask()))
|
||||
}
|
||||
|
||||
// AscType is a sorting function to sort "more secure" types before
|
||||
// "less-secure" types.
|
||||
func AscType(p1Ptr, p2Ptr *SockAddr) int {
|
||||
p1 := *p1Ptr
|
||||
p2 := *p2Ptr
|
||||
p1Type := p1.Type()
|
||||
p2Type := p2.Type()
|
||||
switch {
|
||||
case p1Type < p2Type:
|
||||
return sortReceiverBeforeArg
|
||||
case p1Type == p2Type:
|
||||
return sortDeferDecision
|
||||
case p1Type > p2Type:
|
||||
return sortArgBeforeReceiver
|
||||
default:
|
||||
return sortDeferDecision
|
||||
}
|
||||
}
|
||||
|
||||
// FilterByType returns two lists: a list of matched and unmatched SockAddrs
|
||||
func (sas SockAddrs) FilterByType(type_ SockAddrType) (matched, excluded SockAddrs) {
|
||||
matched = make(SockAddrs, 0, len(sas))
|
||||
excluded = make(SockAddrs, 0, len(sas))
|
||||
|
||||
for _, sa := range sas {
|
||||
if sa.Type()&type_ != 0 {
|
||||
matched = append(matched, sa)
|
||||
} else {
|
||||
excluded = append(excluded, sa)
|
||||
}
|
||||
}
|
||||
return matched, excluded
|
||||
}
|
135
vendor/github.com/hashicorp/go-sockaddr/unixsock.go
generated
vendored
Normal file
135
vendor/github.com/hashicorp/go-sockaddr/unixsock.go
generated
vendored
Normal file
@ -0,0 +1,135 @@
|
||||
package sockaddr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type UnixSock struct {
|
||||
SockAddr
|
||||
path string
|
||||
}
|
||||
type UnixSocks []*UnixSock
|
||||
|
||||
// unixAttrMap is a map of the UnixSockAddr type-specific attributes.
|
||||
var unixAttrMap map[AttrName]func(UnixSock) string
|
||||
var unixAttrs []AttrName
|
||||
|
||||
func init() {
|
||||
unixAttrInit()
|
||||
}
|
||||
|
||||
// NewUnixSock creates an UnixSock from a string path. String can be in the
|
||||
// form of either URI-based string (e.g. `file:///etc/passwd`), an absolute
|
||||
// path (e.g. `/etc/passwd`), or a relative path (e.g. `./foo`).
|
||||
func NewUnixSock(s string) (ret UnixSock, err error) {
|
||||
ret.path = s
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// CmpAddress follows the Cmp() standard protocol and returns:
|
||||
//
|
||||
// - -1 If the receiver should sort first because its name lexically sorts before arg
|
||||
// - 0 if the SockAddr arg is not a UnixSock, or is a UnixSock with the same path.
|
||||
// - 1 If the argument should sort first.
|
||||
func (us UnixSock) CmpAddress(sa SockAddr) int {
|
||||
usb, ok := sa.(UnixSock)
|
||||
if !ok {
|
||||
return sortDeferDecision
|
||||
}
|
||||
|
||||
return strings.Compare(us.Path(), usb.Path())
|
||||
}
|
||||
|
||||
// DialPacketArgs returns the arguments required to be passed to net.DialUnix()
|
||||
// with the `unixgram` network type.
|
||||
func (us UnixSock) DialPacketArgs() (network, dialArgs string) {
|
||||
return "unixgram", us.path
|
||||
}
|
||||
|
||||
// DialStreamArgs returns the arguments required to be passed to net.DialUnix()
|
||||
// with the `unix` network type.
|
||||
func (us UnixSock) DialStreamArgs() (network, dialArgs string) {
|
||||
return "unix", us.path
|
||||
}
|
||||
|
||||
// Equal returns true if a SockAddr is equal to the receiving UnixSock.
|
||||
func (us UnixSock) Equal(sa SockAddr) bool {
|
||||
usb, ok := sa.(UnixSock)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
if us.Path() != usb.Path() {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// ListenPacketArgs returns the arguments required to be passed to
|
||||
// net.ListenUnixgram() with the `unixgram` network type.
|
||||
func (us UnixSock) ListenPacketArgs() (network, dialArgs string) {
|
||||
return "unixgram", us.path
|
||||
}
|
||||
|
||||
// ListenStreamArgs returns the arguments required to be passed to
|
||||
// net.ListenUnix() with the `unix` network type.
|
||||
func (us UnixSock) ListenStreamArgs() (network, dialArgs string) {
|
||||
return "unix", us.path
|
||||
}
|
||||
|
||||
// MustUnixSock is a helper method that must return an UnixSock or panic on
|
||||
// invalid input.
|
||||
func MustUnixSock(addr string) UnixSock {
|
||||
us, err := NewUnixSock(addr)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Unable to create a UnixSock from %+q: %v", addr, err))
|
||||
}
|
||||
return us
|
||||
}
|
||||
|
||||
// Path returns the given path of the UnixSock
|
||||
func (us UnixSock) Path() string {
|
||||
return us.path
|
||||
}
|
||||
|
||||
// String returns the path of the UnixSock
|
||||
func (us UnixSock) String() string {
|
||||
return fmt.Sprintf("%+q", us.path)
|
||||
}
|
||||
|
||||
// Type is used as a type switch and returns TypeUnix
|
||||
func (UnixSock) Type() SockAddrType {
|
||||
return TypeUnix
|
||||
}
|
||||
|
||||
// UnixSockAttrs returns a list of attributes supported by the UnixSockAddr type
|
||||
func UnixSockAttrs() []AttrName {
|
||||
return unixAttrs
|
||||
}
|
||||
|
||||
// UnixSockAttr returns a string representation of an attribute for the given
|
||||
// UnixSock.
|
||||
func UnixSockAttr(us UnixSock, attrName AttrName) string {
|
||||
fn, found := unixAttrMap[attrName]
|
||||
if !found {
|
||||
return ""
|
||||
}
|
||||
|
||||
return fn(us)
|
||||
}
|
||||
|
||||
// unixAttrInit is called once at init()
|
||||
func unixAttrInit() {
|
||||
// Sorted for human readability
|
||||
unixAttrs = []AttrName{
|
||||
"path",
|
||||
}
|
||||
|
||||
unixAttrMap = map[AttrName]func(us UnixSock) string{
|
||||
"path": func(us UnixSock) string {
|
||||
return us.Path()
|
||||
},
|
||||
}
|
||||
}
|
22
vendor/github.com/hashicorp/golang-lru/lru.go
generated
vendored
22
vendor/github.com/hashicorp/golang-lru/lru.go
generated
vendored
@ -37,7 +37,7 @@ func (c *Cache) Purge() {
|
||||
c.lock.Unlock()
|
||||
}
|
||||
|
||||
// Add adds a value to the cache. Returns true if an eviction occurred.
|
||||
// Add adds a value to the cache. Returns true if an eviction occurred.
|
||||
func (c *Cache) Add(key, value interface{}) (evicted bool) {
|
||||
c.lock.Lock()
|
||||
evicted = c.lru.Add(key, value)
|
||||
@ -71,8 +71,8 @@ func (c *Cache) Peek(key interface{}) (value interface{}, ok bool) {
|
||||
return value, ok
|
||||
}
|
||||
|
||||
// ContainsOrAdd checks if a key is in the cache without updating the
|
||||
// recent-ness or deleting it for being stale, and if not, adds the value.
|
||||
// ContainsOrAdd checks if a key is in the cache without updating the
|
||||
// recent-ness or deleting it for being stale, and if not, adds the value.
|
||||
// Returns whether found and whether an eviction occurred.
|
||||
func (c *Cache) ContainsOrAdd(key, value interface{}) (ok, evicted bool) {
|
||||
c.lock.Lock()
|
||||
@ -85,22 +85,6 @@ func (c *Cache) ContainsOrAdd(key, value interface{}) (ok, evicted bool) {
|
||||
return false, evicted
|
||||
}
|
||||
|
||||
// PeekOrAdd checks if a key is in the cache without updating the
|
||||
// recent-ness or deleting it for being stale, and if not, adds the value.
|
||||
// Returns whether found and whether an eviction occurred.
|
||||
func (c *Cache) PeekOrAdd(key, value interface{}) (previous interface{}, ok, evicted bool) {
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
|
||||
previous, ok = c.lru.Peek(key)
|
||||
if ok {
|
||||
return previous, true, false
|
||||
}
|
||||
|
||||
evicted = c.lru.Add(key, value)
|
||||
return nil, false, evicted
|
||||
}
|
||||
|
||||
// Remove removes the provided key from the cache.
|
||||
func (c *Cache) Remove(key interface{}) (present bool) {
|
||||
c.lock.Lock()
|
||||
|
9
vendor/github.com/hashicorp/hcl/.gitignore
generated
vendored
Normal file
9
vendor/github.com/hashicorp/hcl/.gitignore
generated
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
y.output
|
||||
|
||||
# ignore intellij files
|
||||
.idea
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
|
||||
*.test
|
13
vendor/github.com/hashicorp/hcl/.travis.yml
generated
vendored
Normal file
13
vendor/github.com/hashicorp/hcl/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
sudo: false
|
||||
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.x
|
||||
- tip
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
|
||||
script: make test
|
354
vendor/github.com/hashicorp/hcl/LICENSE
generated
vendored
Normal file
354
vendor/github.com/hashicorp/hcl/LICENSE
generated
vendored
Normal file
@ -0,0 +1,354 @@
|
||||
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
Normal file
18
vendor/github.com/hashicorp/hcl/Makefile
generated
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
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
Normal file
125
vendor/github.com/hashicorp/hcl/README.md
generated
vendored
Normal file
@ -0,0 +1,125 @@
|
||||
# HCL
|
||||
|
||||
[](https://godoc.org/github.com/hashicorp/hcl) [](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
Normal file
19
vendor/github.com/hashicorp/hcl/appveyor.yml
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
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 false
|
||||
install:
|
||||
- cmd: >-
|
||||
echo %Path%
|
||||
|
||||
go version
|
||||
|
||||
go env
|
||||
|
||||
go get -t ./...
|
||||
|
||||
build_script:
|
||||
- cmd: go test -v ./...
|
729
vendor/github.com/hashicorp/hcl/decoder.go
generated
vendored
Normal file
729
vendor/github.com/hashicorp/hcl/decoder.go
generated
vendored
Normal file
@ -0,0 +1,729 @@
|
||||
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.Float32, reflect.Float64:
|
||||
return d.decodeFloat(name, node, result)
|
||||
case reflect.Int, reflect.Int32, reflect.Int64:
|
||||
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 || n.Token.Type == token.NUMBER {
|
||||
v, err := strconv.ParseFloat(n.Token.Text, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
result.Set(reflect.ValueOf(v).Convert(result.Type()))
|
||||
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
|
||||
}
|
||||
|
||||
if result.Kind() == reflect.Interface {
|
||||
result.Set(reflect.ValueOf(int(v)))
|
||||
} else {
|
||||
result.SetInt(v)
|
||||
}
|
||||
return nil
|
||||
case token.STRING:
|
||||
v, err := strconv.ParseInt(n.Token.Value().(string), 0, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if result.Kind() == reflect.Interface {
|
||||
result.Set(reflect.ValueOf(int(v)))
|
||||
} else {
|
||||
result.SetInt(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.
|
||||
type field struct {
|
||||
field reflect.StructField
|
||||
val reflect.Value
|
||||
}
|
||||
fields := []field{}
|
||||
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 = append(fields, field{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 _, f := range fields {
|
||||
field, fieldValue := f.field, f.val
|
||||
if !fieldValue.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 !fieldValue.CanSet() {
|
||||
continue
|
||||
}
|
||||
|
||||
fieldName := field.Name
|
||||
|
||||
tagValue := field.Tag.Get(tagName)
|
||||
tagParts := strings.SplitN(tagValue, ",", 2)
|
||||
if len(tagParts) >= 2 {
|
||||
switch tagParts[1] {
|
||||
case "decodedFields":
|
||||
decodedFieldsVal = append(decodedFieldsVal, fieldValue)
|
||||
continue
|
||||
case "key":
|
||||
if item == nil {
|
||||
return &parser.PosError{
|
||||
Pos: node.Pos(),
|
||||
Err: fmt.Errorf("%s: %s asked for 'key', impossible",
|
||||
name, fieldName),
|
||||
}
|
||||
}
|
||||
|
||||
fieldValue.SetString(item.Keys[0].Token.Value().(string))
|
||||
continue
|
||||
case "unusedKeys":
|
||||
unusedKeysVal = append(unusedKeysVal, fieldValue)
|
||||
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, fieldValue); 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, fieldValue); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
decodedFields = append(decodedFields, field.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()
|
||||
}
|
3
vendor/github.com/hashicorp/hcl/go.mod
generated
vendored
Normal file
3
vendor/github.com/hashicorp/hcl/go.mod
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
module github.com/hashicorp/hcl
|
||||
|
||||
require github.com/davecgh/go-spew v1.1.1
|
2
vendor/github.com/hashicorp/hcl/go.sum
generated
vendored
Normal file
2
vendor/github.com/hashicorp/hcl/go.sum
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
11
vendor/github.com/hashicorp/hcl/hcl.go
generated
vendored
Normal file
11
vendor/github.com/hashicorp/hcl/hcl.go
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
// 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
|
219
vendor/github.com/hashicorp/hcl/hcl/ast/ast.go
generated
vendored
Normal file
219
vendor/github.com/hashicorp/hcl/hcl/ast/ast.go
generated
vendored
Normal file
@ -0,0 +1,219 @@
|
||||
// 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
|
||||
|
||||
// comment types, only used when in a list
|
||||
LeadComment *CommentGroup
|
||||
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
Normal file
52
vendor/github.com/hashicorp/hcl/hcl/ast/walk.go
generated
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
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
Normal file
17
vendor/github.com/hashicorp/hcl/hcl/parser/error.go
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
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)
|
||||
}
|
532
vendor/github.com/hashicorp/hcl/hcl/parser/parser.go
generated
vendored
Normal file
532
vendor/github.com/hashicorp/hcl/hcl/parser/parser.go
generated
vendored
Normal file
@ -0,0 +1,532 @@
|
||||
// Package parser implements a parser for HCL (HashiCorp Configuration
|
||||
// Language)
|
||||
package parser
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"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) {
|
||||
// normalize all line endings
|
||||
// since the scanner and output only work with "\n" line endings, we may
|
||||
// end up with dangling "\r" characters in the parsed data.
|
||||
src = bytes.Replace(src, []byte("\r\n"), []byte("\n"), -1)
|
||||
|
||||
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(false)
|
||||
if scerr != nil {
|
||||
return nil, scerr
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
f.Comments = p.comments
|
||||
return f, nil
|
||||
}
|
||||
|
||||
// objectList parses a list of items within an object (generally k/v pairs).
|
||||
// The parameter" obj" tells this whether to we are within an object (braces:
|
||||
// '{', '}') or just at the top level. If we're within an object, we end
|
||||
// at an RBRACE.
|
||||
func (p *Parser) objectList(obj bool) (*ast.ObjectList, error) {
|
||||
defer un(trace(p, "ParseObjectList"))
|
||||
node := &ast.ObjectList{}
|
||||
|
||||
for {
|
||||
if obj {
|
||||
tok := p.scan()
|
||||
p.unscan()
|
||||
if tok.Type == token.RBRACE {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
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, &PosError{
|
||||
Pos: p.tok.Pos,
|
||||
Err: fmt.Errorf(
|
||||
"key '%s' expected start of object ('{') or assignment ('=')",
|
||||
strings.Join(keyStr, " ")),
|
||||
}
|
||||
}
|
||||
|
||||
// key=#comment
|
||||
// val
|
||||
if p.lineComment != nil {
|
||||
o.LineComment, p.lineComment = p.lineComment, nil
|
||||
}
|
||||
|
||||
// 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:
|
||||
return keys, &PosError{
|
||||
Pos: p.tok.Pos,
|
||||
Err: fmt.Errorf("illegal character"),
|
||||
}
|
||||
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(true)
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// No error, scan and expect the ending to be a brace
|
||||
if tok := p.scan(); tok.Type != token.RBRACE {
|
||||
return nil, &PosError{
|
||||
Pos: tok.Pos,
|
||||
Err: fmt.Errorf("object expected closing RBRACE got: %s", 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.BOOL, token.NUMBER, token.FLOAT, token.STRING, token.HEREDOC:
|
||||
node, err := p.literalType()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// If there is a lead comment, apply it
|
||||
if p.leadComment != nil {
|
||||
node.LeadComment = p.leadComment
|
||||
p.leadComment = nil
|
||||
}
|
||||
|
||||
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.LBRACK:
|
||||
node, err := p.listType()
|
||||
if err != nil {
|
||||
return nil, &PosError{
|
||||
Pos: tok.Pos,
|
||||
Err: fmt.Errorf(
|
||||
"error while trying to parse list within list: %s", err),
|
||||
}
|
||||
}
|
||||
l.Add(node)
|
||||
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(")")
|
||||
}
|
652
vendor/github.com/hashicorp/hcl/hcl/scanner/scanner.go
generated
vendored
Normal file
652
vendor/github.com/hashicorp/hcl/hcl/scanner/scanner.go
generated
vendored
Normal file
@ -0,0 +1,652 @@
|
||||
// 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
|
||||
}
|
||||
|
||||
// remember last position
|
||||
s.prevPos = s.srcPos
|
||||
|
||||
s.srcPos.Column++
|
||||
s.lastCharLen = size
|
||||
s.srcPos.Offset += size
|
||||
|
||||
if ch == utf8.RuneError && size == 1 {
|
||||
s.err("illegal UTF-8 encoding")
|
||||
return ch
|
||||
}
|
||||
|
||||
if ch == '\n' {
|
||||
s.srcPos.Line++
|
||||
s.lastLineLen = s.srcPos.Column
|
||||
s.srcPos.Column = 0
|
||||
}
|
||||
|
||||
if ch == '\x00' {
|
||||
s.err("unexpected null character (0x00)")
|
||||
return eof
|
||||
}
|
||||
|
||||
if ch == '\uE123' {
|
||||
s.err("unicode code point U+E123 reserved for internal use")
|
||||
return utf8.RuneError
|
||||
}
|
||||
|
||||
// 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 beginning 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 || (len(identBytes) == 1 && identBytes[0] == '-') {
|
||||
s.err("zero-length heredoc anchor")
|
||||
return
|
||||
}
|
||||
|
||||
var identRegexp *regexp.Regexp
|
||||
if identBytes[0] == '-' {
|
||||
identRegexp = regexp.MustCompile(fmt.Sprintf(`^[[:space:]]*%s\r*\z`, identBytes[1:]))
|
||||
} else {
|
||||
identRegexp = regexp.MustCompile(fmt.Sprintf(`^[[:space:]]*%s\r*\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 == '\n' && braces == 0) || 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 && ch != eof {
|
||||
// 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
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user