vendor: Update vendoring for the exec client and server implementations
Signed-off-by: Jacek J. Łakis <jacek.lakis@intel.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
This commit is contained in:
parent
d25b88583f
commit
bf51655a7b
2124 changed files with 809703 additions and 5 deletions
27
vendor/github.com/coreos/pkg/.gitignore
generated
vendored
Normal file
27
vendor/github.com/coreos/pkg/.gitignore
generated
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
# 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
|
||||
|
||||
bin/
|
||||
coverage/
|
8
vendor/github.com/coreos/pkg/.travis.yml
generated
vendored
Normal file
8
vendor/github.com/coreos/pkg/.travis.yml
generated
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
language: go
|
||||
|
||||
go:
|
||||
- 1.5.4
|
||||
- 1.6.2
|
||||
|
||||
script:
|
||||
- ./test
|
71
vendor/github.com/coreos/pkg/CONTRIBUTING.md
generated
vendored
Normal file
71
vendor/github.com/coreos/pkg/CONTRIBUTING.md
generated
vendored
Normal file
|
@ -0,0 +1,71 @@
|
|||
# How to Contribute
|
||||
|
||||
CoreOS projects are [Apache 2.0 licensed](LICENSE) and accept contributions via
|
||||
GitHub pull requests. This document outlines some of the conventions on
|
||||
development workflow, commit message formatting, contact points and other
|
||||
resources to make it easier to get your contribution accepted.
|
||||
|
||||
# Certificate of Origin
|
||||
|
||||
By contributing to this project you agree to the Developer Certificate of
|
||||
Origin (DCO). This document was created by the Linux Kernel community and is a
|
||||
simple statement that you, as a contributor, have the legal right to make the
|
||||
contribution. See the [DCO](DCO) file for details.
|
||||
|
||||
# Email and Chat
|
||||
|
||||
The project currently uses the general CoreOS email list and IRC channel:
|
||||
- Email: [coreos-dev](https://groups.google.com/forum/#!forum/coreos-dev)
|
||||
- IRC: #[coreos](irc://irc.freenode.org:6667/#coreos) IRC channel on freenode.org
|
||||
|
||||
Please avoid emailing maintainers found in the MAINTAINERS file directly. They
|
||||
are very busy and read the mailing lists.
|
||||
|
||||
## Getting Started
|
||||
|
||||
- Fork the repository on GitHub
|
||||
- Read the [README](README.md) for build and test instructions
|
||||
- Play with the project, submit bugs, submit patches!
|
||||
|
||||
## Contribution Flow
|
||||
|
||||
This is a rough outline of what a contributor's workflow looks like:
|
||||
|
||||
- Create a topic branch from where you want to base your work (usually master).
|
||||
- Make commits of logical units.
|
||||
- Make sure your commit messages are in the proper format (see below).
|
||||
- Push your changes to a topic branch in your fork of the repository.
|
||||
- Make sure the tests pass, and add any new tests as appropriate.
|
||||
- Submit a pull request to the original repository.
|
||||
|
||||
Thanks for your contributions!
|
||||
|
||||
### Format of the Commit Message
|
||||
|
||||
We follow a rough convention for commit messages that is designed to answer two
|
||||
questions: what changed and why. The subject line should feature the what and
|
||||
the body of the commit should describe the why.
|
||||
|
||||
```
|
||||
scripts: add the test-cluster command
|
||||
|
||||
this uses tmux to setup a test cluster that you can easily kill and
|
||||
start for debugging.
|
||||
|
||||
Fixes #38
|
||||
```
|
||||
|
||||
The format can be described more formally as follows:
|
||||
|
||||
```
|
||||
<subsystem>: <what changed>
|
||||
<BLANK LINE>
|
||||
<why this change was made>
|
||||
<BLANK LINE>
|
||||
<footer>
|
||||
```
|
||||
|
||||
The first line is the subject and should be no longer than 70 characters, the
|
||||
second line is always blank, and other lines should be wrapped at 80 characters.
|
||||
This allows the message to be easier to read on GitHub as well as in various
|
||||
git tools.
|
36
vendor/github.com/coreos/pkg/DCO
generated
vendored
Normal file
36
vendor/github.com/coreos/pkg/DCO
generated
vendored
Normal file
|
@ -0,0 +1,36 @@
|
|||
Developer Certificate of Origin
|
||||
Version 1.1
|
||||
|
||||
Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
|
||||
660 York Street, Suite 102,
|
||||
San Francisco, CA 94110 USA
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies of this
|
||||
license document, but changing it is not allowed.
|
||||
|
||||
|
||||
Developer's Certificate of Origin 1.1
|
||||
|
||||
By making a contribution to this project, I certify that:
|
||||
|
||||
(a) The contribution was created in whole or in part by me and I
|
||||
have the right to submit it under the open source license
|
||||
indicated in the file; or
|
||||
|
||||
(b) The contribution is based upon previous work that, to the best
|
||||
of my knowledge, is covered under an appropriate open source
|
||||
license and I have the right under that license to submit that
|
||||
work with modifications, whether created in whole or in part
|
||||
by me, under the same open source license (unless I am
|
||||
permitted to submit under a different license), as indicated
|
||||
in the file; or
|
||||
|
||||
(c) The contribution was provided directly to me by some other
|
||||
person who certified (a), (b) or (c) and I have not modified
|
||||
it.
|
||||
|
||||
(d) I understand and agree that this project and the contribution
|
||||
are public and that a record of the contribution (including all
|
||||
personal information I submit with it, including my sign-off) is
|
||||
maintained indefinitely and may be redistributed consistent with
|
||||
this project or the open source license(s) involved.
|
202
vendor/github.com/coreos/pkg/LICENSE
generated
vendored
Normal file
202
vendor/github.com/coreos/pkg/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,202 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright {yyyy} {name of copyright owner}
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
1
vendor/github.com/coreos/pkg/MAINTAINERS
generated
vendored
Normal file
1
vendor/github.com/coreos/pkg/MAINTAINERS
generated
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
Ed Rooth <ed.rooth@coreos.com> (@sym3tri)
|
5
vendor/github.com/coreos/pkg/NOTICE
generated
vendored
Normal file
5
vendor/github.com/coreos/pkg/NOTICE
generated
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
CoreOS Project
|
||||
Copyright 2014 CoreOS, Inc
|
||||
|
||||
This product includes software developed at CoreOS, Inc.
|
||||
(http://www.coreos.com/).
|
4
vendor/github.com/coreos/pkg/README.md
generated
vendored
Normal file
4
vendor/github.com/coreos/pkg/README.md
generated
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
a collection of go utility packages
|
||||
|
||||
[](https://travis-ci.org/coreos/pkg)
|
||||
[](https://godoc.org/github.com/coreos/pkg)
|
3
vendor/github.com/coreos/pkg/build
generated
vendored
Executable file
3
vendor/github.com/coreos/pkg/build
generated
vendored
Executable file
|
@ -0,0 +1,3 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
go build ./...
|
39
vendor/github.com/coreos/pkg/capnslog/README.md
generated
vendored
Normal file
39
vendor/github.com/coreos/pkg/capnslog/README.md
generated
vendored
Normal file
|
@ -0,0 +1,39 @@
|
|||
# capnslog, the CoreOS logging package
|
||||
|
||||
There are far too many logging packages out there, with varying degrees of licenses, far too many features (colorization, all sorts of log frameworks) or are just a pain to use (lack of `Fatalln()`?).
|
||||
capnslog provides a simple but consistent logging interface suitable for all kinds of projects.
|
||||
|
||||
### Design Principles
|
||||
|
||||
##### `package main` is the place where logging gets turned on and routed
|
||||
|
||||
A library should not touch log options, only generate log entries. Libraries are silent until main lets them speak.
|
||||
|
||||
##### All log options are runtime-configurable.
|
||||
|
||||
Still the job of `main` to expose these configurations. `main` may delegate this to, say, a configuration webhook, but does so explicitly.
|
||||
|
||||
##### There is one log object per package. It is registered under its repository and package name.
|
||||
|
||||
`main` activates logging for its repository and any dependency repositories it would also like to have output in its logstream. `main` also dictates at which level each subpackage logs.
|
||||
|
||||
##### There is *one* output stream, and it is an `io.Writer` composed with a formatter.
|
||||
|
||||
Splitting streams is probably not the job of your program, but rather, your log aggregation framework. If you must split output streams, again, `main` configures this and you can write a very simple two-output struct that satisfies io.Writer.
|
||||
|
||||
Fancy colorful formatting and JSON output are beyond the scope of a basic logging framework -- they're application/log-collector dependant. These are, at best, provided as options, but more likely, provided by your application.
|
||||
|
||||
##### Log objects are an interface
|
||||
|
||||
An object knows best how to print itself. Log objects can collect more interesting metadata if they wish, however, because text isn't going away anytime soon, they must all be marshalable to text. The simplest log object is a string, which returns itself. If you wish to do more fancy tricks for printing your log objects, see also JSON output -- introspect and write a formatter which can handle your advanced log interface. Making strings is the only thing guaranteed.
|
||||
|
||||
##### Log levels have specific meanings:
|
||||
|
||||
* Critical: Unrecoverable. Must fail.
|
||||
* Error: Data has been lost, a request has failed for a bad reason, or a required resource has been lost
|
||||
* Warning: (Hopefully) Temporary conditions that may cause errors, but may work fine. A replica disappearing (that may reconnect) is a warning.
|
||||
* Notice: Normal, but important (uncommon) log information.
|
||||
* Info: Normal, working log information, everything is fine, but helpful notices for auditing or common operations.
|
||||
* Debug: Everything is still fine, but even common operations may be logged, and less helpful but more quantity of notices.
|
||||
* Trace: Anything goes, from logging every function call as part of a common operation, to tracing execution of a query.
|
||||
|
57
vendor/github.com/coreos/pkg/capnslog/example/hello_dolly.go
generated
vendored
Normal file
57
vendor/github.com/coreos/pkg/capnslog/example/hello_dolly.go
generated
vendored
Normal file
|
@ -0,0 +1,57 @@
|
|||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
oldlog "log"
|
||||
|
||||
"github.com/coreos/pkg/capnslog"
|
||||
)
|
||||
|
||||
var logLevel = capnslog.INFO
|
||||
var log = capnslog.NewPackageLogger("github.com/coreos/pkg/capnslog/cmd", "main")
|
||||
var dlog = capnslog.NewPackageLogger("github.com/coreos/pkg/capnslog/cmd", "dolly")
|
||||
|
||||
func init() {
|
||||
flag.Var(&logLevel, "log-level", "Global log level.")
|
||||
}
|
||||
|
||||
func main() {
|
||||
rl := capnslog.MustRepoLogger("github.com/coreos/pkg/capnslog/cmd")
|
||||
|
||||
// We can parse the log level configs from the command line
|
||||
flag.Parse()
|
||||
if flag.NArg() > 1 {
|
||||
cfg, err := rl.ParseLogLevelConfig(flag.Arg(1))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
rl.SetLogLevel(cfg)
|
||||
log.Infof("Setting output to %s", flag.Arg(1))
|
||||
}
|
||||
|
||||
// Send some messages at different levels to the different packages
|
||||
dlog.Infof("Hello Dolly")
|
||||
dlog.Warningf("Well hello, Dolly")
|
||||
log.Errorf("It's so nice to have you back where you belong")
|
||||
dlog.Debugf("You're looking swell, Dolly")
|
||||
dlog.Tracef("I can tell, Dolly")
|
||||
|
||||
// We also have control over the built-in "log" package.
|
||||
capnslog.SetGlobalLogLevel(logLevel)
|
||||
oldlog.Println("You're still glowin', you're still crowin', you're still lookin' strong")
|
||||
log.Fatalf("Dolly'll never go away again")
|
||||
}
|
157
vendor/github.com/coreos/pkg/capnslog/formatters.go
generated
vendored
Normal file
157
vendor/github.com/coreos/pkg/capnslog/formatters.go
generated
vendored
Normal file
|
@ -0,0 +1,157 @@
|
|||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package capnslog
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Formatter interface {
|
||||
Format(pkg string, level LogLevel, depth int, entries ...interface{})
|
||||
Flush()
|
||||
}
|
||||
|
||||
func NewStringFormatter(w io.Writer) Formatter {
|
||||
return &StringFormatter{
|
||||
w: bufio.NewWriter(w),
|
||||
}
|
||||
}
|
||||
|
||||
type StringFormatter struct {
|
||||
w *bufio.Writer
|
||||
}
|
||||
|
||||
func (s *StringFormatter) Format(pkg string, l LogLevel, i int, entries ...interface{}) {
|
||||
now := time.Now().UTC()
|
||||
s.w.WriteString(now.Format(time.RFC3339))
|
||||
s.w.WriteByte(' ')
|
||||
writeEntries(s.w, pkg, l, i, entries...)
|
||||
s.Flush()
|
||||
}
|
||||
|
||||
func writeEntries(w *bufio.Writer, pkg string, _ LogLevel, _ int, entries ...interface{}) {
|
||||
if pkg != "" {
|
||||
w.WriteString(pkg + ": ")
|
||||
}
|
||||
str := fmt.Sprint(entries...)
|
||||
endsInNL := strings.HasSuffix(str, "\n")
|
||||
w.WriteString(str)
|
||||
if !endsInNL {
|
||||
w.WriteString("\n")
|
||||
}
|
||||
}
|
||||
|
||||
func (s *StringFormatter) Flush() {
|
||||
s.w.Flush()
|
||||
}
|
||||
|
||||
func NewPrettyFormatter(w io.Writer, debug bool) Formatter {
|
||||
return &PrettyFormatter{
|
||||
w: bufio.NewWriter(w),
|
||||
debug: debug,
|
||||
}
|
||||
}
|
||||
|
||||
type PrettyFormatter struct {
|
||||
w *bufio.Writer
|
||||
debug bool
|
||||
}
|
||||
|
||||
func (c *PrettyFormatter) Format(pkg string, l LogLevel, depth int, entries ...interface{}) {
|
||||
now := time.Now()
|
||||
ts := now.Format("2006-01-02 15:04:05")
|
||||
c.w.WriteString(ts)
|
||||
ms := now.Nanosecond() / 1000
|
||||
c.w.WriteString(fmt.Sprintf(".%06d", ms))
|
||||
if c.debug {
|
||||
_, file, line, ok := runtime.Caller(depth) // It's always the same number of frames to the user's call.
|
||||
if !ok {
|
||||
file = "???"
|
||||
line = 1
|
||||
} else {
|
||||
slash := strings.LastIndex(file, "/")
|
||||
if slash >= 0 {
|
||||
file = file[slash+1:]
|
||||
}
|
||||
}
|
||||
if line < 0 {
|
||||
line = 0 // not a real line number
|
||||
}
|
||||
c.w.WriteString(fmt.Sprintf(" [%s:%d]", file, line))
|
||||
}
|
||||
c.w.WriteString(fmt.Sprint(" ", l.Char(), " | "))
|
||||
writeEntries(c.w, pkg, l, depth, entries...)
|
||||
c.Flush()
|
||||
}
|
||||
|
||||
func (c *PrettyFormatter) Flush() {
|
||||
c.w.Flush()
|
||||
}
|
||||
|
||||
// LogFormatter emulates the form of the traditional built-in logger.
|
||||
type LogFormatter struct {
|
||||
logger *log.Logger
|
||||
prefix string
|
||||
}
|
||||
|
||||
// NewLogFormatter is a helper to produce a new LogFormatter struct. It uses the
|
||||
// golang log package to actually do the logging work so that logs look similar.
|
||||
func NewLogFormatter(w io.Writer, prefix string, flag int) Formatter {
|
||||
return &LogFormatter{
|
||||
logger: log.New(w, "", flag), // don't use prefix here
|
||||
prefix: prefix, // save it instead
|
||||
}
|
||||
}
|
||||
|
||||
// Format builds a log message for the LogFormatter. The LogLevel is ignored.
|
||||
func (lf *LogFormatter) Format(pkg string, _ LogLevel, _ int, entries ...interface{}) {
|
||||
str := fmt.Sprint(entries...)
|
||||
prefix := lf.prefix
|
||||
if pkg != "" {
|
||||
prefix = fmt.Sprintf("%s%s: ", prefix, pkg)
|
||||
}
|
||||
lf.logger.Output(5, fmt.Sprintf("%s%v", prefix, str)) // call depth is 5
|
||||
}
|
||||
|
||||
// Flush is included so that the interface is complete, but is a no-op.
|
||||
func (lf *LogFormatter) Flush() {
|
||||
// noop
|
||||
}
|
||||
|
||||
// NilFormatter is a no-op log formatter that does nothing.
|
||||
type NilFormatter struct {
|
||||
}
|
||||
|
||||
// NewNilFormatter is a helper to produce a new LogFormatter struct. It logs no
|
||||
// messages so that you can cause part of your logging to be silent.
|
||||
func NewNilFormatter() Formatter {
|
||||
return &NilFormatter{}
|
||||
}
|
||||
|
||||
// Format does nothing.
|
||||
func (_ *NilFormatter) Format(_ string, _ LogLevel, _ int, _ ...interface{}) {
|
||||
// noop
|
||||
}
|
||||
|
||||
// Flush is included so that the interface is complete, but is a no-op.
|
||||
func (_ *NilFormatter) Flush() {
|
||||
// noop
|
||||
}
|
96
vendor/github.com/coreos/pkg/capnslog/glog_formatter.go
generated
vendored
Normal file
96
vendor/github.com/coreos/pkg/capnslog/glog_formatter.go
generated
vendored
Normal file
|
@ -0,0 +1,96 @@
|
|||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package capnslog
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"io"
|
||||
"os"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
var pid = os.Getpid()
|
||||
|
||||
type GlogFormatter struct {
|
||||
StringFormatter
|
||||
}
|
||||
|
||||
func NewGlogFormatter(w io.Writer) *GlogFormatter {
|
||||
g := &GlogFormatter{}
|
||||
g.w = bufio.NewWriter(w)
|
||||
return g
|
||||
}
|
||||
|
||||
func (g GlogFormatter) Format(pkg string, level LogLevel, depth int, entries ...interface{}) {
|
||||
g.w.Write(GlogHeader(level, depth+1))
|
||||
g.StringFormatter.Format(pkg, level, depth+1, entries...)
|
||||
}
|
||||
|
||||
func GlogHeader(level LogLevel, depth int) []byte {
|
||||
// Lmmdd hh:mm:ss.uuuuuu threadid file:line]
|
||||
now := time.Now().UTC()
|
||||
_, file, line, ok := runtime.Caller(depth) // It's always the same number of frames to the user's call.
|
||||
if !ok {
|
||||
file = "???"
|
||||
line = 1
|
||||
} else {
|
||||
slash := strings.LastIndex(file, "/")
|
||||
if slash >= 0 {
|
||||
file = file[slash+1:]
|
||||
}
|
||||
}
|
||||
if line < 0 {
|
||||
line = 0 // not a real line number
|
||||
}
|
||||
buf := &bytes.Buffer{}
|
||||
buf.Grow(30)
|
||||
_, month, day := now.Date()
|
||||
hour, minute, second := now.Clock()
|
||||
buf.WriteString(level.Char())
|
||||
twoDigits(buf, int(month))
|
||||
twoDigits(buf, day)
|
||||
buf.WriteByte(' ')
|
||||
twoDigits(buf, hour)
|
||||
buf.WriteByte(':')
|
||||
twoDigits(buf, minute)
|
||||
buf.WriteByte(':')
|
||||
twoDigits(buf, second)
|
||||
buf.WriteByte('.')
|
||||
buf.WriteString(strconv.Itoa(now.Nanosecond() / 1000))
|
||||
buf.WriteByte('Z')
|
||||
buf.WriteByte(' ')
|
||||
buf.WriteString(strconv.Itoa(pid))
|
||||
buf.WriteByte(' ')
|
||||
buf.WriteString(file)
|
||||
buf.WriteByte(':')
|
||||
buf.WriteString(strconv.Itoa(line))
|
||||
buf.WriteByte(']')
|
||||
buf.WriteByte(' ')
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
const digits = "0123456789"
|
||||
|
||||
func twoDigits(b *bytes.Buffer, d int) {
|
||||
c2 := digits[d%10]
|
||||
d /= 10
|
||||
c1 := digits[d%10]
|
||||
b.WriteByte(c1)
|
||||
b.WriteByte(c2)
|
||||
}
|
49
vendor/github.com/coreos/pkg/capnslog/init.go
generated
vendored
Normal file
49
vendor/github.com/coreos/pkg/capnslog/init.go
generated
vendored
Normal file
|
@ -0,0 +1,49 @@
|
|||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// +build !windows
|
||||
|
||||
package capnslog
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// Here's where the opinionation comes in. We need some sensible defaults,
|
||||
// especially after taking over the log package. Your project (whatever it may
|
||||
// be) may see things differently. That's okay; there should be no defaults in
|
||||
// the main package that cannot be controlled or overridden programatically,
|
||||
// otherwise it's a bug. Doing so is creating your own init_log.go file much
|
||||
// like this one.
|
||||
|
||||
func init() {
|
||||
initHijack()
|
||||
|
||||
// Go `log` pacakge uses os.Stderr.
|
||||
SetFormatter(NewDefaultFormatter(os.Stderr))
|
||||
SetGlobalLogLevel(INFO)
|
||||
}
|
||||
|
||||
func NewDefaultFormatter(out io.Writer) Formatter {
|
||||
if syscall.Getppid() == 1 {
|
||||
// We're running under init, which may be systemd.
|
||||
f, err := NewJournaldFormatter()
|
||||
if err == nil {
|
||||
return f
|
||||
}
|
||||
}
|
||||
return NewPrettyFormatter(out, false)
|
||||
}
|
25
vendor/github.com/coreos/pkg/capnslog/init_windows.go
generated
vendored
Normal file
25
vendor/github.com/coreos/pkg/capnslog/init_windows.go
generated
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package capnslog
|
||||
|
||||
import "os"
|
||||
|
||||
func init() {
|
||||
initHijack()
|
||||
|
||||
// Go `log` package uses os.Stderr.
|
||||
SetFormatter(NewPrettyFormatter(os.Stderr, false))
|
||||
SetGlobalLogLevel(INFO)
|
||||
}
|
68
vendor/github.com/coreos/pkg/capnslog/journald_formatter.go
generated
vendored
Normal file
68
vendor/github.com/coreos/pkg/capnslog/journald_formatter.go
generated
vendored
Normal file
|
@ -0,0 +1,68 @@
|
|||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// +build !windows
|
||||
|
||||
package capnslog
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/coreos/go-systemd/journal"
|
||||
)
|
||||
|
||||
func NewJournaldFormatter() (Formatter, error) {
|
||||
if !journal.Enabled() {
|
||||
return nil, errors.New("No systemd detected")
|
||||
}
|
||||
return &journaldFormatter{}, nil
|
||||
}
|
||||
|
||||
type journaldFormatter struct{}
|
||||
|
||||
func (j *journaldFormatter) Format(pkg string, l LogLevel, _ int, entries ...interface{}) {
|
||||
var pri journal.Priority
|
||||
switch l {
|
||||
case CRITICAL:
|
||||
pri = journal.PriCrit
|
||||
case ERROR:
|
||||
pri = journal.PriErr
|
||||
case WARNING:
|
||||
pri = journal.PriWarning
|
||||
case NOTICE:
|
||||
pri = journal.PriNotice
|
||||
case INFO:
|
||||
pri = journal.PriInfo
|
||||
case DEBUG:
|
||||
pri = journal.PriDebug
|
||||
case TRACE:
|
||||
pri = journal.PriDebug
|
||||
default:
|
||||
panic("Unhandled loglevel")
|
||||
}
|
||||
msg := fmt.Sprint(entries...)
|
||||
tags := map[string]string{
|
||||
"PACKAGE": pkg,
|
||||
"SYSLOG_IDENTIFIER": filepath.Base(os.Args[0]),
|
||||
}
|
||||
err := journal.Send(msg, pri, tags)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
}
|
||||
}
|
||||
|
||||
func (j *journaldFormatter) Flush() {}
|
39
vendor/github.com/coreos/pkg/capnslog/log_hijack.go
generated
vendored
Normal file
39
vendor/github.com/coreos/pkg/capnslog/log_hijack.go
generated
vendored
Normal file
|
@ -0,0 +1,39 @@
|
|||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package capnslog
|
||||
|
||||
import (
|
||||
"log"
|
||||
)
|
||||
|
||||
func initHijack() {
|
||||
pkg := NewPackageLogger("log", "")
|
||||
w := packageWriter{pkg}
|
||||
log.SetFlags(0)
|
||||
log.SetPrefix("")
|
||||
log.SetOutput(w)
|
||||
}
|
||||
|
||||
type packageWriter struct {
|
||||
pl *PackageLogger
|
||||
}
|
||||
|
||||
func (p packageWriter) Write(b []byte) (int, error) {
|
||||
if p.pl.level < INFO {
|
||||
return 0, nil
|
||||
}
|
||||
p.pl.internalLog(calldepth+2, INFO, string(b))
|
||||
return len(b), nil
|
||||
}
|
240
vendor/github.com/coreos/pkg/capnslog/logmap.go
generated
vendored
Normal file
240
vendor/github.com/coreos/pkg/capnslog/logmap.go
generated
vendored
Normal file
|
@ -0,0 +1,240 @@
|
|||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package capnslog
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// LogLevel is the set of all log levels.
|
||||
type LogLevel int8
|
||||
|
||||
const (
|
||||
// CRITICAL is the lowest log level; only errors which will end the program will be propagated.
|
||||
CRITICAL LogLevel = iota - 1
|
||||
// ERROR is for errors that are not fatal but lead to troubling behavior.
|
||||
ERROR
|
||||
// WARNING is for errors which are not fatal and not errors, but are unusual. Often sourced from misconfigurations.
|
||||
WARNING
|
||||
// NOTICE is for normal but significant conditions.
|
||||
NOTICE
|
||||
// INFO is a log level for common, everyday log updates.
|
||||
INFO
|
||||
// DEBUG is the default hidden level for more verbose updates about internal processes.
|
||||
DEBUG
|
||||
// TRACE is for (potentially) call by call tracing of programs.
|
||||
TRACE
|
||||
)
|
||||
|
||||
// Char returns a single-character representation of the log level.
|
||||
func (l LogLevel) Char() string {
|
||||
switch l {
|
||||
case CRITICAL:
|
||||
return "C"
|
||||
case ERROR:
|
||||
return "E"
|
||||
case WARNING:
|
||||
return "W"
|
||||
case NOTICE:
|
||||
return "N"
|
||||
case INFO:
|
||||
return "I"
|
||||
case DEBUG:
|
||||
return "D"
|
||||
case TRACE:
|
||||
return "T"
|
||||
default:
|
||||
panic("Unhandled loglevel")
|
||||
}
|
||||
}
|
||||
|
||||
// String returns a multi-character representation of the log level.
|
||||
func (l LogLevel) String() string {
|
||||
switch l {
|
||||
case CRITICAL:
|
||||
return "CRITICAL"
|
||||
case ERROR:
|
||||
return "ERROR"
|
||||
case WARNING:
|
||||
return "WARNING"
|
||||
case NOTICE:
|
||||
return "NOTICE"
|
||||
case INFO:
|
||||
return "INFO"
|
||||
case DEBUG:
|
||||
return "DEBUG"
|
||||
case TRACE:
|
||||
return "TRACE"
|
||||
default:
|
||||
panic("Unhandled loglevel")
|
||||
}
|
||||
}
|
||||
|
||||
// Update using the given string value. Fulfills the flag.Value interface.
|
||||
func (l *LogLevel) Set(s string) error {
|
||||
value, err := ParseLevel(s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*l = value
|
||||
return nil
|
||||
}
|
||||
|
||||
// ParseLevel translates some potential loglevel strings into their corresponding levels.
|
||||
func ParseLevel(s string) (LogLevel, error) {
|
||||
switch s {
|
||||
case "CRITICAL", "C":
|
||||
return CRITICAL, nil
|
||||
case "ERROR", "0", "E":
|
||||
return ERROR, nil
|
||||
case "WARNING", "1", "W":
|
||||
return WARNING, nil
|
||||
case "NOTICE", "2", "N":
|
||||
return NOTICE, nil
|
||||
case "INFO", "3", "I":
|
||||
return INFO, nil
|
||||
case "DEBUG", "4", "D":
|
||||
return DEBUG, nil
|
||||
case "TRACE", "5", "T":
|
||||
return TRACE, nil
|
||||
}
|
||||
return CRITICAL, errors.New("couldn't parse log level " + s)
|
||||
}
|
||||
|
||||
type RepoLogger map[string]*PackageLogger
|
||||
|
||||
type loggerStruct struct {
|
||||
sync.Mutex
|
||||
repoMap map[string]RepoLogger
|
||||
formatter Formatter
|
||||
}
|
||||
|
||||
// logger is the global logger
|
||||
var logger = new(loggerStruct)
|
||||
|
||||
// SetGlobalLogLevel sets the log level for all packages in all repositories
|
||||
// registered with capnslog.
|
||||
func SetGlobalLogLevel(l LogLevel) {
|
||||
logger.Lock()
|
||||
defer logger.Unlock()
|
||||
for _, r := range logger.repoMap {
|
||||
r.setRepoLogLevelInternal(l)
|
||||
}
|
||||
}
|
||||
|
||||
// GetRepoLogger may return the handle to the repository's set of packages' loggers.
|
||||
func GetRepoLogger(repo string) (RepoLogger, error) {
|
||||
logger.Lock()
|
||||
defer logger.Unlock()
|
||||
r, ok := logger.repoMap[repo]
|
||||
if !ok {
|
||||
return nil, errors.New("no packages registered for repo " + repo)
|
||||
}
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// MustRepoLogger returns the handle to the repository's packages' loggers.
|
||||
func MustRepoLogger(repo string) RepoLogger {
|
||||
r, err := GetRepoLogger(repo)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// SetRepoLogLevel sets the log level for all packages in the repository.
|
||||
func (r RepoLogger) SetRepoLogLevel(l LogLevel) {
|
||||
logger.Lock()
|
||||
defer logger.Unlock()
|
||||
r.setRepoLogLevelInternal(l)
|
||||
}
|
||||
|
||||
func (r RepoLogger) setRepoLogLevelInternal(l LogLevel) {
|
||||
for _, v := range r {
|
||||
v.level = l
|
||||
}
|
||||
}
|
||||
|
||||
// ParseLogLevelConfig parses a comma-separated string of "package=loglevel", in
|
||||
// order, and returns a map of the results, for use in SetLogLevel.
|
||||
func (r RepoLogger) ParseLogLevelConfig(conf string) (map[string]LogLevel, error) {
|
||||
setlist := strings.Split(conf, ",")
|
||||
out := make(map[string]LogLevel)
|
||||
for _, setstring := range setlist {
|
||||
setting := strings.Split(setstring, "=")
|
||||
if len(setting) != 2 {
|
||||
return nil, errors.New("oddly structured `pkg=level` option: " + setstring)
|
||||
}
|
||||
l, err := ParseLevel(setting[1])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out[setting[0]] = l
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// SetLogLevel takes a map of package names within a repository to their desired
|
||||
// loglevel, and sets the levels appropriately. Unknown packages are ignored.
|
||||
// "*" is a special package name that corresponds to all packages, and will be
|
||||
// processed first.
|
||||
func (r RepoLogger) SetLogLevel(m map[string]LogLevel) {
|
||||
logger.Lock()
|
||||
defer logger.Unlock()
|
||||
if l, ok := m["*"]; ok {
|
||||
r.setRepoLogLevelInternal(l)
|
||||
}
|
||||
for k, v := range m {
|
||||
l, ok := r[k]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
l.level = v
|
||||
}
|
||||
}
|
||||
|
||||
// SetFormatter sets the formatting function for all logs.
|
||||
func SetFormatter(f Formatter) {
|
||||
logger.Lock()
|
||||
defer logger.Unlock()
|
||||
logger.formatter = f
|
||||
}
|
||||
|
||||
// NewPackageLogger creates a package logger object.
|
||||
// This should be defined as a global var in your package, referencing your repo.
|
||||
func NewPackageLogger(repo string, pkg string) (p *PackageLogger) {
|
||||
logger.Lock()
|
||||
defer logger.Unlock()
|
||||
if logger.repoMap == nil {
|
||||
logger.repoMap = make(map[string]RepoLogger)
|
||||
}
|
||||
r, rok := logger.repoMap[repo]
|
||||
if !rok {
|
||||
logger.repoMap[repo] = make(RepoLogger)
|
||||
r = logger.repoMap[repo]
|
||||
}
|
||||
p, pok := r[pkg]
|
||||
if !pok {
|
||||
r[pkg] = &PackageLogger{
|
||||
pkg: pkg,
|
||||
level: INFO,
|
||||
}
|
||||
p = r[pkg]
|
||||
}
|
||||
return
|
||||
}
|
177
vendor/github.com/coreos/pkg/capnslog/pkg_logger.go
generated
vendored
Normal file
177
vendor/github.com/coreos/pkg/capnslog/pkg_logger.go
generated
vendored
Normal file
|
@ -0,0 +1,177 @@
|
|||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package capnslog
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
type PackageLogger struct {
|
||||
pkg string
|
||||
level LogLevel
|
||||
}
|
||||
|
||||
const calldepth = 2
|
||||
|
||||
func (p *PackageLogger) internalLog(depth int, inLevel LogLevel, entries ...interface{}) {
|
||||
logger.Lock()
|
||||
defer logger.Unlock()
|
||||
if inLevel != CRITICAL && p.level < inLevel {
|
||||
return
|
||||
}
|
||||
if logger.formatter != nil {
|
||||
logger.formatter.Format(p.pkg, inLevel, depth+1, entries...)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *PackageLogger) LevelAt(l LogLevel) bool {
|
||||
logger.Lock()
|
||||
defer logger.Unlock()
|
||||
return p.level >= l
|
||||
}
|
||||
|
||||
// Log a formatted string at any level between ERROR and TRACE
|
||||
func (p *PackageLogger) Logf(l LogLevel, format string, args ...interface{}) {
|
||||
p.internalLog(calldepth, l, fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
// Log a message at any level between ERROR and TRACE
|
||||
func (p *PackageLogger) Log(l LogLevel, args ...interface{}) {
|
||||
p.internalLog(calldepth, l, fmt.Sprint(args...))
|
||||
}
|
||||
|
||||
// log stdlib compatibility
|
||||
|
||||
func (p *PackageLogger) Println(args ...interface{}) {
|
||||
p.internalLog(calldepth, INFO, fmt.Sprintln(args...))
|
||||
}
|
||||
|
||||
func (p *PackageLogger) Printf(format string, args ...interface{}) {
|
||||
p.Logf(INFO, format, args...)
|
||||
}
|
||||
|
||||
func (p *PackageLogger) Print(args ...interface{}) {
|
||||
p.internalLog(calldepth, INFO, fmt.Sprint(args...))
|
||||
}
|
||||
|
||||
// Panic and fatal
|
||||
|
||||
func (p *PackageLogger) Panicf(format string, args ...interface{}) {
|
||||
s := fmt.Sprintf(format, args...)
|
||||
p.internalLog(calldepth, CRITICAL, s)
|
||||
panic(s)
|
||||
}
|
||||
|
||||
func (p *PackageLogger) Panic(args ...interface{}) {
|
||||
s := fmt.Sprint(args...)
|
||||
p.internalLog(calldepth, CRITICAL, s)
|
||||
panic(s)
|
||||
}
|
||||
|
||||
func (p *PackageLogger) Fatalf(format string, args ...interface{}) {
|
||||
p.Logf(CRITICAL, format, args...)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func (p *PackageLogger) Fatal(args ...interface{}) {
|
||||
s := fmt.Sprint(args...)
|
||||
p.internalLog(calldepth, CRITICAL, s)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func (p *PackageLogger) Fatalln(args ...interface{}) {
|
||||
s := fmt.Sprintln(args...)
|
||||
p.internalLog(calldepth, CRITICAL, s)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Error Functions
|
||||
|
||||
func (p *PackageLogger) Errorf(format string, args ...interface{}) {
|
||||
p.Logf(ERROR, format, args...)
|
||||
}
|
||||
|
||||
func (p *PackageLogger) Error(entries ...interface{}) {
|
||||
p.internalLog(calldepth, ERROR, entries...)
|
||||
}
|
||||
|
||||
// Warning Functions
|
||||
|
||||
func (p *PackageLogger) Warningf(format string, args ...interface{}) {
|
||||
p.Logf(WARNING, format, args...)
|
||||
}
|
||||
|
||||
func (p *PackageLogger) Warning(entries ...interface{}) {
|
||||
p.internalLog(calldepth, WARNING, entries...)
|
||||
}
|
||||
|
||||
// Notice Functions
|
||||
|
||||
func (p *PackageLogger) Noticef(format string, args ...interface{}) {
|
||||
p.Logf(NOTICE, format, args...)
|
||||
}
|
||||
|
||||
func (p *PackageLogger) Notice(entries ...interface{}) {
|
||||
p.internalLog(calldepth, NOTICE, entries...)
|
||||
}
|
||||
|
||||
// Info Functions
|
||||
|
||||
func (p *PackageLogger) Infof(format string, args ...interface{}) {
|
||||
p.Logf(INFO, format, args...)
|
||||
}
|
||||
|
||||
func (p *PackageLogger) Info(entries ...interface{}) {
|
||||
p.internalLog(calldepth, INFO, entries...)
|
||||
}
|
||||
|
||||
// Debug Functions
|
||||
|
||||
func (p *PackageLogger) Debugf(format string, args ...interface{}) {
|
||||
if p.level < DEBUG {
|
||||
return
|
||||
}
|
||||
p.Logf(DEBUG, format, args...)
|
||||
}
|
||||
|
||||
func (p *PackageLogger) Debug(entries ...interface{}) {
|
||||
if p.level < DEBUG {
|
||||
return
|
||||
}
|
||||
p.internalLog(calldepth, DEBUG, entries...)
|
||||
}
|
||||
|
||||
// Trace Functions
|
||||
|
||||
func (p *PackageLogger) Tracef(format string, args ...interface{}) {
|
||||
if p.level < TRACE {
|
||||
return
|
||||
}
|
||||
p.Logf(TRACE, format, args...)
|
||||
}
|
||||
|
||||
func (p *PackageLogger) Trace(entries ...interface{}) {
|
||||
if p.level < TRACE {
|
||||
return
|
||||
}
|
||||
p.internalLog(calldepth, TRACE, entries...)
|
||||
}
|
||||
|
||||
func (p *PackageLogger) Flush() {
|
||||
logger.Lock()
|
||||
defer logger.Unlock()
|
||||
logger.formatter.Flush()
|
||||
}
|
65
vendor/github.com/coreos/pkg/capnslog/syslog_formatter.go
generated
vendored
Normal file
65
vendor/github.com/coreos/pkg/capnslog/syslog_formatter.go
generated
vendored
Normal file
|
@ -0,0 +1,65 @@
|
|||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// +build !windows
|
||||
|
||||
package capnslog
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log/syslog"
|
||||
)
|
||||
|
||||
func NewSyslogFormatter(w *syslog.Writer) Formatter {
|
||||
return &syslogFormatter{w}
|
||||
}
|
||||
|
||||
func NewDefaultSyslogFormatter(tag string) (Formatter, error) {
|
||||
w, err := syslog.New(syslog.LOG_DEBUG, tag)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewSyslogFormatter(w), nil
|
||||
}
|
||||
|
||||
type syslogFormatter struct {
|
||||
w *syslog.Writer
|
||||
}
|
||||
|
||||
func (s *syslogFormatter) Format(pkg string, l LogLevel, _ int, entries ...interface{}) {
|
||||
for _, entry := range entries {
|
||||
str := fmt.Sprint(entry)
|
||||
switch l {
|
||||
case CRITICAL:
|
||||
s.w.Crit(str)
|
||||
case ERROR:
|
||||
s.w.Err(str)
|
||||
case WARNING:
|
||||
s.w.Warning(str)
|
||||
case NOTICE:
|
||||
s.w.Notice(str)
|
||||
case INFO:
|
||||
s.w.Info(str)
|
||||
case DEBUG:
|
||||
s.w.Debug(str)
|
||||
case TRACE:
|
||||
s.w.Debug(str)
|
||||
default:
|
||||
panic("Unhandled loglevel")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *syslogFormatter) Flush() {
|
||||
}
|
94
vendor/github.com/coreos/pkg/cryptoutil/aes.go
generated
vendored
Normal file
94
vendor/github.com/coreos/pkg/cryptoutil/aes.go
generated
vendored
Normal file
|
@ -0,0 +1,94 @@
|
|||
package cryptoutil
|
||||
|
||||
import (
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/rand"
|
||||
"errors"
|
||||
)
|
||||
|
||||
// pad uses the PKCS#7 padding scheme to align the a payload to a specific block size
|
||||
func pad(plaintext []byte, bsize int) ([]byte, error) {
|
||||
if bsize >= 256 {
|
||||
return nil, errors.New("bsize must be < 256")
|
||||
}
|
||||
pad := bsize - (len(plaintext) % bsize)
|
||||
if pad == 0 {
|
||||
pad = bsize
|
||||
}
|
||||
for i := 0; i < pad; i++ {
|
||||
plaintext = append(plaintext, byte(pad))
|
||||
}
|
||||
return plaintext, nil
|
||||
}
|
||||
|
||||
// unpad strips the padding previously added using the PKCS#7 padding scheme
|
||||
func unpad(paddedtext []byte) ([]byte, error) {
|
||||
length := len(paddedtext)
|
||||
paddedtext, lbyte := paddedtext[:length-1], paddedtext[length-1]
|
||||
pad := int(lbyte)
|
||||
if pad >= 256 || pad > length {
|
||||
return nil, errors.New("padding malformed")
|
||||
}
|
||||
return paddedtext[:length-(pad)], nil
|
||||
}
|
||||
|
||||
// AESEncrypt encrypts a payload with an AES cipher.
|
||||
// The returned ciphertext has three notable properties:
|
||||
// 1. ciphertext is aligned to the standard AES block size
|
||||
// 2. ciphertext is padded using PKCS#7
|
||||
// 3. IV is prepended to the ciphertext
|
||||
func AESEncrypt(plaintext, key []byte) ([]byte, error) {
|
||||
plaintext, err := pad(plaintext, aes.BlockSize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ciphertext := make([]byte, aes.BlockSize+len(plaintext))
|
||||
iv := ciphertext[:aes.BlockSize]
|
||||
if _, err := rand.Read(iv); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
mode := cipher.NewCBCEncrypter(block, iv)
|
||||
mode.CryptBlocks(ciphertext[aes.BlockSize:], plaintext)
|
||||
|
||||
return ciphertext, nil
|
||||
}
|
||||
|
||||
// AESDecrypt decrypts an encrypted payload with an AES cipher.
|
||||
// The decryption algorithm makes three assumptions:
|
||||
// 1. ciphertext is aligned to the standard AES block size
|
||||
// 2. ciphertext is padded using PKCS#7
|
||||
// 3. the IV is prepended to ciphertext
|
||||
func AESDecrypt(ciphertext, key []byte) ([]byte, error) {
|
||||
if len(ciphertext) < aes.BlockSize {
|
||||
return nil, errors.New("ciphertext too short")
|
||||
}
|
||||
|
||||
iv := ciphertext[:aes.BlockSize]
|
||||
ciphertext = ciphertext[aes.BlockSize:]
|
||||
|
||||
if len(ciphertext)%aes.BlockSize != 0 {
|
||||
return nil, errors.New("ciphertext is not a multiple of the block size")
|
||||
}
|
||||
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
mode := cipher.NewCBCDecrypter(block, iv)
|
||||
mode.CryptBlocks(ciphertext, ciphertext)
|
||||
|
||||
if len(ciphertext)%aes.BlockSize != 0 {
|
||||
return nil, errors.New("ciphertext is not a multiple of the block size")
|
||||
}
|
||||
|
||||
return unpad(ciphertext)
|
||||
}
|
93
vendor/github.com/coreos/pkg/cryptoutil/aes_test.go
generated
vendored
Normal file
93
vendor/github.com/coreos/pkg/cryptoutil/aes_test.go
generated
vendored
Normal file
|
@ -0,0 +1,93 @@
|
|||
package cryptoutil
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestPadUnpad(t *testing.T) {
|
||||
tests := []struct {
|
||||
plaintext []byte
|
||||
bsize int
|
||||
padded []byte
|
||||
}{
|
||||
{
|
||||
plaintext: []byte{1, 2, 3, 4},
|
||||
bsize: 7,
|
||||
padded: []byte{1, 2, 3, 4, 3, 3, 3},
|
||||
},
|
||||
{
|
||||
plaintext: []byte{1, 2, 3, 4, 5, 6, 7},
|
||||
bsize: 3,
|
||||
padded: []byte{1, 2, 3, 4, 5, 6, 7, 2, 2},
|
||||
},
|
||||
{
|
||||
plaintext: []byte{9, 9, 9, 9},
|
||||
bsize: 4,
|
||||
padded: []byte{9, 9, 9, 9, 4, 4, 4, 4},
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
padded, err := pad(tt.plaintext, tt.bsize)
|
||||
if err != nil {
|
||||
t.Errorf("case %d: unexpected error: %v", i, err)
|
||||
continue
|
||||
}
|
||||
if !reflect.DeepEqual(tt.padded, padded) {
|
||||
t.Errorf("case %d: want=%v got=%v", i, tt.padded, padded)
|
||||
continue
|
||||
}
|
||||
|
||||
plaintext, err := unpad(tt.padded)
|
||||
if err != nil {
|
||||
t.Errorf("case %d: unexpected error: %v", i, err)
|
||||
continue
|
||||
}
|
||||
if !reflect.DeepEqual(tt.plaintext, plaintext) {
|
||||
t.Errorf("case %d: want=%v got=%v", i, tt.plaintext, plaintext)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPadMaxBlockSize(t *testing.T) {
|
||||
_, err := pad([]byte{1, 2, 3}, 256)
|
||||
if err == nil {
|
||||
t.Errorf("Expected non-nil error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAESEncryptDecrypt(t *testing.T) {
|
||||
message := []byte("Let me worry about blank.")
|
||||
key := append([]byte("shark"), make([]byte, 27)...)
|
||||
|
||||
ciphertext, err := AESEncrypt(message, key)
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
if reflect.DeepEqual(message, ciphertext) {
|
||||
t.Fatal("Encrypted data matches original payload")
|
||||
}
|
||||
|
||||
decrypted, err := AESDecrypt(ciphertext, key)
|
||||
if !reflect.DeepEqual(message, decrypted) {
|
||||
t.Fatalf("Decrypted data does not match original payload: want=%v got=%v", message, decrypted)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAESDecryptWrongKey(t *testing.T) {
|
||||
message := []byte("My bones!")
|
||||
key := append([]byte("shark"), make([]byte, 27)...)
|
||||
|
||||
ciphertext, err := AESEncrypt(message, key)
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
|
||||
wrongKey := append([]byte("sheep"), make([]byte, 27)...)
|
||||
decrypted, _ := AESDecrypt(ciphertext, wrongKey)
|
||||
if reflect.DeepEqual(message, decrypted) {
|
||||
t.Fatalf("Data decrypted with different key matches original payload")
|
||||
}
|
||||
}
|
82
vendor/github.com/coreos/pkg/dlopen/dlopen.go
generated
vendored
Normal file
82
vendor/github.com/coreos/pkg/dlopen/dlopen.go
generated
vendored
Normal file
|
@ -0,0 +1,82 @@
|
|||
// Copyright 2016 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package dlopen provides some convenience functions to dlopen a library and
|
||||
// get its symbols.
|
||||
package dlopen
|
||||
|
||||
// #cgo LDFLAGS: -ldl
|
||||
// #include <stdlib.h>
|
||||
// #include <dlfcn.h>
|
||||
import "C"
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var ErrSoNotFound = errors.New("unable to open a handle to the library")
|
||||
|
||||
// LibHandle represents an open handle to a library (.so)
|
||||
type LibHandle struct {
|
||||
Handle unsafe.Pointer
|
||||
Libname string
|
||||
}
|
||||
|
||||
// GetHandle tries to get a handle to a library (.so), attempting to access it
|
||||
// by the names specified in libs and returning the first that is successfully
|
||||
// opened. Callers are responsible for closing the handler. If no library can
|
||||
// be successfully opened, an error is returned.
|
||||
func GetHandle(libs []string) (*LibHandle, error) {
|
||||
for _, name := range libs {
|
||||
libname := C.CString(name)
|
||||
defer C.free(unsafe.Pointer(libname))
|
||||
handle := C.dlopen(libname, C.RTLD_LAZY)
|
||||
if handle != nil {
|
||||
h := &LibHandle{
|
||||
Handle: handle,
|
||||
Libname: name,
|
||||
}
|
||||
return h, nil
|
||||
}
|
||||
}
|
||||
return nil, ErrSoNotFound
|
||||
}
|
||||
|
||||
// GetSymbolPointer takes a symbol name and returns a pointer to the symbol.
|
||||
func (l *LibHandle) GetSymbolPointer(symbol string) (unsafe.Pointer, error) {
|
||||
sym := C.CString(symbol)
|
||||
defer C.free(unsafe.Pointer(sym))
|
||||
|
||||
C.dlerror()
|
||||
p := C.dlsym(l.Handle, sym)
|
||||
e := C.dlerror()
|
||||
if e != nil {
|
||||
return nil, fmt.Errorf("error resolving symbol %q: %v", symbol, errors.New(C.GoString(e)))
|
||||
}
|
||||
|
||||
return p, nil
|
||||
}
|
||||
|
||||
// Close closes a LibHandle.
|
||||
func (l *LibHandle) Close() error {
|
||||
C.dlerror()
|
||||
C.dlclose(l.Handle)
|
||||
e := C.dlerror()
|
||||
if e != nil {
|
||||
return fmt.Errorf("error closing %v: %v", l.Libname, errors.New(C.GoString(e)))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
56
vendor/github.com/coreos/pkg/dlopen/dlopen_example.go
generated
vendored
Normal file
56
vendor/github.com/coreos/pkg/dlopen/dlopen_example.go
generated
vendored
Normal file
|
@ -0,0 +1,56 @@
|
|||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// +build linux
|
||||
|
||||
package dlopen
|
||||
|
||||
// #include <string.h>
|
||||
// #include <stdlib.h>
|
||||
//
|
||||
// int
|
||||
// my_strlen(void *f, const char *s)
|
||||
// {
|
||||
// size_t (*strlen)(const char *);
|
||||
//
|
||||
// strlen = (size_t (*)(const char *))f;
|
||||
// return strlen(s);
|
||||
// }
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func strlen(libs []string, s string) (int, error) {
|
||||
h, err := GetHandle(libs)
|
||||
if err != nil {
|
||||
return -1, fmt.Errorf(`couldn't get a handle to the library: %v`, err)
|
||||
}
|
||||
defer h.Close()
|
||||
|
||||
f := "strlen"
|
||||
cs := C.CString(s)
|
||||
defer C.free(unsafe.Pointer(cs))
|
||||
|
||||
strlen, err := h.GetSymbolPointer(f)
|
||||
if err != nil {
|
||||
return -1, fmt.Errorf(`couldn't get symbol %q: %v`, f, err)
|
||||
}
|
||||
|
||||
len := C.my_strlen(strlen, cs)
|
||||
|
||||
return int(len), nil
|
||||
}
|
63
vendor/github.com/coreos/pkg/dlopen/dlopen_test.go
generated
vendored
Normal file
63
vendor/github.com/coreos/pkg/dlopen/dlopen_test.go
generated
vendored
Normal file
|
@ -0,0 +1,63 @@
|
|||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
package dlopen
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func checkFailure(shouldSucceed bool, err error) (rErr error) {
|
||||
switch {
|
||||
case err != nil && shouldSucceed:
|
||||
rErr = fmt.Errorf("expected test to succeed, failed unexpectedly: %v", err)
|
||||
case err == nil && !shouldSucceed:
|
||||
rErr = fmt.Errorf("expected test to fail, succeeded unexpectedly")
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func TestDlopen(t *testing.T) {
|
||||
tests := []struct {
|
||||
libs []string
|
||||
shouldSucceed bool
|
||||
}{
|
||||
{
|
||||
libs: []string{
|
||||
"libc.so.6",
|
||||
"libc.so",
|
||||
},
|
||||
shouldSucceed: true,
|
||||
},
|
||||
{
|
||||
libs: []string{
|
||||
"libstrange.so",
|
||||
},
|
||||
shouldSucceed: false,
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
expLen := 4
|
||||
len, err := strlen(tt.libs, "test")
|
||||
if checkFailure(tt.shouldSucceed, err) != nil {
|
||||
t.Errorf("case %d: %v", i, err)
|
||||
}
|
||||
|
||||
if tt.shouldSucceed && len != expLen {
|
||||
t.Errorf("case %d: expected length %d, got %d", i, expLen, len)
|
||||
}
|
||||
}
|
||||
}
|
33
vendor/github.com/coreos/pkg/flagutil/env.go
generated
vendored
Normal file
33
vendor/github.com/coreos/pkg/flagutil/env.go
generated
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
package flagutil
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// SetFlagsFromEnv parses all registered flags in the given flagset,
|
||||
// and if they are not already set it attempts to set their values from
|
||||
// environment variables. Environment variables take the name of the flag but
|
||||
// are UPPERCASE, and any dashes are replaced by underscores. Environment
|
||||
// variables additionally are prefixed by the given string followed by
|
||||
// and underscore. For example, if prefix=PREFIX: some-flag => PREFIX_SOME_FLAG
|
||||
func SetFlagsFromEnv(fs *flag.FlagSet, prefix string) (err error) {
|
||||
alreadySet := make(map[string]bool)
|
||||
fs.Visit(func(f *flag.Flag) {
|
||||
alreadySet[f.Name] = true
|
||||
})
|
||||
fs.VisitAll(func(f *flag.Flag) {
|
||||
if !alreadySet[f.Name] {
|
||||
key := prefix + "_" + strings.ToUpper(strings.Replace(f.Name, "-", "_", -1))
|
||||
val := os.Getenv(key)
|
||||
if val != "" {
|
||||
if serr := fs.Set(f.Name, val); serr != nil {
|
||||
err = fmt.Errorf("invalid value %q for %s: %v", val, key, serr)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
return err
|
||||
}
|
77
vendor/github.com/coreos/pkg/flagutil/env_file.go
generated
vendored
Normal file
77
vendor/github.com/coreos/pkg/flagutil/env_file.go
generated
vendored
Normal file
|
@ -0,0 +1,77 @@
|
|||
package flagutil
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// SetFlagsFromEnvFile iterates the given flagset and if any flags are not
|
||||
// already set it attempts to set their values from the given env file. Env
|
||||
// files may have KEY=VALUE lines where the environment variable names are
|
||||
// in UPPERCASE, prefixed by the given PREFIX, and dashes are replaced by
|
||||
// underscores. For example, if prefix=PREFIX, some-flag is named
|
||||
// PREFIX_SOME_FLAG.
|
||||
// Comment lines are skipped, but more complex env file parsing is not
|
||||
// performed.
|
||||
func SetFlagsFromEnvFile(fs *flag.FlagSet, prefix string, path string) (err error) {
|
||||
alreadySet := make(map[string]bool)
|
||||
fs.Visit(func(f *flag.Flag) {
|
||||
alreadySet[f.Name] = true
|
||||
})
|
||||
envs, err := parseEnvFile(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fs.VisitAll(func(f *flag.Flag) {
|
||||
if !alreadySet[f.Name] {
|
||||
key := prefix + "_" + strings.ToUpper(strings.Replace(f.Name, "-", "_", -1))
|
||||
val := envs[key]
|
||||
if val != "" {
|
||||
if serr := fs.Set(f.Name, val); serr != nil {
|
||||
err = fmt.Errorf("invalid value %q for %s: %v", val, key, serr)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func parseEnvFile(path string) (map[string]string, error) {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
envs := make(map[string]string)
|
||||
scanner := bufio.NewScanner(file)
|
||||
for scanner.Scan() {
|
||||
token := scanner.Text()
|
||||
if !skipLine(token) {
|
||||
key, val, err := parseLine(token)
|
||||
if err == nil {
|
||||
envs[key] = val
|
||||
}
|
||||
}
|
||||
}
|
||||
return envs, nil
|
||||
}
|
||||
|
||||
func skipLine(line string) bool {
|
||||
return len(line) == 0 || strings.HasPrefix(line, "#")
|
||||
}
|
||||
|
||||
func parseLine(line string) (key string, val string, err error) {
|
||||
trimmed := strings.TrimSpace(line)
|
||||
pair := strings.SplitN(trimmed, "=", 2)
|
||||
if len(pair) != 2 {
|
||||
err = fmt.Errorf("invalid KEY=value line: %q", line)
|
||||
return
|
||||
}
|
||||
key = strings.TrimSpace(pair[0])
|
||||
val = strings.TrimSpace(pair[1])
|
||||
return
|
||||
}
|
64
vendor/github.com/coreos/pkg/flagutil/env_test.go
generated
vendored
Normal file
64
vendor/github.com/coreos/pkg/flagutil/env_test.go
generated
vendored
Normal file
|
@ -0,0 +1,64 @@
|
|||
package flagutil
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSetFlagsFromEnv(t *testing.T) {
|
||||
fs := flag.NewFlagSet("testing", flag.ExitOnError)
|
||||
fs.String("a", "", "")
|
||||
fs.String("b", "", "")
|
||||
fs.String("c", "", "")
|
||||
fs.Parse([]string{})
|
||||
|
||||
os.Clearenv()
|
||||
// flags should be settable using env vars
|
||||
os.Setenv("MYPROJ_A", "foo")
|
||||
// and command-line flags
|
||||
if err := fs.Set("b", "bar"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// command-line flags take precedence over env vars
|
||||
os.Setenv("MYPROJ_C", "woof")
|
||||
if err := fs.Set("c", "quack"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// first verify that flags are as expected before reading the env
|
||||
for f, want := range map[string]string{
|
||||
"a": "",
|
||||
"b": "bar",
|
||||
"c": "quack",
|
||||
} {
|
||||
if got := fs.Lookup(f).Value.String(); got != want {
|
||||
t.Fatalf("flag %q=%q, want %q", f, got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// now read the env and verify flags were updated as expected
|
||||
err := SetFlagsFromEnv(fs, "MYPROJ")
|
||||
if err != nil {
|
||||
t.Errorf("err=%v, want nil", err)
|
||||
}
|
||||
for f, want := range map[string]string{
|
||||
"a": "foo",
|
||||
"b": "bar",
|
||||
"c": "quack",
|
||||
} {
|
||||
if got := fs.Lookup(f).Value.String(); got != want {
|
||||
t.Errorf("flag %q=%q, want %q", f, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetFlagsFromEnvBad(t *testing.T) {
|
||||
// now verify that an error is propagated
|
||||
fs := flag.NewFlagSet("testing", flag.ExitOnError)
|
||||
fs.Int("x", 0, "")
|
||||
os.Setenv("MYPROJ_X", "not_a_number")
|
||||
if err := SetFlagsFromEnv(fs, "MYPROJ"); err == nil {
|
||||
t.Errorf("err=nil, want != nil")
|
||||
}
|
||||
}
|
107
vendor/github.com/coreos/pkg/flagutil/file_env_test.go
generated
vendored
Normal file
107
vendor/github.com/coreos/pkg/flagutil/file_env_test.go
generated
vendored
Normal file
|
@ -0,0 +1,107 @@
|
|||
package flagutil
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var envFile = `
|
||||
# some secret env vars
|
||||
MYPROJ_A=foo
|
||||
MYPROJ_C=woof
|
||||
`
|
||||
|
||||
func TestSetFlagsFromEnvFile(t *testing.T) {
|
||||
fs := flag.NewFlagSet("testing", flag.ExitOnError)
|
||||
fs.String("a", "", "")
|
||||
fs.String("b", "", "")
|
||||
fs.String("c", "", "")
|
||||
fs.Parse([]string{})
|
||||
|
||||
// add command-line flags
|
||||
if err := fs.Set("b", "bar"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := fs.Set("c", "quack"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// first verify that flags are as expected before reading the env
|
||||
for f, want := range map[string]string{
|
||||
"a": "",
|
||||
"b": "bar",
|
||||
"c": "quack",
|
||||
} {
|
||||
if got := fs.Lookup(f).Value.String(); got != want {
|
||||
t.Fatalf("flag %q=%q, want %q", f, got, want)
|
||||
}
|
||||
}
|
||||
|
||||
file, err := ioutil.TempFile("", "env-file")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.Remove(file.Name())
|
||||
file.Write([]byte(envFile))
|
||||
|
||||
// read env file and verify flags were updated as expected
|
||||
err = SetFlagsFromEnvFile(fs, "MYPROJ", file.Name())
|
||||
if err != nil {
|
||||
t.Errorf("err=%v, want nil", err)
|
||||
}
|
||||
for f, want := range map[string]string{
|
||||
"a": "foo",
|
||||
"b": "bar",
|
||||
"c": "quack",
|
||||
} {
|
||||
if got := fs.Lookup(f).Value.String(); got != want {
|
||||
t.Errorf("flag %q=%q, want %q", f, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetFlagsFromEnvFile_FlagSetError(t *testing.T) {
|
||||
// now verify that an error is propagated
|
||||
fs := flag.NewFlagSet("testing", flag.ExitOnError)
|
||||
fs.Int("x", 0, "")
|
||||
file, err := ioutil.TempFile("", "env-file")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.Remove(file.Name())
|
||||
file.Write([]byte("MYPROJ_X=not_a_number"))
|
||||
if err := SetFlagsFromEnvFile(fs, "MYPROJ", file.Name()); err == nil {
|
||||
t.Errorf("err=nil, want != nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseLine(t *testing.T) {
|
||||
cases := []struct {
|
||||
line string
|
||||
expectedKey string
|
||||
expectedVal string
|
||||
nilErr bool
|
||||
}{
|
||||
{"key=value", "key", "value", true},
|
||||
{" key = value ", "key", "value", true},
|
||||
{"key='#gopher' #blah", "key", "'#gopher' #blah", true},
|
||||
// invalid
|
||||
{"key:value", "", "", false},
|
||||
{"keyvalue", "", "", false},
|
||||
}
|
||||
for _, c := range cases {
|
||||
key, val, err := parseLine(c.line)
|
||||
if (err == nil) != c.nilErr {
|
||||
if c.nilErr {
|
||||
t.Errorf("got %s, want err=nil", err)
|
||||
} else {
|
||||
t.Errorf("got err=nil, want err!=nil")
|
||||
}
|
||||
}
|
||||
if c.expectedKey != key || c.expectedVal != val {
|
||||
t.Errorf("got %q=%q, want %q=%q", key, val, c.expectedKey, c.expectedVal)
|
||||
}
|
||||
}
|
||||
}
|
44
vendor/github.com/coreos/pkg/flagutil/types.go
generated
vendored
Normal file
44
vendor/github.com/coreos/pkg/flagutil/types.go
generated
vendored
Normal file
|
@ -0,0 +1,44 @@
|
|||
package flagutil
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// IPv4Flag parses a string into a net.IP after asserting that it
|
||||
// is an IPv4 address. This type implements the flag.Value interface.
|
||||
type IPv4Flag struct {
|
||||
val net.IP
|
||||
}
|
||||
|
||||
func (f *IPv4Flag) IP() net.IP {
|
||||
return f.val
|
||||
}
|
||||
|
||||
func (f *IPv4Flag) Set(v string) error {
|
||||
ip := net.ParseIP(v)
|
||||
if ip == nil || ip.To4() == nil {
|
||||
return errors.New("not an IPv4 address")
|
||||
}
|
||||
f.val = ip
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *IPv4Flag) String() string {
|
||||
return f.val.String()
|
||||
}
|
||||
|
||||
// StringSliceFlag parses a comma-delimited list of strings into
|
||||
// a []string. This type implements the flag.Value interface.
|
||||
type StringSliceFlag []string
|
||||
|
||||
func (ss *StringSliceFlag) String() string {
|
||||
return fmt.Sprintf("%+v", *ss)
|
||||
}
|
||||
|
||||
func (ss *StringSliceFlag) Set(v string) error {
|
||||
*ss = strings.Split(v, ",")
|
||||
return nil
|
||||
}
|
57
vendor/github.com/coreos/pkg/flagutil/types_test.go
generated
vendored
Normal file
57
vendor/github.com/coreos/pkg/flagutil/types_test.go
generated
vendored
Normal file
|
@ -0,0 +1,57 @@
|
|||
package flagutil
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestIPv4FlagSetInvalidArgument(t *testing.T) {
|
||||
tests := []string{
|
||||
"",
|
||||
"foo",
|
||||
"::",
|
||||
"127.0.0.1:4328",
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
var f IPv4Flag
|
||||
if err := f.Set(tt); err == nil {
|
||||
t.Errorf("case %d: expected non-nil error", i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIPv4FlagSetValidArgument(t *testing.T) {
|
||||
tests := []string{
|
||||
"127.0.0.1",
|
||||
"0.0.0.0",
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
var f IPv4Flag
|
||||
if err := f.Set(tt); err != nil {
|
||||
t.Errorf("case %d: err=%v", i, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestStringSliceFlag(t *testing.T) {
|
||||
tests := []struct {
|
||||
input string
|
||||
want []string
|
||||
}{
|
||||
{input: "", want: []string{""}},
|
||||
{input: "foo", want: []string{"foo"}},
|
||||
{input: "foo,bar", want: []string{"foo", "bar"}},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
var f StringSliceFlag
|
||||
if err := f.Set(tt.input); err != nil {
|
||||
t.Errorf("case %d: err=%v", i, err)
|
||||
}
|
||||
if !reflect.DeepEqual(tt.want, []string(f)) {
|
||||
t.Errorf("case %d: want=%v got=%v", i, tt.want, f)
|
||||
}
|
||||
}
|
||||
}
|
11
vendor/github.com/coreos/pkg/health/README.md
generated
vendored
Normal file
11
vendor/github.com/coreos/pkg/health/README.md
generated
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
health
|
||||
====
|
||||
|
||||
A simple framework for implementing an HTTP health check endpoint on servers.
|
||||
|
||||
Users implement their `health.Checkable` types, and create a `health.Checker`, from which they can get an `http.HandlerFunc` using `health.Checker.MakeHealthHandlerFunc`.
|
||||
|
||||
### Documentation
|
||||
|
||||
For more details, visit the docs on [gopkgdoc](http://godoc.org/github.com/coreos/pkg/health)
|
||||
|
127
vendor/github.com/coreos/pkg/health/health.go
generated
vendored
Normal file
127
vendor/github.com/coreos/pkg/health/health.go
generated
vendored
Normal file
|
@ -0,0 +1,127 @@
|
|||
package health
|
||||
|
||||
import (
|
||||
"expvar"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/coreos/pkg/httputil"
|
||||
)
|
||||
|
||||
// Checkables should return nil when the thing they are checking is healthy, and an error otherwise.
|
||||
type Checkable interface {
|
||||
Healthy() error
|
||||
}
|
||||
|
||||
// Checker provides a way to make an endpoint which can be probed for system health.
|
||||
type Checker struct {
|
||||
// Checks are the Checkables to be checked when probing.
|
||||
Checks []Checkable
|
||||
|
||||
// Unhealthyhandler is called when one or more of the checks are unhealthy.
|
||||
// If not provided DefaultUnhealthyHandler is called.
|
||||
UnhealthyHandler UnhealthyHandler
|
||||
|
||||
// HealthyHandler is called when all checks are healthy.
|
||||
// If not provided, DefaultHealthyHandler is called.
|
||||
HealthyHandler http.HandlerFunc
|
||||
}
|
||||
|
||||
func (c Checker) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
unhealthyHandler := c.UnhealthyHandler
|
||||
if unhealthyHandler == nil {
|
||||
unhealthyHandler = DefaultUnhealthyHandler
|
||||
}
|
||||
|
||||
successHandler := c.HealthyHandler
|
||||
if successHandler == nil {
|
||||
successHandler = DefaultHealthyHandler
|
||||
}
|
||||
|
||||
if r.Method != "GET" {
|
||||
w.Header().Set("Allow", "GET")
|
||||
w.WriteHeader(http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
|
||||
if err := Check(c.Checks); err != nil {
|
||||
unhealthyHandler(w, r, err)
|
||||
return
|
||||
}
|
||||
|
||||
successHandler(w, r)
|
||||
}
|
||||
|
||||
type UnhealthyHandler func(w http.ResponseWriter, r *http.Request, err error)
|
||||
|
||||
type StatusResponse struct {
|
||||
Status string `json:"status"`
|
||||
Details *StatusResponseDetails `json:"details,omitempty"`
|
||||
}
|
||||
|
||||
type StatusResponseDetails struct {
|
||||
Code int `json:"code,omitempty"`
|
||||
Message string `json:"message,omitempty"`
|
||||
}
|
||||
|
||||
func Check(checks []Checkable) (err error) {
|
||||
errs := []error{}
|
||||
for _, c := range checks {
|
||||
if e := c.Healthy(); e != nil {
|
||||
errs = append(errs, e)
|
||||
}
|
||||
}
|
||||
|
||||
switch len(errs) {
|
||||
case 0:
|
||||
err = nil
|
||||
case 1:
|
||||
err = errs[0]
|
||||
default:
|
||||
err = fmt.Errorf("multiple health check failure: %v", errs)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func DefaultHealthyHandler(w http.ResponseWriter, r *http.Request) {
|
||||
err := httputil.WriteJSONResponse(w, http.StatusOK, StatusResponse{
|
||||
Status: "ok",
|
||||
})
|
||||
if err != nil {
|
||||
// TODO(bobbyrullo): replace with logging from new logging pkg,
|
||||
// once it lands.
|
||||
log.Printf("Failed to write JSON response: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func DefaultUnhealthyHandler(w http.ResponseWriter, r *http.Request, err error) {
|
||||
writeErr := httputil.WriteJSONResponse(w, http.StatusInternalServerError, StatusResponse{
|
||||
Status: "error",
|
||||
Details: &StatusResponseDetails{
|
||||
Code: http.StatusInternalServerError,
|
||||
Message: err.Error(),
|
||||
},
|
||||
})
|
||||
if writeErr != nil {
|
||||
// TODO(bobbyrullo): replace with logging from new logging pkg,
|
||||
// once it lands.
|
||||
log.Printf("Failed to write JSON response: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// ExpvarHandler is copied from https://golang.org/src/expvar/expvar.go, where it's sadly unexported.
|
||||
func ExpvarHandler(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
fmt.Fprintf(w, "{\n")
|
||||
first := true
|
||||
expvar.Do(func(kv expvar.KeyValue) {
|
||||
if !first {
|
||||
fmt.Fprintf(w, ",\n")
|
||||
}
|
||||
first = false
|
||||
fmt.Fprintf(w, "%q: %s", kv.Key, kv.Value)
|
||||
})
|
||||
fmt.Fprintf(w, "\n}\n")
|
||||
}
|
198
vendor/github.com/coreos/pkg/health/health_test.go
generated
vendored
Normal file
198
vendor/github.com/coreos/pkg/health/health_test.go
generated
vendored
Normal file
|
@ -0,0 +1,198 @@
|
|||
package health
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/coreos/pkg/httputil"
|
||||
)
|
||||
|
||||
type boolChecker bool
|
||||
|
||||
func (b boolChecker) Healthy() error {
|
||||
if b {
|
||||
return nil
|
||||
}
|
||||
return errors.New("Unhealthy")
|
||||
}
|
||||
|
||||
func errString(err error) string {
|
||||
if err == nil {
|
||||
return ""
|
||||
}
|
||||
return err.Error()
|
||||
}
|
||||
|
||||
func TestCheck(t *testing.T) {
|
||||
for i, test := range []struct {
|
||||
checks []Checkable
|
||||
expected string
|
||||
}{
|
||||
{[]Checkable{}, ""},
|
||||
|
||||
{[]Checkable{boolChecker(true)}, ""},
|
||||
|
||||
{[]Checkable{boolChecker(true), boolChecker(true)}, ""},
|
||||
|
||||
{[]Checkable{boolChecker(true), boolChecker(false)}, "Unhealthy"},
|
||||
|
||||
{[]Checkable{boolChecker(true), boolChecker(false), boolChecker(false)}, "multiple health check failure: [Unhealthy Unhealthy]"},
|
||||
} {
|
||||
err := Check(test.checks)
|
||||
|
||||
if errString(err) != test.expected {
|
||||
t.Errorf("case %d: want %v, got %v", i, test.expected, errString(err))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandlerFunc(t *testing.T) {
|
||||
for i, test := range []struct {
|
||||
checker Checker
|
||||
method string
|
||||
expectedStatus string
|
||||
expectedCode int
|
||||
expectedMessage string
|
||||
}{
|
||||
{
|
||||
Checker{
|
||||
Checks: []Checkable{
|
||||
boolChecker(true),
|
||||
},
|
||||
},
|
||||
"GET",
|
||||
"ok",
|
||||
http.StatusOK,
|
||||
"",
|
||||
},
|
||||
|
||||
// Wrong method.
|
||||
{
|
||||
Checker{
|
||||
Checks: []Checkable{
|
||||
boolChecker(true),
|
||||
},
|
||||
},
|
||||
"POST",
|
||||
"",
|
||||
http.StatusMethodNotAllowed,
|
||||
"GET only acceptable method",
|
||||
},
|
||||
|
||||
// Health check fails.
|
||||
{
|
||||
Checker{
|
||||
Checks: []Checkable{
|
||||
boolChecker(false),
|
||||
},
|
||||
},
|
||||
"GET",
|
||||
"error",
|
||||
http.StatusInternalServerError,
|
||||
"Unhealthy",
|
||||
},
|
||||
|
||||
// Health check fails, with overridden ErrorHandler.
|
||||
{
|
||||
Checker{
|
||||
Checks: []Checkable{
|
||||
boolChecker(false),
|
||||
},
|
||||
UnhealthyHandler: func(w http.ResponseWriter, r *http.Request, err error) {
|
||||
httputil.WriteJSONResponse(w,
|
||||
http.StatusInternalServerError, StatusResponse{
|
||||
Status: "error",
|
||||
Details: &StatusResponseDetails{
|
||||
Code: http.StatusInternalServerError,
|
||||
Message: "Override!",
|
||||
},
|
||||
})
|
||||
},
|
||||
},
|
||||
"GET",
|
||||
"error",
|
||||
http.StatusInternalServerError,
|
||||
"Override!",
|
||||
},
|
||||
|
||||
// Health check succeeds, with overridden SuccessHandler.
|
||||
{
|
||||
Checker{
|
||||
Checks: []Checkable{
|
||||
boolChecker(true),
|
||||
},
|
||||
HealthyHandler: func(w http.ResponseWriter, r *http.Request) {
|
||||
httputil.WriteJSONResponse(w,
|
||||
http.StatusOK, StatusResponse{
|
||||
Status: "okey-dokey",
|
||||
})
|
||||
},
|
||||
},
|
||||
"GET",
|
||||
"okey-dokey",
|
||||
http.StatusOK,
|
||||
"",
|
||||
},
|
||||
} {
|
||||
w := httptest.NewRecorder()
|
||||
r := &http.Request{}
|
||||
r.Method = test.method
|
||||
test.checker.ServeHTTP(w, r)
|
||||
if w.Code != test.expectedCode {
|
||||
t.Errorf("case %d: w.code == %v, want %v", i, w.Code, test.expectedCode)
|
||||
}
|
||||
|
||||
if test.expectedStatus == "" {
|
||||
// This is to handle the wrong-method case, when the
|
||||
// body of the response is empty.
|
||||
continue
|
||||
}
|
||||
|
||||
statusMap := make(map[string]interface{})
|
||||
err := json.Unmarshal(w.Body.Bytes(), &statusMap)
|
||||
if err != nil {
|
||||
t.Fatalf("case %d: failed to Unmarshal response body: %v", i, err)
|
||||
}
|
||||
|
||||
status, ok := statusMap["status"].(string)
|
||||
if !ok {
|
||||
t.Errorf("case %d: status not present or not a string in json: %q", i, w.Body.Bytes())
|
||||
}
|
||||
if status != test.expectedStatus {
|
||||
t.Errorf("case %d: status == %v, want %v", i, status, test.expectedStatus)
|
||||
}
|
||||
|
||||
detailMap, ok := statusMap["details"].(map[string]interface{})
|
||||
if test.expectedMessage != "" {
|
||||
if !ok {
|
||||
t.Fatalf("case %d: could not find/unmarshal detailMap", i)
|
||||
}
|
||||
message, ok := detailMap["message"].(string)
|
||||
if !ok {
|
||||
t.Fatalf("case %d: message not present or not a string in json: %q",
|
||||
i, w.Body.Bytes())
|
||||
}
|
||||
if message != test.expectedMessage {
|
||||
t.Errorf("case %d: message == %v, want %v", i, message, test.expectedMessage)
|
||||
}
|
||||
|
||||
code, ok := detailMap["code"].(float64)
|
||||
if !ok {
|
||||
t.Fatalf("case %d: code not present or not an int in json: %q",
|
||||
i, w.Body.Bytes())
|
||||
}
|
||||
if int(code) != test.expectedCode {
|
||||
t.Errorf("case %d: code == %v, want %v", i, code, test.expectedCode)
|
||||
}
|
||||
|
||||
} else {
|
||||
if ok {
|
||||
t.Errorf("case %d: unwanted detailMap present: %q", i, detailMap)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
13
vendor/github.com/coreos/pkg/httputil/README.md
generated
vendored
Normal file
13
vendor/github.com/coreos/pkg/httputil/README.md
generated
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
httputil
|
||||
====
|
||||
|
||||
Common code for dealing with HTTP.
|
||||
|
||||
Includes:
|
||||
|
||||
* Code for returning JSON responses.
|
||||
|
||||
### Documentation
|
||||
|
||||
Visit the docs on [gopkgdoc](http://godoc.org/github.com/coreos/pkg/httputil)
|
||||
|
21
vendor/github.com/coreos/pkg/httputil/cookie.go
generated
vendored
Normal file
21
vendor/github.com/coreos/pkg/httputil/cookie.go
generated
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
package httputil
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
// DeleteCookies effectively deletes all named cookies
|
||||
// by wiping all data and setting to expire immediately.
|
||||
func DeleteCookies(w http.ResponseWriter, cookieNames ...string) {
|
||||
for _, n := range cookieNames {
|
||||
c := &http.Cookie{
|
||||
Name: n,
|
||||
Value: "",
|
||||
Path: "/",
|
||||
MaxAge: -1,
|
||||
Expires: time.Time{},
|
||||
}
|
||||
http.SetCookie(w, c)
|
||||
}
|
||||
}
|
51
vendor/github.com/coreos/pkg/httputil/cookie_test.go
generated
vendored
Normal file
51
vendor/github.com/coreos/pkg/httputil/cookie_test.go
generated
vendored
Normal file
|
@ -0,0 +1,51 @@
|
|||
package httputil
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestDeleteCookies(t *testing.T) {
|
||||
tests := []struct {
|
||||
// cookie names to delete
|
||||
n []string
|
||||
}{
|
||||
// single
|
||||
{
|
||||
n: []string{"foo"},
|
||||
},
|
||||
// multiple
|
||||
{
|
||||
n: []string{"foo", "bar"},
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
w := httptest.NewRecorder()
|
||||
DeleteCookies(w, tt.n...)
|
||||
resp := &http.Response{}
|
||||
resp.Header = w.Header()
|
||||
cks := resp.Cookies()
|
||||
|
||||
if len(cks) != len(tt.n) {
|
||||
t.Errorf("case %d: unexpected number of cookies, want: %d, got: %d", i, len(tt.n), len(cks))
|
||||
}
|
||||
|
||||
for _, c := range cks {
|
||||
if c.Value != "" {
|
||||
t.Errorf("case %d: unexpected cookie value, want: %q, got: %q", i, "", c.Value)
|
||||
}
|
||||
if c.Path != "/" {
|
||||
t.Errorf("case %d: unexpected cookie path, want: %q, got: %q", i, "/", c.Path)
|
||||
}
|
||||
if c.MaxAge != -1 {
|
||||
t.Errorf("case %d: unexpected cookie max-age, want: %q, got: %q", i, -1, c.MaxAge)
|
||||
}
|
||||
if !c.Expires.IsZero() {
|
||||
t.Errorf("case %d: unexpected cookie expires, want: %q, got: %q", i, time.Time{}, c.MaxAge)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
27
vendor/github.com/coreos/pkg/httputil/json.go
generated
vendored
Normal file
27
vendor/github.com/coreos/pkg/httputil/json.go
generated
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
package httputil
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
const (
|
||||
JSONContentType = "application/json"
|
||||
)
|
||||
|
||||
func WriteJSONResponse(w http.ResponseWriter, code int, resp interface{}) error {
|
||||
enc, err := json.Marshal(resp)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return err
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", JSONContentType)
|
||||
w.WriteHeader(code)
|
||||
|
||||
_, err = w.Write(enc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
56
vendor/github.com/coreos/pkg/httputil/json_test.go
generated
vendored
Normal file
56
vendor/github.com/coreos/pkg/httputil/json_test.go
generated
vendored
Normal file
|
@ -0,0 +1,56 @@
|
|||
package httputil
|
||||
|
||||
import (
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestWriteJSONResponse(t *testing.T) {
|
||||
for i, test := range []struct {
|
||||
code int
|
||||
resp interface{}
|
||||
expectedJSON string
|
||||
expectErr bool
|
||||
}{
|
||||
{
|
||||
200,
|
||||
struct {
|
||||
A string
|
||||
B string
|
||||
}{A: "foo", B: "bar"},
|
||||
`{"A":"foo","B":"bar"}`,
|
||||
false,
|
||||
},
|
||||
{
|
||||
500,
|
||||
// Something that json.Marshal cannot serialize.
|
||||
make(chan int),
|
||||
"",
|
||||
true,
|
||||
},
|
||||
} {
|
||||
w := httptest.NewRecorder()
|
||||
err := WriteJSONResponse(w, test.code, test.resp)
|
||||
|
||||
if w.Code != test.code {
|
||||
t.Errorf("case %d: w.code == %v, want %v", i, w.Code, test.code)
|
||||
}
|
||||
|
||||
if (err != nil) != test.expectErr {
|
||||
t.Errorf("case %d: (err != nil) == %v, want %v. err: %v", i, err != nil, test.expectErr, err)
|
||||
}
|
||||
|
||||
if string(w.Body.Bytes()) != test.expectedJSON {
|
||||
t.Errorf("case %d: w.Body.Bytes()) == %q, want %q", i,
|
||||
string(w.Body.Bytes()), test.expectedJSON)
|
||||
}
|
||||
|
||||
if !test.expectErr {
|
||||
contentType := w.Header()["Content-Type"][0]
|
||||
if contentType != JSONContentType {
|
||||
t.Errorf("case %d: contentType == %v, want %v", i, contentType, JSONContentType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
140
vendor/github.com/coreos/pkg/k8s-tlsutil/k8s-tlsutil.go
generated
vendored
Normal file
140
vendor/github.com/coreos/pkg/k8s-tlsutil/k8s-tlsutil.go
generated
vendored
Normal file
|
@ -0,0 +1,140 @@
|
|||
package k8stlsutil
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"math"
|
||||
"math/big"
|
||||
"net"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
RSAKeySize = 2048
|
||||
Duration365d = time.Hour * 24 * 365
|
||||
)
|
||||
|
||||
type CertConfig struct {
|
||||
CommonName string
|
||||
Organization []string
|
||||
AltNames AltNames
|
||||
}
|
||||
|
||||
// AltNames contains the domain names and IP addresses that will be added
|
||||
// to the API Server's x509 certificate SubAltNames field. The values will
|
||||
// be passed directly to the x509.Certificate object.
|
||||
type AltNames struct {
|
||||
DNSNames []string
|
||||
IPs []net.IP
|
||||
}
|
||||
|
||||
func NewPrivateKey() (*rsa.PrivateKey, error) {
|
||||
return rsa.GenerateKey(rand.Reader, RSAKeySize)
|
||||
}
|
||||
|
||||
func EncodePublicKeyPEM(key *rsa.PublicKey) ([]byte, error) {
|
||||
der, err := x509.MarshalPKIXPublicKey(key)
|
||||
if err != nil {
|
||||
return []byte{}, err
|
||||
}
|
||||
block := pem.Block{
|
||||
Type: "PUBLIC KEY",
|
||||
Bytes: der,
|
||||
}
|
||||
return pem.EncodeToMemory(&block), nil
|
||||
}
|
||||
|
||||
func EncodePrivateKeyPEM(key *rsa.PrivateKey) []byte {
|
||||
block := pem.Block{
|
||||
Type: "RSA PRIVATE KEY",
|
||||
Bytes: x509.MarshalPKCS1PrivateKey(key),
|
||||
}
|
||||
return pem.EncodeToMemory(&block)
|
||||
}
|
||||
|
||||
func EncodeCertificatePEM(cert *x509.Certificate) []byte {
|
||||
block := pem.Block{
|
||||
Type: "CERTIFICATE",
|
||||
Bytes: cert.Raw,
|
||||
}
|
||||
return pem.EncodeToMemory(&block)
|
||||
}
|
||||
|
||||
func NewSelfSignedCACertificate(cfg CertConfig, key *rsa.PrivateKey, validDuration time.Duration) (*x509.Certificate, error) {
|
||||
now := time.Now()
|
||||
|
||||
dur := Duration365d * 10
|
||||
if validDuration != 0 {
|
||||
dur = validDuration
|
||||
}
|
||||
|
||||
tmpl := x509.Certificate{
|
||||
SerialNumber: new(big.Int).SetInt64(0),
|
||||
Subject: pkix.Name{
|
||||
CommonName: cfg.CommonName,
|
||||
Organization: cfg.Organization,
|
||||
},
|
||||
NotBefore: now,
|
||||
NotAfter: now.Add(dur),
|
||||
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
|
||||
BasicConstraintsValid: true,
|
||||
IsCA: true,
|
||||
}
|
||||
|
||||
certDERBytes, err := x509.CreateCertificate(rand.Reader, &tmpl, &tmpl, key.Public(), key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return x509.ParseCertificate(certDERBytes)
|
||||
}
|
||||
|
||||
func ParsePEMEncodedCACert(pemdata []byte) (*x509.Certificate, error) {
|
||||
decoded, _ := pem.Decode(pemdata)
|
||||
if decoded == nil {
|
||||
return nil, errors.New("no PEM data found")
|
||||
}
|
||||
return x509.ParseCertificate(decoded.Bytes)
|
||||
}
|
||||
|
||||
func ParsePEMEncodedPrivateKey(pemdata []byte) (*rsa.PrivateKey, error) {
|
||||
decoded, _ := pem.Decode(pemdata)
|
||||
if decoded == nil {
|
||||
return nil, errors.New("no PEM data found")
|
||||
}
|
||||
return x509.ParsePKCS1PrivateKey(decoded.Bytes)
|
||||
}
|
||||
|
||||
func NewSignedCertificate(cfg CertConfig, key *rsa.PrivateKey, caCert *x509.Certificate, caKey *rsa.PrivateKey, validDuration time.Duration) (*x509.Certificate, error) {
|
||||
serial, err := rand.Int(rand.Reader, new(big.Int).SetInt64(math.MaxInt64))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
dur := Duration365d
|
||||
if validDuration != 0 {
|
||||
dur = validDuration
|
||||
}
|
||||
|
||||
certTmpl := x509.Certificate{
|
||||
Subject: pkix.Name{
|
||||
CommonName: cfg.CommonName,
|
||||
Organization: caCert.Subject.Organization,
|
||||
},
|
||||
DNSNames: cfg.AltNames.DNSNames,
|
||||
IPAddresses: cfg.AltNames.IPs,
|
||||
SerialNumber: serial,
|
||||
NotBefore: caCert.NotBefore,
|
||||
NotAfter: time.Now().Add(dur),
|
||||
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
|
||||
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
|
||||
}
|
||||
certDERBytes, err := x509.CreateCertificate(rand.Reader, &certTmpl, caCert, key.Public(), caKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return x509.ParseCertificate(certDERBytes)
|
||||
}
|
32
vendor/github.com/coreos/pkg/multierror/multierror.go
generated
vendored
Normal file
32
vendor/github.com/coreos/pkg/multierror/multierror.go
generated
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
// Package multierror wraps a slice of errors and implements the error interface.
|
||||
// This can be used to collect a bunch of errors (such as during form validation)
|
||||
// and then return them all together as a single error. To see usage examples
|
||||
// refer to the unit tests.
|
||||
package multierror
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Error []error
|
||||
|
||||
func (me Error) Error() string {
|
||||
if me == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
strs := make([]string, len(me))
|
||||
for i, err := range me {
|
||||
strs[i] = fmt.Sprintf("[%d] %v", i, err)
|
||||
}
|
||||
return strings.Join(strs, " ")
|
||||
}
|
||||
|
||||
func (me Error) AsError() error {
|
||||
if len([]error(me)) <= 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return me
|
||||
}
|
59
vendor/github.com/coreos/pkg/multierror/multierror_test.go
generated
vendored
Normal file
59
vendor/github.com/coreos/pkg/multierror/multierror_test.go
generated
vendored
Normal file
|
@ -0,0 +1,59 @@
|
|||
package multierror
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAsError(t *testing.T) {
|
||||
tests := []struct {
|
||||
multierr Error
|
||||
want error
|
||||
}{
|
||||
{
|
||||
multierr: Error([]error{errors.New("foo"), errors.New("bar")}),
|
||||
want: Error([]error{errors.New("foo"), errors.New("bar")}),
|
||||
},
|
||||
{
|
||||
multierr: Error([]error{}),
|
||||
want: nil,
|
||||
},
|
||||
{
|
||||
multierr: Error(nil),
|
||||
want: nil,
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
got := tt.multierr.AsError()
|
||||
if !reflect.DeepEqual(tt.want, got) {
|
||||
t.Errorf("case %d: incorrect error value: want=%+v got=%+v", i, tt.want, got)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestErrorAppend(t *testing.T) {
|
||||
var multierr Error
|
||||
multierr = append(multierr, errors.New("foo"))
|
||||
multierr = append(multierr, errors.New("bar"))
|
||||
multierr = append(multierr, errors.New("baz"))
|
||||
want := Error([]error{errors.New("foo"), errors.New("bar"), errors.New("baz")})
|
||||
got := multierr.AsError()
|
||||
if !reflect.DeepEqual(want, got) {
|
||||
t.Fatalf("incorrect error value: want=%+v got=%+v", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrorString(t *testing.T) {
|
||||
var multierr Error
|
||||
multierr = append(multierr, errors.New("foo"))
|
||||
multierr = append(multierr, errors.New("bar"))
|
||||
multierr = append(multierr, errors.New("baz"))
|
||||
got := multierr.Error()
|
||||
want := "[0] foo [1] bar [2] baz"
|
||||
if want != got {
|
||||
t.Fatalf("incorrect output: want=%q got=%q", want, got)
|
||||
}
|
||||
}
|
48
vendor/github.com/coreos/pkg/netutil/proxy.go
generated
vendored
Normal file
48
vendor/github.com/coreos/pkg/netutil/proxy.go
generated
vendored
Normal file
|
@ -0,0 +1,48 @@
|
|||
package netutil
|
||||
|
||||
import (
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// ProxyTCP proxies between two TCP connections.
|
||||
// Because TLS connections don't have CloseRead() and CloseWrite() methods, our
|
||||
// temporary solution is to use timeouts.
|
||||
func ProxyTCP(conn1, conn2 net.Conn, tlsWriteDeadline, tlsReadDeadline time.Duration) {
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(2)
|
||||
|
||||
go copyBytes(conn1, conn2, &wg, tlsWriteDeadline, tlsReadDeadline)
|
||||
go copyBytes(conn2, conn1, &wg, tlsWriteDeadline, tlsReadDeadline)
|
||||
|
||||
wg.Wait()
|
||||
conn1.Close()
|
||||
conn2.Close()
|
||||
}
|
||||
|
||||
func copyBytes(dst, src net.Conn, wg *sync.WaitGroup, writeDeadline, readDeadline time.Duration) {
|
||||
defer wg.Done()
|
||||
_, err := io.Copy(dst, src)
|
||||
if err != nil {
|
||||
log.Printf("proxy i/o error: %v", err)
|
||||
}
|
||||
|
||||
if cr, ok := src.(*net.TCPConn); ok {
|
||||
cr.CloseRead()
|
||||
} else {
|
||||
// For TLS connections.
|
||||
wto := time.Now().Add(writeDeadline)
|
||||
src.SetWriteDeadline(wto)
|
||||
}
|
||||
|
||||
if cw, ok := dst.(*net.TCPConn); ok {
|
||||
cw.CloseWrite()
|
||||
} else {
|
||||
// For TLS connections.
|
||||
rto := time.Now().Add(readDeadline)
|
||||
dst.SetReadDeadline(rto)
|
||||
}
|
||||
}
|
17
vendor/github.com/coreos/pkg/netutil/url.go
generated
vendored
Normal file
17
vendor/github.com/coreos/pkg/netutil/url.go
generated
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
package netutil
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
)
|
||||
|
||||
// MergeQuery appends additional query values to an existing URL.
|
||||
func MergeQuery(u url.URL, q url.Values) url.URL {
|
||||
uv := u.Query()
|
||||
for k, vs := range q {
|
||||
for _, v := range vs {
|
||||
uv.Add(k, v)
|
||||
}
|
||||
}
|
||||
u.RawQuery = uv.Encode()
|
||||
return u
|
||||
}
|
86
vendor/github.com/coreos/pkg/netutil/url_test.go
generated
vendored
Normal file
86
vendor/github.com/coreos/pkg/netutil/url_test.go
generated
vendored
Normal file
|
@ -0,0 +1,86 @@
|
|||
package netutil
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestMergeQuery(t *testing.T) {
|
||||
tests := []struct {
|
||||
u string
|
||||
q url.Values
|
||||
w string
|
||||
}{
|
||||
// No values
|
||||
{
|
||||
u: "http://example.com",
|
||||
q: nil,
|
||||
w: "http://example.com",
|
||||
},
|
||||
// No additional values
|
||||
{
|
||||
u: "http://example.com?foo=bar",
|
||||
q: nil,
|
||||
w: "http://example.com?foo=bar",
|
||||
},
|
||||
// Simple addition
|
||||
{
|
||||
u: "http://example.com",
|
||||
q: url.Values{
|
||||
"foo": []string{"bar"},
|
||||
},
|
||||
w: "http://example.com?foo=bar",
|
||||
},
|
||||
// Addition with existing values
|
||||
{
|
||||
u: "http://example.com?dog=boo",
|
||||
q: url.Values{
|
||||
"foo": []string{"bar"},
|
||||
},
|
||||
w: "http://example.com?dog=boo&foo=bar",
|
||||
},
|
||||
// Merge
|
||||
{
|
||||
u: "http://example.com?dog=boo",
|
||||
q: url.Values{
|
||||
"dog": []string{"elroy"},
|
||||
},
|
||||
w: "http://example.com?dog=boo&dog=elroy",
|
||||
},
|
||||
// Add and merge
|
||||
{
|
||||
u: "http://example.com?dog=boo",
|
||||
q: url.Values{
|
||||
"dog": []string{"elroy"},
|
||||
"foo": []string{"bar"},
|
||||
},
|
||||
w: "http://example.com?dog=boo&dog=elroy&foo=bar",
|
||||
},
|
||||
// Multivalue merge
|
||||
{
|
||||
u: "http://example.com?dog=boo",
|
||||
q: url.Values{
|
||||
"dog": []string{"elroy", "penny"},
|
||||
},
|
||||
w: "http://example.com?dog=boo&dog=elroy&dog=penny",
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
ur, err := url.Parse(tt.u)
|
||||
if err != nil {
|
||||
t.Errorf("case %d: failed parsing test url: %v, error: %v", i, tt.u, err)
|
||||
}
|
||||
|
||||
got := MergeQuery(*ur, tt.q)
|
||||
want, err := url.Parse(tt.w)
|
||||
if err != nil {
|
||||
t.Errorf("case %d: failed parsing want url: %v, error: %v", i, tt.w, err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(*want, got) {
|
||||
t.Errorf("case %d: want: %v, got: %v", i, *want, got)
|
||||
}
|
||||
}
|
||||
}
|
189
vendor/github.com/coreos/pkg/progressutil/iocopy.go
generated
vendored
Normal file
189
vendor/github.com/coreos/pkg/progressutil/iocopy.go
generated
vendored
Normal file
|
@ -0,0 +1,189 @@
|
|||
// Copyright 2016 CoreOS Inc
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package progressutil
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrAlreadyStarted = errors.New("cannot add copies after PrintAndWait has been called")
|
||||
)
|
||||
|
||||
type copyReader struct {
|
||||
reader io.Reader
|
||||
current int64
|
||||
total int64
|
||||
pb *ProgressBar
|
||||
}
|
||||
|
||||
func (cr *copyReader) Read(p []byte) (int, error) {
|
||||
n, err := cr.reader.Read(p)
|
||||
cr.current += int64(n)
|
||||
err1 := cr.updateProgressBar()
|
||||
if err == nil {
|
||||
err = err1
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (cr *copyReader) updateProgressBar() error {
|
||||
cr.pb.SetPrintAfter(cr.formattedProgress())
|
||||
|
||||
progress := float64(cr.current) / float64(cr.total)
|
||||
if progress > 1 {
|
||||
progress = 1
|
||||
}
|
||||
return cr.pb.SetCurrentProgress(progress)
|
||||
}
|
||||
|
||||
// NewCopyProgressPrinter returns a new CopyProgressPrinter
|
||||
func NewCopyProgressPrinter() *CopyProgressPrinter {
|
||||
return &CopyProgressPrinter{
|
||||
results: make(chan error),
|
||||
cancel: make(chan struct{}),
|
||||
pbp: &ProgressBarPrinter{PadToBeEven: true},
|
||||
}
|
||||
}
|
||||
|
||||
// CopyProgressPrinter will perform an arbitrary number of io.Copy calls, while
|
||||
// continually printing the progress of each copy.
|
||||
type CopyProgressPrinter struct {
|
||||
results chan error
|
||||
cancel chan struct{}
|
||||
|
||||
// `lock` mutex protects all fields below it in CopyProgressPrinter struct
|
||||
lock sync.Mutex
|
||||
readers []*copyReader
|
||||
started bool
|
||||
pbp *ProgressBarPrinter
|
||||
}
|
||||
|
||||
// AddCopy adds a copy for this CopyProgressPrinter to perform. An io.Copy call
|
||||
// will be made to copy bytes from reader to dest, and name and size will be
|
||||
// used to label the progress bar and display how much progress has been made.
|
||||
// If size is 0, the total size of the reader is assumed to be unknown.
|
||||
// AddCopy can only be called before PrintAndWait; otherwise, ErrAlreadyStarted
|
||||
// will be returned.
|
||||
func (cpp *CopyProgressPrinter) AddCopy(reader io.Reader, name string, size int64, dest io.Writer) error {
|
||||
cpp.lock.Lock()
|
||||
defer cpp.lock.Unlock()
|
||||
|
||||
if cpp.started {
|
||||
return ErrAlreadyStarted
|
||||
}
|
||||
|
||||
cr := ©Reader{
|
||||
reader: reader,
|
||||
current: 0,
|
||||
total: size,
|
||||
pb: cpp.pbp.AddProgressBar(),
|
||||
}
|
||||
cr.pb.SetPrintBefore(name)
|
||||
cr.pb.SetPrintAfter(cr.formattedProgress())
|
||||
|
||||
cpp.readers = append(cpp.readers, cr)
|
||||
|
||||
go func() {
|
||||
_, err := io.Copy(dest, cr)
|
||||
select {
|
||||
case <-cpp.cancel:
|
||||
return
|
||||
case cpp.results <- err:
|
||||
return
|
||||
}
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
// PrintAndWait will print the progress for each copy operation added with
|
||||
// AddCopy to printTo every printInterval. This will continue until every added
|
||||
// copy is finished, or until cancel is written to.
|
||||
// PrintAndWait may only be called once; any subsequent calls will immediately
|
||||
// return ErrAlreadyStarted. After PrintAndWait has been called, no more
|
||||
// copies may be added to the CopyProgressPrinter.
|
||||
func (cpp *CopyProgressPrinter) PrintAndWait(printTo io.Writer, printInterval time.Duration, cancel chan struct{}) error {
|
||||
cpp.lock.Lock()
|
||||
if cpp.started {
|
||||
cpp.lock.Unlock()
|
||||
return ErrAlreadyStarted
|
||||
}
|
||||
cpp.started = true
|
||||
cpp.lock.Unlock()
|
||||
|
||||
n := len(cpp.readers)
|
||||
if n == 0 {
|
||||
// Nothing to do.
|
||||
return nil
|
||||
}
|
||||
|
||||
defer close(cpp.cancel)
|
||||
t := time.NewTicker(printInterval)
|
||||
allDone := false
|
||||
for i := 0; i < n; {
|
||||
select {
|
||||
case <-cancel:
|
||||
return nil
|
||||
case <-t.C:
|
||||
_, err := cpp.pbp.Print(printTo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case err := <-cpp.results:
|
||||
i++
|
||||
// Once completion is signaled, further on this just drains
|
||||
// (unlikely) errors from the channel.
|
||||
if err == nil && !allDone {
|
||||
allDone, err = cpp.pbp.Print(printTo)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cr *copyReader) formattedProgress() string {
|
||||
var totalStr string
|
||||
if cr.total == 0 {
|
||||
totalStr = "?"
|
||||
} else {
|
||||
totalStr = ByteUnitStr(cr.total)
|
||||
}
|
||||
return fmt.Sprintf("%s / %s", ByteUnitStr(cr.current), totalStr)
|
||||
}
|
||||
|
||||
var byteUnits = []string{"B", "KB", "MB", "GB", "TB", "PB"}
|
||||
|
||||
// ByteUnitStr pretty prints a number of bytes.
|
||||
func ByteUnitStr(n int64) string {
|
||||
var unit string
|
||||
size := float64(n)
|
||||
for i := 1; i < len(byteUnits); i++ {
|
||||
if size < 1000 {
|
||||
unit = byteUnits[i-1]
|
||||
break
|
||||
}
|
||||
|
||||
size = size / 1000
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%.3g %s", size, unit)
|
||||
}
|
140
vendor/github.com/coreos/pkg/progressutil/iocopy_test.go
generated
vendored
Normal file
140
vendor/github.com/coreos/pkg/progressutil/iocopy_test.go
generated
vendored
Normal file
|
@ -0,0 +1,140 @@
|
|||
// Copyright 2016 CoreOS Inc
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package progressutil
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
type fakeReader struct {
|
||||
input chan []byte
|
||||
done bool
|
||||
}
|
||||
|
||||
func (fr *fakeReader) Read(p []byte) (int, error) {
|
||||
if fr.done {
|
||||
return 0, io.EOF
|
||||
}
|
||||
i := copy(p, <-fr.input)
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func TestCopyOne(t *testing.T) {
|
||||
cpp := NewCopyProgressPrinter()
|
||||
cpp.pbp.printToTTYAlways = true
|
||||
|
||||
sampleData := []byte("this is a test!")
|
||||
|
||||
fr := &fakeReader{make(chan []byte, 1), false}
|
||||
fw := &bytes.Buffer{}
|
||||
|
||||
out := &bytes.Buffer{}
|
||||
|
||||
err := cpp.AddCopy(fr, "download", int64(len(sampleData)*10), fw)
|
||||
if err != nil {
|
||||
t.Errorf("%v\n", err)
|
||||
}
|
||||
|
||||
doneChan := make(chan error)
|
||||
go func() {
|
||||
doneChan <- cpp.PrintAndWait(out, time.Millisecond*10, nil)
|
||||
}()
|
||||
|
||||
time.Sleep(time.Millisecond * 15)
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
// Empty the buffer
|
||||
printedData := out.Bytes()
|
||||
sizeString := ByteUnitStr(int64(len(sampleData)*i)) + " / " + ByteUnitStr(int64(len(sampleData)*10))
|
||||
bar := renderExpectedBar(80, "download", float64(i)/10, sizeString)
|
||||
var expectedOutput string
|
||||
if i == 0 {
|
||||
expectedOutput = fmt.Sprintf("%s\n", bar)
|
||||
} else {
|
||||
expectedOutput = fmt.Sprintf("\033[1A%s\n", bar)
|
||||
}
|
||||
if string(printedData) != expectedOutput {
|
||||
t.Errorf("unexpected output:\nexpected:\n\n%sactual:\n\n%s", expectedOutput, string(printedData))
|
||||
}
|
||||
if i == 9 {
|
||||
fr.done = true
|
||||
}
|
||||
fr.input <- sampleData
|
||||
|
||||
out.Reset()
|
||||
|
||||
time.Sleep(time.Millisecond * 10)
|
||||
}
|
||||
|
||||
err = <-doneChan
|
||||
if err != nil {
|
||||
t.Errorf("error from PrintAndWait: %v", err)
|
||||
}
|
||||
|
||||
if bytes.Compare(fw.Bytes(), bytes.Repeat(sampleData, 10)) != 0 {
|
||||
t.Errorf("copied bytes don't match!")
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrAlreadyStarted(t *testing.T) {
|
||||
cpp := NewCopyProgressPrinter()
|
||||
fr := &fakeReader{make(chan []byte, 1), false}
|
||||
fw := &bytes.Buffer{}
|
||||
|
||||
out := &bytes.Buffer{}
|
||||
|
||||
err := cpp.AddCopy(fr, "download", 10^10, fw)
|
||||
if err != nil {
|
||||
t.Errorf("%v\n", err)
|
||||
}
|
||||
|
||||
cancel := make(chan struct{})
|
||||
doneChan := make(chan error)
|
||||
go func() {
|
||||
doneChan <- cpp.PrintAndWait(out, time.Second, cancel)
|
||||
}()
|
||||
|
||||
for {
|
||||
cpp.lock.Lock()
|
||||
started := cpp.started
|
||||
cpp.lock.Unlock()
|
||||
if !started {
|
||||
time.Sleep(time.Millisecond * 5)
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
err = cpp.AddCopy(fr, "download", 10^10, fw)
|
||||
if err != ErrAlreadyStarted {
|
||||
t.Errorf("Was expecting ErrAlreadyStarted, got something else: %v\n", err)
|
||||
}
|
||||
|
||||
err = cpp.PrintAndWait(out, time.Second, cancel)
|
||||
if err != ErrAlreadyStarted {
|
||||
t.Errorf("Was expecting ErrAlreadyStarted, got something else: %v\n", err)
|
||||
}
|
||||
|
||||
cancel <- struct{}{}
|
||||
|
||||
err = <-doneChan
|
||||
if err != nil {
|
||||
t.Errorf("%v\n", err)
|
||||
}
|
||||
}
|
263
vendor/github.com/coreos/pkg/progressutil/progressbar.go
generated
vendored
Normal file
263
vendor/github.com/coreos/pkg/progressutil/progressbar.go
generated
vendored
Normal file
|
@ -0,0 +1,263 @@
|
|||
// Copyright 2016 CoreOS Inc
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package progressutil
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"golang.org/x/crypto/ssh/terminal"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrorProgressOutOfBounds is returned if the progress is set to a value
|
||||
// not between 0 and 1.
|
||||
ErrorProgressOutOfBounds = fmt.Errorf("progress is out of bounds (0 to 1)")
|
||||
|
||||
// ErrorNoBarsAdded is returned when no progress bars have been added to a
|
||||
// ProgressBarPrinter before PrintAndWait is called.
|
||||
ErrorNoBarsAdded = fmt.Errorf("AddProgressBar hasn't been called yet")
|
||||
)
|
||||
|
||||
// ProgressBar represents one progress bar in a ProgressBarPrinter. Should not
|
||||
// be created directly, use the AddProgressBar on a ProgressBarPrinter to
|
||||
// create these.
|
||||
type ProgressBar struct {
|
||||
lock sync.Mutex
|
||||
|
||||
currentProgress float64
|
||||
printBefore string
|
||||
printAfter string
|
||||
done bool
|
||||
}
|
||||
|
||||
func (pb *ProgressBar) clone() *ProgressBar {
|
||||
pb.lock.Lock()
|
||||
pbClone := &ProgressBar{
|
||||
currentProgress: pb.currentProgress,
|
||||
printBefore: pb.printBefore,
|
||||
printAfter: pb.printAfter,
|
||||
done: pb.done,
|
||||
}
|
||||
pb.lock.Unlock()
|
||||
return pbClone
|
||||
}
|
||||
|
||||
func (pb *ProgressBar) GetCurrentProgress() float64 {
|
||||
pb.lock.Lock()
|
||||
val := pb.currentProgress
|
||||
pb.lock.Unlock()
|
||||
return val
|
||||
}
|
||||
|
||||
// SetCurrentProgress sets the progress of this ProgressBar. The progress must
|
||||
// be between 0 and 1 inclusive.
|
||||
func (pb *ProgressBar) SetCurrentProgress(progress float64) error {
|
||||
if progress < 0 || progress > 1 {
|
||||
return ErrorProgressOutOfBounds
|
||||
}
|
||||
pb.lock.Lock()
|
||||
pb.currentProgress = progress
|
||||
pb.lock.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetDone returns whether or not this progress bar is done
|
||||
func (pb *ProgressBar) GetDone() bool {
|
||||
pb.lock.Lock()
|
||||
val := pb.done
|
||||
pb.lock.Unlock()
|
||||
return val
|
||||
}
|
||||
|
||||
// SetDone sets whether or not this progress bar is done
|
||||
func (pb *ProgressBar) SetDone(val bool) {
|
||||
pb.lock.Lock()
|
||||
pb.done = val
|
||||
pb.lock.Unlock()
|
||||
}
|
||||
|
||||
// GetPrintBefore gets the text printed on the line before the progress bar.
|
||||
func (pb *ProgressBar) GetPrintBefore() string {
|
||||
pb.lock.Lock()
|
||||
val := pb.printBefore
|
||||
pb.lock.Unlock()
|
||||
return val
|
||||
}
|
||||
|
||||
// SetPrintBefore sets the text printed on the line before the progress bar.
|
||||
func (pb *ProgressBar) SetPrintBefore(before string) {
|
||||
pb.lock.Lock()
|
||||
pb.printBefore = before
|
||||
pb.lock.Unlock()
|
||||
}
|
||||
|
||||
// GetPrintAfter gets the text printed on the line after the progress bar.
|
||||
func (pb *ProgressBar) GetPrintAfter() string {
|
||||
pb.lock.Lock()
|
||||
val := pb.printAfter
|
||||
pb.lock.Unlock()
|
||||
return val
|
||||
}
|
||||
|
||||
// SetPrintAfter sets the text printed on the line after the progress bar.
|
||||
func (pb *ProgressBar) SetPrintAfter(after string) {
|
||||
pb.lock.Lock()
|
||||
pb.printAfter = after
|
||||
pb.lock.Unlock()
|
||||
}
|
||||
|
||||
// ProgressBarPrinter will print out the progress of some number of
|
||||
// ProgressBars.
|
||||
type ProgressBarPrinter struct {
|
||||
lock sync.Mutex
|
||||
|
||||
// DisplayWidth can be set to influence how large the progress bars are.
|
||||
// The bars will be scaled to attempt to produce lines of this number of
|
||||
// characters, but lines of different lengths may still be printed. When
|
||||
// this value is 0 (aka unset), 80 character columns are assumed.
|
||||
DisplayWidth int
|
||||
// PadToBeEven, when set to true, will make Print pad the printBefore text
|
||||
// with trailing spaces and the printAfter text with leading spaces to make
|
||||
// the progress bars the same length.
|
||||
PadToBeEven bool
|
||||
numLinesInLastPrint int
|
||||
progressBars []*ProgressBar
|
||||
maxBefore int
|
||||
maxAfter int
|
||||
|
||||
// printToTTYAlways forces this ProgressBarPrinter to always behave as if
|
||||
// in a tty. Used for tests.
|
||||
printToTTYAlways bool
|
||||
}
|
||||
|
||||
// AddProgressBar will create a new ProgressBar, register it with this
|
||||
// ProgressBarPrinter, and return it. This must be called at least once before
|
||||
// PrintAndWait is called.
|
||||
func (pbp *ProgressBarPrinter) AddProgressBar() *ProgressBar {
|
||||
pb := &ProgressBar{}
|
||||
pbp.lock.Lock()
|
||||
pbp.progressBars = append(pbp.progressBars, pb)
|
||||
pbp.lock.Unlock()
|
||||
return pb
|
||||
}
|
||||
|
||||
// Print will print out progress information for each ProgressBar that has been
|
||||
// added to this ProgressBarPrinter. The progress will be written to printTo,
|
||||
// and if printTo is a terminal it will draw progress bars. AddProgressBar
|
||||
// must be called at least once before Print is called. If printing to a
|
||||
// terminal, all draws after the first one will move the cursor up to draw over
|
||||
// the previously printed bars.
|
||||
func (pbp *ProgressBarPrinter) Print(printTo io.Writer) (bool, error) {
|
||||
pbp.lock.Lock()
|
||||
var bars []*ProgressBar
|
||||
for _, bar := range pbp.progressBars {
|
||||
bars = append(bars, bar.clone())
|
||||
}
|
||||
numColumns := pbp.DisplayWidth
|
||||
pbp.lock.Unlock()
|
||||
|
||||
if len(bars) == 0 {
|
||||
return false, ErrorNoBarsAdded
|
||||
}
|
||||
|
||||
if numColumns == 0 {
|
||||
numColumns = 80
|
||||
}
|
||||
|
||||
if pbp.isTerminal(printTo) {
|
||||
moveCursorUp(printTo, pbp.numLinesInLastPrint)
|
||||
}
|
||||
|
||||
for _, bar := range bars {
|
||||
beforeSize := len(bar.GetPrintBefore())
|
||||
afterSize := len(bar.GetPrintAfter())
|
||||
if beforeSize > pbp.maxBefore {
|
||||
pbp.maxBefore = beforeSize
|
||||
}
|
||||
if afterSize > pbp.maxAfter {
|
||||
pbp.maxAfter = afterSize
|
||||
}
|
||||
}
|
||||
|
||||
allDone := true
|
||||
for _, bar := range bars {
|
||||
if pbp.isTerminal(printTo) {
|
||||
bar.printToTerminal(printTo, numColumns, pbp.PadToBeEven, pbp.maxBefore, pbp.maxAfter)
|
||||
} else {
|
||||
bar.printToNonTerminal(printTo)
|
||||
}
|
||||
allDone = allDone && bar.GetCurrentProgress() == 1
|
||||
}
|
||||
|
||||
pbp.numLinesInLastPrint = len(bars)
|
||||
|
||||
return allDone, nil
|
||||
}
|
||||
|
||||
// moveCursorUp moves the cursor up numLines in the terminal
|
||||
func moveCursorUp(printTo io.Writer, numLines int) {
|
||||
if numLines > 0 {
|
||||
fmt.Fprintf(printTo, "\033[%dA", numLines)
|
||||
}
|
||||
}
|
||||
|
||||
func (pb *ProgressBar) printToTerminal(printTo io.Writer, numColumns int, padding bool, maxBefore, maxAfter int) {
|
||||
before := pb.GetPrintBefore()
|
||||
after := pb.GetPrintAfter()
|
||||
|
||||
if padding {
|
||||
before = before + strings.Repeat(" ", maxBefore-len(before))
|
||||
after = strings.Repeat(" ", maxAfter-len(after)) + after
|
||||
}
|
||||
|
||||
progressBarSize := numColumns - (len(fmt.Sprintf("%s [] %s", before, after)))
|
||||
progressBar := ""
|
||||
if progressBarSize > 0 {
|
||||
currentProgress := int(pb.GetCurrentProgress() * float64(progressBarSize))
|
||||
progressBar = fmt.Sprintf("[%s%s] ",
|
||||
strings.Repeat("=", currentProgress),
|
||||
strings.Repeat(" ", progressBarSize-currentProgress))
|
||||
} else {
|
||||
// If we can't fit the progress bar, better to not pad the before/after.
|
||||
before = pb.GetPrintBefore()
|
||||
after = pb.GetPrintAfter()
|
||||
}
|
||||
|
||||
fmt.Fprintf(printTo, "%s %s%s\n", before, progressBar, after)
|
||||
}
|
||||
|
||||
func (pb *ProgressBar) printToNonTerminal(printTo io.Writer) {
|
||||
if !pb.GetDone() {
|
||||
fmt.Fprintf(printTo, "%s %s\n", pb.printBefore, pb.printAfter)
|
||||
if pb.GetCurrentProgress() == 1 {
|
||||
pb.SetDone(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// isTerminal returns True when w is going to a tty, and false otherwise.
|
||||
func (pbp *ProgressBarPrinter) isTerminal(w io.Writer) bool {
|
||||
if pbp.printToTTYAlways {
|
||||
return true
|
||||
}
|
||||
if f, ok := w.(*os.File); ok {
|
||||
return terminal.IsTerminal(int(f.Fd()))
|
||||
}
|
||||
return false
|
||||
}
|
116
vendor/github.com/coreos/pkg/progressutil/progressbar_test.go
generated
vendored
Normal file
116
vendor/github.com/coreos/pkg/progressutil/progressbar_test.go
generated
vendored
Normal file
|
@ -0,0 +1,116 @@
|
|||
// Copyright 2016 CoreOS Inc
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package progressutil
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNoBarsAdded(t *testing.T) {
|
||||
pbp := &ProgressBarPrinter{}
|
||||
allDone, err := pbp.Print(ioutil.Discard)
|
||||
if allDone {
|
||||
t.Errorf("shouldn't have gotten all done when no bars have been added")
|
||||
}
|
||||
if err != ErrorNoBarsAdded {
|
||||
t.Errorf("was expecting ErrorNoBarsAdded, got this instead: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProgressOutOfBounds(t *testing.T) {
|
||||
pbp := &ProgressBarPrinter{}
|
||||
pb := pbp.AddProgressBar()
|
||||
|
||||
for _, testcase := range []struct {
|
||||
progress float64
|
||||
expectedErr error
|
||||
}{
|
||||
{-0.1, ErrorProgressOutOfBounds},
|
||||
{0, nil},
|
||||
{0.5, nil},
|
||||
{1, nil},
|
||||
{1.1, ErrorProgressOutOfBounds},
|
||||
} {
|
||||
err := pb.SetCurrentProgress(testcase.progress)
|
||||
if err != testcase.expectedErr {
|
||||
t.Errorf("got unexpected error. expected=%v actual=%v", testcase.expectedErr, err)
|
||||
}
|
||||
if err == nil {
|
||||
currProgress := pb.GetCurrentProgress()
|
||||
if currProgress != testcase.progress {
|
||||
t.Errorf("no error was returned, but the progress wasn't updated. should be: %f, actual: %f", testcase.progress, currProgress)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDrawOne(t *testing.T) {
|
||||
pbp := ProgressBarPrinter{}
|
||||
pbp.printToTTYAlways = true
|
||||
pb := pbp.AddProgressBar()
|
||||
|
||||
pbp.Print(ioutil.Discard)
|
||||
|
||||
for _, testcase := range []struct {
|
||||
beforeText string
|
||||
progress float64
|
||||
afterText string
|
||||
shouldBeDone bool
|
||||
}{
|
||||
{"before", 0, "after", false},
|
||||
{"before2", 0.1, "after2", false},
|
||||
{"before3", 0.5, "after3", false},
|
||||
{"before4", 1, "after4", true},
|
||||
} {
|
||||
buf := &bytes.Buffer{}
|
||||
pb.SetPrintBefore(testcase.beforeText)
|
||||
pb.SetPrintAfter(testcase.afterText)
|
||||
err := pb.SetCurrentProgress(testcase.progress)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
done, err := pbp.Print(buf)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if done != testcase.shouldBeDone {
|
||||
t.Errorf("unexpected done, expected=%t actual=%t", testcase.shouldBeDone, done)
|
||||
}
|
||||
|
||||
output := buf.String()
|
||||
|
||||
bar := renderExpectedBar(80, testcase.beforeText, testcase.progress, testcase.afterText)
|
||||
|
||||
expectedOutput := fmt.Sprintf("\033[1A%s\n", bar)
|
||||
|
||||
if output != expectedOutput {
|
||||
t.Errorf("unexpected output:\nexpected:\n\n%sactual:\n\n%s", expectedOutput, output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func renderExpectedBar(numColumns int, before string, progress float64, after string) string {
|
||||
progressBarSize := numColumns - len(fmt.Sprintf("%s [] %s", before, after))
|
||||
currentProgress := int(progress * float64(progressBarSize))
|
||||
|
||||
bar := fmt.Sprintf("[%s%s]",
|
||||
strings.Repeat("=", currentProgress),
|
||||
strings.Repeat(" ", progressBarSize-currentProgress))
|
||||
return fmt.Sprintf("%s %s %s", before, bar, after)
|
||||
}
|
56
vendor/github.com/coreos/pkg/test
generated
vendored
Executable file
56
vendor/github.com/coreos/pkg/test
generated
vendored
Executable file
|
@ -0,0 +1,56 @@
|
|||
#!/bin/bash -e
|
||||
#
|
||||
# Run all tests (not including functional)
|
||||
# ./test
|
||||
# ./test -v
|
||||
#
|
||||
# Run tests for one package
|
||||
# PKG=./unit ./test
|
||||
# PKG=ssh ./test
|
||||
#
|
||||
|
||||
# Invoke ./cover for HTML output
|
||||
COVER=${COVER:-"-cover"}
|
||||
|
||||
source ./build
|
||||
|
||||
TESTABLE="cryptoutil flagutil timeutil netutil yamlutil httputil health multierror dlopen progressutil"
|
||||
FORMATTABLE="$TESTABLE capnslog"
|
||||
|
||||
# user has not provided PKG override
|
||||
if [ -z "$PKG" ]; then
|
||||
TEST=$TESTABLE
|
||||
FMT=$FORMATTABLE
|
||||
|
||||
# user has provided PKG override
|
||||
else
|
||||
# strip out slashes and dots from PKG=./foo/
|
||||
TEST=${PKG//\//}
|
||||
TEST=${TEST//./}
|
||||
|
||||
# only run gofmt on packages provided by user
|
||||
FMT="$TEST"
|
||||
fi
|
||||
|
||||
# split TEST into an array and prepend repo path to each local package
|
||||
split=(${TEST// / })
|
||||
TEST=${split[@]/#/github.com/coreos/pkg/}
|
||||
|
||||
echo "Running tests..."
|
||||
go test ${COVER} $@ ${TEST}
|
||||
|
||||
echo "Checking gofmt..."
|
||||
fmtRes=$(gofmt -l $FMT)
|
||||
if [ -n "${fmtRes}" ]; then
|
||||
echo -e "gofmt checking failed:\n${fmtRes}"
|
||||
exit 255
|
||||
fi
|
||||
|
||||
echo "Checking govet..."
|
||||
vetRes=$(go vet $TEST)
|
||||
if [ -n "${vetRes}" ]; then
|
||||
echo -e "govet checking failed:\n${vetRes}"
|
||||
exit 255
|
||||
fi
|
||||
|
||||
echo "Success"
|
15
vendor/github.com/coreos/pkg/timeutil/backoff.go
generated
vendored
Normal file
15
vendor/github.com/coreos/pkg/timeutil/backoff.go
generated
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
package timeutil
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
func ExpBackoff(prev, max time.Duration) time.Duration {
|
||||
if prev == 0 {
|
||||
return time.Second
|
||||
}
|
||||
if prev > max/2 {
|
||||
return max
|
||||
}
|
||||
return 2 * prev
|
||||
}
|
52
vendor/github.com/coreos/pkg/timeutil/backoff_test.go
generated
vendored
Normal file
52
vendor/github.com/coreos/pkg/timeutil/backoff_test.go
generated
vendored
Normal file
|
@ -0,0 +1,52 @@
|
|||
package timeutil
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestExpBackoff(t *testing.T) {
|
||||
tests := []struct {
|
||||
prev time.Duration
|
||||
max time.Duration
|
||||
want time.Duration
|
||||
}{
|
||||
{
|
||||
prev: time.Duration(0),
|
||||
max: time.Minute,
|
||||
want: time.Second,
|
||||
},
|
||||
{
|
||||
prev: time.Second,
|
||||
max: time.Minute,
|
||||
want: 2 * time.Second,
|
||||
},
|
||||
{
|
||||
prev: 16 * time.Second,
|
||||
max: time.Minute,
|
||||
want: 32 * time.Second,
|
||||
},
|
||||
{
|
||||
prev: 32 * time.Second,
|
||||
max: time.Minute,
|
||||
want: time.Minute,
|
||||
},
|
||||
{
|
||||
prev: time.Minute,
|
||||
max: time.Minute,
|
||||
want: time.Minute,
|
||||
},
|
||||
{
|
||||
prev: 2 * time.Minute,
|
||||
max: time.Minute,
|
||||
want: time.Minute,
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
got := ExpBackoff(tt.prev, tt.max)
|
||||
if tt.want != got {
|
||||
t.Errorf("case %d: want=%v got=%v", i, tt.want, got)
|
||||
}
|
||||
}
|
||||
}
|
55
vendor/github.com/coreos/pkg/yamlutil/yaml.go
generated
vendored
Normal file
55
vendor/github.com/coreos/pkg/yamlutil/yaml.go
generated
vendored
Normal file
|
@ -0,0 +1,55 @@
|
|||
package yamlutil
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"gopkg.in/yaml.v1"
|
||||
)
|
||||
|
||||
// SetFlagsFromYaml goes through all registered flags in the given flagset,
|
||||
// and if they are not already set it attempts to set their values from
|
||||
// the YAML config. It will use the key REPLACE(UPPERCASE(flagname), '-', '_')
|
||||
func SetFlagsFromYaml(fs *flag.FlagSet, rawYaml []byte) (err error) {
|
||||
conf := make(map[string]string)
|
||||
if err = yaml.Unmarshal(rawYaml, conf); err != nil {
|
||||
return
|
||||
}
|
||||
alreadySet := map[string]struct{}{}
|
||||
fs.Visit(func(f *flag.Flag) {
|
||||
alreadySet[f.Name] = struct{}{}
|
||||
})
|
||||
|
||||
errs := make([]error, 0)
|
||||
fs.VisitAll(func(f *flag.Flag) {
|
||||
if f.Name == "" {
|
||||
return
|
||||
}
|
||||
if _, ok := alreadySet[f.Name]; ok {
|
||||
return
|
||||
}
|
||||
tag := strings.Replace(strings.ToUpper(f.Name), "-", "_", -1)
|
||||
val, ok := conf[tag]
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if serr := fs.Set(f.Name, val); serr != nil {
|
||||
errs = append(errs, fmt.Errorf("invalid value %q for %s: %v", val, tag, serr))
|
||||
}
|
||||
})
|
||||
if len(errs) != 0 {
|
||||
err = ErrorSlice(errs)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type ErrorSlice []error
|
||||
|
||||
func (e ErrorSlice) Error() string {
|
||||
s := ""
|
||||
for _, err := range e {
|
||||
s += ", " + err.Error()
|
||||
}
|
||||
return "Errors: " + s
|
||||
}
|
80
vendor/github.com/coreos/pkg/yamlutil/yaml_test.go
generated
vendored
Normal file
80
vendor/github.com/coreos/pkg/yamlutil/yaml_test.go
generated
vendored
Normal file
|
@ -0,0 +1,80 @@
|
|||
package yamlutil
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSetFlagsFromYaml(t *testing.T) {
|
||||
config := "A: foo\nC: woof"
|
||||
fs := flag.NewFlagSet("testing", flag.ExitOnError)
|
||||
fs.String("a", "", "")
|
||||
fs.String("b", "", "")
|
||||
fs.String("c", "", "")
|
||||
fs.Parse([]string{})
|
||||
|
||||
// flags should be settable using yaml vars
|
||||
// and command-line flags
|
||||
if err := fs.Set("b", "bar"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// command-line flags take precedence over the file
|
||||
if err := fs.Set("c", "quack"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// first verify that flags are as expected before reading the file
|
||||
for f, want := range map[string]string{
|
||||
"a": "",
|
||||
"b": "bar",
|
||||
"c": "quack",
|
||||
} {
|
||||
if got := fs.Lookup(f).Value.String(); got != want {
|
||||
t.Fatalf("flag %q=%q, want %q", f, got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// now read the yaml and verify flags were updated as expected
|
||||
err := SetFlagsFromYaml(fs, []byte(config))
|
||||
if err != nil {
|
||||
t.Errorf("err=%v, want nil", err)
|
||||
}
|
||||
for f, want := range map[string]string{
|
||||
"a": "foo",
|
||||
"b": "bar",
|
||||
"c": "quack",
|
||||
} {
|
||||
if got := fs.Lookup(f).Value.String(); got != want {
|
||||
t.Errorf("flag %q=%q, want %q", f, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetFlagsFromYamlBad(t *testing.T) {
|
||||
// now verify that an error is propagated
|
||||
fs := flag.NewFlagSet("testing", flag.ExitOnError)
|
||||
fs.Int("x", 0, "")
|
||||
badConf := "X: not_a_number"
|
||||
if err := SetFlagsFromYaml(fs, []byte(badConf)); err == nil {
|
||||
t.Errorf("got err=nil, flag x=%q, want err != nil", fs.Lookup("x").Value.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetFlagsFromYamlMultiError(t *testing.T) {
|
||||
fs := flag.NewFlagSet("testing", flag.ExitOnError)
|
||||
fs.Int("x", 0, "")
|
||||
fs.Int("y", 0, "")
|
||||
fs.Int("z", 0, "")
|
||||
conf := "X: foo\nY: bar\nZ: 3"
|
||||
err := SetFlagsFromYaml(fs, []byte(conf))
|
||||
if err == nil {
|
||||
t.Errorf("got err= nil, want err != nil")
|
||||
}
|
||||
es, ok := err.(ErrorSlice)
|
||||
if !ok {
|
||||
t.Errorf("Got ok=false want ok=true")
|
||||
}
|
||||
if len(es) != 2 {
|
||||
t.Errorf("2 errors should be contained in the error, got %d errors", len(es))
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue