mirror of
https://github.com/linuxkit/linuxkit.git
synced 2025-09-03 16:07:43 +00:00
@@ -53,3 +53,11 @@ golang.org/x/text c4d099d611ac3ded35360abf03581e13d91c828f
|
||||
google.golang.org/api 373a4c220f5c90e5b7ff7101779c5be385d171be
|
||||
google.golang.org/grpc 0713829b980f4ddd276689a36235c5fcc82a21bf
|
||||
gopkg.in/yaml.v2 a3f3340b5840cee44f372bddb5880fcbc419b46a
|
||||
github.com/scaleway/go-scaleway f8c3b31c65867b4cb96b3bd41e574c33fd1d69ae
|
||||
github.com/moul/anonuuid c6987e46f8a0231504bcd402962749f8dd9970b0
|
||||
golang.org/x/sync 1d60e4601c6fd243af51cc01ddf169918a5407ca
|
||||
github.com/renstrom/fuzzysearch 7a8f9a1c4bed53899ecd512daeaf8207cc454156
|
||||
github.com/moul/gotty-client e5589f6df35953284b091b8394daa6be6c453469
|
||||
github.com/gorilla/websocket 21ab95fa12b9bdd8fecf5fa3586aad941cc98785
|
||||
github.com/creack/goselect 58854f77ee8d858ce751b0a9bcc5533fef7bfa9e
|
||||
github.com/containerd/console cb7008ab3d8359b78c5f464cb7cf160107ad5925
|
||||
|
201
src/cmd/linuxkit/vendor/github.com/containerd/console/LICENSE
generated
vendored
Normal file
201
src/cmd/linuxkit/vendor/github.com/containerd/console/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,201 @@
|
||||
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.
|
17
src/cmd/linuxkit/vendor/github.com/containerd/console/README.md
generated
vendored
Normal file
17
src/cmd/linuxkit/vendor/github.com/containerd/console/README.md
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
# console
|
||||
|
||||
[](https://travis-ci.org/containerd/console)
|
||||
|
||||
Golang package for dealing with consoles. Light on deps and a simple API.
|
||||
|
||||
## Modifying the current process
|
||||
|
||||
```go
|
||||
current := console.Current()
|
||||
defer current.Reset()
|
||||
|
||||
if err := current.SetRaw(); err != nil {
|
||||
}
|
||||
ws, err := current.Size()
|
||||
current.Resize(ws)
|
||||
```
|
78
src/cmd/linuxkit/vendor/github.com/containerd/console/console.go
generated
vendored
Normal file
78
src/cmd/linuxkit/vendor/github.com/containerd/console/console.go
generated
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
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 console
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
var ErrNotAConsole = errors.New("provided file is not a console")
|
||||
|
||||
type Console interface {
|
||||
io.Reader
|
||||
io.Writer
|
||||
io.Closer
|
||||
|
||||
// Resize resizes the console to the provided window size
|
||||
Resize(WinSize) error
|
||||
// ResizeFrom resizes the calling console to the size of the
|
||||
// provided console
|
||||
ResizeFrom(Console) error
|
||||
// SetRaw sets the console in raw mode
|
||||
SetRaw() error
|
||||
// DisableEcho disables echo on the console
|
||||
DisableEcho() error
|
||||
// Reset restores the console to its orignal state
|
||||
Reset() error
|
||||
// Size returns the window size of the console
|
||||
Size() (WinSize, error)
|
||||
// Fd returns the console's file descriptor
|
||||
Fd() uintptr
|
||||
// Name returns the console's file name
|
||||
Name() string
|
||||
}
|
||||
|
||||
// WinSize specifies the window size of the console
|
||||
type WinSize struct {
|
||||
// Height of the console
|
||||
Height uint16
|
||||
// Width of the console
|
||||
Width uint16
|
||||
x uint16
|
||||
y uint16
|
||||
}
|
||||
|
||||
// Current returns the current processes console
|
||||
func Current() Console {
|
||||
c, err := ConsoleFromFile(os.Stdin)
|
||||
if err != nil {
|
||||
// stdin should always be a console for the design
|
||||
// of this function
|
||||
panic(err)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// ConsoleFromFile returns a console using the provided file
|
||||
func ConsoleFromFile(f *os.File) (Console, error) {
|
||||
if err := checkConsole(f); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return newMaster(f)
|
||||
}
|
271
src/cmd/linuxkit/vendor/github.com/containerd/console/console_linux.go
generated
vendored
Normal file
271
src/cmd/linuxkit/vendor/github.com/containerd/console/console_linux.go
generated
vendored
Normal file
@@ -0,0 +1,271 @@
|
||||
// +build linux
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
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 console
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const (
|
||||
maxEvents = 128
|
||||
)
|
||||
|
||||
// Epoller manages multiple epoll consoles using edge-triggered epoll api so we
|
||||
// dont have to deal with repeated wake-up of EPOLLER or EPOLLHUP.
|
||||
// For more details, see:
|
||||
// - https://github.com/systemd/systemd/pull/4262
|
||||
// - https://github.com/moby/moby/issues/27202
|
||||
//
|
||||
// Example usage of Epoller and EpollConsole can be as follow:
|
||||
//
|
||||
// epoller, _ := NewEpoller()
|
||||
// epollConsole, _ := epoller.Add(console)
|
||||
// go epoller.Wait()
|
||||
// var (
|
||||
// b bytes.Buffer
|
||||
// wg sync.WaitGroup
|
||||
// )
|
||||
// wg.Add(1)
|
||||
// go func() {
|
||||
// io.Copy(&b, epollConsole)
|
||||
// wg.Done()
|
||||
// }()
|
||||
// // perform I/O on the console
|
||||
// epollConsole.Shutdown(epoller.CloseConsole)
|
||||
// wg.Wait()
|
||||
// epollConsole.Close()
|
||||
type Epoller struct {
|
||||
efd int
|
||||
mu sync.Mutex
|
||||
fdMapping map[int]*EpollConsole
|
||||
}
|
||||
|
||||
// NewEpoller returns an instance of epoller with a valid epoll fd.
|
||||
func NewEpoller() (*Epoller, error) {
|
||||
efd, err := unix.EpollCreate1(unix.EPOLL_CLOEXEC)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Epoller{
|
||||
efd: efd,
|
||||
fdMapping: make(map[int]*EpollConsole),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Add creates a epoll console based on the provided console. The console will
|
||||
// be registered with EPOLLET (i.e. using edge-triggered notification) and its
|
||||
// file descriptor will be set to non-blocking mode. After this, user should use
|
||||
// the return console to perform I/O.
|
||||
func (e *Epoller) Add(console Console) (*EpollConsole, error) {
|
||||
sysfd := int(console.Fd())
|
||||
// Set sysfd to non-blocking mode
|
||||
if err := unix.SetNonblock(sysfd, true); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ev := unix.EpollEvent{
|
||||
Events: unix.EPOLLIN | unix.EPOLLOUT | unix.EPOLLRDHUP | unix.EPOLLET,
|
||||
Fd: int32(sysfd),
|
||||
}
|
||||
if err := unix.EpollCtl(e.efd, unix.EPOLL_CTL_ADD, sysfd, &ev); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ef := &EpollConsole{
|
||||
Console: console,
|
||||
sysfd: sysfd,
|
||||
readc: sync.NewCond(&sync.Mutex{}),
|
||||
writec: sync.NewCond(&sync.Mutex{}),
|
||||
}
|
||||
e.mu.Lock()
|
||||
e.fdMapping[sysfd] = ef
|
||||
e.mu.Unlock()
|
||||
return ef, nil
|
||||
}
|
||||
|
||||
// Wait starts the loop to wait for its consoles' notifications and signal
|
||||
// appropriate console that it can perform I/O.
|
||||
func (e *Epoller) Wait() error {
|
||||
events := make([]unix.EpollEvent, maxEvents)
|
||||
for {
|
||||
n, err := unix.EpollWait(e.efd, events, -1)
|
||||
if err != nil {
|
||||
// EINTR: The call was interrupted by a signal handler before either
|
||||
// any of the requested events occurred or the timeout expired
|
||||
if err == unix.EINTR {
|
||||
continue
|
||||
}
|
||||
return err
|
||||
}
|
||||
for i := 0; i < n; i++ {
|
||||
ev := &events[i]
|
||||
// the console is ready to be read from
|
||||
if ev.Events&(unix.EPOLLIN|unix.EPOLLHUP|unix.EPOLLERR) != 0 {
|
||||
if epfile := e.getConsole(int(ev.Fd)); epfile != nil {
|
||||
epfile.signalRead()
|
||||
}
|
||||
}
|
||||
// the console is ready to be written to
|
||||
if ev.Events&(unix.EPOLLOUT|unix.EPOLLHUP|unix.EPOLLERR) != 0 {
|
||||
if epfile := e.getConsole(int(ev.Fd)); epfile != nil {
|
||||
epfile.signalWrite()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Close unregister the console's file descriptor from epoll interface
|
||||
func (e *Epoller) CloseConsole(fd int) error {
|
||||
e.mu.Lock()
|
||||
defer e.mu.Unlock()
|
||||
delete(e.fdMapping, fd)
|
||||
return unix.EpollCtl(e.efd, unix.EPOLL_CTL_DEL, fd, &unix.EpollEvent{})
|
||||
}
|
||||
|
||||
func (e *Epoller) getConsole(sysfd int) *EpollConsole {
|
||||
e.mu.Lock()
|
||||
f := e.fdMapping[sysfd]
|
||||
e.mu.Unlock()
|
||||
return f
|
||||
}
|
||||
|
||||
// Close the epoll fd
|
||||
func (e *Epoller) Close() error {
|
||||
return unix.Close(e.efd)
|
||||
}
|
||||
|
||||
// EpollConsole acts like a console but register its file descriptor with a
|
||||
// epoll fd and uses epoll API to perform I/O.
|
||||
type EpollConsole struct {
|
||||
Console
|
||||
readc *sync.Cond
|
||||
writec *sync.Cond
|
||||
sysfd int
|
||||
closed bool
|
||||
}
|
||||
|
||||
// Read reads up to len(p) bytes into p. It returns the number of bytes read
|
||||
// (0 <= n <= len(p)) and any error encountered.
|
||||
//
|
||||
// If the console's read returns EAGAIN or EIO, we assumes that its a
|
||||
// temporary error because the other side went away and wait for the signal
|
||||
// generated by epoll event to continue.
|
||||
func (ec *EpollConsole) Read(p []byte) (n int, err error) {
|
||||
var read int
|
||||
ec.readc.L.Lock()
|
||||
defer ec.readc.L.Unlock()
|
||||
for {
|
||||
read, err = ec.Console.Read(p[n:])
|
||||
n += read
|
||||
if err != nil {
|
||||
var hangup bool
|
||||
if perr, ok := err.(*os.PathError); ok {
|
||||
hangup = (perr.Err == unix.EAGAIN || perr.Err == unix.EIO)
|
||||
} else {
|
||||
hangup = (err == unix.EAGAIN || err == unix.EIO)
|
||||
}
|
||||
// if the other end disappear, assume this is temporary and wait for the
|
||||
// signal to continue again. Unless we didnt read anything and the
|
||||
// console is already marked as closed then we should exit
|
||||
if hangup && !(n == 0 && len(p) > 0 && ec.closed) {
|
||||
ec.readc.Wait()
|
||||
continue
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
// if we didnt read anything then return io.EOF to end gracefully
|
||||
if n == 0 && len(p) > 0 && err == nil {
|
||||
err = io.EOF
|
||||
}
|
||||
// signal for others that we finished the read
|
||||
ec.readc.Signal()
|
||||
return n, err
|
||||
}
|
||||
|
||||
// Writes len(p) bytes from p to the console. It returns the number of bytes
|
||||
// written from p (0 <= n <= len(p)) and any error encountered that caused
|
||||
// the write to stop early.
|
||||
//
|
||||
// If writes to the console returns EAGAIN or EIO, we assumes that its a
|
||||
// temporary error because the other side went away and wait for the signal
|
||||
// generated by epoll event to continue.
|
||||
func (ec *EpollConsole) Write(p []byte) (n int, err error) {
|
||||
var written int
|
||||
ec.writec.L.Lock()
|
||||
defer ec.writec.L.Unlock()
|
||||
for {
|
||||
written, err = ec.Console.Write(p[n:])
|
||||
n += written
|
||||
if err != nil {
|
||||
var hangup bool
|
||||
if perr, ok := err.(*os.PathError); ok {
|
||||
hangup = (perr.Err == unix.EAGAIN || perr.Err == unix.EIO)
|
||||
} else {
|
||||
hangup = (err == unix.EAGAIN || err == unix.EIO)
|
||||
}
|
||||
// if the other end disappear, assume this is temporary and wait for the
|
||||
// signal to continue again.
|
||||
if hangup {
|
||||
ec.writec.Wait()
|
||||
continue
|
||||
}
|
||||
}
|
||||
// unrecoverable error, break the loop and return the error
|
||||
break
|
||||
}
|
||||
if n < len(p) && err == nil {
|
||||
err = io.ErrShortWrite
|
||||
}
|
||||
// signal for others that we finished the write
|
||||
ec.writec.Signal()
|
||||
return n, err
|
||||
}
|
||||
|
||||
// Close closed the file descriptor and signal call waiters for this fd.
|
||||
// It accepts a callback which will be called with the console's fd. The
|
||||
// callback typically will be used to do further cleanup such as unregister the
|
||||
// console's fd from the epoll interface.
|
||||
// User should call Shutdown and wait for all I/O operation to be finished
|
||||
// before closing the console.
|
||||
func (ec *EpollConsole) Shutdown(close func(int) error) error {
|
||||
ec.readc.L.Lock()
|
||||
defer ec.readc.L.Unlock()
|
||||
ec.writec.L.Lock()
|
||||
defer ec.writec.L.Unlock()
|
||||
|
||||
ec.readc.Broadcast()
|
||||
ec.writec.Broadcast()
|
||||
ec.closed = true
|
||||
return close(ec.sysfd)
|
||||
}
|
||||
|
||||
// signalRead signals that the console is readable.
|
||||
func (ec *EpollConsole) signalRead() {
|
||||
ec.readc.Signal()
|
||||
}
|
||||
|
||||
// signalWrite signals that the console is writable.
|
||||
func (ec *EpollConsole) signalWrite() {
|
||||
ec.writec.Signal()
|
||||
}
|
158
src/cmd/linuxkit/vendor/github.com/containerd/console/console_unix.go
generated
vendored
Normal file
158
src/cmd/linuxkit/vendor/github.com/containerd/console/console_unix.go
generated
vendored
Normal file
@@ -0,0 +1,158 @@
|
||||
// +build darwin freebsd linux openbsd solaris
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
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 console
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// NewPty creates a new pty pair
|
||||
// The master is returned as the first console and a string
|
||||
// with the path to the pty slave is returned as the second
|
||||
func NewPty() (Console, string, error) {
|
||||
f, err := os.OpenFile("/dev/ptmx", unix.O_RDWR|unix.O_NOCTTY|unix.O_CLOEXEC, 0)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
slave, err := ptsname(f)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
if err := unlockpt(f); err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
m, err := newMaster(f)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
return m, slave, nil
|
||||
}
|
||||
|
||||
type master struct {
|
||||
f *os.File
|
||||
original *unix.Termios
|
||||
}
|
||||
|
||||
func (m *master) Read(b []byte) (int, error) {
|
||||
return m.f.Read(b)
|
||||
}
|
||||
|
||||
func (m *master) Write(b []byte) (int, error) {
|
||||
return m.f.Write(b)
|
||||
}
|
||||
|
||||
func (m *master) Close() error {
|
||||
return m.f.Close()
|
||||
}
|
||||
|
||||
func (m *master) Resize(ws WinSize) error {
|
||||
return tcswinsz(m.f.Fd(), ws)
|
||||
}
|
||||
|
||||
func (m *master) ResizeFrom(c Console) error {
|
||||
ws, err := c.Size()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return m.Resize(ws)
|
||||
}
|
||||
|
||||
func (m *master) Reset() error {
|
||||
if m.original == nil {
|
||||
return nil
|
||||
}
|
||||
return tcset(m.f.Fd(), m.original)
|
||||
}
|
||||
|
||||
func (m *master) getCurrent() (unix.Termios, error) {
|
||||
var termios unix.Termios
|
||||
if err := tcget(m.f.Fd(), &termios); err != nil {
|
||||
return unix.Termios{}, err
|
||||
}
|
||||
return termios, nil
|
||||
}
|
||||
|
||||
func (m *master) SetRaw() error {
|
||||
rawState, err := m.getCurrent()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rawState = cfmakeraw(rawState)
|
||||
rawState.Oflag = rawState.Oflag | unix.OPOST
|
||||
return tcset(m.f.Fd(), &rawState)
|
||||
}
|
||||
|
||||
func (m *master) DisableEcho() error {
|
||||
rawState, err := m.getCurrent()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rawState.Lflag = rawState.Lflag &^ unix.ECHO
|
||||
return tcset(m.f.Fd(), &rawState)
|
||||
}
|
||||
|
||||
func (m *master) Size() (WinSize, error) {
|
||||
return tcgwinsz(m.f.Fd())
|
||||
}
|
||||
|
||||
func (m *master) Fd() uintptr {
|
||||
return m.f.Fd()
|
||||
}
|
||||
|
||||
func (m *master) Name() string {
|
||||
return m.f.Name()
|
||||
}
|
||||
|
||||
// checkConsole checks if the provided file is a console
|
||||
func checkConsole(f *os.File) error {
|
||||
var termios unix.Termios
|
||||
if tcget(f.Fd(), &termios) != nil {
|
||||
return ErrNotAConsole
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func newMaster(f *os.File) (Console, error) {
|
||||
m := &master{
|
||||
f: f,
|
||||
}
|
||||
t, err := m.getCurrent()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m.original = &t
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// ClearONLCR sets the necessary tty_ioctl(4)s to ensure that a pty pair
|
||||
// created by us acts normally. In particular, a not-very-well-known default of
|
||||
// Linux unix98 ptys is that they have +onlcr by default. While this isn't a
|
||||
// problem for terminal emulators, because we relay data from the terminal we
|
||||
// also relay that funky line discipline.
|
||||
func ClearONLCR(fd uintptr) error {
|
||||
return setONLCR(fd, false)
|
||||
}
|
||||
|
||||
// SetONLCR sets the necessary tty_ioctl(4)s to ensure that a pty pair
|
||||
// created by us acts as intended for a terminal emulator.
|
||||
func SetONLCR(fd uintptr) error {
|
||||
return setONLCR(fd, true)
|
||||
}
|
216
src/cmd/linuxkit/vendor/github.com/containerd/console/console_windows.go
generated
vendored
Normal file
216
src/cmd/linuxkit/vendor/github.com/containerd/console/console_windows.go
generated
vendored
Normal file
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
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 console
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
var (
|
||||
vtInputSupported bool
|
||||
ErrNotImplemented = errors.New("not implemented")
|
||||
)
|
||||
|
||||
func (m *master) initStdios() {
|
||||
m.in = windows.Handle(os.Stdin.Fd())
|
||||
if err := windows.GetConsoleMode(m.in, &m.inMode); err == nil {
|
||||
// Validate that windows.ENABLE_VIRTUAL_TERMINAL_INPUT is supported, but do not set it.
|
||||
if err = windows.SetConsoleMode(m.in, m.inMode|windows.ENABLE_VIRTUAL_TERMINAL_INPUT); err == nil {
|
||||
vtInputSupported = true
|
||||
}
|
||||
// Unconditionally set the console mode back even on failure because SetConsoleMode
|
||||
// remembers invalid bits on input handles.
|
||||
windows.SetConsoleMode(m.in, m.inMode)
|
||||
} else {
|
||||
fmt.Printf("failed to get console mode for stdin: %v\n", err)
|
||||
}
|
||||
|
||||
m.out = windows.Handle(os.Stdout.Fd())
|
||||
if err := windows.GetConsoleMode(m.out, &m.outMode); err == nil {
|
||||
if err := windows.SetConsoleMode(m.out, m.outMode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING); err == nil {
|
||||
m.outMode |= windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING
|
||||
} else {
|
||||
windows.SetConsoleMode(m.out, m.outMode)
|
||||
}
|
||||
} else {
|
||||
fmt.Printf("failed to get console mode for stdout: %v\n", err)
|
||||
}
|
||||
|
||||
m.err = windows.Handle(os.Stderr.Fd())
|
||||
if err := windows.GetConsoleMode(m.err, &m.errMode); err == nil {
|
||||
if err := windows.SetConsoleMode(m.err, m.errMode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING); err == nil {
|
||||
m.errMode |= windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING
|
||||
} else {
|
||||
windows.SetConsoleMode(m.err, m.errMode)
|
||||
}
|
||||
} else {
|
||||
fmt.Printf("failed to get console mode for stderr: %v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
type master struct {
|
||||
in windows.Handle
|
||||
inMode uint32
|
||||
|
||||
out windows.Handle
|
||||
outMode uint32
|
||||
|
||||
err windows.Handle
|
||||
errMode uint32
|
||||
}
|
||||
|
||||
func (m *master) SetRaw() error {
|
||||
if err := makeInputRaw(m.in, m.inMode); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Set StdOut and StdErr to raw mode, we ignore failures since
|
||||
// windows.DISABLE_NEWLINE_AUTO_RETURN might not be supported on this version of
|
||||
// Windows.
|
||||
|
||||
windows.SetConsoleMode(m.out, m.outMode|windows.DISABLE_NEWLINE_AUTO_RETURN)
|
||||
|
||||
windows.SetConsoleMode(m.err, m.errMode|windows.DISABLE_NEWLINE_AUTO_RETURN)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *master) Reset() error {
|
||||
for _, s := range []struct {
|
||||
fd windows.Handle
|
||||
mode uint32
|
||||
}{
|
||||
{m.in, m.inMode},
|
||||
{m.out, m.outMode},
|
||||
{m.err, m.errMode},
|
||||
} {
|
||||
if err := windows.SetConsoleMode(s.fd, s.mode); err != nil {
|
||||
return errors.Wrap(err, "unable to restore console mode")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *master) Size() (WinSize, error) {
|
||||
var info windows.ConsoleScreenBufferInfo
|
||||
err := windows.GetConsoleScreenBufferInfo(m.out, &info)
|
||||
if err != nil {
|
||||
return WinSize{}, errors.Wrap(err, "unable to get console info")
|
||||
}
|
||||
|
||||
winsize := WinSize{
|
||||
Width: uint16(info.Window.Right - info.Window.Left + 1),
|
||||
Height: uint16(info.Window.Bottom - info.Window.Top + 1),
|
||||
}
|
||||
|
||||
return winsize, nil
|
||||
}
|
||||
|
||||
func (m *master) Resize(ws WinSize) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
func (m *master) ResizeFrom(c Console) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
func (m *master) DisableEcho() error {
|
||||
mode := m.inMode &^ windows.ENABLE_ECHO_INPUT
|
||||
mode |= windows.ENABLE_PROCESSED_INPUT
|
||||
mode |= windows.ENABLE_LINE_INPUT
|
||||
|
||||
if err := windows.SetConsoleMode(m.in, mode); err != nil {
|
||||
return errors.Wrap(err, "unable to set console to disable echo")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *master) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *master) Read(b []byte) (int, error) {
|
||||
panic("not implemented on windows")
|
||||
}
|
||||
|
||||
func (m *master) Write(b []byte) (int, error) {
|
||||
panic("not implemented on windows")
|
||||
}
|
||||
|
||||
func (m *master) Fd() uintptr {
|
||||
return uintptr(m.in)
|
||||
}
|
||||
|
||||
// on windows, console can only be made from os.Std{in,out,err}, hence there
|
||||
// isnt a single name here we can use. Return a dummy "console" value in this
|
||||
// case should be sufficient.
|
||||
func (m *master) Name() string {
|
||||
return "console"
|
||||
}
|
||||
|
||||
// makeInputRaw puts the terminal (Windows Console) connected to the given
|
||||
// file descriptor into raw mode
|
||||
func makeInputRaw(fd windows.Handle, mode uint32) error {
|
||||
// See
|
||||
// -- https://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx
|
||||
// -- https://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx
|
||||
|
||||
// Disable these modes
|
||||
mode &^= windows.ENABLE_ECHO_INPUT
|
||||
mode &^= windows.ENABLE_LINE_INPUT
|
||||
mode &^= windows.ENABLE_MOUSE_INPUT
|
||||
mode &^= windows.ENABLE_WINDOW_INPUT
|
||||
mode &^= windows.ENABLE_PROCESSED_INPUT
|
||||
|
||||
// Enable these modes
|
||||
mode |= windows.ENABLE_EXTENDED_FLAGS
|
||||
mode |= windows.ENABLE_INSERT_MODE
|
||||
mode |= windows.ENABLE_QUICK_EDIT_MODE
|
||||
|
||||
if vtInputSupported {
|
||||
mode |= windows.ENABLE_VIRTUAL_TERMINAL_INPUT
|
||||
}
|
||||
|
||||
if err := windows.SetConsoleMode(fd, mode); err != nil {
|
||||
return errors.Wrap(err, "unable to set console to raw mode")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkConsole(f *os.File) error {
|
||||
var mode uint32
|
||||
if err := windows.GetConsoleMode(windows.Handle(f.Fd()), &mode); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func newMaster(f *os.File) (Console, error) {
|
||||
if f != os.Stdin && f != os.Stdout && f != os.Stderr {
|
||||
return nil, errors.New("creating a console from a file is not supported on windows")
|
||||
}
|
||||
m := &master{}
|
||||
m.initStdios()
|
||||
return m, nil
|
||||
}
|
53
src/cmd/linuxkit/vendor/github.com/containerd/console/tc_darwin.go
generated
vendored
Normal file
53
src/cmd/linuxkit/vendor/github.com/containerd/console/tc_darwin.go
generated
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
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 console
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const (
|
||||
cmdTcGet = unix.TIOCGETA
|
||||
cmdTcSet = unix.TIOCSETA
|
||||
)
|
||||
|
||||
func ioctl(fd, flag, data uintptr) error {
|
||||
if _, _, err := unix.Syscall(unix.SYS_IOCTL, fd, flag, data); err != 0 {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// unlockpt unlocks the slave pseudoterminal device corresponding to the master pseudoterminal referred to by f.
|
||||
// unlockpt should be called before opening the slave side of a pty.
|
||||
func unlockpt(f *os.File) error {
|
||||
var u int32
|
||||
return ioctl(f.Fd(), unix.TIOCPTYUNLK, uintptr(unsafe.Pointer(&u)))
|
||||
}
|
||||
|
||||
// ptsname retrieves the name of the first available pts for the given master.
|
||||
func ptsname(f *os.File) (string, error) {
|
||||
n, err := unix.IoctlGetInt(int(f.Fd()), unix.TIOCPTYGNAME)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return fmt.Sprintf("/dev/pts/%d", n), nil
|
||||
}
|
45
src/cmd/linuxkit/vendor/github.com/containerd/console/tc_freebsd.go
generated
vendored
Normal file
45
src/cmd/linuxkit/vendor/github.com/containerd/console/tc_freebsd.go
generated
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
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 console
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const (
|
||||
cmdTcGet = unix.TIOCGETA
|
||||
cmdTcSet = unix.TIOCSETA
|
||||
)
|
||||
|
||||
// unlockpt unlocks the slave pseudoterminal device corresponding to the master pseudoterminal referred to by f.
|
||||
// unlockpt should be called before opening the slave side of a pty.
|
||||
// This does not exist on FreeBSD, it does not allocate controlling terminals on open
|
||||
func unlockpt(f *os.File) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ptsname retrieves the name of the first available pts for the given master.
|
||||
func ptsname(f *os.File) (string, error) {
|
||||
n, err := unix.IoctlGetInt(int(f.Fd()), unix.TIOCGPTN)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return fmt.Sprintf("/dev/pts/%d", n), nil
|
||||
}
|
49
src/cmd/linuxkit/vendor/github.com/containerd/console/tc_linux.go
generated
vendored
Normal file
49
src/cmd/linuxkit/vendor/github.com/containerd/console/tc_linux.go
generated
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
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 console
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const (
|
||||
cmdTcGet = unix.TCGETS
|
||||
cmdTcSet = unix.TCSETS
|
||||
)
|
||||
|
||||
// unlockpt unlocks the slave pseudoterminal device corresponding to the master pseudoterminal referred to by f.
|
||||
// unlockpt should be called before opening the slave side of a pty.
|
||||
func unlockpt(f *os.File) error {
|
||||
var u int32
|
||||
if _, _, err := unix.Syscall(unix.SYS_IOCTL, f.Fd(), unix.TIOCSPTLCK, uintptr(unsafe.Pointer(&u))); err != 0 {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ptsname retrieves the name of the first available pts for the given master.
|
||||
func ptsname(f *os.File) (string, error) {
|
||||
var u uint32
|
||||
if _, _, err := unix.Syscall(unix.SYS_IOCTL, f.Fd(), unix.TIOCGPTN, uintptr(unsafe.Pointer(&u))); err != 0 {
|
||||
return "", err
|
||||
}
|
||||
return fmt.Sprintf("/dev/pts/%d", u), nil
|
||||
}
|
51
src/cmd/linuxkit/vendor/github.com/containerd/console/tc_openbsd_cgo.go
generated
vendored
Normal file
51
src/cmd/linuxkit/vendor/github.com/containerd/console/tc_openbsd_cgo.go
generated
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
// +build openbsd,cgo
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
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 console
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
//#include <stdlib.h>
|
||||
import "C"
|
||||
|
||||
const (
|
||||
cmdTcGet = unix.TIOCGETA
|
||||
cmdTcSet = unix.TIOCSETA
|
||||
)
|
||||
|
||||
// ptsname retrieves the name of the first available pts for the given master.
|
||||
func ptsname(f *os.File) (string, error) {
|
||||
ptspath, err := C.ptsname(C.int(f.Fd()))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return C.GoString(ptspath), nil
|
||||
}
|
||||
|
||||
// unlockpt unlocks the slave pseudoterminal device corresponding to the master pseudoterminal referred to by f.
|
||||
// unlockpt should be called before opening the slave side of a pty.
|
||||
func unlockpt(f *os.File) error {
|
||||
if _, err := C.grantpt(C.int(f.Fd())); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
47
src/cmd/linuxkit/vendor/github.com/containerd/console/tc_openbsd_nocgo.go
generated
vendored
Normal file
47
src/cmd/linuxkit/vendor/github.com/containerd/console/tc_openbsd_nocgo.go
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
// +build openbsd,!cgo
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
//
|
||||
// Implementing the functions below requires cgo support. Non-cgo stubs
|
||||
// versions are defined below to enable cross-compilation of source code
|
||||
// that depends on these functions, but the resultant cross-compiled
|
||||
// binaries cannot actually be used. If the stub function(s) below are
|
||||
// actually invoked they will display an error message and cause the
|
||||
// calling process to exit.
|
||||
//
|
||||
|
||||
package console
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const (
|
||||
cmdTcGet = unix.TIOCGETA
|
||||
cmdTcSet = unix.TIOCSETA
|
||||
)
|
||||
|
||||
func ptsname(f *os.File) (string, error) {
|
||||
panic("ptsname() support requires cgo.")
|
||||
}
|
||||
|
||||
func unlockpt(f *os.File) error {
|
||||
panic("unlockpt() support requires cgo.")
|
||||
}
|
51
src/cmd/linuxkit/vendor/github.com/containerd/console/tc_solaris_cgo.go
generated
vendored
Normal file
51
src/cmd/linuxkit/vendor/github.com/containerd/console/tc_solaris_cgo.go
generated
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
// +build solaris,cgo
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
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 console
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
//#include <stdlib.h>
|
||||
import "C"
|
||||
|
||||
const (
|
||||
cmdTcGet = unix.TCGETS
|
||||
cmdTcSet = unix.TCSETS
|
||||
)
|
||||
|
||||
// ptsname retrieves the name of the first available pts for the given master.
|
||||
func ptsname(f *os.File) (string, error) {
|
||||
ptspath, err := C.ptsname(C.int(f.Fd()))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return C.GoString(ptspath), nil
|
||||
}
|
||||
|
||||
// unlockpt unlocks the slave pseudoterminal device corresponding to the master pseudoterminal referred to by f.
|
||||
// unlockpt should be called before opening the slave side of a pty.
|
||||
func unlockpt(f *os.File) error {
|
||||
if _, err := C.grantpt(C.int(f.Fd())); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
47
src/cmd/linuxkit/vendor/github.com/containerd/console/tc_solaris_nocgo.go
generated
vendored
Normal file
47
src/cmd/linuxkit/vendor/github.com/containerd/console/tc_solaris_nocgo.go
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
// +build solaris,!cgo
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
//
|
||||
// Implementing the functions below requires cgo support. Non-cgo stubs
|
||||
// versions are defined below to enable cross-compilation of source code
|
||||
// that depends on these functions, but the resultant cross-compiled
|
||||
// binaries cannot actually be used. If the stub function(s) below are
|
||||
// actually invoked they will display an error message and cause the
|
||||
// calling process to exit.
|
||||
//
|
||||
|
||||
package console
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const (
|
||||
cmdTcGet = unix.TCGETS
|
||||
cmdTcSet = unix.TCSETS
|
||||
)
|
||||
|
||||
func ptsname(f *os.File) (string, error) {
|
||||
panic("ptsname() support requires cgo.")
|
||||
}
|
||||
|
||||
func unlockpt(f *os.File) error {
|
||||
panic("unlockpt() support requires cgo.")
|
||||
}
|
91
src/cmd/linuxkit/vendor/github.com/containerd/console/tc_unix.go
generated
vendored
Normal file
91
src/cmd/linuxkit/vendor/github.com/containerd/console/tc_unix.go
generated
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
// +build darwin freebsd linux openbsd solaris
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
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 console
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func tcget(fd uintptr, p *unix.Termios) error {
|
||||
termios, err := unix.IoctlGetTermios(int(fd), cmdTcGet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*p = *termios
|
||||
return nil
|
||||
}
|
||||
|
||||
func tcset(fd uintptr, p *unix.Termios) error {
|
||||
return unix.IoctlSetTermios(int(fd), cmdTcSet, p)
|
||||
}
|
||||
|
||||
func tcgwinsz(fd uintptr) (WinSize, error) {
|
||||
var ws WinSize
|
||||
|
||||
uws, err := unix.IoctlGetWinsize(int(fd), unix.TIOCGWINSZ)
|
||||
if err != nil {
|
||||
return ws, err
|
||||
}
|
||||
|
||||
// Translate from unix.Winsize to console.WinSize
|
||||
ws.Height = uws.Row
|
||||
ws.Width = uws.Col
|
||||
ws.x = uws.Xpixel
|
||||
ws.y = uws.Ypixel
|
||||
return ws, nil
|
||||
}
|
||||
|
||||
func tcswinsz(fd uintptr, ws WinSize) error {
|
||||
// Translate from console.WinSize to unix.Winsize
|
||||
|
||||
var uws unix.Winsize
|
||||
uws.Row = ws.Height
|
||||
uws.Col = ws.Width
|
||||
uws.Xpixel = ws.x
|
||||
uws.Ypixel = ws.y
|
||||
|
||||
return unix.IoctlSetWinsize(int(fd), unix.TIOCSWINSZ, &uws)
|
||||
}
|
||||
|
||||
func setONLCR(fd uintptr, enable bool) error {
|
||||
var termios unix.Termios
|
||||
if err := tcget(fd, &termios); err != nil {
|
||||
return err
|
||||
}
|
||||
if enable {
|
||||
// Set +onlcr so we can act like a real terminal
|
||||
termios.Oflag |= unix.ONLCR
|
||||
} else {
|
||||
// Set -onlcr so we don't have to deal with \r.
|
||||
termios.Oflag &^= unix.ONLCR
|
||||
}
|
||||
return tcset(fd, &termios)
|
||||
}
|
||||
|
||||
func cfmakeraw(t unix.Termios) unix.Termios {
|
||||
t.Iflag &^= (unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON)
|
||||
t.Oflag &^= unix.OPOST
|
||||
t.Lflag &^= (unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN)
|
||||
t.Cflag &^= (unix.CSIZE | unix.PARENB)
|
||||
t.Cflag &^= unix.CS8
|
||||
t.Cc[unix.VMIN] = 1
|
||||
t.Cc[unix.VTIME] = 0
|
||||
|
||||
return t
|
||||
}
|
22
src/cmd/linuxkit/vendor/github.com/creack/goselect/LICENSE
generated
vendored
Normal file
22
src/cmd/linuxkit/vendor/github.com/creack/goselect/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Guillaume J. Charmes
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
30
src/cmd/linuxkit/vendor/github.com/creack/goselect/README.md
generated
vendored
Normal file
30
src/cmd/linuxkit/vendor/github.com/creack/goselect/README.md
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
# go-select
|
||||
|
||||
select(2) implementation in Go
|
||||
|
||||
## Supported platforms
|
||||
|
||||
| | 386 | amd64 | arm | arm64 |
|
||||
|---------------|-----|-------|-----|-------|
|
||||
| **linux** | yes | yes | yes | yes |
|
||||
| **darwin** | yes | yes | n/a | ?? |
|
||||
| **freebsd** | yes | yes | yes | ?? |
|
||||
| **openbsd** | yes | yes | yes | ?? |
|
||||
| **netbsd** | yes | yes | yes | ?? |
|
||||
| **dragonfly** | n/a | yes | n/a | ?? |
|
||||
| **solaris** | n/a | no | n/a | ?? |
|
||||
| **plan9** | no | no | n/a | ?? |
|
||||
| **windows** | yes | yes | n/a | ?? |
|
||||
| **android** | n/a | n/a | no | ?? |
|
||||
|
||||
*n/a: platform not supported by Go
|
||||
|
||||
Go on `plan9` and `solaris` do not implement `syscall.Select` not `syscall.SYS_SELECT`.
|
||||
|
||||
## Cross compile
|
||||
|
||||
Using davecheney's https://github.com/davecheney/golang-crosscompile
|
||||
|
||||
```
|
||||
export PLATFORMS="darwin/386 darwin/amd64 freebsd/386 freebsd/amd64 freebsd/arm linux/386 linux/amd64 linux/arm windows/386 windows/amd64 openbsd/386 openbsd/amd64 netbsd/386 netbsd/amd64 dragonfly/amd64 plan9/386 plan9/amd64 solaris/amd64"
|
||||
```
|
33
src/cmd/linuxkit/vendor/github.com/creack/goselect/fdset.go
generated
vendored
Normal file
33
src/cmd/linuxkit/vendor/github.com/creack/goselect/fdset.go
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
// +build !freebsd,!windows,!plan9
|
||||
|
||||
package goselect
|
||||
|
||||
import "syscall"
|
||||
|
||||
const FD_SETSIZE = syscall.FD_SETSIZE
|
||||
|
||||
// FDSet wraps syscall.FdSet with convenience methods
|
||||
type FDSet syscall.FdSet
|
||||
|
||||
// Set adds the fd to the set
|
||||
func (fds *FDSet) Set(fd uintptr) {
|
||||
fds.Bits[fd/NFDBITS] |= (1 << (fd % NFDBITS))
|
||||
}
|
||||
|
||||
// Clear remove the fd from the set
|
||||
func (fds *FDSet) Clear(fd uintptr) {
|
||||
fds.Bits[fd/NFDBITS] &^= (1 << (fd % NFDBITS))
|
||||
}
|
||||
|
||||
// IsSet check if the given fd is set
|
||||
func (fds *FDSet) IsSet(fd uintptr) bool {
|
||||
return fds.Bits[fd/NFDBITS]&(1<<(fd%NFDBITS)) != 0
|
||||
}
|
||||
|
||||
// Keep a null set to avoid reinstatiation
|
||||
var nullFdSet = &FDSet{}
|
||||
|
||||
// Zero empties the Set
|
||||
func (fds *FDSet) Zero() {
|
||||
copy(fds.Bits[:], (nullFdSet).Bits[:])
|
||||
}
|
10
src/cmd/linuxkit/vendor/github.com/creack/goselect/fdset_32.go
generated
vendored
Normal file
10
src/cmd/linuxkit/vendor/github.com/creack/goselect/fdset_32.go
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
// +build darwin openbsd netbsd 386 arm mips mipsle
|
||||
|
||||
package goselect
|
||||
|
||||
// darwin, netbsd and openbsd uses uint32 on both amd64 and 386
|
||||
|
||||
const (
|
||||
// NFDBITS is the amount of bits per mask
|
||||
NFDBITS = 4 * 8
|
||||
)
|
11
src/cmd/linuxkit/vendor/github.com/creack/goselect/fdset_64.go
generated
vendored
Normal file
11
src/cmd/linuxkit/vendor/github.com/creack/goselect/fdset_64.go
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
// +build !darwin,!netbsd,!openbsd
|
||||
// +build amd64 arm64 ppc64le mips64 mips64le s390x
|
||||
|
||||
package goselect
|
||||
|
||||
// darwin, netbsd and openbsd uses uint32 on both amd64 and 386
|
||||
|
||||
const (
|
||||
// NFDBITS is the amount of bits per mask
|
||||
NFDBITS = 8 * 8
|
||||
)
|
93
src/cmd/linuxkit/vendor/github.com/creack/goselect/fdset_doc.go
generated
vendored
Normal file
93
src/cmd/linuxkit/vendor/github.com/creack/goselect/fdset_doc.go
generated
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
package goselect
|
||||
|
||||
/**
|
||||
From: XCode's MacOSX10.10.sdk/System/Library/Frameworks/Kernel.framework/Versions/A/Headers/sys/select.h
|
||||
--
|
||||
// darwin/amd64 / 386
|
||||
sizeof(__int32_t) == 4
|
||||
--
|
||||
|
||||
typedef __int32_t __fd_mask;
|
||||
|
||||
#define FD_SETSIZE 1024
|
||||
#define __NFDBITS (sizeof(__fd_mask) * 8)
|
||||
#define __howmany(x, y) ((((x) % (y)) == 0) ? ((x) / (y)) : (((x) / (y)) + 1))
|
||||
|
||||
typedef struct fd_set {
|
||||
__fd_mask fds_bits[__howmany(__FD_SETSIZE, __NFDBITS)];
|
||||
} fd_set;
|
||||
|
||||
#define __FD_MASK(n) ((__fd_mask)1 << ((n) % __NFDBITS))
|
||||
#define FD_SET(n, p) ((p)->fds_bits[(n)/__NFDBITS] |= __FD_MASK(n))
|
||||
#define FD_CLR(n, p) ((p)->fds_bits[(n)/__NFDBITS] &= ~__FD_MASK(n))
|
||||
#define FD_ISSET(n, p) (((p)->fds_bits[(n)/__NFDBITS] & __FD_MASK(n)) != 0)
|
||||
*/
|
||||
|
||||
/**
|
||||
From: /usr/include/i386-linux-gnu/sys/select.h
|
||||
--
|
||||
// linux/i686
|
||||
sizeof(long int) == 4
|
||||
--
|
||||
|
||||
typedef long int __fd_mask;
|
||||
|
||||
#define FD_SETSIZE 1024
|
||||
#define __NFDBITS (sizeof(__fd_mask) * 8)
|
||||
|
||||
|
||||
typedef struct fd_set {
|
||||
__fd_mask fds_bits[__FD_SETSIZE / __NFDBITS];
|
||||
} fd_set;
|
||||
|
||||
#define __FD_MASK(n) ((__fd_mask)1 << ((n) % __NFDBITS))
|
||||
#define FD_SET(n, p) ((p)->fds_bits[(n)/__NFDBITS] |= __FD_MASK(n))
|
||||
#define FD_CLR(n, p) ((p)->fds_bits[(n)/__NFDBITS] &= ~__FD_MASK(n))
|
||||
#define FD_ISSET(n, p) (((p)->fds_bits[(n)/__NFDBITS] & __FD_MASK(n)) != 0)
|
||||
*/
|
||||
|
||||
/**
|
||||
From: /usr/include/x86_64-linux-gnu/sys/select.h
|
||||
--
|
||||
// linux/amd64
|
||||
sizeof(long int) == 8
|
||||
--
|
||||
|
||||
typedef long int __fd_mask;
|
||||
|
||||
#define FD_SETSIZE 1024
|
||||
#define __NFDBITS (sizeof(__fd_mask) * 8)
|
||||
|
||||
|
||||
typedef struct fd_set {
|
||||
__fd_mask fds_bits[__FD_SETSIZE / __NFDBITS];
|
||||
} fd_set;
|
||||
|
||||
#define __FD_MASK(n) ((__fd_mask)1 << ((n) % __NFDBITS))
|
||||
#define FD_SET(n, p) ((p)->fds_bits[(n)/__NFDBITS] |= __FD_MASK(n))
|
||||
#define FD_CLR(n, p) ((p)->fds_bits[(n)/__NFDBITS] &= ~__FD_MASK(n))
|
||||
#define FD_ISSET(n, p) (((p)->fds_bits[(n)/__NFDBITS] & __FD_MASK(n)) != 0)
|
||||
*/
|
||||
|
||||
/**
|
||||
From: /usr/include/sys/select.h
|
||||
--
|
||||
// freebsd/amd64
|
||||
sizeof(unsigned long) == 8
|
||||
--
|
||||
|
||||
typedef unsigned long __fd_mask;
|
||||
|
||||
#define FD_SETSIZE 1024U
|
||||
#define __NFDBITS (sizeof(__fd_mask) * 8)
|
||||
#define _howmany(x, y) (((x) + ((y) - 1)) / (y))
|
||||
|
||||
typedef struct fd_set {
|
||||
__fd_mask fds_bits[_howmany(FD_SETSIZE, __NFDBITS)];
|
||||
} fd_set;
|
||||
|
||||
#define __FD_MASK(n) ((__fd_mask)1 << ((n) % __NFDBITS))
|
||||
#define FD_SET(n, p) ((p)->fds_bits[(n)/__NFDBITS] |= __FD_MASK(n))
|
||||
#define FD_CLR(n, p) ((p)->fds_bits[(n)/__NFDBITS] &= ~__FD_MASK(n))
|
||||
#define FD_ISSET(n, p) (((p)->fds_bits[(n)/__NFDBITS] & __FD_MASK(n)) != 0)
|
||||
*/
|
33
src/cmd/linuxkit/vendor/github.com/creack/goselect/fdset_freebsd.go
generated
vendored
Normal file
33
src/cmd/linuxkit/vendor/github.com/creack/goselect/fdset_freebsd.go
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
// +build freebsd
|
||||
|
||||
package goselect
|
||||
|
||||
import "syscall"
|
||||
|
||||
const FD_SETSIZE = syscall.FD_SETSIZE
|
||||
|
||||
// FDSet wraps syscall.FdSet with convenience methods
|
||||
type FDSet syscall.FdSet
|
||||
|
||||
// Set adds the fd to the set
|
||||
func (fds *FDSet) Set(fd uintptr) {
|
||||
fds.X__fds_bits[fd/NFDBITS] |= (1 << (fd % NFDBITS))
|
||||
}
|
||||
|
||||
// Clear remove the fd from the set
|
||||
func (fds *FDSet) Clear(fd uintptr) {
|
||||
fds.X__fds_bits[fd/NFDBITS] &^= (1 << (fd % NFDBITS))
|
||||
}
|
||||
|
||||
// IsSet check if the given fd is set
|
||||
func (fds *FDSet) IsSet(fd uintptr) bool {
|
||||
return fds.X__fds_bits[fd/NFDBITS]&(1<<(fd%NFDBITS)) != 0
|
||||
}
|
||||
|
||||
// Keep a null set to avoid reinstatiation
|
||||
var nullFdSet = &FDSet{}
|
||||
|
||||
// Zero empties the Set
|
||||
func (fds *FDSet) Zero() {
|
||||
copy(fds.X__fds_bits[:], (nullFdSet).X__fds_bits[:])
|
||||
}
|
20
src/cmd/linuxkit/vendor/github.com/creack/goselect/fdset_unsupported.go
generated
vendored
Normal file
20
src/cmd/linuxkit/vendor/github.com/creack/goselect/fdset_unsupported.go
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
// +build plan9
|
||||
|
||||
package goselect
|
||||
|
||||
const FD_SETSIZE = 0
|
||||
|
||||
// FDSet wraps syscall.FdSet with convenience methods
|
||||
type FDSet struct{}
|
||||
|
||||
// Set adds the fd to the set
|
||||
func (fds *FDSet) Set(fd uintptr) {}
|
||||
|
||||
// Clear remove the fd from the set
|
||||
func (fds *FDSet) Clear(fd uintptr) {}
|
||||
|
||||
// IsSet check if the given fd is set
|
||||
func (fds *FDSet) IsSet(fd uintptr) bool { return false }
|
||||
|
||||
// Zero empties the Set
|
||||
func (fds *FDSet) Zero() {}
|
57
src/cmd/linuxkit/vendor/github.com/creack/goselect/fdset_windows.go
generated
vendored
Normal file
57
src/cmd/linuxkit/vendor/github.com/creack/goselect/fdset_windows.go
generated
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
// +build windows
|
||||
|
||||
package goselect
|
||||
|
||||
import "syscall"
|
||||
|
||||
const FD_SETSIZE = 64
|
||||
|
||||
// FDSet extracted from mingw libs source code
|
||||
type FDSet struct {
|
||||
fd_count uint
|
||||
fd_array [FD_SETSIZE]uintptr
|
||||
}
|
||||
|
||||
// Set adds the fd to the set
|
||||
func (fds *FDSet) Set(fd uintptr) {
|
||||
var i uint
|
||||
for i = 0; i < fds.fd_count; i++ {
|
||||
if fds.fd_array[i] == fd {
|
||||
break
|
||||
}
|
||||
}
|
||||
if i == fds.fd_count {
|
||||
if fds.fd_count < FD_SETSIZE {
|
||||
fds.fd_array[i] = fd
|
||||
fds.fd_count++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clear remove the fd from the set
|
||||
func (fds *FDSet) Clear(fd uintptr) {
|
||||
var i uint
|
||||
for i = 0; i < fds.fd_count; i++ {
|
||||
if fds.fd_array[i] == fd {
|
||||
for i < fds.fd_count-1 {
|
||||
fds.fd_array[i] = fds.fd_array[i+1]
|
||||
i++
|
||||
}
|
||||
fds.fd_count--
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// IsSet check if the given fd is set
|
||||
func (fds *FDSet) IsSet(fd uintptr) bool {
|
||||
if isset, err := __WSAFDIsSet(syscall.Handle(fd), fds); err == nil && isset != 0 {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Zero empties the Set
|
||||
func (fds *FDSet) Zero() {
|
||||
fds.fd_count = 0
|
||||
}
|
28
src/cmd/linuxkit/vendor/github.com/creack/goselect/select.go
generated
vendored
Normal file
28
src/cmd/linuxkit/vendor/github.com/creack/goselect/select.go
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
package goselect
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Select wraps syscall.Select with Go types
|
||||
func Select(n int, r, w, e *FDSet, timeout time.Duration) error {
|
||||
var timeval *syscall.Timeval
|
||||
if timeout >= 0 {
|
||||
t := syscall.NsecToTimeval(timeout.Nanoseconds())
|
||||
timeval = &t
|
||||
}
|
||||
|
||||
return sysSelect(n, r, w, e, timeval)
|
||||
}
|
||||
|
||||
// RetrySelect wraps syscall.Select with Go types, and retries a number of times, with a given retryDelay.
|
||||
func RetrySelect(n int, r, w, e *FDSet, timeout time.Duration, retries int, retryDelay time.Duration) (err error) {
|
||||
for i := 0; i < retries; i++ {
|
||||
if err = Select(n, r, w, e, timeout); err != syscall.EINTR {
|
||||
return err
|
||||
}
|
||||
time.Sleep(retryDelay)
|
||||
}
|
||||
return err
|
||||
}
|
10
src/cmd/linuxkit/vendor/github.com/creack/goselect/select_linux.go
generated
vendored
Normal file
10
src/cmd/linuxkit/vendor/github.com/creack/goselect/select_linux.go
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
// +build linux
|
||||
|
||||
package goselect
|
||||
|
||||
import "syscall"
|
||||
|
||||
func sysSelect(n int, r, w, e *FDSet, timeout *syscall.Timeval) error {
|
||||
_, err := syscall.Select(n, (*syscall.FdSet)(r), (*syscall.FdSet)(w), (*syscall.FdSet)(e), timeout)
|
||||
return err
|
||||
}
|
9
src/cmd/linuxkit/vendor/github.com/creack/goselect/select_other.go
generated
vendored
Normal file
9
src/cmd/linuxkit/vendor/github.com/creack/goselect/select_other.go
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
// +build !linux,!windows,!plan9,!solaris
|
||||
|
||||
package goselect
|
||||
|
||||
import "syscall"
|
||||
|
||||
func sysSelect(n int, r, w, e *FDSet, timeout *syscall.Timeval) error {
|
||||
return syscall.Select(n, (*syscall.FdSet)(r), (*syscall.FdSet)(w), (*syscall.FdSet)(e), timeout)
|
||||
}
|
16
src/cmd/linuxkit/vendor/github.com/creack/goselect/select_unsupported.go
generated
vendored
Normal file
16
src/cmd/linuxkit/vendor/github.com/creack/goselect/select_unsupported.go
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
// +build plan9 solaris
|
||||
|
||||
package goselect
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// ErrUnsupported .
|
||||
var ErrUnsupported = fmt.Errorf("Platofrm %s/%s unsupported", runtime.GOOS, runtime.GOARCH)
|
||||
|
||||
func sysSelect(n int, r, w, e *FDSet, timeout *syscall.Timeval) error {
|
||||
return ErrUnsupported
|
||||
}
|
13
src/cmd/linuxkit/vendor/github.com/creack/goselect/select_windows.go
generated
vendored
Normal file
13
src/cmd/linuxkit/vendor/github.com/creack/goselect/select_windows.go
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
// +build windows
|
||||
|
||||
package goselect
|
||||
|
||||
import "syscall"
|
||||
|
||||
//sys _select(nfds int, readfds *FDSet, writefds *FDSet, exceptfds *FDSet, timeout *syscall.Timeval) (total int, err error) = ws2_32.select
|
||||
//sys __WSAFDIsSet(handle syscall.Handle, fdset *FDSet) (isset int, err error) = ws2_32.__WSAFDIsSet
|
||||
|
||||
func sysSelect(n int, r, w, e *FDSet, timeout *syscall.Timeval) error {
|
||||
_, err := _select(n, r, w, e, timeout)
|
||||
return err
|
||||
}
|
39
src/cmd/linuxkit/vendor/github.com/creack/goselect/zselect_windows.go
generated
vendored
Normal file
39
src/cmd/linuxkit/vendor/github.com/creack/goselect/zselect_windows.go
generated
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
// MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDIT
|
||||
|
||||
package goselect
|
||||
|
||||
import "unsafe"
|
||||
import "syscall"
|
||||
|
||||
var _ unsafe.Pointer
|
||||
|
||||
var (
|
||||
modws2_32 = syscall.NewLazyDLL("ws2_32.dll")
|
||||
|
||||
procselect = modws2_32.NewProc("select")
|
||||
proc__WSAFDIsSet = modws2_32.NewProc("__WSAFDIsSet")
|
||||
)
|
||||
|
||||
func _select(nfds int, readfds *FDSet, writefds *FDSet, exceptfds *FDSet, timeout *syscall.Timeval) (total int, err error) {
|
||||
r0, _, e1 := syscall.Syscall6(procselect.Addr(), 5, uintptr(nfds), uintptr(unsafe.Pointer(readfds)), uintptr(unsafe.Pointer(writefds)), uintptr(unsafe.Pointer(exceptfds)), uintptr(unsafe.Pointer(timeout)), 0)
|
||||
total = int(r0)
|
||||
if total == 0 {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func __WSAFDIsSet(handle syscall.Handle, fdset *FDSet) (isset int, err error) {
|
||||
r0, _, e1 := syscall.Syscall(proc__WSAFDIsSet.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(fdset)), 0)
|
||||
isset = int(r0)
|
||||
if isset == 0 {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
22
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/LICENSE
generated
vendored
Normal file
22
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
Copyright (c) 2013 The Gorilla WebSocket Authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
64
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/README.md
generated
vendored
Normal file
64
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/README.md
generated
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
# Gorilla WebSocket
|
||||
|
||||
Gorilla WebSocket is a [Go](http://golang.org/) implementation of the
|
||||
[WebSocket](http://www.rfc-editor.org/rfc/rfc6455.txt) protocol.
|
||||
|
||||
[](https://travis-ci.org/gorilla/websocket)
|
||||
[](https://godoc.org/github.com/gorilla/websocket)
|
||||
|
||||
### Documentation
|
||||
|
||||
* [API Reference](http://godoc.org/github.com/gorilla/websocket)
|
||||
* [Chat example](https://github.com/gorilla/websocket/tree/master/examples/chat)
|
||||
* [Command example](https://github.com/gorilla/websocket/tree/master/examples/command)
|
||||
* [Client and server example](https://github.com/gorilla/websocket/tree/master/examples/echo)
|
||||
* [File watch example](https://github.com/gorilla/websocket/tree/master/examples/filewatch)
|
||||
|
||||
### Status
|
||||
|
||||
The Gorilla WebSocket package provides a complete and tested implementation of
|
||||
the [WebSocket](http://www.rfc-editor.org/rfc/rfc6455.txt) protocol. The
|
||||
package API is stable.
|
||||
|
||||
### Installation
|
||||
|
||||
go get github.com/gorilla/websocket
|
||||
|
||||
### Protocol Compliance
|
||||
|
||||
The Gorilla WebSocket package passes the server tests in the [Autobahn Test
|
||||
Suite](http://autobahn.ws/testsuite) using the application in the [examples/autobahn
|
||||
subdirectory](https://github.com/gorilla/websocket/tree/master/examples/autobahn).
|
||||
|
||||
### Gorilla WebSocket compared with other packages
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th><a href="http://godoc.org/github.com/gorilla/websocket">github.com/gorilla</a></th>
|
||||
<th><a href="http://godoc.org/golang.org/x/net/websocket">golang.org/x/net</a></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr><td colspan="3"><a href="http://tools.ietf.org/html/rfc6455">RFC 6455</a> Features</td></tr>
|
||||
<tr><td>Passes <a href="http://autobahn.ws/testsuite/">Autobahn Test Suite</a></td><td><a href="https://github.com/gorilla/websocket/tree/master/examples/autobahn">Yes</a></td><td>No</td></tr>
|
||||
<tr><td>Receive <a href="https://tools.ietf.org/html/rfc6455#section-5.4">fragmented</a> message<td>Yes</td><td><a href="https://code.google.com/p/go/issues/detail?id=7632">No</a>, see note 1</td></tr>
|
||||
<tr><td>Send <a href="https://tools.ietf.org/html/rfc6455#section-5.5.1">close</a> message</td><td><a href="http://godoc.org/github.com/gorilla/websocket#hdr-Control_Messages">Yes</a></td><td><a href="https://code.google.com/p/go/issues/detail?id=4588">No</a></td></tr>
|
||||
<tr><td>Send <a href="https://tools.ietf.org/html/rfc6455#section-5.5.2">pings</a> and receive <a href="https://tools.ietf.org/html/rfc6455#section-5.5.3">pongs</a></td><td><a href="http://godoc.org/github.com/gorilla/websocket#hdr-Control_Messages">Yes</a></td><td>No</td></tr>
|
||||
<tr><td>Get the <a href="https://tools.ietf.org/html/rfc6455#section-5.6">type</a> of a received data message</td><td>Yes</td><td>Yes, see note 2</td></tr>
|
||||
<tr><td colspan="3">Other Features</tr></td>
|
||||
<tr><td><a href="https://tools.ietf.org/html/rfc7692">Compression Extensions</a></td><td>Experimental</td><td>No</td></tr>
|
||||
<tr><td>Read message using io.Reader</td><td><a href="http://godoc.org/github.com/gorilla/websocket#Conn.NextReader">Yes</a></td><td>No, see note 3</td></tr>
|
||||
<tr><td>Write message using io.WriteCloser</td><td><a href="http://godoc.org/github.com/gorilla/websocket#Conn.NextWriter">Yes</a></td><td>No, see note 3</td></tr>
|
||||
</table>
|
||||
|
||||
Notes:
|
||||
|
||||
1. Large messages are fragmented in [Chrome's new WebSocket implementation](http://www.ietf.org/mail-archive/web/hybi/current/msg10503.html).
|
||||
2. The application can get the type of a received data message by implementing
|
||||
a [Codec marshal](http://godoc.org/golang.org/x/net/websocket#Codec.Marshal)
|
||||
function.
|
||||
3. The go.net io.Reader and io.Writer operate across WebSocket frame boundaries.
|
||||
Read returns when the input buffer is full or a frame boundary is
|
||||
encountered. Each call to Write sends a single frame message. The Gorilla
|
||||
io.Reader and io.WriteCloser operate on a single WebSocket message.
|
||||
|
330
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/client.go
generated
vendored
Normal file
330
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/client.go
generated
vendored
Normal file
@@ -0,0 +1,330 @@
|
||||
// Copyright 2013 The Gorilla WebSocket Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package websocket
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// ErrBadHandshake is returned when the server response to opening handshake is
|
||||
// invalid.
|
||||
var ErrBadHandshake = errors.New("websocket: bad handshake")
|
||||
|
||||
var errInvalidCompression = errors.New("websocket: invalid compression negotiation")
|
||||
|
||||
// NewClient creates a new client connection using the given net connection.
|
||||
// The URL u specifies the host and request URI. Use requestHeader to specify
|
||||
// the origin (Origin), subprotocols (Sec-WebSocket-Protocol) and cookies
|
||||
// (Cookie). Use the response.Header to get the selected subprotocol
|
||||
// (Sec-WebSocket-Protocol) and cookies (Set-Cookie).
|
||||
//
|
||||
// If the WebSocket handshake fails, ErrBadHandshake is returned along with a
|
||||
// non-nil *http.Response so that callers can handle redirects, authentication,
|
||||
// etc.
|
||||
//
|
||||
// Deprecated: Use Dialer instead.
|
||||
func NewClient(netConn net.Conn, u *url.URL, requestHeader http.Header, readBufSize, writeBufSize int) (c *Conn, response *http.Response, err error) {
|
||||
d := Dialer{
|
||||
ReadBufferSize: readBufSize,
|
||||
WriteBufferSize: writeBufSize,
|
||||
NetDial: func(net, addr string) (net.Conn, error) {
|
||||
return netConn, nil
|
||||
},
|
||||
}
|
||||
return d.Dial(u.String(), requestHeader)
|
||||
}
|
||||
|
||||
// A Dialer contains options for connecting to WebSocket server.
|
||||
type Dialer struct {
|
||||
// NetDial specifies the dial function for creating TCP connections. If
|
||||
// NetDial is nil, net.Dial is used.
|
||||
NetDial func(network, addr string) (net.Conn, error)
|
||||
|
||||
// Proxy specifies a function to return a proxy for a given
|
||||
// Request. If the function returns a non-nil error, the
|
||||
// request is aborted with the provided error.
|
||||
// If Proxy is nil or returns a nil *URL, no proxy is used.
|
||||
Proxy func(*http.Request) (*url.URL, error)
|
||||
|
||||
// TLSClientConfig specifies the TLS configuration to use with tls.Client.
|
||||
// If nil, the default configuration is used.
|
||||
TLSClientConfig *tls.Config
|
||||
|
||||
// HandshakeTimeout specifies the duration for the handshake to complete.
|
||||
HandshakeTimeout time.Duration
|
||||
|
||||
// ReadBufferSize and WriteBufferSize specify I/O buffer sizes. If a buffer
|
||||
// size is zero, then a useful default size is used. The I/O buffer sizes
|
||||
// do not limit the size of the messages that can be sent or received.
|
||||
ReadBufferSize, WriteBufferSize int
|
||||
|
||||
// Subprotocols specifies the client's requested subprotocols.
|
||||
Subprotocols []string
|
||||
|
||||
// EnableCompression specifies if the client should attempt to negotiate
|
||||
// per message compression (RFC 7692). Setting this value to true does not
|
||||
// guarantee that compression will be supported. Currently only "no context
|
||||
// takeover" modes are supported.
|
||||
EnableCompression bool
|
||||
|
||||
// Jar specifies the cookie jar.
|
||||
// If Jar is nil, cookies are not sent in requests and ignored
|
||||
// in responses.
|
||||
Jar http.CookieJar
|
||||
}
|
||||
|
||||
var errMalformedURL = errors.New("malformed ws or wss URL")
|
||||
|
||||
func hostPortNoPort(u *url.URL) (hostPort, hostNoPort string) {
|
||||
hostPort = u.Host
|
||||
hostNoPort = u.Host
|
||||
if i := strings.LastIndex(u.Host, ":"); i > strings.LastIndex(u.Host, "]") {
|
||||
hostNoPort = hostNoPort[:i]
|
||||
} else {
|
||||
switch u.Scheme {
|
||||
case "wss":
|
||||
hostPort += ":443"
|
||||
case "https":
|
||||
hostPort += ":443"
|
||||
default:
|
||||
hostPort += ":80"
|
||||
}
|
||||
}
|
||||
return hostPort, hostNoPort
|
||||
}
|
||||
|
||||
// DefaultDialer is a dialer with all fields set to the default values.
|
||||
var DefaultDialer = &Dialer{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
HandshakeTimeout: 45 * time.Second,
|
||||
}
|
||||
|
||||
// nilDialer is dialer to use when receiver is nil.
|
||||
var nilDialer Dialer = *DefaultDialer
|
||||
|
||||
// Dial creates a new client connection. Use requestHeader to specify the
|
||||
// origin (Origin), subprotocols (Sec-WebSocket-Protocol) and cookies (Cookie).
|
||||
// Use the response.Header to get the selected subprotocol
|
||||
// (Sec-WebSocket-Protocol) and cookies (Set-Cookie).
|
||||
//
|
||||
// If the WebSocket handshake fails, ErrBadHandshake is returned along with a
|
||||
// non-nil *http.Response so that callers can handle redirects, authentication,
|
||||
// etcetera. The response body may not contain the entire response and does not
|
||||
// need to be closed by the application.
|
||||
func (d *Dialer) Dial(urlStr string, requestHeader http.Header) (*Conn, *http.Response, error) {
|
||||
|
||||
if d == nil {
|
||||
d = &nilDialer
|
||||
}
|
||||
|
||||
challengeKey, err := generateChallengeKey()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
u, err := url.Parse(urlStr)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
switch u.Scheme {
|
||||
case "ws":
|
||||
u.Scheme = "http"
|
||||
case "wss":
|
||||
u.Scheme = "https"
|
||||
default:
|
||||
return nil, nil, errMalformedURL
|
||||
}
|
||||
|
||||
if u.User != nil {
|
||||
// User name and password are not allowed in websocket URIs.
|
||||
return nil, nil, errMalformedURL
|
||||
}
|
||||
|
||||
req := &http.Request{
|
||||
Method: "GET",
|
||||
URL: u,
|
||||
Proto: "HTTP/1.1",
|
||||
ProtoMajor: 1,
|
||||
ProtoMinor: 1,
|
||||
Header: make(http.Header),
|
||||
Host: u.Host,
|
||||
}
|
||||
|
||||
// Set the cookies present in the cookie jar of the dialer
|
||||
if d.Jar != nil {
|
||||
for _, cookie := range d.Jar.Cookies(u) {
|
||||
req.AddCookie(cookie)
|
||||
}
|
||||
}
|
||||
|
||||
// Set the request headers using the capitalization for names and values in
|
||||
// RFC examples. Although the capitalization shouldn't matter, there are
|
||||
// servers that depend on it. The Header.Set method is not used because the
|
||||
// method canonicalizes the header names.
|
||||
req.Header["Upgrade"] = []string{"websocket"}
|
||||
req.Header["Connection"] = []string{"Upgrade"}
|
||||
req.Header["Sec-WebSocket-Key"] = []string{challengeKey}
|
||||
req.Header["Sec-WebSocket-Version"] = []string{"13"}
|
||||
if len(d.Subprotocols) > 0 {
|
||||
req.Header["Sec-WebSocket-Protocol"] = []string{strings.Join(d.Subprotocols, ", ")}
|
||||
}
|
||||
for k, vs := range requestHeader {
|
||||
switch {
|
||||
case k == "Host":
|
||||
if len(vs) > 0 {
|
||||
req.Host = vs[0]
|
||||
}
|
||||
case k == "Upgrade" ||
|
||||
k == "Connection" ||
|
||||
k == "Sec-Websocket-Key" ||
|
||||
k == "Sec-Websocket-Version" ||
|
||||
k == "Sec-Websocket-Extensions" ||
|
||||
(k == "Sec-Websocket-Protocol" && len(d.Subprotocols) > 0):
|
||||
return nil, nil, errors.New("websocket: duplicate header not allowed: " + k)
|
||||
case k == "Sec-Websocket-Protocol":
|
||||
req.Header["Sec-WebSocket-Protocol"] = vs
|
||||
default:
|
||||
req.Header[k] = vs
|
||||
}
|
||||
}
|
||||
|
||||
if d.EnableCompression {
|
||||
req.Header["Sec-WebSocket-Extensions"] = []string{"permessage-deflate; server_no_context_takeover; client_no_context_takeover"}
|
||||
}
|
||||
|
||||
var deadline time.Time
|
||||
if d.HandshakeTimeout != 0 {
|
||||
deadline = time.Now().Add(d.HandshakeTimeout)
|
||||
}
|
||||
|
||||
// Get network dial function.
|
||||
netDial := d.NetDial
|
||||
if netDial == nil {
|
||||
netDialer := &net.Dialer{Deadline: deadline}
|
||||
netDial = netDialer.Dial
|
||||
}
|
||||
|
||||
// If needed, wrap the dial function to set the connection deadline.
|
||||
if !deadline.Equal(time.Time{}) {
|
||||
forwardDial := netDial
|
||||
netDial = func(network, addr string) (net.Conn, error) {
|
||||
c, err := forwardDial(network, addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = c.SetDeadline(deadline)
|
||||
if err != nil {
|
||||
c.Close()
|
||||
return nil, err
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
}
|
||||
|
||||
// If needed, wrap the dial function to connect through a proxy.
|
||||
if d.Proxy != nil {
|
||||
proxyURL, err := d.Proxy(req)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if proxyURL != nil {
|
||||
dialer, err := proxy_FromURL(proxyURL, netDialerFunc(netDial))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
netDial = dialer.Dial
|
||||
}
|
||||
}
|
||||
|
||||
hostPort, hostNoPort := hostPortNoPort(u)
|
||||
netConn, err := netDial("tcp", hostPort)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if netConn != nil {
|
||||
netConn.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
if u.Scheme == "https" {
|
||||
cfg := cloneTLSConfig(d.TLSClientConfig)
|
||||
if cfg.ServerName == "" {
|
||||
cfg.ServerName = hostNoPort
|
||||
}
|
||||
tlsConn := tls.Client(netConn, cfg)
|
||||
netConn = tlsConn
|
||||
if err := tlsConn.Handshake(); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if !cfg.InsecureSkipVerify {
|
||||
if err := tlsConn.VerifyHostname(cfg.ServerName); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
conn := newConn(netConn, false, d.ReadBufferSize, d.WriteBufferSize)
|
||||
|
||||
if err := req.Write(netConn); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
resp, err := http.ReadResponse(conn.br, req)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if d.Jar != nil {
|
||||
if rc := resp.Cookies(); len(rc) > 0 {
|
||||
d.Jar.SetCookies(u, rc)
|
||||
}
|
||||
}
|
||||
|
||||
if resp.StatusCode != 101 ||
|
||||
!strings.EqualFold(resp.Header.Get("Upgrade"), "websocket") ||
|
||||
!strings.EqualFold(resp.Header.Get("Connection"), "upgrade") ||
|
||||
resp.Header.Get("Sec-Websocket-Accept") != computeAcceptKey(challengeKey) {
|
||||
// Before closing the network connection on return from this
|
||||
// function, slurp up some of the response to aid application
|
||||
// debugging.
|
||||
buf := make([]byte, 1024)
|
||||
n, _ := io.ReadFull(resp.Body, buf)
|
||||
resp.Body = ioutil.NopCloser(bytes.NewReader(buf[:n]))
|
||||
return nil, resp, ErrBadHandshake
|
||||
}
|
||||
|
||||
for _, ext := range parseExtensions(resp.Header) {
|
||||
if ext[""] != "permessage-deflate" {
|
||||
continue
|
||||
}
|
||||
_, snct := ext["server_no_context_takeover"]
|
||||
_, cnct := ext["client_no_context_takeover"]
|
||||
if !snct || !cnct {
|
||||
return nil, resp, errInvalidCompression
|
||||
}
|
||||
conn.newCompressionWriter = compressNoContextTakeover
|
||||
conn.newDecompressionReader = decompressNoContextTakeover
|
||||
break
|
||||
}
|
||||
|
||||
resp.Body = ioutil.NopCloser(bytes.NewReader([]byte{}))
|
||||
conn.subprotocol = resp.Header.Get("Sec-Websocket-Protocol")
|
||||
|
||||
netConn.SetDeadline(time.Time{})
|
||||
netConn = nil // to avoid close in defer.
|
||||
return conn, resp, nil
|
||||
}
|
16
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/client_clone.go
generated
vendored
Normal file
16
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/client_clone.go
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
// Copyright 2013 The Gorilla WebSocket Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build go1.8
|
||||
|
||||
package websocket
|
||||
|
||||
import "crypto/tls"
|
||||
|
||||
func cloneTLSConfig(cfg *tls.Config) *tls.Config {
|
||||
if cfg == nil {
|
||||
return &tls.Config{}
|
||||
}
|
||||
return cfg.Clone()
|
||||
}
|
38
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/client_clone_legacy.go
generated
vendored
Normal file
38
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/client_clone_legacy.go
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
// Copyright 2013 The Gorilla WebSocket Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !go1.8
|
||||
|
||||
package websocket
|
||||
|
||||
import "crypto/tls"
|
||||
|
||||
// cloneTLSConfig clones all public fields except the fields
|
||||
// SessionTicketsDisabled and SessionTicketKey. This avoids copying the
|
||||
// sync.Mutex in the sync.Once and makes it safe to call cloneTLSConfig on a
|
||||
// config in active use.
|
||||
func cloneTLSConfig(cfg *tls.Config) *tls.Config {
|
||||
if cfg == nil {
|
||||
return &tls.Config{}
|
||||
}
|
||||
return &tls.Config{
|
||||
Rand: cfg.Rand,
|
||||
Time: cfg.Time,
|
||||
Certificates: cfg.Certificates,
|
||||
NameToCertificate: cfg.NameToCertificate,
|
||||
GetCertificate: cfg.GetCertificate,
|
||||
RootCAs: cfg.RootCAs,
|
||||
NextProtos: cfg.NextProtos,
|
||||
ServerName: cfg.ServerName,
|
||||
ClientAuth: cfg.ClientAuth,
|
||||
ClientCAs: cfg.ClientCAs,
|
||||
InsecureSkipVerify: cfg.InsecureSkipVerify,
|
||||
CipherSuites: cfg.CipherSuites,
|
||||
PreferServerCipherSuites: cfg.PreferServerCipherSuites,
|
||||
ClientSessionCache: cfg.ClientSessionCache,
|
||||
MinVersion: cfg.MinVersion,
|
||||
MaxVersion: cfg.MaxVersion,
|
||||
CurvePreferences: cfg.CurvePreferences,
|
||||
}
|
||||
}
|
148
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/compression.go
generated
vendored
Normal file
148
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/compression.go
generated
vendored
Normal file
@@ -0,0 +1,148 @@
|
||||
// Copyright 2017 The Gorilla WebSocket Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package websocket
|
||||
|
||||
import (
|
||||
"compress/flate"
|
||||
"errors"
|
||||
"io"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
const (
|
||||
minCompressionLevel = -2 // flate.HuffmanOnly not defined in Go < 1.6
|
||||
maxCompressionLevel = flate.BestCompression
|
||||
defaultCompressionLevel = 1
|
||||
)
|
||||
|
||||
var (
|
||||
flateWriterPools [maxCompressionLevel - minCompressionLevel + 1]sync.Pool
|
||||
flateReaderPool = sync.Pool{New: func() interface{} {
|
||||
return flate.NewReader(nil)
|
||||
}}
|
||||
)
|
||||
|
||||
func decompressNoContextTakeover(r io.Reader) io.ReadCloser {
|
||||
const tail =
|
||||
// Add four bytes as specified in RFC
|
||||
"\x00\x00\xff\xff" +
|
||||
// Add final block to squelch unexpected EOF error from flate reader.
|
||||
"\x01\x00\x00\xff\xff"
|
||||
|
||||
fr, _ := flateReaderPool.Get().(io.ReadCloser)
|
||||
fr.(flate.Resetter).Reset(io.MultiReader(r, strings.NewReader(tail)), nil)
|
||||
return &flateReadWrapper{fr}
|
||||
}
|
||||
|
||||
func isValidCompressionLevel(level int) bool {
|
||||
return minCompressionLevel <= level && level <= maxCompressionLevel
|
||||
}
|
||||
|
||||
func compressNoContextTakeover(w io.WriteCloser, level int) io.WriteCloser {
|
||||
p := &flateWriterPools[level-minCompressionLevel]
|
||||
tw := &truncWriter{w: w}
|
||||
fw, _ := p.Get().(*flate.Writer)
|
||||
if fw == nil {
|
||||
fw, _ = flate.NewWriter(tw, level)
|
||||
} else {
|
||||
fw.Reset(tw)
|
||||
}
|
||||
return &flateWriteWrapper{fw: fw, tw: tw, p: p}
|
||||
}
|
||||
|
||||
// truncWriter is an io.Writer that writes all but the last four bytes of the
|
||||
// stream to another io.Writer.
|
||||
type truncWriter struct {
|
||||
w io.WriteCloser
|
||||
n int
|
||||
p [4]byte
|
||||
}
|
||||
|
||||
func (w *truncWriter) Write(p []byte) (int, error) {
|
||||
n := 0
|
||||
|
||||
// fill buffer first for simplicity.
|
||||
if w.n < len(w.p) {
|
||||
n = copy(w.p[w.n:], p)
|
||||
p = p[n:]
|
||||
w.n += n
|
||||
if len(p) == 0 {
|
||||
return n, nil
|
||||
}
|
||||
}
|
||||
|
||||
m := len(p)
|
||||
if m > len(w.p) {
|
||||
m = len(w.p)
|
||||
}
|
||||
|
||||
if nn, err := w.w.Write(w.p[:m]); err != nil {
|
||||
return n + nn, err
|
||||
}
|
||||
|
||||
copy(w.p[:], w.p[m:])
|
||||
copy(w.p[len(w.p)-m:], p[len(p)-m:])
|
||||
nn, err := w.w.Write(p[:len(p)-m])
|
||||
return n + nn, err
|
||||
}
|
||||
|
||||
type flateWriteWrapper struct {
|
||||
fw *flate.Writer
|
||||
tw *truncWriter
|
||||
p *sync.Pool
|
||||
}
|
||||
|
||||
func (w *flateWriteWrapper) Write(p []byte) (int, error) {
|
||||
if w.fw == nil {
|
||||
return 0, errWriteClosed
|
||||
}
|
||||
return w.fw.Write(p)
|
||||
}
|
||||
|
||||
func (w *flateWriteWrapper) Close() error {
|
||||
if w.fw == nil {
|
||||
return errWriteClosed
|
||||
}
|
||||
err1 := w.fw.Flush()
|
||||
w.p.Put(w.fw)
|
||||
w.fw = nil
|
||||
if w.tw.p != [4]byte{0, 0, 0xff, 0xff} {
|
||||
return errors.New("websocket: internal error, unexpected bytes at end of flate stream")
|
||||
}
|
||||
err2 := w.tw.w.Close()
|
||||
if err1 != nil {
|
||||
return err1
|
||||
}
|
||||
return err2
|
||||
}
|
||||
|
||||
type flateReadWrapper struct {
|
||||
fr io.ReadCloser
|
||||
}
|
||||
|
||||
func (r *flateReadWrapper) Read(p []byte) (int, error) {
|
||||
if r.fr == nil {
|
||||
return 0, io.ErrClosedPipe
|
||||
}
|
||||
n, err := r.fr.Read(p)
|
||||
if err == io.EOF {
|
||||
// Preemptively place the reader back in the pool. This helps with
|
||||
// scenarios where the application does not call NextReader() soon after
|
||||
// this final read.
|
||||
r.Close()
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (r *flateReadWrapper) Close() error {
|
||||
if r.fr == nil {
|
||||
return io.ErrClosedPipe
|
||||
}
|
||||
err := r.fr.Close()
|
||||
flateReaderPool.Put(r.fr)
|
||||
r.fr = nil
|
||||
return err
|
||||
}
|
1157
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/conn.go
generated
vendored
Normal file
1157
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/conn.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
18
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/conn_read.go
generated
vendored
Normal file
18
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/conn_read.go
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
// Copyright 2016 The Gorilla WebSocket Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build go1.5
|
||||
|
||||
package websocket
|
||||
|
||||
import "io"
|
||||
|
||||
func (c *Conn) read(n int) ([]byte, error) {
|
||||
p, err := c.br.Peek(n)
|
||||
if err == io.EOF {
|
||||
err = errUnexpectedEOF
|
||||
}
|
||||
c.br.Discard(len(p))
|
||||
return p, err
|
||||
}
|
21
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/conn_read_legacy.go
generated
vendored
Normal file
21
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/conn_read_legacy.go
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
// Copyright 2016 The Gorilla WebSocket Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !go1.5
|
||||
|
||||
package websocket
|
||||
|
||||
import "io"
|
||||
|
||||
func (c *Conn) read(n int) ([]byte, error) {
|
||||
p, err := c.br.Peek(n)
|
||||
if err == io.EOF {
|
||||
err = errUnexpectedEOF
|
||||
}
|
||||
if len(p) > 0 {
|
||||
// advance over the bytes just read
|
||||
io.ReadFull(c.br, p)
|
||||
}
|
||||
return p, err
|
||||
}
|
15
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/conn_write.go
generated
vendored
Normal file
15
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/conn_write.go
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
// Copyright 2016 The Gorilla WebSocket Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build go1.8
|
||||
|
||||
package websocket
|
||||
|
||||
import "net"
|
||||
|
||||
func (c *Conn) writeBufs(bufs ...[]byte) error {
|
||||
b := net.Buffers(bufs)
|
||||
_, err := b.WriteTo(c.conn)
|
||||
return err
|
||||
}
|
18
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/conn_write_legacy.go
generated
vendored
Normal file
18
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/conn_write_legacy.go
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
// Copyright 2016 The Gorilla WebSocket Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !go1.8
|
||||
|
||||
package websocket
|
||||
|
||||
func (c *Conn) writeBufs(bufs ...[]byte) error {
|
||||
for _, buf := range bufs {
|
||||
if len(buf) > 0 {
|
||||
if _, err := c.conn.Write(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
180
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/doc.go
generated
vendored
Normal file
180
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/doc.go
generated
vendored
Normal file
@@ -0,0 +1,180 @@
|
||||
// Copyright 2013 The Gorilla WebSocket Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package websocket implements the WebSocket protocol defined in RFC 6455.
|
||||
//
|
||||
// Overview
|
||||
//
|
||||
// The Conn type represents a WebSocket connection. A server application calls
|
||||
// the Upgrader.Upgrade method from an HTTP request handler to get a *Conn:
|
||||
//
|
||||
// var upgrader = websocket.Upgrader{
|
||||
// ReadBufferSize: 1024,
|
||||
// WriteBufferSize: 1024,
|
||||
// }
|
||||
//
|
||||
// func handler(w http.ResponseWriter, r *http.Request) {
|
||||
// conn, err := upgrader.Upgrade(w, r, nil)
|
||||
// if err != nil {
|
||||
// log.Println(err)
|
||||
// return
|
||||
// }
|
||||
// ... Use conn to send and receive messages.
|
||||
// }
|
||||
//
|
||||
// Call the connection's WriteMessage and ReadMessage methods to send and
|
||||
// receive messages as a slice of bytes. This snippet of code shows how to echo
|
||||
// messages using these methods:
|
||||
//
|
||||
// for {
|
||||
// messageType, p, err := conn.ReadMessage()
|
||||
// if err != nil {
|
||||
// log.Println(err)
|
||||
// return
|
||||
// }
|
||||
// if err := conn.WriteMessage(messageType, p); err != nil {
|
||||
// log.Println(err)
|
||||
// return
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// In above snippet of code, p is a []byte and messageType is an int with value
|
||||
// websocket.BinaryMessage or websocket.TextMessage.
|
||||
//
|
||||
// An application can also send and receive messages using the io.WriteCloser
|
||||
// and io.Reader interfaces. To send a message, call the connection NextWriter
|
||||
// method to get an io.WriteCloser, write the message to the writer and close
|
||||
// the writer when done. To receive a message, call the connection NextReader
|
||||
// method to get an io.Reader and read until io.EOF is returned. This snippet
|
||||
// shows how to echo messages using the NextWriter and NextReader methods:
|
||||
//
|
||||
// for {
|
||||
// messageType, r, err := conn.NextReader()
|
||||
// if err != nil {
|
||||
// return
|
||||
// }
|
||||
// w, err := conn.NextWriter(messageType)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// if _, err := io.Copy(w, r); err != nil {
|
||||
// return err
|
||||
// }
|
||||
// if err := w.Close(); err != nil {
|
||||
// return err
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Data Messages
|
||||
//
|
||||
// The WebSocket protocol distinguishes between text and binary data messages.
|
||||
// Text messages are interpreted as UTF-8 encoded text. The interpretation of
|
||||
// binary messages is left to the application.
|
||||
//
|
||||
// This package uses the TextMessage and BinaryMessage integer constants to
|
||||
// identify the two data message types. The ReadMessage and NextReader methods
|
||||
// return the type of the received message. The messageType argument to the
|
||||
// WriteMessage and NextWriter methods specifies the type of a sent message.
|
||||
//
|
||||
// It is the application's responsibility to ensure that text messages are
|
||||
// valid UTF-8 encoded text.
|
||||
//
|
||||
// Control Messages
|
||||
//
|
||||
// The WebSocket protocol defines three types of control messages: close, ping
|
||||
// and pong. Call the connection WriteControl, WriteMessage or NextWriter
|
||||
// methods to send a control message to the peer.
|
||||
//
|
||||
// Connections handle received close messages by calling the handler function
|
||||
// set with the SetCloseHandler method and by returning a *CloseError from the
|
||||
// NextReader, ReadMessage or the message Read method. The default close
|
||||
// handler sends a close message to the peer.
|
||||
//
|
||||
// Connections handle received ping messages by calling the handler function
|
||||
// set with the SetPingHandler method. The default ping handler sends a pong
|
||||
// message to the peer.
|
||||
//
|
||||
// Connections handle received pong messages by calling the handler function
|
||||
// set with the SetPongHandler method. The default pong handler does nothing.
|
||||
// If an application sends ping messages, then the application should set a
|
||||
// pong handler to receive the corresponding pong.
|
||||
//
|
||||
// The control message handler functions are called from the NextReader,
|
||||
// ReadMessage and message reader Read methods. The default close and ping
|
||||
// handlers can block these methods for a short time when the handler writes to
|
||||
// the connection.
|
||||
//
|
||||
// The application must read the connection to process close, ping and pong
|
||||
// messages sent from the peer. If the application is not otherwise interested
|
||||
// in messages from the peer, then the application should start a goroutine to
|
||||
// read and discard messages from the peer. A simple example is:
|
||||
//
|
||||
// func readLoop(c *websocket.Conn) {
|
||||
// for {
|
||||
// if _, _, err := c.NextReader(); err != nil {
|
||||
// c.Close()
|
||||
// break
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Concurrency
|
||||
//
|
||||
// Connections support one concurrent reader and one concurrent writer.
|
||||
//
|
||||
// Applications are responsible for ensuring that no more than one goroutine
|
||||
// calls the write methods (NextWriter, SetWriteDeadline, WriteMessage,
|
||||
// WriteJSON, EnableWriteCompression, SetCompressionLevel) concurrently and
|
||||
// that no more than one goroutine calls the read methods (NextReader,
|
||||
// SetReadDeadline, ReadMessage, ReadJSON, SetPongHandler, SetPingHandler)
|
||||
// concurrently.
|
||||
//
|
||||
// The Close and WriteControl methods can be called concurrently with all other
|
||||
// methods.
|
||||
//
|
||||
// Origin Considerations
|
||||
//
|
||||
// Web browsers allow Javascript applications to open a WebSocket connection to
|
||||
// any host. It's up to the server to enforce an origin policy using the Origin
|
||||
// request header sent by the browser.
|
||||
//
|
||||
// The Upgrader calls the function specified in the CheckOrigin field to check
|
||||
// the origin. If the CheckOrigin function returns false, then the Upgrade
|
||||
// method fails the WebSocket handshake with HTTP status 403.
|
||||
//
|
||||
// If the CheckOrigin field is nil, then the Upgrader uses a safe default: fail
|
||||
// the handshake if the Origin request header is present and the Origin host is
|
||||
// not equal to the Host request header.
|
||||
//
|
||||
// The deprecated package-level Upgrade function does not perform origin
|
||||
// checking. The application is responsible for checking the Origin header
|
||||
// before calling the Upgrade function.
|
||||
//
|
||||
// Compression EXPERIMENTAL
|
||||
//
|
||||
// Per message compression extensions (RFC 7692) are experimentally supported
|
||||
// by this package in a limited capacity. Setting the EnableCompression option
|
||||
// to true in Dialer or Upgrader will attempt to negotiate per message deflate
|
||||
// support.
|
||||
//
|
||||
// var upgrader = websocket.Upgrader{
|
||||
// EnableCompression: true,
|
||||
// }
|
||||
//
|
||||
// If compression was successfully negotiated with the connection's peer, any
|
||||
// message received in compressed form will be automatically decompressed.
|
||||
// All Read methods will return uncompressed bytes.
|
||||
//
|
||||
// Per message compression of messages written to a connection can be enabled
|
||||
// or disabled by calling the corresponding Conn method:
|
||||
//
|
||||
// conn.EnableWriteCompression(false)
|
||||
//
|
||||
// Currently this package does not support compression with "context takeover".
|
||||
// This means that messages must be compressed and decompressed in isolation,
|
||||
// without retaining sliding window or dictionary state across messages. For
|
||||
// more details refer to RFC 7692.
|
||||
//
|
||||
// Use of compression is experimental and may result in decreased performance.
|
||||
package websocket
|
60
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/json.go
generated
vendored
Normal file
60
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/json.go
generated
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
// Copyright 2013 The Gorilla WebSocket Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package websocket
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
)
|
||||
|
||||
// WriteJSON writes the JSON encoding of v as a message.
|
||||
//
|
||||
// Deprecated: Use c.WriteJSON instead.
|
||||
func WriteJSON(c *Conn, v interface{}) error {
|
||||
return c.WriteJSON(v)
|
||||
}
|
||||
|
||||
// WriteJSON writes the JSON encoding of v as a message.
|
||||
//
|
||||
// See the documentation for encoding/json Marshal for details about the
|
||||
// conversion of Go values to JSON.
|
||||
func (c *Conn) WriteJSON(v interface{}) error {
|
||||
w, err := c.NextWriter(TextMessage)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err1 := json.NewEncoder(w).Encode(v)
|
||||
err2 := w.Close()
|
||||
if err1 != nil {
|
||||
return err1
|
||||
}
|
||||
return err2
|
||||
}
|
||||
|
||||
// ReadJSON reads the next JSON-encoded message from the connection and stores
|
||||
// it in the value pointed to by v.
|
||||
//
|
||||
// Deprecated: Use c.ReadJSON instead.
|
||||
func ReadJSON(c *Conn, v interface{}) error {
|
||||
return c.ReadJSON(v)
|
||||
}
|
||||
|
||||
// ReadJSON reads the next JSON-encoded message from the connection and stores
|
||||
// it in the value pointed to by v.
|
||||
//
|
||||
// See the documentation for the encoding/json Unmarshal function for details
|
||||
// about the conversion of JSON to a Go value.
|
||||
func (c *Conn) ReadJSON(v interface{}) error {
|
||||
_, r, err := c.NextReader()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = json.NewDecoder(r).Decode(v)
|
||||
if err == io.EOF {
|
||||
// One value is expected in the message.
|
||||
err = io.ErrUnexpectedEOF
|
||||
}
|
||||
return err
|
||||
}
|
54
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/mask.go
generated
vendored
Normal file
54
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/mask.go
generated
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
// Copyright 2016 The Gorilla WebSocket Authors. All rights reserved. Use of
|
||||
// this source code is governed by a BSD-style license that can be found in the
|
||||
// LICENSE file.
|
||||
|
||||
// +build !appengine
|
||||
|
||||
package websocket
|
||||
|
||||
import "unsafe"
|
||||
|
||||
const wordSize = int(unsafe.Sizeof(uintptr(0)))
|
||||
|
||||
func maskBytes(key [4]byte, pos int, b []byte) int {
|
||||
// Mask one byte at a time for small buffers.
|
||||
if len(b) < 2*wordSize {
|
||||
for i := range b {
|
||||
b[i] ^= key[pos&3]
|
||||
pos++
|
||||
}
|
||||
return pos & 3
|
||||
}
|
||||
|
||||
// Mask one byte at a time to word boundary.
|
||||
if n := int(uintptr(unsafe.Pointer(&b[0]))) % wordSize; n != 0 {
|
||||
n = wordSize - n
|
||||
for i := range b[:n] {
|
||||
b[i] ^= key[pos&3]
|
||||
pos++
|
||||
}
|
||||
b = b[n:]
|
||||
}
|
||||
|
||||
// Create aligned word size key.
|
||||
var k [wordSize]byte
|
||||
for i := range k {
|
||||
k[i] = key[(pos+i)&3]
|
||||
}
|
||||
kw := *(*uintptr)(unsafe.Pointer(&k))
|
||||
|
||||
// Mask one word at a time.
|
||||
n := (len(b) / wordSize) * wordSize
|
||||
for i := 0; i < n; i += wordSize {
|
||||
*(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&b[0])) + uintptr(i))) ^= kw
|
||||
}
|
||||
|
||||
// Mask one byte at a time for remaining bytes.
|
||||
b = b[n:]
|
||||
for i := range b {
|
||||
b[i] ^= key[pos&3]
|
||||
pos++
|
||||
}
|
||||
|
||||
return pos & 3
|
||||
}
|
15
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/mask_safe.go
generated
vendored
Normal file
15
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/mask_safe.go
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
// Copyright 2016 The Gorilla WebSocket Authors. All rights reserved. Use of
|
||||
// this source code is governed by a BSD-style license that can be found in the
|
||||
// LICENSE file.
|
||||
|
||||
// +build appengine
|
||||
|
||||
package websocket
|
||||
|
||||
func maskBytes(key [4]byte, pos int, b []byte) int {
|
||||
for i := range b {
|
||||
b[i] ^= key[pos&3]
|
||||
pos++
|
||||
}
|
||||
return pos & 3
|
||||
}
|
103
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/prepared.go
generated
vendored
Normal file
103
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/prepared.go
generated
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
// Copyright 2017 The Gorilla WebSocket Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package websocket
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// PreparedMessage caches on the wire representations of a message payload.
|
||||
// Use PreparedMessage to efficiently send a message payload to multiple
|
||||
// connections. PreparedMessage is especially useful when compression is used
|
||||
// because the CPU and memory expensive compression operation can be executed
|
||||
// once for a given set of compression options.
|
||||
type PreparedMessage struct {
|
||||
messageType int
|
||||
data []byte
|
||||
err error
|
||||
mu sync.Mutex
|
||||
frames map[prepareKey]*preparedFrame
|
||||
}
|
||||
|
||||
// prepareKey defines a unique set of options to cache prepared frames in PreparedMessage.
|
||||
type prepareKey struct {
|
||||
isServer bool
|
||||
compress bool
|
||||
compressionLevel int
|
||||
}
|
||||
|
||||
// preparedFrame contains data in wire representation.
|
||||
type preparedFrame struct {
|
||||
once sync.Once
|
||||
data []byte
|
||||
}
|
||||
|
||||
// NewPreparedMessage returns an initialized PreparedMessage. You can then send
|
||||
// it to connection using WritePreparedMessage method. Valid wire
|
||||
// representation will be calculated lazily only once for a set of current
|
||||
// connection options.
|
||||
func NewPreparedMessage(messageType int, data []byte) (*PreparedMessage, error) {
|
||||
pm := &PreparedMessage{
|
||||
messageType: messageType,
|
||||
frames: make(map[prepareKey]*preparedFrame),
|
||||
data: data,
|
||||
}
|
||||
|
||||
// Prepare a plain server frame.
|
||||
_, frameData, err := pm.frame(prepareKey{isServer: true, compress: false})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// To protect against caller modifying the data argument, remember the data
|
||||
// copied to the plain server frame.
|
||||
pm.data = frameData[len(frameData)-len(data):]
|
||||
return pm, nil
|
||||
}
|
||||
|
||||
func (pm *PreparedMessage) frame(key prepareKey) (int, []byte, error) {
|
||||
pm.mu.Lock()
|
||||
frame, ok := pm.frames[key]
|
||||
if !ok {
|
||||
frame = &preparedFrame{}
|
||||
pm.frames[key] = frame
|
||||
}
|
||||
pm.mu.Unlock()
|
||||
|
||||
var err error
|
||||
frame.once.Do(func() {
|
||||
// Prepare a frame using a 'fake' connection.
|
||||
// TODO: Refactor code in conn.go to allow more direct construction of
|
||||
// the frame.
|
||||
mu := make(chan bool, 1)
|
||||
mu <- true
|
||||
var nc prepareConn
|
||||
c := &Conn{
|
||||
conn: &nc,
|
||||
mu: mu,
|
||||
isServer: key.isServer,
|
||||
compressionLevel: key.compressionLevel,
|
||||
enableWriteCompression: true,
|
||||
writeBuf: make([]byte, defaultWriteBufferSize+maxFrameHeaderSize),
|
||||
}
|
||||
if key.compress {
|
||||
c.newCompressionWriter = compressNoContextTakeover
|
||||
}
|
||||
err = c.WriteMessage(pm.messageType, pm.data)
|
||||
frame.data = nc.buf.Bytes()
|
||||
})
|
||||
return pm.messageType, frame.data, err
|
||||
}
|
||||
|
||||
type prepareConn struct {
|
||||
buf bytes.Buffer
|
||||
net.Conn
|
||||
}
|
||||
|
||||
func (pc *prepareConn) Write(p []byte) (int, error) { return pc.buf.Write(p) }
|
||||
func (pc *prepareConn) SetWriteDeadline(t time.Time) error { return nil }
|
77
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/proxy.go
generated
vendored
Normal file
77
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/proxy.go
generated
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
// Copyright 2017 The Gorilla WebSocket Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package websocket
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type netDialerFunc func(network, addr string) (net.Conn, error)
|
||||
|
||||
func (fn netDialerFunc) Dial(network, addr string) (net.Conn, error) {
|
||||
return fn(network, addr)
|
||||
}
|
||||
|
||||
func init() {
|
||||
proxy_RegisterDialerType("http", func(proxyURL *url.URL, forwardDialer proxy_Dialer) (proxy_Dialer, error) {
|
||||
return &httpProxyDialer{proxyURL: proxyURL, fowardDial: forwardDialer.Dial}, nil
|
||||
})
|
||||
}
|
||||
|
||||
type httpProxyDialer struct {
|
||||
proxyURL *url.URL
|
||||
fowardDial func(network, addr string) (net.Conn, error)
|
||||
}
|
||||
|
||||
func (hpd *httpProxyDialer) Dial(network string, addr string) (net.Conn, error) {
|
||||
hostPort, _ := hostPortNoPort(hpd.proxyURL)
|
||||
conn, err := hpd.fowardDial(network, hostPort)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
connectHeader := make(http.Header)
|
||||
if user := hpd.proxyURL.User; user != nil {
|
||||
proxyUser := user.Username()
|
||||
if proxyPassword, passwordSet := user.Password(); passwordSet {
|
||||
credential := base64.StdEncoding.EncodeToString([]byte(proxyUser + ":" + proxyPassword))
|
||||
connectHeader.Set("Proxy-Authorization", "Basic "+credential)
|
||||
}
|
||||
}
|
||||
|
||||
connectReq := &http.Request{
|
||||
Method: "CONNECT",
|
||||
URL: &url.URL{Opaque: addr},
|
||||
Host: addr,
|
||||
Header: connectHeader,
|
||||
}
|
||||
|
||||
if err := connectReq.Write(conn); err != nil {
|
||||
conn.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Read response. It's OK to use and discard buffered reader here becaue
|
||||
// the remote server does not speak until spoken to.
|
||||
br := bufio.NewReader(conn)
|
||||
resp, err := http.ReadResponse(br, connectReq)
|
||||
if err != nil {
|
||||
conn.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if resp.StatusCode != 200 {
|
||||
conn.Close()
|
||||
f := strings.SplitN(resp.Status, " ", 2)
|
||||
return nil, errors.New(f[1])
|
||||
}
|
||||
return conn, nil
|
||||
}
|
298
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/server.go
generated
vendored
Normal file
298
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/server.go
generated
vendored
Normal file
@@ -0,0 +1,298 @@
|
||||
// Copyright 2013 The Gorilla WebSocket Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package websocket
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// HandshakeError describes an error with the handshake from the peer.
|
||||
type HandshakeError struct {
|
||||
message string
|
||||
}
|
||||
|
||||
func (e HandshakeError) Error() string { return e.message }
|
||||
|
||||
// Upgrader specifies parameters for upgrading an HTTP connection to a
|
||||
// WebSocket connection.
|
||||
type Upgrader struct {
|
||||
// HandshakeTimeout specifies the duration for the handshake to complete.
|
||||
HandshakeTimeout time.Duration
|
||||
|
||||
// ReadBufferSize and WriteBufferSize specify I/O buffer sizes. If a buffer
|
||||
// size is zero, then buffers allocated by the HTTP server are used. The
|
||||
// I/O buffer sizes do not limit the size of the messages that can be sent
|
||||
// or received.
|
||||
ReadBufferSize, WriteBufferSize int
|
||||
|
||||
// Subprotocols specifies the server's supported protocols in order of
|
||||
// preference. If this field is set, then the Upgrade method negotiates a
|
||||
// subprotocol by selecting the first match in this list with a protocol
|
||||
// requested by the client.
|
||||
Subprotocols []string
|
||||
|
||||
// Error specifies the function for generating HTTP error responses. If Error
|
||||
// is nil, then http.Error is used to generate the HTTP response.
|
||||
Error func(w http.ResponseWriter, r *http.Request, status int, reason error)
|
||||
|
||||
// CheckOrigin returns true if the request Origin header is acceptable. If
|
||||
// CheckOrigin is nil, then a safe default is used: return false if the
|
||||
// Origin request header is present and the origin host is not equal to
|
||||
// request Host header.
|
||||
//
|
||||
// A CheckOrigin function should carefully validate the request origin to
|
||||
// prevent cross-site request forgery.
|
||||
CheckOrigin func(r *http.Request) bool
|
||||
|
||||
// EnableCompression specify if the server should attempt to negotiate per
|
||||
// message compression (RFC 7692). Setting this value to true does not
|
||||
// guarantee that compression will be supported. Currently only "no context
|
||||
// takeover" modes are supported.
|
||||
EnableCompression bool
|
||||
}
|
||||
|
||||
func (u *Upgrader) returnError(w http.ResponseWriter, r *http.Request, status int, reason string) (*Conn, error) {
|
||||
err := HandshakeError{reason}
|
||||
if u.Error != nil {
|
||||
u.Error(w, r, status, err)
|
||||
} else {
|
||||
w.Header().Set("Sec-Websocket-Version", "13")
|
||||
http.Error(w, http.StatusText(status), status)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// checkSameOrigin returns true if the origin is not set or is equal to the request host.
|
||||
func checkSameOrigin(r *http.Request) bool {
|
||||
origin := r.Header["Origin"]
|
||||
if len(origin) == 0 {
|
||||
return true
|
||||
}
|
||||
u, err := url.Parse(origin[0])
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return equalASCIIFold(u.Host, r.Host)
|
||||
}
|
||||
|
||||
func (u *Upgrader) selectSubprotocol(r *http.Request, responseHeader http.Header) string {
|
||||
if u.Subprotocols != nil {
|
||||
clientProtocols := Subprotocols(r)
|
||||
for _, serverProtocol := range u.Subprotocols {
|
||||
for _, clientProtocol := range clientProtocols {
|
||||
if clientProtocol == serverProtocol {
|
||||
return clientProtocol
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if responseHeader != nil {
|
||||
return responseHeader.Get("Sec-Websocket-Protocol")
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// Upgrade upgrades the HTTP server connection to the WebSocket protocol.
|
||||
//
|
||||
// The responseHeader is included in the response to the client's upgrade
|
||||
// request. Use the responseHeader to specify cookies (Set-Cookie) and the
|
||||
// application negotiated subprotocol (Sec-WebSocket-Protocol).
|
||||
//
|
||||
// If the upgrade fails, then Upgrade replies to the client with an HTTP error
|
||||
// response.
|
||||
func (u *Upgrader) Upgrade(w http.ResponseWriter, r *http.Request, responseHeader http.Header) (*Conn, error) {
|
||||
const badHandshake = "websocket: the client is not using the websocket protocol: "
|
||||
|
||||
if !tokenListContainsValue(r.Header, "Connection", "upgrade") {
|
||||
return u.returnError(w, r, http.StatusBadRequest, badHandshake+"'upgrade' token not found in 'Connection' header")
|
||||
}
|
||||
|
||||
if !tokenListContainsValue(r.Header, "Upgrade", "websocket") {
|
||||
return u.returnError(w, r, http.StatusBadRequest, badHandshake+"'websocket' token not found in 'Upgrade' header")
|
||||
}
|
||||
|
||||
if r.Method != "GET" {
|
||||
return u.returnError(w, r, http.StatusMethodNotAllowed, badHandshake+"request method is not GET")
|
||||
}
|
||||
|
||||
if !tokenListContainsValue(r.Header, "Sec-Websocket-Version", "13") {
|
||||
return u.returnError(w, r, http.StatusBadRequest, "websocket: unsupported version: 13 not found in 'Sec-Websocket-Version' header")
|
||||
}
|
||||
|
||||
if _, ok := responseHeader["Sec-Websocket-Extensions"]; ok {
|
||||
return u.returnError(w, r, http.StatusInternalServerError, "websocket: application specific 'Sec-WebSocket-Extensions' headers are unsupported")
|
||||
}
|
||||
|
||||
checkOrigin := u.CheckOrigin
|
||||
if checkOrigin == nil {
|
||||
checkOrigin = checkSameOrigin
|
||||
}
|
||||
if !checkOrigin(r) {
|
||||
return u.returnError(w, r, http.StatusForbidden, "websocket: request origin not allowed by Upgrader.CheckOrigin")
|
||||
}
|
||||
|
||||
challengeKey := r.Header.Get("Sec-Websocket-Key")
|
||||
if challengeKey == "" {
|
||||
return u.returnError(w, r, http.StatusBadRequest, "websocket: not a websocket handshake: `Sec-WebSocket-Key' header is missing or blank")
|
||||
}
|
||||
|
||||
subprotocol := u.selectSubprotocol(r, responseHeader)
|
||||
|
||||
// Negotiate PMCE
|
||||
var compress bool
|
||||
if u.EnableCompression {
|
||||
for _, ext := range parseExtensions(r.Header) {
|
||||
if ext[""] != "permessage-deflate" {
|
||||
continue
|
||||
}
|
||||
compress = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
netConn net.Conn
|
||||
err error
|
||||
)
|
||||
|
||||
h, ok := w.(http.Hijacker)
|
||||
if !ok {
|
||||
return u.returnError(w, r, http.StatusInternalServerError, "websocket: response does not implement http.Hijacker")
|
||||
}
|
||||
var brw *bufio.ReadWriter
|
||||
netConn, brw, err = h.Hijack()
|
||||
if err != nil {
|
||||
return u.returnError(w, r, http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
if brw.Reader.Buffered() > 0 {
|
||||
netConn.Close()
|
||||
return nil, errors.New("websocket: client sent data before handshake is complete")
|
||||
}
|
||||
|
||||
c := newConnBRW(netConn, true, u.ReadBufferSize, u.WriteBufferSize, brw)
|
||||
c.subprotocol = subprotocol
|
||||
|
||||
if compress {
|
||||
c.newCompressionWriter = compressNoContextTakeover
|
||||
c.newDecompressionReader = decompressNoContextTakeover
|
||||
}
|
||||
|
||||
p := c.writeBuf[:0]
|
||||
p = append(p, "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: "...)
|
||||
p = append(p, computeAcceptKey(challengeKey)...)
|
||||
p = append(p, "\r\n"...)
|
||||
if c.subprotocol != "" {
|
||||
p = append(p, "Sec-WebSocket-Protocol: "...)
|
||||
p = append(p, c.subprotocol...)
|
||||
p = append(p, "\r\n"...)
|
||||
}
|
||||
if compress {
|
||||
p = append(p, "Sec-WebSocket-Extensions: permessage-deflate; server_no_context_takeover; client_no_context_takeover\r\n"...)
|
||||
}
|
||||
for k, vs := range responseHeader {
|
||||
if k == "Sec-Websocket-Protocol" {
|
||||
continue
|
||||
}
|
||||
for _, v := range vs {
|
||||
p = append(p, k...)
|
||||
p = append(p, ": "...)
|
||||
for i := 0; i < len(v); i++ {
|
||||
b := v[i]
|
||||
if b <= 31 {
|
||||
// prevent response splitting.
|
||||
b = ' '
|
||||
}
|
||||
p = append(p, b)
|
||||
}
|
||||
p = append(p, "\r\n"...)
|
||||
}
|
||||
}
|
||||
p = append(p, "\r\n"...)
|
||||
|
||||
// Clear deadlines set by HTTP server.
|
||||
netConn.SetDeadline(time.Time{})
|
||||
|
||||
if u.HandshakeTimeout > 0 {
|
||||
netConn.SetWriteDeadline(time.Now().Add(u.HandshakeTimeout))
|
||||
}
|
||||
if _, err = netConn.Write(p); err != nil {
|
||||
netConn.Close()
|
||||
return nil, err
|
||||
}
|
||||
if u.HandshakeTimeout > 0 {
|
||||
netConn.SetWriteDeadline(time.Time{})
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// Upgrade upgrades the HTTP server connection to the WebSocket protocol.
|
||||
//
|
||||
// Deprecated: Use websocket.Upgrader instead.
|
||||
//
|
||||
// Upgrade does not perform origin checking. The application is responsible for
|
||||
// checking the Origin header before calling Upgrade. An example implementation
|
||||
// of the same origin policy check is:
|
||||
//
|
||||
// if req.Header.Get("Origin") != "http://"+req.Host {
|
||||
// http.Error(w, "Origin not allowed", http.StatusForbidden)
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// If the endpoint supports subprotocols, then the application is responsible
|
||||
// for negotiating the protocol used on the connection. Use the Subprotocols()
|
||||
// function to get the subprotocols requested by the client. Use the
|
||||
// Sec-Websocket-Protocol response header to specify the subprotocol selected
|
||||
// by the application.
|
||||
//
|
||||
// The responseHeader is included in the response to the client's upgrade
|
||||
// request. Use the responseHeader to specify cookies (Set-Cookie) and the
|
||||
// negotiated subprotocol (Sec-Websocket-Protocol).
|
||||
//
|
||||
// The connection buffers IO to the underlying network connection. The
|
||||
// readBufSize and writeBufSize parameters specify the size of the buffers to
|
||||
// use. Messages can be larger than the buffers.
|
||||
//
|
||||
// If the request is not a valid WebSocket handshake, then Upgrade returns an
|
||||
// error of type HandshakeError. Applications should handle this error by
|
||||
// replying to the client with an HTTP error response.
|
||||
func Upgrade(w http.ResponseWriter, r *http.Request, responseHeader http.Header, readBufSize, writeBufSize int) (*Conn, error) {
|
||||
u := Upgrader{ReadBufferSize: readBufSize, WriteBufferSize: writeBufSize}
|
||||
u.Error = func(w http.ResponseWriter, r *http.Request, status int, reason error) {
|
||||
// don't return errors to maintain backwards compatibility
|
||||
}
|
||||
u.CheckOrigin = func(r *http.Request) bool {
|
||||
// allow all connections by default
|
||||
return true
|
||||
}
|
||||
return u.Upgrade(w, r, responseHeader)
|
||||
}
|
||||
|
||||
// Subprotocols returns the subprotocols requested by the client in the
|
||||
// Sec-Websocket-Protocol header.
|
||||
func Subprotocols(r *http.Request) []string {
|
||||
h := strings.TrimSpace(r.Header.Get("Sec-Websocket-Protocol"))
|
||||
if h == "" {
|
||||
return nil
|
||||
}
|
||||
protocols := strings.Split(h, ",")
|
||||
for i := range protocols {
|
||||
protocols[i] = strings.TrimSpace(protocols[i])
|
||||
}
|
||||
return protocols
|
||||
}
|
||||
|
||||
// IsWebSocketUpgrade returns true if the client requested upgrade to the
|
||||
// WebSocket protocol.
|
||||
func IsWebSocketUpgrade(r *http.Request) bool {
|
||||
return tokenListContainsValue(r.Header, "Connection", "upgrade") &&
|
||||
tokenListContainsValue(r.Header, "Upgrade", "websocket")
|
||||
}
|
237
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/util.go
generated
vendored
Normal file
237
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/util.go
generated
vendored
Normal file
@@ -0,0 +1,237 @@
|
||||
// Copyright 2013 The Gorilla WebSocket Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package websocket
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/sha1"
|
||||
"encoding/base64"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
var keyGUID = []byte("258EAFA5-E914-47DA-95CA-C5AB0DC85B11")
|
||||
|
||||
func computeAcceptKey(challengeKey string) string {
|
||||
h := sha1.New()
|
||||
h.Write([]byte(challengeKey))
|
||||
h.Write(keyGUID)
|
||||
return base64.StdEncoding.EncodeToString(h.Sum(nil))
|
||||
}
|
||||
|
||||
func generateChallengeKey() (string, error) {
|
||||
p := make([]byte, 16)
|
||||
if _, err := io.ReadFull(rand.Reader, p); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return base64.StdEncoding.EncodeToString(p), nil
|
||||
}
|
||||
|
||||
// Octet types from RFC 2616.
|
||||
var octetTypes [256]byte
|
||||
|
||||
const (
|
||||
isTokenOctet = 1 << iota
|
||||
isSpaceOctet
|
||||
)
|
||||
|
||||
func init() {
|
||||
// From RFC 2616
|
||||
//
|
||||
// OCTET = <any 8-bit sequence of data>
|
||||
// CHAR = <any US-ASCII character (octets 0 - 127)>
|
||||
// CTL = <any US-ASCII control character (octets 0 - 31) and DEL (127)>
|
||||
// CR = <US-ASCII CR, carriage return (13)>
|
||||
// LF = <US-ASCII LF, linefeed (10)>
|
||||
// SP = <US-ASCII SP, space (32)>
|
||||
// HT = <US-ASCII HT, horizontal-tab (9)>
|
||||
// <"> = <US-ASCII double-quote mark (34)>
|
||||
// CRLF = CR LF
|
||||
// LWS = [CRLF] 1*( SP | HT )
|
||||
// TEXT = <any OCTET except CTLs, but including LWS>
|
||||
// separators = "(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\" | <">
|
||||
// | "/" | "[" | "]" | "?" | "=" | "{" | "}" | SP | HT
|
||||
// token = 1*<any CHAR except CTLs or separators>
|
||||
// qdtext = <any TEXT except <">>
|
||||
|
||||
for c := 0; c < 256; c++ {
|
||||
var t byte
|
||||
isCtl := c <= 31 || c == 127
|
||||
isChar := 0 <= c && c <= 127
|
||||
isSeparator := strings.IndexRune(" \t\"(),/:;<=>?@[]\\{}", rune(c)) >= 0
|
||||
if strings.IndexRune(" \t\r\n", rune(c)) >= 0 {
|
||||
t |= isSpaceOctet
|
||||
}
|
||||
if isChar && !isCtl && !isSeparator {
|
||||
t |= isTokenOctet
|
||||
}
|
||||
octetTypes[c] = t
|
||||
}
|
||||
}
|
||||
|
||||
func skipSpace(s string) (rest string) {
|
||||
i := 0
|
||||
for ; i < len(s); i++ {
|
||||
if octetTypes[s[i]]&isSpaceOctet == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return s[i:]
|
||||
}
|
||||
|
||||
func nextToken(s string) (token, rest string) {
|
||||
i := 0
|
||||
for ; i < len(s); i++ {
|
||||
if octetTypes[s[i]]&isTokenOctet == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return s[:i], s[i:]
|
||||
}
|
||||
|
||||
func nextTokenOrQuoted(s string) (value string, rest string) {
|
||||
if !strings.HasPrefix(s, "\"") {
|
||||
return nextToken(s)
|
||||
}
|
||||
s = s[1:]
|
||||
for i := 0; i < len(s); i++ {
|
||||
switch s[i] {
|
||||
case '"':
|
||||
return s[:i], s[i+1:]
|
||||
case '\\':
|
||||
p := make([]byte, len(s)-1)
|
||||
j := copy(p, s[:i])
|
||||
escape := true
|
||||
for i = i + 1; i < len(s); i++ {
|
||||
b := s[i]
|
||||
switch {
|
||||
case escape:
|
||||
escape = false
|
||||
p[j] = b
|
||||
j++
|
||||
case b == '\\':
|
||||
escape = true
|
||||
case b == '"':
|
||||
return string(p[:j]), s[i+1:]
|
||||
default:
|
||||
p[j] = b
|
||||
j++
|
||||
}
|
||||
}
|
||||
return "", ""
|
||||
}
|
||||
}
|
||||
return "", ""
|
||||
}
|
||||
|
||||
// equalASCIIFold returns true if s is equal to t with ASCII case folding.
|
||||
func equalASCIIFold(s, t string) bool {
|
||||
for s != "" && t != "" {
|
||||
sr, size := utf8.DecodeRuneInString(s)
|
||||
s = s[size:]
|
||||
tr, size := utf8.DecodeRuneInString(t)
|
||||
t = t[size:]
|
||||
if sr == tr {
|
||||
continue
|
||||
}
|
||||
if 'A' <= sr && sr <= 'Z' {
|
||||
sr = sr + 'a' - 'A'
|
||||
}
|
||||
if 'A' <= tr && tr <= 'Z' {
|
||||
tr = tr + 'a' - 'A'
|
||||
}
|
||||
if sr != tr {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return s == t
|
||||
}
|
||||
|
||||
// tokenListContainsValue returns true if the 1#token header with the given
|
||||
// name contains a token equal to value with ASCII case folding.
|
||||
func tokenListContainsValue(header http.Header, name string, value string) bool {
|
||||
headers:
|
||||
for _, s := range header[name] {
|
||||
for {
|
||||
var t string
|
||||
t, s = nextToken(skipSpace(s))
|
||||
if t == "" {
|
||||
continue headers
|
||||
}
|
||||
s = skipSpace(s)
|
||||
if s != "" && s[0] != ',' {
|
||||
continue headers
|
||||
}
|
||||
if equalASCIIFold(t, value) {
|
||||
return true
|
||||
}
|
||||
if s == "" {
|
||||
continue headers
|
||||
}
|
||||
s = s[1:]
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// parseExtensiosn parses WebSocket extensions from a header.
|
||||
func parseExtensions(header http.Header) []map[string]string {
|
||||
// From RFC 6455:
|
||||
//
|
||||
// Sec-WebSocket-Extensions = extension-list
|
||||
// extension-list = 1#extension
|
||||
// extension = extension-token *( ";" extension-param )
|
||||
// extension-token = registered-token
|
||||
// registered-token = token
|
||||
// extension-param = token [ "=" (token | quoted-string) ]
|
||||
// ;When using the quoted-string syntax variant, the value
|
||||
// ;after quoted-string unescaping MUST conform to the
|
||||
// ;'token' ABNF.
|
||||
|
||||
var result []map[string]string
|
||||
headers:
|
||||
for _, s := range header["Sec-Websocket-Extensions"] {
|
||||
for {
|
||||
var t string
|
||||
t, s = nextToken(skipSpace(s))
|
||||
if t == "" {
|
||||
continue headers
|
||||
}
|
||||
ext := map[string]string{"": t}
|
||||
for {
|
||||
s = skipSpace(s)
|
||||
if !strings.HasPrefix(s, ";") {
|
||||
break
|
||||
}
|
||||
var k string
|
||||
k, s = nextToken(skipSpace(s[1:]))
|
||||
if k == "" {
|
||||
continue headers
|
||||
}
|
||||
s = skipSpace(s)
|
||||
var v string
|
||||
if strings.HasPrefix(s, "=") {
|
||||
v, s = nextTokenOrQuoted(skipSpace(s[1:]))
|
||||
s = skipSpace(s)
|
||||
}
|
||||
if s != "" && s[0] != ',' && s[0] != ';' {
|
||||
continue headers
|
||||
}
|
||||
ext[k] = v
|
||||
}
|
||||
if s != "" && s[0] != ',' {
|
||||
continue headers
|
||||
}
|
||||
result = append(result, ext)
|
||||
if s == "" {
|
||||
continue headers
|
||||
}
|
||||
s = s[1:]
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
473
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/x_net_proxy.go
generated
vendored
Normal file
473
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/x_net_proxy.go
generated
vendored
Normal file
@@ -0,0 +1,473 @@
|
||||
// Code generated by golang.org/x/tools/cmd/bundle. DO NOT EDIT.
|
||||
//go:generate bundle -o x_net_proxy.go golang.org/x/net/proxy
|
||||
|
||||
// Package proxy provides support for a variety of protocols to proxy network
|
||||
// data.
|
||||
//
|
||||
|
||||
package websocket
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"net"
|
||||
"net/url"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type proxy_direct struct{}
|
||||
|
||||
// Direct is a direct proxy: one that makes network connections directly.
|
||||
var proxy_Direct = proxy_direct{}
|
||||
|
||||
func (proxy_direct) Dial(network, addr string) (net.Conn, error) {
|
||||
return net.Dial(network, addr)
|
||||
}
|
||||
|
||||
// A PerHost directs connections to a default Dialer unless the host name
|
||||
// requested matches one of a number of exceptions.
|
||||
type proxy_PerHost struct {
|
||||
def, bypass proxy_Dialer
|
||||
|
||||
bypassNetworks []*net.IPNet
|
||||
bypassIPs []net.IP
|
||||
bypassZones []string
|
||||
bypassHosts []string
|
||||
}
|
||||
|
||||
// NewPerHost returns a PerHost Dialer that directs connections to either
|
||||
// defaultDialer or bypass, depending on whether the connection matches one of
|
||||
// the configured rules.
|
||||
func proxy_NewPerHost(defaultDialer, bypass proxy_Dialer) *proxy_PerHost {
|
||||
return &proxy_PerHost{
|
||||
def: defaultDialer,
|
||||
bypass: bypass,
|
||||
}
|
||||
}
|
||||
|
||||
// Dial connects to the address addr on the given network through either
|
||||
// defaultDialer or bypass.
|
||||
func (p *proxy_PerHost) Dial(network, addr string) (c net.Conn, err error) {
|
||||
host, _, err := net.SplitHostPort(addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return p.dialerForRequest(host).Dial(network, addr)
|
||||
}
|
||||
|
||||
func (p *proxy_PerHost) dialerForRequest(host string) proxy_Dialer {
|
||||
if ip := net.ParseIP(host); ip != nil {
|
||||
for _, net := range p.bypassNetworks {
|
||||
if net.Contains(ip) {
|
||||
return p.bypass
|
||||
}
|
||||
}
|
||||
for _, bypassIP := range p.bypassIPs {
|
||||
if bypassIP.Equal(ip) {
|
||||
return p.bypass
|
||||
}
|
||||
}
|
||||
return p.def
|
||||
}
|
||||
|
||||
for _, zone := range p.bypassZones {
|
||||
if strings.HasSuffix(host, zone) {
|
||||
return p.bypass
|
||||
}
|
||||
if host == zone[1:] {
|
||||
// For a zone ".example.com", we match "example.com"
|
||||
// too.
|
||||
return p.bypass
|
||||
}
|
||||
}
|
||||
for _, bypassHost := range p.bypassHosts {
|
||||
if bypassHost == host {
|
||||
return p.bypass
|
||||
}
|
||||
}
|
||||
return p.def
|
||||
}
|
||||
|
||||
// AddFromString parses a string that contains comma-separated values
|
||||
// specifying hosts that should use the bypass proxy. Each value is either an
|
||||
// IP address, a CIDR range, a zone (*.example.com) or a host name
|
||||
// (localhost). A best effort is made to parse the string and errors are
|
||||
// ignored.
|
||||
func (p *proxy_PerHost) AddFromString(s string) {
|
||||
hosts := strings.Split(s, ",")
|
||||
for _, host := range hosts {
|
||||
host = strings.TrimSpace(host)
|
||||
if len(host) == 0 {
|
||||
continue
|
||||
}
|
||||
if strings.Contains(host, "/") {
|
||||
// We assume that it's a CIDR address like 127.0.0.0/8
|
||||
if _, net, err := net.ParseCIDR(host); err == nil {
|
||||
p.AddNetwork(net)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if ip := net.ParseIP(host); ip != nil {
|
||||
p.AddIP(ip)
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(host, "*.") {
|
||||
p.AddZone(host[1:])
|
||||
continue
|
||||
}
|
||||
p.AddHost(host)
|
||||
}
|
||||
}
|
||||
|
||||
// AddIP specifies an IP address that will use the bypass proxy. Note that
|
||||
// this will only take effect if a literal IP address is dialed. A connection
|
||||
// to a named host will never match an IP.
|
||||
func (p *proxy_PerHost) AddIP(ip net.IP) {
|
||||
p.bypassIPs = append(p.bypassIPs, ip)
|
||||
}
|
||||
|
||||
// AddNetwork specifies an IP range that will use the bypass proxy. Note that
|
||||
// this will only take effect if a literal IP address is dialed. A connection
|
||||
// to a named host will never match.
|
||||
func (p *proxy_PerHost) AddNetwork(net *net.IPNet) {
|
||||
p.bypassNetworks = append(p.bypassNetworks, net)
|
||||
}
|
||||
|
||||
// AddZone specifies a DNS suffix that will use the bypass proxy. A zone of
|
||||
// "example.com" matches "example.com" and all of its subdomains.
|
||||
func (p *proxy_PerHost) AddZone(zone string) {
|
||||
if strings.HasSuffix(zone, ".") {
|
||||
zone = zone[:len(zone)-1]
|
||||
}
|
||||
if !strings.HasPrefix(zone, ".") {
|
||||
zone = "." + zone
|
||||
}
|
||||
p.bypassZones = append(p.bypassZones, zone)
|
||||
}
|
||||
|
||||
// AddHost specifies a host name that will use the bypass proxy.
|
||||
func (p *proxy_PerHost) AddHost(host string) {
|
||||
if strings.HasSuffix(host, ".") {
|
||||
host = host[:len(host)-1]
|
||||
}
|
||||
p.bypassHosts = append(p.bypassHosts, host)
|
||||
}
|
||||
|
||||
// A Dialer is a means to establish a connection.
|
||||
type proxy_Dialer interface {
|
||||
// Dial connects to the given address via the proxy.
|
||||
Dial(network, addr string) (c net.Conn, err error)
|
||||
}
|
||||
|
||||
// Auth contains authentication parameters that specific Dialers may require.
|
||||
type proxy_Auth struct {
|
||||
User, Password string
|
||||
}
|
||||
|
||||
// FromEnvironment returns the dialer specified by the proxy related variables in
|
||||
// the environment.
|
||||
func proxy_FromEnvironment() proxy_Dialer {
|
||||
allProxy := proxy_allProxyEnv.Get()
|
||||
if len(allProxy) == 0 {
|
||||
return proxy_Direct
|
||||
}
|
||||
|
||||
proxyURL, err := url.Parse(allProxy)
|
||||
if err != nil {
|
||||
return proxy_Direct
|
||||
}
|
||||
proxy, err := proxy_FromURL(proxyURL, proxy_Direct)
|
||||
if err != nil {
|
||||
return proxy_Direct
|
||||
}
|
||||
|
||||
noProxy := proxy_noProxyEnv.Get()
|
||||
if len(noProxy) == 0 {
|
||||
return proxy
|
||||
}
|
||||
|
||||
perHost := proxy_NewPerHost(proxy, proxy_Direct)
|
||||
perHost.AddFromString(noProxy)
|
||||
return perHost
|
||||
}
|
||||
|
||||
// proxySchemes is a map from URL schemes to a function that creates a Dialer
|
||||
// from a URL with such a scheme.
|
||||
var proxy_proxySchemes map[string]func(*url.URL, proxy_Dialer) (proxy_Dialer, error)
|
||||
|
||||
// RegisterDialerType takes a URL scheme and a function to generate Dialers from
|
||||
// a URL with that scheme and a forwarding Dialer. Registered schemes are used
|
||||
// by FromURL.
|
||||
func proxy_RegisterDialerType(scheme string, f func(*url.URL, proxy_Dialer) (proxy_Dialer, error)) {
|
||||
if proxy_proxySchemes == nil {
|
||||
proxy_proxySchemes = make(map[string]func(*url.URL, proxy_Dialer) (proxy_Dialer, error))
|
||||
}
|
||||
proxy_proxySchemes[scheme] = f
|
||||
}
|
||||
|
||||
// FromURL returns a Dialer given a URL specification and an underlying
|
||||
// Dialer for it to make network requests.
|
||||
func proxy_FromURL(u *url.URL, forward proxy_Dialer) (proxy_Dialer, error) {
|
||||
var auth *proxy_Auth
|
||||
if u.User != nil {
|
||||
auth = new(proxy_Auth)
|
||||
auth.User = u.User.Username()
|
||||
if p, ok := u.User.Password(); ok {
|
||||
auth.Password = p
|
||||
}
|
||||
}
|
||||
|
||||
switch u.Scheme {
|
||||
case "socks5":
|
||||
return proxy_SOCKS5("tcp", u.Host, auth, forward)
|
||||
}
|
||||
|
||||
// If the scheme doesn't match any of the built-in schemes, see if it
|
||||
// was registered by another package.
|
||||
if proxy_proxySchemes != nil {
|
||||
if f, ok := proxy_proxySchemes[u.Scheme]; ok {
|
||||
return f(u, forward)
|
||||
}
|
||||
}
|
||||
|
||||
return nil, errors.New("proxy: unknown scheme: " + u.Scheme)
|
||||
}
|
||||
|
||||
var (
|
||||
proxy_allProxyEnv = &proxy_envOnce{
|
||||
names: []string{"ALL_PROXY", "all_proxy"},
|
||||
}
|
||||
proxy_noProxyEnv = &proxy_envOnce{
|
||||
names: []string{"NO_PROXY", "no_proxy"},
|
||||
}
|
||||
)
|
||||
|
||||
// envOnce looks up an environment variable (optionally by multiple
|
||||
// names) once. It mitigates expensive lookups on some platforms
|
||||
// (e.g. Windows).
|
||||
// (Borrowed from net/http/transport.go)
|
||||
type proxy_envOnce struct {
|
||||
names []string
|
||||
once sync.Once
|
||||
val string
|
||||
}
|
||||
|
||||
func (e *proxy_envOnce) Get() string {
|
||||
e.once.Do(e.init)
|
||||
return e.val
|
||||
}
|
||||
|
||||
func (e *proxy_envOnce) init() {
|
||||
for _, n := range e.names {
|
||||
e.val = os.Getenv(n)
|
||||
if e.val != "" {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SOCKS5 returns a Dialer that makes SOCKSv5 connections to the given address
|
||||
// with an optional username and password. See RFC 1928 and RFC 1929.
|
||||
func proxy_SOCKS5(network, addr string, auth *proxy_Auth, forward proxy_Dialer) (proxy_Dialer, error) {
|
||||
s := &proxy_socks5{
|
||||
network: network,
|
||||
addr: addr,
|
||||
forward: forward,
|
||||
}
|
||||
if auth != nil {
|
||||
s.user = auth.User
|
||||
s.password = auth.Password
|
||||
}
|
||||
|
||||
return s, nil
|
||||
}
|
||||
|
||||
type proxy_socks5 struct {
|
||||
user, password string
|
||||
network, addr string
|
||||
forward proxy_Dialer
|
||||
}
|
||||
|
||||
const proxy_socks5Version = 5
|
||||
|
||||
const (
|
||||
proxy_socks5AuthNone = 0
|
||||
proxy_socks5AuthPassword = 2
|
||||
)
|
||||
|
||||
const proxy_socks5Connect = 1
|
||||
|
||||
const (
|
||||
proxy_socks5IP4 = 1
|
||||
proxy_socks5Domain = 3
|
||||
proxy_socks5IP6 = 4
|
||||
)
|
||||
|
||||
var proxy_socks5Errors = []string{
|
||||
"",
|
||||
"general failure",
|
||||
"connection forbidden",
|
||||
"network unreachable",
|
||||
"host unreachable",
|
||||
"connection refused",
|
||||
"TTL expired",
|
||||
"command not supported",
|
||||
"address type not supported",
|
||||
}
|
||||
|
||||
// Dial connects to the address addr on the given network via the SOCKS5 proxy.
|
||||
func (s *proxy_socks5) Dial(network, addr string) (net.Conn, error) {
|
||||
switch network {
|
||||
case "tcp", "tcp6", "tcp4":
|
||||
default:
|
||||
return nil, errors.New("proxy: no support for SOCKS5 proxy connections of type " + network)
|
||||
}
|
||||
|
||||
conn, err := s.forward.Dial(s.network, s.addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := s.connect(conn, addr); err != nil {
|
||||
conn.Close()
|
||||
return nil, err
|
||||
}
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
// connect takes an existing connection to a socks5 proxy server,
|
||||
// and commands the server to extend that connection to target,
|
||||
// which must be a canonical address with a host and port.
|
||||
func (s *proxy_socks5) connect(conn net.Conn, target string) error {
|
||||
host, portStr, err := net.SplitHostPort(target)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
port, err := strconv.Atoi(portStr)
|
||||
if err != nil {
|
||||
return errors.New("proxy: failed to parse port number: " + portStr)
|
||||
}
|
||||
if port < 1 || port > 0xffff {
|
||||
return errors.New("proxy: port number out of range: " + portStr)
|
||||
}
|
||||
|
||||
// the size here is just an estimate
|
||||
buf := make([]byte, 0, 6+len(host))
|
||||
|
||||
buf = append(buf, proxy_socks5Version)
|
||||
if len(s.user) > 0 && len(s.user) < 256 && len(s.password) < 256 {
|
||||
buf = append(buf, 2 /* num auth methods */, proxy_socks5AuthNone, proxy_socks5AuthPassword)
|
||||
} else {
|
||||
buf = append(buf, 1 /* num auth methods */, proxy_socks5AuthNone)
|
||||
}
|
||||
|
||||
if _, err := conn.Write(buf); err != nil {
|
||||
return errors.New("proxy: failed to write greeting to SOCKS5 proxy at " + s.addr + ": " + err.Error())
|
||||
}
|
||||
|
||||
if _, err := io.ReadFull(conn, buf[:2]); err != nil {
|
||||
return errors.New("proxy: failed to read greeting from SOCKS5 proxy at " + s.addr + ": " + err.Error())
|
||||
}
|
||||
if buf[0] != 5 {
|
||||
return errors.New("proxy: SOCKS5 proxy at " + s.addr + " has unexpected version " + strconv.Itoa(int(buf[0])))
|
||||
}
|
||||
if buf[1] == 0xff {
|
||||
return errors.New("proxy: SOCKS5 proxy at " + s.addr + " requires authentication")
|
||||
}
|
||||
|
||||
// See RFC 1929
|
||||
if buf[1] == proxy_socks5AuthPassword {
|
||||
buf = buf[:0]
|
||||
buf = append(buf, 1 /* password protocol version */)
|
||||
buf = append(buf, uint8(len(s.user)))
|
||||
buf = append(buf, s.user...)
|
||||
buf = append(buf, uint8(len(s.password)))
|
||||
buf = append(buf, s.password...)
|
||||
|
||||
if _, err := conn.Write(buf); err != nil {
|
||||
return errors.New("proxy: failed to write authentication request to SOCKS5 proxy at " + s.addr + ": " + err.Error())
|
||||
}
|
||||
|
||||
if _, err := io.ReadFull(conn, buf[:2]); err != nil {
|
||||
return errors.New("proxy: failed to read authentication reply from SOCKS5 proxy at " + s.addr + ": " + err.Error())
|
||||
}
|
||||
|
||||
if buf[1] != 0 {
|
||||
return errors.New("proxy: SOCKS5 proxy at " + s.addr + " rejected username/password")
|
||||
}
|
||||
}
|
||||
|
||||
buf = buf[:0]
|
||||
buf = append(buf, proxy_socks5Version, proxy_socks5Connect, 0 /* reserved */)
|
||||
|
||||
if ip := net.ParseIP(host); ip != nil {
|
||||
if ip4 := ip.To4(); ip4 != nil {
|
||||
buf = append(buf, proxy_socks5IP4)
|
||||
ip = ip4
|
||||
} else {
|
||||
buf = append(buf, proxy_socks5IP6)
|
||||
}
|
||||
buf = append(buf, ip...)
|
||||
} else {
|
||||
if len(host) > 255 {
|
||||
return errors.New("proxy: destination host name too long: " + host)
|
||||
}
|
||||
buf = append(buf, proxy_socks5Domain)
|
||||
buf = append(buf, byte(len(host)))
|
||||
buf = append(buf, host...)
|
||||
}
|
||||
buf = append(buf, byte(port>>8), byte(port))
|
||||
|
||||
if _, err := conn.Write(buf); err != nil {
|
||||
return errors.New("proxy: failed to write connect request to SOCKS5 proxy at " + s.addr + ": " + err.Error())
|
||||
}
|
||||
|
||||
if _, err := io.ReadFull(conn, buf[:4]); err != nil {
|
||||
return errors.New("proxy: failed to read connect reply from SOCKS5 proxy at " + s.addr + ": " + err.Error())
|
||||
}
|
||||
|
||||
failure := "unknown error"
|
||||
if int(buf[1]) < len(proxy_socks5Errors) {
|
||||
failure = proxy_socks5Errors[buf[1]]
|
||||
}
|
||||
|
||||
if len(failure) > 0 {
|
||||
return errors.New("proxy: SOCKS5 proxy at " + s.addr + " failed to connect: " + failure)
|
||||
}
|
||||
|
||||
bytesToDiscard := 0
|
||||
switch buf[3] {
|
||||
case proxy_socks5IP4:
|
||||
bytesToDiscard = net.IPv4len
|
||||
case proxy_socks5IP6:
|
||||
bytesToDiscard = net.IPv6len
|
||||
case proxy_socks5Domain:
|
||||
_, err := io.ReadFull(conn, buf[:1])
|
||||
if err != nil {
|
||||
return errors.New("proxy: failed to read domain length from SOCKS5 proxy at " + s.addr + ": " + err.Error())
|
||||
}
|
||||
bytesToDiscard = int(buf[0])
|
||||
default:
|
||||
return errors.New("proxy: got unknown address type " + strconv.Itoa(int(buf[3])) + " from SOCKS5 proxy at " + s.addr)
|
||||
}
|
||||
|
||||
if cap(buf) < bytesToDiscard {
|
||||
buf = make([]byte, bytesToDiscard)
|
||||
} else {
|
||||
buf = buf[:bytesToDiscard]
|
||||
}
|
||||
if _, err := io.ReadFull(conn, buf); err != nil {
|
||||
return errors.New("proxy: failed to read address from SOCKS5 proxy at " + s.addr + ": " + err.Error())
|
||||
}
|
||||
|
||||
// Also need to discard the port number
|
||||
if _, err := io.ReadFull(conn, buf[:2]); err != nil {
|
||||
return errors.New("proxy: failed to read port from SOCKS5 proxy at " + s.addr + ": " + err.Error())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
22
src/cmd/linuxkit/vendor/github.com/moul/anonuuid/LICENSE
generated
vendored
Normal file
22
src/cmd/linuxkit/vendor/github.com/moul/anonuuid/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Manfred Touron
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
171
src/cmd/linuxkit/vendor/github.com/moul/anonuuid/README.md
generated
vendored
Normal file
171
src/cmd/linuxkit/vendor/github.com/moul/anonuuid/README.md
generated
vendored
Normal file
@@ -0,0 +1,171 @@
|
||||
# AnonUUID
|
||||
|
||||
[](https://travis-ci.org/moul/anonuuid)
|
||||
[](https://godoc.org/github.com/moul/anonuuid)
|
||||
[](https://coveralls.io/github/moul/anonuuid?branch=master)
|
||||
|
||||
:wrench: Anonymize UUIDs outputs (written in Golang)
|
||||
|
||||

|
||||
|
||||
**anonuuid** anonymize an input string by replacing all UUIDs by an anonymized
|
||||
new one.
|
||||
|
||||
The fake UUIDs are cached, so if AnonUUID encounter the same real UUIDs multiple
|
||||
times, the translation will be the same.
|
||||
|
||||
## Usage
|
||||
|
||||
```console
|
||||
$ anonuuid --help
|
||||
NAME:
|
||||
anonuuid - Anonymize UUIDs outputs
|
||||
|
||||
USAGE:
|
||||
anonuuid [global options] command [command options] [arguments...]
|
||||
|
||||
VERSION:
|
||||
1.0.0-dev
|
||||
|
||||
AUTHOR(S):
|
||||
Manfred Touron <https://github.com/moul>
|
||||
|
||||
COMMANDS:
|
||||
help, h Shows a list of commands or help for one command
|
||||
|
||||
GLOBAL OPTIONS:
|
||||
--hexspeak Generate hexspeak style fake UUIDs
|
||||
--random, -r Generate random fake UUIDs
|
||||
--keep-beginning Keep first part of the UUID unchanged
|
||||
--keep-end Keep last part of the UUID unchanged
|
||||
--prefix, -p Prefix generated UUIDs
|
||||
--suffix Suffix generated UUIDs
|
||||
--help, -h show help
|
||||
--version, -v print the version
|
||||
```
|
||||
|
||||
## Example
|
||||
|
||||
Replace all UUIDs and cache the correspondance.
|
||||
|
||||
```command
|
||||
$ anonuuid git:(master) ✗ cat <<EOF | anonuuid
|
||||
VOLUMES_0_SERVER_ID=15573749-c89d-41dd-a655-16e79bed52e0
|
||||
VOLUMES_0_SERVER_NAME=hello
|
||||
VOLUMES_0_ID=c245c3cb-3336-4567-ada1-70cb1fe4eefe
|
||||
VOLUMES_0_SIZE=50000000000
|
||||
ORGANIZATION=fe1e54e8-d69d-4f7c-a9f1-42069e03da31
|
||||
TEST=15573749-c89d-41dd-a655-16e79bed52e0
|
||||
EOF
|
||||
VOLUMES_0_SERVER_ID=00000000-0000-0000-0000-000000000000
|
||||
VOLUMES_0_SERVER_NAME=hello
|
||||
VOLUMES_0_ID=11111111-1111-1111-1111-111111111111
|
||||
VOLUMES_0_SIZE=50000000000
|
||||
ORGANIZATION=22222222-2222-2222-2222-222222222222
|
||||
TEST=00000000-0000-0000-0000-000000000000
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Inline
|
||||
|
||||
```command
|
||||
$ echo 'VOLUMES_0_SERVER_ID=15573749-c89d-41dd-a655-16e79bed52e0 VOLUMES_0_SERVER_NAME=bitrig1 VOLUMES_0_ID=c245c3cb-3336-4567-ada1-70cb1fe4eefe VOLUMES_0_SIZE=50000000000 ORGANIZATION=fe1e54e8-d69d-4f7c-a9f1-42069e03da31 TEST=15573749-c89d-41dd-a655-16e79bed52e0' | ./anonuuid
|
||||
VOLUMES_0_SERVER_ID=00000000-0000-0000-0000-000000000000 VOLUMES_0_SERVER_NAME=bitrig1 VOLUMES_0_ID=11111111-1111-1111-1111-111111111111 VOLUMES_0_SIZE=50000000000 ORGANIZATION=22222222-2222-2222-2222-222222222222 TEST=00000000-0000-0000-0000-000000000000
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
```command
|
||||
$ curl -s https://api.pathwar.net/achievements\?max_results\=2 | anonuuid | jq .
|
||||
{
|
||||
"_items": [
|
||||
{
|
||||
"_updated": "Thu, 30 Apr 2015 13:00:58 GMT",
|
||||
"description": "You",
|
||||
"_links": {
|
||||
"self": {
|
||||
"href": "achievements/00000000-0000-0000-0000-000000000000",
|
||||
"title": "achievement"
|
||||
}
|
||||
},
|
||||
"_created": "Thu, 30 Apr 2015 13:00:58 GMT",
|
||||
"_id": "00000000-0000-0000-0000-000000000000",
|
||||
"_etag": "b1e9f850accfcb952c58384db41d89728890a69f",
|
||||
"name": "finish-20-levels"
|
||||
},
|
||||
{
|
||||
"_updated": "Thu, 30 Apr 2015 13:01:07 GMT",
|
||||
"description": "You",
|
||||
"_links": {
|
||||
"self": {
|
||||
"href": "achievements/11111111-1111-1111-1111-111111111111",
|
||||
"title": "achievement"
|
||||
}
|
||||
},
|
||||
"_created": "Thu, 30 Apr 2015 13:01:07 GMT",
|
||||
"_id": "11111111-1111-1111-1111-111111111111",
|
||||
"_etag": "c346f5e1c4f7658f2dfc4124efa87aba909a9821",
|
||||
"name": "buy-30-levels"
|
||||
}
|
||||
],
|
||||
"_links": {
|
||||
"self": {
|
||||
"href": "achievements?max_results=2",
|
||||
"title": "achievements"
|
||||
},
|
||||
"last": {
|
||||
"href": "achievements?max_results=2&page=23",
|
||||
"title": "last page"
|
||||
},
|
||||
"parent": {
|
||||
"href": "/",
|
||||
"title": "home"
|
||||
},
|
||||
"next": {
|
||||
"href": "achievements?max_results=2&page=2",
|
||||
"title": "next page"
|
||||
}
|
||||
},
|
||||
"_meta": {
|
||||
"max_results": 2,
|
||||
"total": 46,
|
||||
"page": 1
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Install
|
||||
|
||||
Using go
|
||||
|
||||
- `go get github.com/moul/anonuuid/...`
|
||||
|
||||
## Changelog
|
||||
|
||||
### [v1.1.0](https://github.com/moul/anonuuid/releases/tag/v1.1.0) (2018-04-02)
|
||||
|
||||
* Switch from `Godep` to `Glide`
|
||||
* Add mutex to protect the cache field ([@QuentinPerez](https://github.com/QuentinPerez))
|
||||
* Switch from `Party` to `Godep`
|
||||
* Support of `--suffix=xxx`, `--keep-beginning` and `--keep-end` options ([#4](https://github.com/moul/anonuuid/issues/4))
|
||||
* Using **party** to stabilize vendor package versions ([#8](https://github.com/moul/anonuuid/issues/8))
|
||||
* Add homebrew package ([#6](https://github.com/moul/anonuuid/issues/6))
|
||||
|
||||
[full commits list](https://github.com/moul/anonuuid/compare/v1.0.0...master)
|
||||
|
||||
### [v1.0.0](https://github.com/moul/anonuuid/releases/tag/v1.0.0) (2015-10-07)
|
||||
|
||||
**Initial release**
|
||||
|
||||
#### Features
|
||||
|
||||
* Support of `--hexspeak` option
|
||||
* Support of `--random` option
|
||||
* Support of `--prefix` option
|
||||
* Anonymize input stream
|
||||
* Anonymize files
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
229
src/cmd/linuxkit/vendor/github.com/moul/anonuuid/anonuuid.go
generated
vendored
Normal file
229
src/cmd/linuxkit/vendor/github.com/moul/anonuuid/anonuuid.go
generated
vendored
Normal file
@@ -0,0 +1,229 @@
|
||||
package anonuuid
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"math/rand"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
// UUIDRegex is the regex used to find UUIDs in texts
|
||||
UUIDRegex = "[a-z0-9]{8}-[a-z0-9]{4}-[1-5][a-z0-9]{3}-[a-z0-9]{4}-[a-z0-9]{12}"
|
||||
)
|
||||
|
||||
// AnonUUID is the main structure, it contains the cache map and helpers
|
||||
type AnonUUID struct {
|
||||
cache map[string]string
|
||||
|
||||
guard sync.Mutex // cache guard
|
||||
|
||||
// Hexspeak flag will generate hexspeak style fake UUIDs
|
||||
Hexspeak bool
|
||||
|
||||
// Random flag will generate random fake UUIDs
|
||||
Random bool
|
||||
|
||||
// Prefix will be the beginning of all the generated UUIDs
|
||||
Prefix string
|
||||
|
||||
// Suffix will be the end of all the generated UUIDs
|
||||
Suffix string
|
||||
|
||||
// AllowNonUUIDInput tells FakeUUID to accept non UUID input string
|
||||
AllowNonUUIDInput bool
|
||||
|
||||
// KeepBeginning tells FakeUUID to let the beginning of the UUID as it is
|
||||
KeepBeginning bool
|
||||
|
||||
// KeepEnd tells FakeUUID to let the last part of the UUID as it is
|
||||
KeepEnd bool
|
||||
}
|
||||
|
||||
// Sanitize takes a string as input and return sanitized string
|
||||
func (a *AnonUUID) Sanitize(input string) string {
|
||||
r := regexp.MustCompile(UUIDRegex)
|
||||
|
||||
return r.ReplaceAllStringFunc(input, func(m string) string {
|
||||
parts := r.FindStringSubmatch(m)
|
||||
return a.FakeUUID(parts[0])
|
||||
})
|
||||
}
|
||||
|
||||
// FakeUUID takes a word (real UUID or standard string) and returns its corresponding (mapped) fakeUUID
|
||||
func (a *AnonUUID) FakeUUID(input string) string {
|
||||
if !a.AllowNonUUIDInput {
|
||||
err := IsUUID(input)
|
||||
if err != nil {
|
||||
return "invaliduuid"
|
||||
}
|
||||
}
|
||||
a.guard.Lock()
|
||||
defer a.guard.Unlock()
|
||||
if _, ok := a.cache[input]; !ok {
|
||||
|
||||
if a.KeepBeginning {
|
||||
a.Prefix = input[:8]
|
||||
}
|
||||
|
||||
if a.KeepEnd {
|
||||
a.Suffix = input[36-12:]
|
||||
}
|
||||
|
||||
if a.Prefix != "" {
|
||||
matched, err := regexp.MatchString("^[a-z0-9]+$", a.Prefix)
|
||||
if err != nil || !matched {
|
||||
a.Prefix = "invalidprefix"
|
||||
}
|
||||
}
|
||||
|
||||
if a.Suffix != "" {
|
||||
matched, err := regexp.MatchString("^[a-z0-9]+$", a.Suffix)
|
||||
if err != nil || !matched {
|
||||
a.Suffix = "invalsuffix"
|
||||
}
|
||||
}
|
||||
|
||||
var fakeUUID string
|
||||
var err error
|
||||
if a.Hexspeak {
|
||||
fakeUUID, err = GenerateHexspeakUUID(len(a.cache))
|
||||
} else if a.Random {
|
||||
fakeUUID, err = GenerateRandomUUID(10)
|
||||
} else {
|
||||
fakeUUID, err = GenerateLenUUID(len(a.cache))
|
||||
}
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to generate an UUID: %v", err)
|
||||
}
|
||||
|
||||
if a.Prefix != "" {
|
||||
fakeUUID, err = PrefixUUID(a.Prefix, fakeUUID)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
if a.Suffix != "" {
|
||||
fakeUUID, err = SuffixUUID(a.Suffix, fakeUUID)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: check for duplicates and retry
|
||||
|
||||
a.cache[input] = fakeUUID
|
||||
}
|
||||
return a.cache[input]
|
||||
}
|
||||
|
||||
// New returns a prepared AnonUUID structure
|
||||
func New() *AnonUUID {
|
||||
return &AnonUUID{
|
||||
cache: make(map[string]string),
|
||||
Hexspeak: false,
|
||||
Random: false,
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
rand.Seed(time.Now().UTC().UnixNano())
|
||||
}
|
||||
|
||||
// PrefixUUID returns a prefixed UUID
|
||||
func PrefixUUID(prefix string, uuid string) (string, error) {
|
||||
uuidLetters := uuid[:8] + uuid[9:13] + uuid[14:18] + uuid[19:23] + uuid[24:36]
|
||||
prefixedUUID, err := FormatUUID(prefix + uuidLetters)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return prefixedUUID, nil
|
||||
}
|
||||
|
||||
// SuffixUUID returns a suffixed UUID
|
||||
func SuffixUUID(suffix string, uuid string) (string, error) {
|
||||
uuidLetters := uuid[:8] + uuid[9:13] + uuid[14:18] + uuid[19:23] + uuid[24:36]
|
||||
uuidLetters = uuidLetters[:32-len(suffix)] + suffix
|
||||
suffixedUUID, err := FormatUUID(uuidLetters)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return suffixedUUID, nil
|
||||
}
|
||||
|
||||
// IsUUID returns nil if the input is an UUID, else it returns an error
|
||||
func IsUUID(input string) error {
|
||||
matched, err := regexp.MatchString("^"+UUIDRegex+"$", input)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !matched {
|
||||
return fmt.Errorf("String '%s' is not a valid UUID", input)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FormatUUID takes a string in input and return an UUID formatted string by repeating the string and placing dashes if necessary
|
||||
func FormatUUID(part string) (string, error) {
|
||||
if len(part) < 1 {
|
||||
return "", fmt.Errorf("Empty UUID")
|
||||
}
|
||||
if len(part) < 32 {
|
||||
part = strings.Repeat(part, 32)
|
||||
}
|
||||
if len(part) > 32 {
|
||||
part = part[:32]
|
||||
}
|
||||
uuid := part[:8] + "-" + part[8:12] + "-1" + part[13:16] + "-" + part[16:20] + "-" + part[20:32]
|
||||
|
||||
err := IsUUID(uuid)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return uuid, nil
|
||||
}
|
||||
|
||||
// GenerateRandomUUID returns an UUID based on random strings
|
||||
func GenerateRandomUUID(length int) (string, error) {
|
||||
var letters = []rune("abcdef0123456789")
|
||||
|
||||
b := make([]rune, length)
|
||||
for i := range b {
|
||||
b[i] = letters[rand.Intn(len(letters))]
|
||||
}
|
||||
return FormatUUID(string(b))
|
||||
}
|
||||
|
||||
// GenerateHexspeakUUID returns an UUID formatted string containing hexspeak words
|
||||
func GenerateHexspeakUUID(i int) (string, error) {
|
||||
if i < 0 {
|
||||
i = -i
|
||||
}
|
||||
hexspeaks := []string{
|
||||
"0ff1ce",
|
||||
"31337",
|
||||
"4b1d",
|
||||
"badc0de",
|
||||
"badcafe",
|
||||
"badf00d",
|
||||
"deadbabe",
|
||||
"deadbeef",
|
||||
"deadc0de",
|
||||
"deadfeed",
|
||||
"fee1bad",
|
||||
}
|
||||
return FormatUUID(hexspeaks[i%len(hexspeaks)])
|
||||
}
|
||||
|
||||
// GenerateLenUUID returns an UUID formatted string based on an index number
|
||||
func GenerateLenUUID(i int) (string, error) {
|
||||
if i < 0 {
|
||||
i = 2<<29 + i
|
||||
}
|
||||
return FormatUUID(fmt.Sprintf("%x", i))
|
||||
}
|
22
src/cmd/linuxkit/vendor/github.com/moul/gotty-client/LICENSE
generated
vendored
Normal file
22
src/cmd/linuxkit/vendor/github.com/moul/gotty-client/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Manfred Touron
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
192
src/cmd/linuxkit/vendor/github.com/moul/gotty-client/LICENSE.apache
generated
vendored
Normal file
192
src/cmd/linuxkit/vendor/github.com/moul/gotty-client/LICENSE.apache
generated
vendored
Normal file
@@ -0,0 +1,192 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
https://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
|
||||
|
||||
Copyright 2013-2017 Docker, 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
|
||||
|
||||
https://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.
|
||||
|
217
src/cmd/linuxkit/vendor/github.com/moul/gotty-client/README.md
generated
vendored
Normal file
217
src/cmd/linuxkit/vendor/github.com/moul/gotty-client/README.md
generated
vendored
Normal file
@@ -0,0 +1,217 @@
|
||||
# gotty-client
|
||||
:wrench: Terminal client for [GoTTY](https://github.com/yudai/gotty).
|
||||
|
||||

|
||||
|
||||
[](https://travis-ci.org/moul/gotty-client)
|
||||
[](https://godoc.org/github.com/moul/gotty-client)
|
||||
[](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fmoul%2Fgotty-client?ref=badge_shield)
|
||||
|
||||
```ruby
|
||||
┌─────────────────┐
|
||||
┌──────▶│ /bin/bash │
|
||||
│ └─────────────────┘
|
||||
┌──────────────┐ ┌──────────┐
|
||||
│ │ │ Gotty │
|
||||
┌───────┐ ┌──▶│ Browser │───────┐ │ │
|
||||
│ │ │ │ │ │ │ │
|
||||
│ │ │ └──────────────┘ │ │ │ ┌─────────────────┐
|
||||
│ Bob │───┤ websockets─▶│ │─▶│ emacs /var/www │
|
||||
│ │ │ ╔═ ══ ══ ══ ══ ╗ │ │ │ └─────────────────┘
|
||||
│ │ │ ║ ║ │ │ │
|
||||
└───────┘ └──▶║ gotty-client ───────┘ │ │
|
||||
║ │ │
|
||||
╚═ ══ ══ ══ ══ ╝ └──────────┘
|
||||
│ ┌─────────────────┐
|
||||
└──────▶│ tmux attach │
|
||||
└─────────────────┘
|
||||
```
|
||||
|
||||
## Example
|
||||
|
||||
Server side ([GoTTY](https://github.com/yudai/gotty))
|
||||
|
||||
```console
|
||||
$ gotty -p 9191 sh -c 'while true; do date; sleep 1; done'
|
||||
2015/08/24 18:54:31 Server is starting with command: sh -c while true; do date; sleep 1; done
|
||||
2015/08/24 18:54:31 URL: http://[::1]:9191/
|
||||
2015/08/24 18:54:34 GET /ws
|
||||
2015/08/24 18:54:34 New client connected: 127.0.0.1:61811
|
||||
2015/08/24 18:54:34 Command is running for client 127.0.0.1:61811 with PID 64834
|
||||
2015/08/24 18:54:39 Command exited for: 127.0.0.1:61811
|
||||
2015/08/24 18:54:39 Connection closed: 127.0.0.1:61811
|
||||
...
|
||||
```
|
||||
|
||||
**Client side**
|
||||
|
||||
```console
|
||||
$ gotty-client http://localhost:9191/
|
||||
INFO[0000] New title: GoTTY - sh -c while true; do date; sleep 1; done (jean-michel-van-damme.local)
|
||||
WARN[0000] Unhandled protocol message: json pref: 2{}
|
||||
Mon Aug 24 18:54:34 CEST 2015
|
||||
Mon Aug 24 18:54:35 CEST 2015
|
||||
Mon Aug 24 18:54:36 CEST 2015
|
||||
Mon Aug 24 18:54:37 CEST 2015
|
||||
Mon Aug 24 18:54:38 CEST 2015
|
||||
^C
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```console
|
||||
$ gotty-client -h
|
||||
NAME:
|
||||
gotty-client - GoTTY client for your terminal
|
||||
|
||||
USAGE:
|
||||
gotty-client [global options] command [command options] GOTTY_URL
|
||||
|
||||
AUTHOR:
|
||||
Manfred Touron <https://github.com/moul/gotty-client>
|
||||
|
||||
COMMANDS:
|
||||
help, h Shows a list of commands or help for one command
|
||||
|
||||
GLOBAL OPTIONS:
|
||||
--debug, -D Enable debug mode [$GOTTY_CLIENT_DEBUG]
|
||||
--skip-tls-verify Skip TLS verify [$SKIP_TLS_VERIFY]
|
||||
--use-proxy-from-env Use Proxy from environment [$USE_PROXY_FROM_ENV]
|
||||
--detach-keys value Key sequence for detaching gotty-client (default: "ctrl-p,ctrl-q")
|
||||
--v2 For Gotty 2.0 [$GOTTY_CLIENT_GOTTY2]
|
||||
--ws-origin value, -w value WebSocket Origin URL [$GOTTY_CLIENT_WS_ORIGIN]
|
||||
--help, -h show help
|
||||
--version, -v print the version
|
||||
```
|
||||
|
||||
## Install
|
||||
|
||||
Install latest version using Golang (recommended)
|
||||
|
||||
```console
|
||||
$ go get github.com/moul/gotty-client/cmd/gotty-client
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Install latest version using Homebrew (Mac OS X)
|
||||
|
||||
```console
|
||||
$ brew install https://raw.githubusercontent.com/moul/gotty-client/master/contrib/homebrew/gotty-client.rb --HEAD
|
||||
```
|
||||
|
||||
or the latest released version
|
||||
|
||||
```console
|
||||
$ brew install https://raw.githubusercontent.com/moul/gotty-client/master/contrib/homebrew/gotty-client.rb
|
||||
```
|
||||
|
||||
## Changelog
|
||||
|
||||
### master (unreleased)
|
||||
|
||||
* Fix TTY restoring by switching to [`github.com/moby/moby/pkg/term`](https://github.com/moby/moby/tree/master/pkg/term) ([#59](https://github.com/moul/gotty-client/pull/59) + ([#60](https://github.com/moul/gotty-client/pull/60) + ([#62](https://github.com/moul/gotty-client/pull/62) ([@Sh4d1](https://github.com/Sh4d1))
|
||||
|
||||
[full commits list](https://github.com/moul/gotty-client/compare/v1.7.0...master)
|
||||
|
||||
### [v1.7.0](https://github.com/moul/gotty-client/releases/tag/v1.7.0) (2018-04-11)
|
||||
|
||||
* Add `--detach-keys` option ([#52](https://github.com/moul/gotty-client/issues/52))
|
||||
* Cross build on Solaris ([#55](https://github.com/moul/gotty-client/pull/55) ([@dimtion](https://github.com/dimtion))
|
||||
* Fix terminal resizing issue ([#56](https://github.com/moul/gotty-client/pull/56) ([@byung2](https://github.com/byung2))
|
||||
* Support for gotty v2.0 ([#58](https://github.com/moul/gotty-client/pull/58) ([@byung2](https://github.com/byung2))
|
||||
* Support ws-origin (CORS) ([#58](https://github.com/moul/gotty-client/pull/58) ([@byung2](https://github.com/byung2))
|
||||
|
||||
[full commits list](https://github.com/moul/gotty-client/compare/v1.6.1...v1.7.0)
|
||||
|
||||
### [v1.6.1](https://github.com/moul/gotty-client/releases/tag/v1.6.1) (2017-01-19)
|
||||
|
||||
* Do not exit on EOF ([#45](https://github.com/moul/gotty-client/pull/45)) ([@gurjeet](https://github.com/gurjeet))
|
||||
|
||||
[full commits list](https://github.com/moul/gotty-client/compare/v1.6.0...v1.6.1)
|
||||
|
||||
### [v1.6.0](https://github.com/moul/gotty-client/releases/tag/v1.6.0) (2016-05-23)
|
||||
|
||||
* Support of `--use-proxy-from-env` (Add Proxy support) ([#36](https://github.com/moul/gotty-client/pull/36)) ([@byung2](https://github.com/byung2))
|
||||
* Add debug mode ([#18](https://github.com/moul/gotty-client/issues/18))
|
||||
* Fix argument passing ([#16](https://github.com/moul/gotty-client/issues/16))
|
||||
* Remove warnings + golang fixes and refactoring ([@QuentinPerez](https://github.com/QuentinPerez))
|
||||
|
||||
[full commits list](https://github.com/moul/gotty-client/compare/v1.5.0...v1.6.0)
|
||||
|
||||
### [v1.5.0](https://github.com/moul/gotty-client/releases/tag/v1.5.0) (2016-02-18)
|
||||
|
||||
* Add autocomplete support ([#19](https://github.com/moul/gotty-client/issues/19))
|
||||
* Switch from `Party` to `Godep`
|
||||
* Fix terminal data being interpreted as format string ([#34](https://github.com/moul/gotty-client/pull/34)) ([@mickael9](https://github.com/mickael9))
|
||||
|
||||
[full commits list](https://github.com/moul/gotty-client/compare/v1.4.0...v1.5.0)
|
||||
|
||||
### [v1.4.0](https://github.com/moul/gotty-client/releases/tag/v1.4.0) (2015-12-09)
|
||||
|
||||
* Remove solaris,plan9,nacl for `.goxc.json`
|
||||
* Add an error if the go version is lower than 1.5
|
||||
* Flexible parsing of the input URL
|
||||
* Add tests
|
||||
* Support of `--skip-tls-verify`
|
||||
|
||||
[full commits list](https://github.com/moul/gotty-client/compare/v1.3.0...v1.4.0)
|
||||
|
||||
### [v1.3.0](https://github.com/moul/gotty-client/releases/tag/v1.3.0) (2015-10-27)
|
||||
|
||||
* Fix `connected` state when using `Connect()` + `Loop()` methods
|
||||
* Add `ExitLoop` which allow to exit from `Loop` function
|
||||
|
||||
[full commits list](https://github.com/moul/gotty-client/compare/v1.2.0...v1.3.0)
|
||||
|
||||
### [v1.2.0](https://github.com/moul/gotty-client/releases/tag/v1.2.0) (2015-10-23)
|
||||
|
||||
* Removed an annoying warning when exiting connection ([#22](https://github.com/moul/gotty-client/issues/22)) ([@QuentinPerez](https://github.com/QuentinPerez))
|
||||
* Add the ability to configure alternative stdout ([#21](https://github.com/moul/gotty-client/issues/21)) ([@QuentinPerez](https://github.com/QuentinPerez))
|
||||
* Refactored the goroutine system with select, improve speed and stability ([@QuentinPerez](https://github.com/QuentinPerez))
|
||||
* Add debug mode (`--debug`/`-D`) ([#18](https://github.com/moul/gotty-client/issues/18))
|
||||
* Improve error message when connecting by checking HTTP status code
|
||||
* Fix arguments passing ([#16](https://github.com/moul/gotty-client/issues/16))
|
||||
* Dropped support for golang<1.5
|
||||
* Small fixes
|
||||
|
||||
[full commits list](https://github.com/moul/gotty-client/compare/v1.1.0...v1.2.0)
|
||||
|
||||
### [v1.1.0](https://github.com/moul/gotty-client/releases/tag/v1.1.0) (2015-10-10)
|
||||
|
||||
* Handling arguments + using mutexes (thanks to [@QuentinPerez](https://github.com/QuentinPerez))
|
||||
* Add logo ([#9](https://github.com/moul/gotty-client/issues/9))
|
||||
* Using codegansta/cli for CLI parsing ([#3](https://github.com/moul/gotty-client/issues/3))
|
||||
* Fix panic when running on older GoTTY server ([#13](https://github.com/moul/gotty-client/issues/13))
|
||||
* Add 'homebrew support' ([#1](https://github.com/moul/gotty-client/issues/1))
|
||||
* Add Changelog ([#5](https://github.com/moul/gotty-client/issues/5))
|
||||
* Add GOXC configuration to build binaries for multiple architectures ([#2](https://github.com/moul/gotty-client/issues/2))
|
||||
|
||||
[full commits list](https://github.com/moul/gotty-client/compare/v1.0.1...v1.1.0)
|
||||
|
||||
### [v1.0.1](https://github.com/moul/gotty-client/releases/tag/v1.0.1) (2015-09-27)
|
||||
|
||||
* Using party to manage dependencies
|
||||
|
||||
[full commits list](https://github.com/moul/gotty-client/compare/v1.0.0...v1.0.1)
|
||||
|
||||
### [v1.0.0](https://github.com/moul/gotty-client/releases/tag/v1.0.0) (2015-09-27)
|
||||
|
||||
Compatible with [GoTTY](https://github.com/yudai/gotty) version: [v0.0.10](https://github.com/yudai/gotty/releases/tag/v0.0.10)
|
||||
|
||||
#### Features
|
||||
|
||||
* Support **basic-auth**
|
||||
* Support **terminal-(re)size**
|
||||
* Support **write**
|
||||
* Support **title**
|
||||
* Support **custom URI**
|
||||
|
||||
[full commits list](https://github.com/moul/gotty-client/compare/cf0c1146c7ce20fe0bd65764c13253bc575cd43a...v1.0.0)
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
|
||||
|
||||
[](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fmoul%2Fgotty-client?ref=badge_large)
|
33
src/cmd/linuxkit/vendor/github.com/moul/gotty-client/arch.go
generated
vendored
Normal file
33
src/cmd/linuxkit/vendor/github.com/moul/gotty-client/arch.go
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
// +build !windows
|
||||
|
||||
package gottyclient
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"golang.org/x/sys/unix"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func notifySignalSIGWINCH(c chan<- os.Signal) {
|
||||
signal.Notify(c, syscall.SIGWINCH)
|
||||
}
|
||||
|
||||
func resetSignalSIGWINCH() {
|
||||
signal.Reset(syscall.SIGWINCH)
|
||||
}
|
||||
|
||||
func syscallTIOCGWINSZ() ([]byte, error) {
|
||||
ws, err := unix.IoctlGetWinsize(0, unix.TIOCGWINSZ)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("ioctl error: %v", err)
|
||||
}
|
||||
tws := winsize{Rows: ws.Row, Columns: ws.Col}
|
||||
b, err := json.Marshal(tws)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("json.Marshal error: %v", err)
|
||||
}
|
||||
return b, err
|
||||
}
|
16
src/cmd/linuxkit/vendor/github.com/moul/gotty-client/arch_windows.go
generated
vendored
Normal file
16
src/cmd/linuxkit/vendor/github.com/moul/gotty-client/arch_windows.go
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
package gottyclient
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
)
|
||||
|
||||
func notifySignalSIGWINCH(c chan<- os.Signal) {
|
||||
}
|
||||
|
||||
func resetSignalSIGWINCH() {
|
||||
}
|
||||
|
||||
func syscallTIOCGWINSZ() ([]byte, error) {
|
||||
return nil, errors.New("SIGWINCH isn't supported on this ARCH")
|
||||
}
|
66
src/cmd/linuxkit/vendor/github.com/moul/gotty-client/ascii.go
generated
vendored
Normal file
66
src/cmd/linuxkit/vendor/github.com/moul/gotty-client/ascii.go
generated
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
package gottyclient // from github.com/moby/moby/pkg/term
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ASCII list the possible supported ASCII key sequence
|
||||
var ASCII = []string{
|
||||
"ctrl-@",
|
||||
"ctrl-a",
|
||||
"ctrl-b",
|
||||
"ctrl-c",
|
||||
"ctrl-d",
|
||||
"ctrl-e",
|
||||
"ctrl-f",
|
||||
"ctrl-g",
|
||||
"ctrl-h",
|
||||
"ctrl-i",
|
||||
"ctrl-j",
|
||||
"ctrl-k",
|
||||
"ctrl-l",
|
||||
"ctrl-m",
|
||||
"ctrl-n",
|
||||
"ctrl-o",
|
||||
"ctrl-p",
|
||||
"ctrl-q",
|
||||
"ctrl-r",
|
||||
"ctrl-s",
|
||||
"ctrl-t",
|
||||
"ctrl-u",
|
||||
"ctrl-v",
|
||||
"ctrl-w",
|
||||
"ctrl-x",
|
||||
"ctrl-y",
|
||||
"ctrl-z",
|
||||
"ctrl-[",
|
||||
"ctrl-\\",
|
||||
"ctrl-]",
|
||||
"ctrl-^",
|
||||
"ctrl-_",
|
||||
}
|
||||
|
||||
// ToBytes converts a string representing a suite of key-sequence to the corresponding ASCII code.
|
||||
func ToBytes(keys string) ([]byte, error) {
|
||||
codes := []byte{}
|
||||
next:
|
||||
for _, key := range strings.Split(keys, ",") {
|
||||
if len(key) != 1 {
|
||||
for code, ctrl := range ASCII {
|
||||
if ctrl == key {
|
||||
codes = append(codes, byte(code))
|
||||
continue next
|
||||
}
|
||||
}
|
||||
if key == "DEL" {
|
||||
codes = append(codes, 127)
|
||||
} else {
|
||||
return nil, fmt.Errorf("Unknown character: '%s'", key)
|
||||
}
|
||||
} else {
|
||||
codes = append(codes, key[0])
|
||||
}
|
||||
}
|
||||
return codes, nil
|
||||
}
|
560
src/cmd/linuxkit/vendor/github.com/moul/gotty-client/gotty-client.go
generated
vendored
Normal file
560
src/cmd/linuxkit/vendor/github.com/moul/gotty-client/gotty-client.go
generated
vendored
Normal file
@@ -0,0 +1,560 @@
|
||||
package gottyclient
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/containerd/console"
|
||||
"github.com/creack/goselect"
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// message types for gotty
|
||||
const (
|
||||
OutputV1 = '0'
|
||||
PongV1 = '1'
|
||||
SetWindowTitleV1 = '2'
|
||||
SetPreferencesV1 = '3'
|
||||
SetReconnectV1 = '4'
|
||||
|
||||
InputV1 = '0'
|
||||
PingV1 = '1'
|
||||
ResizeTerminalV1 = '2'
|
||||
)
|
||||
|
||||
// message types for gotty v2.0
|
||||
const (
|
||||
// Unknown message type, maybe set by a bug
|
||||
UnknownOutput = '0'
|
||||
// Normal output to the terminal
|
||||
Output = '1'
|
||||
// Pong to the browser
|
||||
Pong = '2'
|
||||
// Set window title of the terminal
|
||||
SetWindowTitle = '3'
|
||||
// Set terminal preference
|
||||
SetPreferences = '4'
|
||||
// Make terminal to reconnect
|
||||
SetReconnect = '5'
|
||||
|
||||
// Unknown message type, maybe sent by a bug
|
||||
UnknownInput = '0'
|
||||
// User input typically from a keyboard
|
||||
Input = '1'
|
||||
// Ping to the server
|
||||
Ping = '2'
|
||||
// Notify that the browser size has been changed
|
||||
ResizeTerminal = '3'
|
||||
)
|
||||
|
||||
type gottyMessageType struct {
|
||||
output byte
|
||||
pong byte
|
||||
setWindowTitle byte
|
||||
setPreferences byte
|
||||
setReconnect byte
|
||||
input byte
|
||||
ping byte
|
||||
resizeTerminal byte
|
||||
}
|
||||
|
||||
// GetAuthTokenURL transforms a GoTTY http URL to its AuthToken file URL
|
||||
func GetAuthTokenURL(httpURL string) (*url.URL, *http.Header, error) {
|
||||
header := http.Header{}
|
||||
target, err := url.Parse(httpURL)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
target.Path = strings.TrimLeft(target.Path+"auth_token.js", "/")
|
||||
|
||||
if target.User != nil {
|
||||
header.Add("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(target.User.String())))
|
||||
target.User = nil
|
||||
}
|
||||
|
||||
return target, &header, nil
|
||||
}
|
||||
|
||||
// GetURLQuery returns url.query
|
||||
func GetURLQuery(rawurl string) (url.Values, error) {
|
||||
target, err := url.Parse(rawurl)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return target.Query(), nil
|
||||
}
|
||||
|
||||
// GetWebsocketURL transforms a GoTTY http URL to its WebSocket URL
|
||||
func GetWebsocketURL(httpURL string) (*url.URL, *http.Header, error) {
|
||||
header := http.Header{}
|
||||
target, err := url.Parse(httpURL)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if target.Scheme == "https" {
|
||||
target.Scheme = "wss"
|
||||
} else {
|
||||
target.Scheme = "ws"
|
||||
}
|
||||
|
||||
target.Path = strings.TrimLeft(target.Path+"ws", "/")
|
||||
|
||||
if target.User != nil {
|
||||
header.Add("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(target.User.String())))
|
||||
target.User = nil
|
||||
}
|
||||
|
||||
return target, &header, nil
|
||||
}
|
||||
|
||||
type Client struct {
|
||||
Dialer *websocket.Dialer
|
||||
Conn *websocket.Conn
|
||||
URL string
|
||||
WriteMutex *sync.Mutex
|
||||
Output io.Writer
|
||||
poison chan bool
|
||||
SkipTLSVerify bool
|
||||
UseProxyFromEnv bool
|
||||
Connected bool
|
||||
EscapeKeys []byte
|
||||
V2 bool
|
||||
message *gottyMessageType
|
||||
WSOrigin string
|
||||
}
|
||||
|
||||
type querySingleType struct {
|
||||
AuthToken string `json:"AuthToken"`
|
||||
Arguments string `json:"Arguments"`
|
||||
}
|
||||
|
||||
func (c *Client) write(data []byte) error {
|
||||
c.WriteMutex.Lock()
|
||||
defer c.WriteMutex.Unlock()
|
||||
return c.Conn.WriteMessage(websocket.TextMessage, data)
|
||||
}
|
||||
|
||||
// GetAuthToken retrieves an Auth Token from dynamic auth_token.js file
|
||||
func (c *Client) GetAuthToken() (string, error) {
|
||||
target, header, err := GetAuthTokenURL(c.URL)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
logrus.Debugf("Fetching auth token auth-token: %q", target.String())
|
||||
req, err := http.NewRequest("GET", target.String(), nil)
|
||||
req.Header = *header
|
||||
tr := &http.Transport{}
|
||||
if c.SkipTLSVerify {
|
||||
conf := &tls.Config{InsecureSkipVerify: true}
|
||||
tr.TLSClientConfig = conf
|
||||
}
|
||||
if c.UseProxyFromEnv {
|
||||
tr.Proxy = http.ProxyFromEnvironment
|
||||
}
|
||||
client := &http.Client{Transport: tr}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
switch resp.StatusCode {
|
||||
case 200:
|
||||
// Everything is OK
|
||||
default:
|
||||
return "", fmt.Errorf("unknown status code: %d (%s)", resp.StatusCode, http.StatusText(resp.StatusCode))
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
re := regexp.MustCompile("var gotty_auth_token = '(.*)'")
|
||||
output := re.FindStringSubmatch(string(body))
|
||||
if len(output) == 0 {
|
||||
return "", fmt.Errorf("Cannot fetch GoTTY auth-token, please upgrade your GoTTY server.")
|
||||
}
|
||||
|
||||
return output[1], nil
|
||||
}
|
||||
|
||||
// Connect tries to dial a websocket server
|
||||
func (c *Client) Connect() error {
|
||||
// Retrieve AuthToken
|
||||
authToken, err := c.GetAuthToken()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
logrus.Debugf("Auth-token: %q", authToken)
|
||||
|
||||
// Open WebSocket connection
|
||||
target, header, err := GetWebsocketURL(c.URL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if c.WSOrigin != "" {
|
||||
header.Add("Origin", c.WSOrigin)
|
||||
}
|
||||
logrus.Debugf("Connecting to websocket: %q", target.String())
|
||||
if c.SkipTLSVerify {
|
||||
c.Dialer.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
|
||||
}
|
||||
if c.UseProxyFromEnv {
|
||||
c.Dialer.Proxy = http.ProxyFromEnvironment
|
||||
}
|
||||
conn, _, err := c.Dialer.Dial(target.String(), *header)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.Conn = conn
|
||||
c.Connected = true
|
||||
|
||||
// Pass arguments and auth-token
|
||||
query, err := GetURLQuery(c.URL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
querySingle := querySingleType{
|
||||
Arguments: "?" + query.Encode(),
|
||||
AuthToken: authToken,
|
||||
}
|
||||
json, err := json.Marshal(querySingle)
|
||||
if err != nil {
|
||||
logrus.Errorf("Failed to parse init message %v", err)
|
||||
return err
|
||||
}
|
||||
// Send Json
|
||||
logrus.Debugf("Sending arguments and auth-token")
|
||||
err = c.write(json)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Initialize message types for gotty
|
||||
c.initMessageType()
|
||||
|
||||
go c.pingLoop()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// initMessageType initialize message types for gotty
|
||||
func (c *Client) initMessageType() {
|
||||
if c.V2 {
|
||||
c.message = &gottyMessageType{
|
||||
output: Output,
|
||||
pong: Pong,
|
||||
setWindowTitle: SetWindowTitle,
|
||||
setPreferences: SetPreferences,
|
||||
setReconnect: SetReconnect,
|
||||
input: Input,
|
||||
ping: Ping,
|
||||
resizeTerminal: ResizeTerminal,
|
||||
}
|
||||
} else {
|
||||
c.message = &gottyMessageType{
|
||||
output: OutputV1,
|
||||
pong: PongV1,
|
||||
setWindowTitle: SetWindowTitleV1,
|
||||
setPreferences: SetPreferencesV1,
|
||||
setReconnect: SetReconnectV1,
|
||||
input: InputV1,
|
||||
ping: PingV1,
|
||||
resizeTerminal: ResizeTerminalV1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) pingLoop() {
|
||||
for {
|
||||
logrus.Debugf("Sending ping")
|
||||
c.write([]byte{c.message.ping})
|
||||
time.Sleep(30 * time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
// Close will nicely close the dialer
|
||||
func (c *Client) Close() {
|
||||
c.Conn.Close()
|
||||
}
|
||||
|
||||
// ExitLoop will kill all goroutines launched by c.Loop()
|
||||
// ExitLoop() -> wait Loop() -> Close()
|
||||
func (c *Client) ExitLoop() {
|
||||
fname := "ExitLoop"
|
||||
openPoison(fname, c.poison)
|
||||
}
|
||||
|
||||
// Loop will look indefinitely for new messages
|
||||
func (c *Client) Loop() error {
|
||||
|
||||
if !c.Connected {
|
||||
err := c.Connect()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
term := console.Current()
|
||||
err := term.SetRaw()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error setting raw terminal: %v", err)
|
||||
}
|
||||
defer term.Reset()
|
||||
|
||||
wg := &sync.WaitGroup{}
|
||||
|
||||
wg.Add(1)
|
||||
go c.termsizeLoop(wg)
|
||||
|
||||
wg.Add(1)
|
||||
go c.readLoop(wg)
|
||||
|
||||
wg.Add(1)
|
||||
go c.writeLoop(wg)
|
||||
|
||||
/* Wait for all of the above goroutines to finish */
|
||||
wg.Wait()
|
||||
|
||||
logrus.Debug("Client.Loop() exiting")
|
||||
return nil
|
||||
}
|
||||
|
||||
type winsize struct {
|
||||
Rows uint16 `json:"rows"`
|
||||
Columns uint16 `json:"columns"`
|
||||
// unused
|
||||
x uint16
|
||||
y uint16
|
||||
}
|
||||
|
||||
type posionReason int
|
||||
|
||||
const (
|
||||
committedSuicide = iota
|
||||
killed
|
||||
)
|
||||
|
||||
func openPoison(fname string, poison chan bool) posionReason {
|
||||
logrus.Debug(fname + " suicide")
|
||||
|
||||
/*
|
||||
* The close() may raise panic if multiple goroutines commit suicide at the
|
||||
* same time. Prevent that panic from bubbling up.
|
||||
*/
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
logrus.Debug("Prevented panic() of simultaneous suicides", r)
|
||||
}
|
||||
}()
|
||||
|
||||
/* Signal others to die */
|
||||
close(poison)
|
||||
return committedSuicide
|
||||
}
|
||||
|
||||
func die(fname string, poison chan bool) posionReason {
|
||||
logrus.Debug(fname + " died")
|
||||
|
||||
wasOpen := <-poison
|
||||
if wasOpen {
|
||||
logrus.Error("ERROR: The channel was open when it wasn't suppoed to be")
|
||||
}
|
||||
|
||||
return killed
|
||||
}
|
||||
|
||||
func (c *Client) termsizeLoop(wg *sync.WaitGroup) posionReason {
|
||||
defer wg.Done()
|
||||
fname := "termsizeLoop"
|
||||
|
||||
ch := make(chan os.Signal, 1)
|
||||
notifySignalSIGWINCH(ch)
|
||||
defer resetSignalSIGWINCH()
|
||||
|
||||
for {
|
||||
if b, err := syscallTIOCGWINSZ(); err != nil {
|
||||
logrus.Warn(err)
|
||||
} else {
|
||||
if err = c.write(append([]byte{c.message.resizeTerminal}, b...)); err != nil {
|
||||
logrus.Warnf("ws.WriteMessage failed: %v", err)
|
||||
}
|
||||
}
|
||||
select {
|
||||
case <-c.poison:
|
||||
/* Somebody poisoned the well; die */
|
||||
return die(fname, c.poison)
|
||||
case <-ch:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type exposeFd interface {
|
||||
Fd() uintptr
|
||||
}
|
||||
|
||||
func (c *Client) writeLoop(wg *sync.WaitGroup) posionReason {
|
||||
defer wg.Done()
|
||||
fname := "writeLoop"
|
||||
|
||||
buff := make([]byte, 128)
|
||||
|
||||
rdfs := &goselect.FDSet{}
|
||||
reader := io.ReadCloser(os.Stdin)
|
||||
|
||||
pr := NewEscapeProxy(reader, c.EscapeKeys)
|
||||
defer reader.Close()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-c.poison:
|
||||
/* Somebody poisoned the well; die */
|
||||
return die(fname, c.poison)
|
||||
default:
|
||||
}
|
||||
|
||||
rdfs.Zero()
|
||||
rdfs.Set(reader.(exposeFd).Fd())
|
||||
err := goselect.Select(1, rdfs, nil, nil, 50*time.Millisecond)
|
||||
if err != nil {
|
||||
return openPoison(fname, c.poison)
|
||||
}
|
||||
if rdfs.IsSet(reader.(exposeFd).Fd()) {
|
||||
size, err := pr.Read(buff)
|
||||
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
// Send EOF to GoTTY
|
||||
|
||||
// Send 'Input' marker, as defined in GoTTY::client_context.go,
|
||||
// followed by EOT (a translation of Ctrl-D for terminals)
|
||||
err = c.write(append([]byte{c.message.input}, byte(4)))
|
||||
|
||||
if err != nil {
|
||||
return openPoison(fname, c.poison)
|
||||
}
|
||||
continue
|
||||
} else {
|
||||
return openPoison(fname, c.poison)
|
||||
}
|
||||
}
|
||||
|
||||
if size <= 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
data := buff[:size]
|
||||
err = c.write(append([]byte{c.message.input}, data...))
|
||||
if err != nil {
|
||||
return openPoison(fname, c.poison)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (c *Client) readLoop(wg *sync.WaitGroup) posionReason {
|
||||
defer wg.Done()
|
||||
fname := "readLoop"
|
||||
|
||||
type MessageNonBlocking struct {
|
||||
Data []byte
|
||||
Err error
|
||||
}
|
||||
msgChan := make(chan MessageNonBlocking)
|
||||
|
||||
for {
|
||||
go func() {
|
||||
_, data, err := c.Conn.ReadMessage()
|
||||
msgChan <- MessageNonBlocking{Data: data, Err: err}
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-c.poison:
|
||||
/* Somebody poisoned the well; die */
|
||||
return die(fname, c.poison)
|
||||
case msg := <-msgChan:
|
||||
if msg.Err != nil {
|
||||
|
||||
if _, ok := msg.Err.(*websocket.CloseError); !ok {
|
||||
logrus.Warnf("c.Conn.ReadMessage: %v", msg.Err)
|
||||
}
|
||||
return openPoison(fname, c.poison)
|
||||
}
|
||||
if len(msg.Data) == 0 {
|
||||
|
||||
logrus.Warnf("An error has occured")
|
||||
return openPoison(fname, c.poison)
|
||||
}
|
||||
switch msg.Data[0] {
|
||||
case c.message.output: // data
|
||||
buf, err := base64.StdEncoding.DecodeString(string(msg.Data[1:]))
|
||||
if err != nil {
|
||||
logrus.Warnf("Invalid base64 content: %q", msg.Data[1:])
|
||||
break
|
||||
}
|
||||
c.Output.Write(buf)
|
||||
case c.message.pong: // pong
|
||||
case c.message.setWindowTitle: // new title
|
||||
newTitle := string(msg.Data[1:])
|
||||
fmt.Fprintf(c.Output, "\033]0;%s\007", newTitle)
|
||||
case c.message.setPreferences: // json prefs
|
||||
logrus.Debugf("Unhandled protocol message: json pref: %s", string(msg.Data[1:]))
|
||||
case c.message.setReconnect: // autoreconnect
|
||||
logrus.Debugf("Unhandled protocol message: autoreconnect: %s", string(msg.Data))
|
||||
default:
|
||||
logrus.Warnf("Unhandled protocol message: %s", string(msg.Data))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SetOutput changes the output stream
|
||||
func (c *Client) SetOutput(w io.Writer) {
|
||||
c.Output = w
|
||||
}
|
||||
|
||||
// ParseURL parses an URL which may be incomplete and tries to standardize it
|
||||
func ParseURL(input string) (string, error) {
|
||||
parsed, err := url.Parse(input)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
switch parsed.Scheme {
|
||||
case "http", "https":
|
||||
// everything is ok
|
||||
default:
|
||||
return ParseURL(fmt.Sprintf("http://%s", input))
|
||||
}
|
||||
return parsed.String(), nil
|
||||
}
|
||||
|
||||
// NewClient returns a GoTTY client object
|
||||
func NewClient(inputURL string) (*Client, error) {
|
||||
url, err := ParseURL(inputURL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Client{
|
||||
Dialer: &websocket.Dialer{},
|
||||
URL: url,
|
||||
WriteMutex: &sync.Mutex{},
|
||||
Output: os.Stdout,
|
||||
poison: make(chan bool),
|
||||
}, nil
|
||||
}
|
93
src/cmd/linuxkit/vendor/github.com/moul/gotty-client/proxy.go
generated
vendored
Normal file
93
src/cmd/linuxkit/vendor/github.com/moul/gotty-client/proxy.go
generated
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
// Copyright 2013-2017 Docker, 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.
|
||||
|
||||
// CHANGES:
|
||||
// - update package
|
||||
|
||||
package gottyclient
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
// EscapeError is special error which returned by a TTY proxy reader's Read()
|
||||
// method in case its detach escape sequence is read.
|
||||
type EscapeError struct{}
|
||||
|
||||
func (EscapeError) Error() string {
|
||||
return "read escape sequence"
|
||||
}
|
||||
|
||||
// escapeProxy is used only for attaches with a TTY. It is used to proxy
|
||||
// stdin keypresses from the underlying reader and look for the passed in
|
||||
// escape key sequence to signal a detach.
|
||||
type escapeProxy struct {
|
||||
escapeKeys []byte
|
||||
escapeKeyPos int
|
||||
r io.Reader
|
||||
}
|
||||
|
||||
// NewEscapeProxy returns a new TTY proxy reader which wraps the given reader
|
||||
// and detects when the specified escape keys are read, in which case the Read
|
||||
// method will return an error of type EscapeError.
|
||||
func NewEscapeProxy(r io.Reader, escapeKeys []byte) io.Reader {
|
||||
return &escapeProxy{
|
||||
escapeKeys: escapeKeys,
|
||||
r: r,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *escapeProxy) Read(buf []byte) (int, error) {
|
||||
nr, err := r.r.Read(buf)
|
||||
|
||||
if len(r.escapeKeys) == 0 {
|
||||
return nr, err
|
||||
}
|
||||
|
||||
preserve := func() {
|
||||
// this preserves the original key presses in the passed in buffer
|
||||
nr += r.escapeKeyPos
|
||||
preserve := make([]byte, 0, r.escapeKeyPos+len(buf))
|
||||
preserve = append(preserve, r.escapeKeys[:r.escapeKeyPos]...)
|
||||
preserve = append(preserve, buf...)
|
||||
r.escapeKeyPos = 0
|
||||
copy(buf[0:nr], preserve)
|
||||
}
|
||||
|
||||
if nr != 1 || err != nil {
|
||||
if r.escapeKeyPos > 0 {
|
||||
preserve()
|
||||
}
|
||||
return nr, err
|
||||
}
|
||||
|
||||
if buf[0] != r.escapeKeys[r.escapeKeyPos] {
|
||||
if r.escapeKeyPos > 0 {
|
||||
preserve()
|
||||
}
|
||||
return nr, nil
|
||||
}
|
||||
|
||||
if r.escapeKeyPos == len(r.escapeKeys)-1 {
|
||||
return 0, EscapeError{}
|
||||
}
|
||||
|
||||
// Looks like we've got an escape key, but we need to match again on the next
|
||||
// read.
|
||||
// Store the current escape key we found so we can look for the next one on
|
||||
// the next read.
|
||||
// Since this is an escape key, make sure we don't let the caller read it
|
||||
// If later on we find that this is not the escape sequence, we'll add the
|
||||
// keys back
|
||||
r.escapeKeyPos++
|
||||
return nr - r.escapeKeyPos, nil
|
||||
}
|
21
src/cmd/linuxkit/vendor/github.com/renstrom/fuzzysearch/LICENSE
generated
vendored
Normal file
21
src/cmd/linuxkit/vendor/github.com/renstrom/fuzzysearch/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Peter Renström
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
43
src/cmd/linuxkit/vendor/github.com/renstrom/fuzzysearch/README.md
generated
vendored
Normal file
43
src/cmd/linuxkit/vendor/github.com/renstrom/fuzzysearch/README.md
generated
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
# Fuzzy Search
|
||||
|
||||
[](https://travis-ci.org/renstrom/fuzzysearch)
|
||||
[](https://godoc.org/github.com/renstrom/fuzzysearch/fuzzy)
|
||||
|
||||
Inspired by _[bevacqua/fuzzysearch][1]_, a fuzzy matching library written in JavaScript. But contains some extras like ranking using _[Levenshtein distance][2]_ (see [`RankMatch()`](https://godoc.org/github.com/renstrom/fuzzysearch/fuzzy#RankMatch)) and finding matches in a list of words (see [`Find()`](https://godoc.org/github.com/renstrom/fuzzysearch/fuzzy#Find)).
|
||||
|
||||
Fuzzy searching allows for flexibly matching a string with partial input, useful for filtering data very quickly based on lightweight user input.
|
||||
|
||||
The current implementation uses the algorithm suggested by Mr. Aleph, a russian compiler engineer working at V8.
|
||||
|
||||
## Usage
|
||||
|
||||
```go
|
||||
fuzzy.Match("twl", "cartwheel") // true
|
||||
fuzzy.Match("cart", "cartwheel") // true
|
||||
fuzzy.Match("cw", "cartwheel") // true
|
||||
fuzzy.Match("ee", "cartwheel") // true
|
||||
fuzzy.Match("art", "cartwheel") // true
|
||||
fuzzy.Match("eeel", "cartwheel") // false
|
||||
fuzzy.Match("dog", "cartwheel") // false
|
||||
|
||||
fuzzy.RankMatch("kitten", "sitting") // 3
|
||||
|
||||
words := []string{"cartwheel", "foobar", "wheel", "baz"}
|
||||
fuzzy.Find("whl", words) // [cartwheel wheel]
|
||||
|
||||
fuzzy.RankFind("whl", words) // [{whl cartwheel 6} {whl wheel 2}]
|
||||
```
|
||||
|
||||
You can sort the result of a `fuzzy.RankFind()` call using the [`sort`](https://golang.org/pkg/sort/) package in the standard library:
|
||||
|
||||
```go
|
||||
matches := fuzzy.RankFind("whl", words) // [{whl cartwheel 6} {whl wheel 2}]
|
||||
sort.Sort(matches) // [{whl wheel 2} {whl cartwheel 6}]
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
|
||||
[1]: https://github.com/bevacqua/fuzzysearch
|
||||
[2]: http://en.wikipedia.org/wiki/Levenshtein_distance
|
167
src/cmd/linuxkit/vendor/github.com/renstrom/fuzzysearch/fuzzy/fuzzy.go
generated
vendored
Normal file
167
src/cmd/linuxkit/vendor/github.com/renstrom/fuzzysearch/fuzzy/fuzzy.go
generated
vendored
Normal file
@@ -0,0 +1,167 @@
|
||||
// Fuzzy searching allows for flexibly matching a string with partial input,
|
||||
// useful for filtering data very quickly based on lightweight user input.
|
||||
package fuzzy
|
||||
|
||||
import (
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
var noop = func(r rune) rune { return r }
|
||||
|
||||
// Match returns true if source matches target using a fuzzy-searching
|
||||
// algorithm. Note that it doesn't implement Levenshtein distance (see
|
||||
// RankMatch instead), but rather a simplified version where there's no
|
||||
// approximation. The method will return true only if each character in the
|
||||
// source can be found in the target and occurs after the preceding matches.
|
||||
func Match(source, target string) bool {
|
||||
return match(source, target, noop)
|
||||
}
|
||||
|
||||
// MatchFold is a case-insensitive version of Match.
|
||||
func MatchFold(source, target string) bool {
|
||||
return match(source, target, unicode.ToLower)
|
||||
}
|
||||
|
||||
func match(source, target string, fn func(rune) rune) bool {
|
||||
lenDiff := len(target) - len(source)
|
||||
|
||||
if lenDiff < 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
if lenDiff == 0 && source == target {
|
||||
return true
|
||||
}
|
||||
|
||||
Outer:
|
||||
for _, r1 := range source {
|
||||
for i, r2 := range target {
|
||||
if fn(r1) == fn(r2) {
|
||||
target = target[i+utf8.RuneLen(r2):]
|
||||
continue Outer
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// Find will return a list of strings in targets that fuzzy matches source.
|
||||
func Find(source string, targets []string) []string {
|
||||
return find(source, targets, noop)
|
||||
}
|
||||
|
||||
// FindFold is a case-insensitive version of Find.
|
||||
func FindFold(source string, targets []string) []string {
|
||||
return find(source, targets, unicode.ToLower)
|
||||
}
|
||||
|
||||
func find(source string, targets []string, fn func(rune) rune) []string {
|
||||
var matches []string
|
||||
|
||||
for _, target := range targets {
|
||||
if match(source, target, fn) {
|
||||
matches = append(matches, target)
|
||||
}
|
||||
}
|
||||
|
||||
return matches
|
||||
}
|
||||
|
||||
// RankMatch is similar to Match except it will measure the Levenshtein
|
||||
// distance between the source and the target and return its result. If there
|
||||
// was no match, it will return -1.
|
||||
// Given the requirements of match, RankMatch only needs to perform a subset of
|
||||
// the Levenshtein calculation, only deletions need be considered, required
|
||||
// additions and substitutions would fail the match test.
|
||||
func RankMatch(source, target string) int {
|
||||
return rank(source, target, noop)
|
||||
}
|
||||
|
||||
// RankMatchFold is a case-insensitive version of RankMatch.
|
||||
func RankMatchFold(source, target string) int {
|
||||
return rank(source, target, unicode.ToLower)
|
||||
}
|
||||
|
||||
func rank(source, target string, fn func(rune) rune) int {
|
||||
lenDiff := len(target) - len(source)
|
||||
|
||||
if lenDiff < 0 {
|
||||
return -1
|
||||
}
|
||||
|
||||
if lenDiff == 0 && source == target {
|
||||
return 0
|
||||
}
|
||||
|
||||
runeDiff := 0
|
||||
|
||||
Outer:
|
||||
for _, r1 := range source {
|
||||
for i, r2 := range target {
|
||||
if fn(r1) == fn(r2) {
|
||||
target = target[i+utf8.RuneLen(r2):]
|
||||
continue Outer
|
||||
} else {
|
||||
runeDiff++
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
// Count up remaining char
|
||||
for len(target) > 0 {
|
||||
target = target[utf8.RuneLen(rune(target[0])):]
|
||||
runeDiff++
|
||||
}
|
||||
|
||||
return runeDiff
|
||||
}
|
||||
|
||||
// RankFind is similar to Find, except it will also rank all matches using
|
||||
// Levenshtein distance.
|
||||
func RankFind(source string, targets []string) Ranks {
|
||||
var r Ranks
|
||||
for _, target := range find(source, targets, noop) {
|
||||
distance := LevenshteinDistance(source, target)
|
||||
r = append(r, Rank{source, target, distance})
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// RankFindFold is a case-insensitive version of RankFind.
|
||||
func RankFindFold(source string, targets []string) Ranks {
|
||||
var r Ranks
|
||||
for _, target := range find(source, targets, unicode.ToLower) {
|
||||
distance := LevenshteinDistance(source, target)
|
||||
r = append(r, Rank{source, target, distance})
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
type Rank struct {
|
||||
// Source is used as the source for matching.
|
||||
Source string
|
||||
|
||||
// Target is the word matched against.
|
||||
Target string
|
||||
|
||||
// Distance is the Levenshtein distance between Source and Target.
|
||||
Distance int
|
||||
}
|
||||
|
||||
type Ranks []Rank
|
||||
|
||||
func (r Ranks) Len() int {
|
||||
return len(r)
|
||||
}
|
||||
|
||||
func (r Ranks) Swap(i, j int) {
|
||||
r[i], r[j] = r[j], r[i]
|
||||
}
|
||||
|
||||
func (r Ranks) Less(i, j int) bool {
|
||||
return r[i].Distance < r[j].Distance
|
||||
}
|
43
src/cmd/linuxkit/vendor/github.com/renstrom/fuzzysearch/fuzzy/levenshtein.go
generated
vendored
Normal file
43
src/cmd/linuxkit/vendor/github.com/renstrom/fuzzysearch/fuzzy/levenshtein.go
generated
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
package fuzzy
|
||||
|
||||
// LevenshteinDistance measures the difference between two strings.
|
||||
// The Levenshtein distance between two words is the minimum number of
|
||||
// single-character edits (i.e. insertions, deletions or substitutions)
|
||||
// required to change one word into the other.
|
||||
//
|
||||
// This implemention is optimized to use O(min(m,n)) space and is based on the
|
||||
// optimized C version found here:
|
||||
// http://en.wikibooks.org/wiki/Algorithm_implementation/Strings/Levenshtein_distance#C
|
||||
func LevenshteinDistance(s, t string) int {
|
||||
r1, r2 := []rune(s), []rune(t)
|
||||
column := make([]int, len(r1)+1)
|
||||
|
||||
for y := 1; y <= len(r1); y++ {
|
||||
column[y] = y
|
||||
}
|
||||
|
||||
for x := 1; x <= len(r2); x++ {
|
||||
column[0] = x
|
||||
|
||||
for y, lastDiag := 1, x-1; y <= len(r1); y++ {
|
||||
oldDiag := column[y]
|
||||
cost := 0
|
||||
if r1[y-1] != r2[x-1] {
|
||||
cost = 1
|
||||
}
|
||||
column[y] = min(column[y]+1, column[y-1]+1, lastDiag+cost)
|
||||
lastDiag = oldDiag
|
||||
}
|
||||
}
|
||||
|
||||
return column[len(r1)]
|
||||
}
|
||||
|
||||
func min(a, b, c int) int {
|
||||
if a < b && a < c {
|
||||
return a
|
||||
} else if b < c {
|
||||
return b
|
||||
}
|
||||
return c
|
||||
}
|
21
src/cmd/linuxkit/vendor/github.com/scaleway/go-scaleway/LICENSE
generated
vendored
Normal file
21
src/cmd/linuxkit/vendor/github.com/scaleway/go-scaleway/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018 Scaleway
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
27
src/cmd/linuxkit/vendor/github.com/scaleway/go-scaleway/README.md
generated
vendored
Normal file
27
src/cmd/linuxkit/vendor/github.com/scaleway/go-scaleway/README.md
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
# Scaleway's API golang client
|
||||
|
||||
[](https://godoc.org/github.com/scaleway/go-scaleway)
|
||||
|
||||
This package contains facilities to play with the Scaleway API, it includes the following features:
|
||||
|
||||
- dedicated configuration file containing credentials to deal with the API
|
||||
- caching to resolve UUIDs without contacting the API
|
||||
|
||||
## Links
|
||||
|
||||
- [API documentation](https://developer.scaleway.com)
|
||||
- [Official Python SDK](https://github.com/scaleway/python-scaleway)
|
||||
- Projects using this SDK
|
||||
- https://github.com/scaleway/scaleway-cli
|
||||
- https://github.com/scaleway/devhub
|
||||
- https://github.com/scaleway/docker-machine-driver-scaleway
|
||||
- https://github.com/huseyin/docker-machine-driver-scaleway
|
||||
- https://github.com/scaleway-community/scaleway-ubuntu-coreos/blob/master/overlay/usr/local/update-firewall/scw-api/cache.go
|
||||
- https://github.com/pulcy/quark
|
||||
- https://github.com/hex-sh/terraform-provider-scaleway
|
||||
- https://github.com/tscolari/bosh-scaleway-cpi
|
||||
- Other **golang** clients
|
||||
- https://github.com/lalyos/onlabs
|
||||
- https://github.com/meatballhat/packer-builder-onlinelabs
|
||||
- https://github.com/nlamirault/go-scaleway
|
||||
- https://github.com/golang/build/blob/master/cmd/scaleway/scaleway.go
|
2003
src/cmd/linuxkit/vendor/github.com/scaleway/go-scaleway/api.go
generated
vendored
Normal file
2003
src/cmd/linuxkit/vendor/github.com/scaleway/go-scaleway/api.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
693
src/cmd/linuxkit/vendor/github.com/scaleway/go-scaleway/cache/cache.go
generated
vendored
Normal file
693
src/cmd/linuxkit/vendor/github.com/scaleway/go-scaleway/cache/cache.go
generated
vendored
Normal file
@@ -0,0 +1,693 @@
|
||||
// Copyright (C) 2018 Scaleway. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE.md file.
|
||||
|
||||
package cache
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/moul/anonuuid"
|
||||
"github.com/renstrom/fuzzysearch/fuzzy"
|
||||
"github.com/scaleway/go-scaleway/types"
|
||||
)
|
||||
|
||||
const (
|
||||
// CacheRegion permits to access at the region field
|
||||
CacheRegion = iota
|
||||
// CacheArch permits to access at the arch field
|
||||
CacheArch
|
||||
// CacheOwner permits to access at the owner field
|
||||
CacheOwner
|
||||
// CacheTitle permits to access at the title field
|
||||
CacheTitle
|
||||
// CacheMarketPlaceUUID is used to determine the UUID of local images
|
||||
CacheMarketPlaceUUID
|
||||
// CacheMaxfield is used to determine the size of array
|
||||
CacheMaxfield
|
||||
)
|
||||
|
||||
// ScalewayCache is used not to query the API to resolve full identifiers
|
||||
type ScalewayCache struct {
|
||||
// Images contains names of Scaleway images indexed by identifier
|
||||
Images map[string][CacheMaxfield]string `json:"images"`
|
||||
|
||||
// Snapshots contains names of Scaleway snapshots indexed by identifier
|
||||
Snapshots map[string][CacheMaxfield]string `json:"snapshots"`
|
||||
|
||||
// Volumes contains names of Scaleway volumes indexed by identifier
|
||||
Volumes map[string][CacheMaxfield]string `json:"volumes"`
|
||||
|
||||
// Bootscripts contains names of Scaleway bootscripts indexed by identifier
|
||||
Bootscripts map[string][CacheMaxfield]string `json:"bootscripts"`
|
||||
|
||||
// Servers contains names of Scaleway servers indexed by identifier
|
||||
Servers map[string][CacheMaxfield]string `json:"servers"`
|
||||
|
||||
// Path is the path to the cache file
|
||||
Path string `json:"-"`
|
||||
|
||||
// Modified tells if the cache needs to be overwritten or not
|
||||
Modified bool `json:"-"`
|
||||
|
||||
// Lock allows ScalewayCache to be used concurrently
|
||||
Lock sync.Mutex `json:"-"`
|
||||
|
||||
hookSave func()
|
||||
}
|
||||
|
||||
// NewScalewayCache loads a per-user cache
|
||||
func NewScalewayCache(hookSave func()) (*ScalewayCache, error) {
|
||||
var cache ScalewayCache
|
||||
|
||||
cache.hookSave = hookSave
|
||||
homeDir := os.Getenv("HOME") // *nix
|
||||
if homeDir == "" { // Windows
|
||||
homeDir = os.Getenv("USERPROFILE")
|
||||
}
|
||||
if homeDir == "" {
|
||||
homeDir = "/tmp"
|
||||
}
|
||||
cachePath := filepath.Join(homeDir, ".scw-cache.db")
|
||||
cache.Path = cachePath
|
||||
_, err := os.Stat(cachePath)
|
||||
if os.IsNotExist(err) {
|
||||
cache.Clear()
|
||||
return &cache, nil
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
file, err := ioutil.ReadFile(cachePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = json.Unmarshal(file, &cache)
|
||||
if err != nil {
|
||||
// fix compatibility with older version
|
||||
if err = os.Remove(cachePath); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cache.Clear()
|
||||
return &cache, nil
|
||||
}
|
||||
if cache.Images == nil {
|
||||
cache.Images = make(map[string][CacheMaxfield]string)
|
||||
}
|
||||
if cache.Snapshots == nil {
|
||||
cache.Snapshots = make(map[string][CacheMaxfield]string)
|
||||
}
|
||||
if cache.Volumes == nil {
|
||||
cache.Volumes = make(map[string][CacheMaxfield]string)
|
||||
}
|
||||
if cache.Servers == nil {
|
||||
cache.Servers = make(map[string][CacheMaxfield]string)
|
||||
}
|
||||
if cache.Bootscripts == nil {
|
||||
cache.Bootscripts = make(map[string][CacheMaxfield]string)
|
||||
}
|
||||
return &cache, nil
|
||||
}
|
||||
|
||||
// Clear removes all information from the cache
|
||||
func (c *ScalewayCache) Clear() {
|
||||
c.Images = make(map[string][CacheMaxfield]string)
|
||||
c.Snapshots = make(map[string][CacheMaxfield]string)
|
||||
c.Volumes = make(map[string][CacheMaxfield]string)
|
||||
c.Bootscripts = make(map[string][CacheMaxfield]string)
|
||||
c.Servers = make(map[string][CacheMaxfield]string)
|
||||
c.Modified = true
|
||||
}
|
||||
|
||||
// Flush flushes the cache database
|
||||
func (c *ScalewayCache) Flush() error {
|
||||
return os.Remove(c.Path)
|
||||
}
|
||||
|
||||
// Save atomically overwrites the current cache database
|
||||
func (c *ScalewayCache) Save() error {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
c.hookSave()
|
||||
if c.Modified {
|
||||
file, err := ioutil.TempFile(filepath.Dir(c.Path), filepath.Base(c.Path))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := json.NewEncoder(file).Encode(c); err != nil {
|
||||
file.Close()
|
||||
os.Remove(file.Name())
|
||||
return err
|
||||
}
|
||||
|
||||
file.Close()
|
||||
if err := os.Rename(file.Name(), c.Path); err != nil {
|
||||
os.Remove(file.Name())
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ComputeRankMatch fills `ScalewayResolverResult.RankMatch` with its `fuzzy` score
|
||||
func ComputeRankMatch(s *types.ScalewayResolverResult, needle string) {
|
||||
s.Needle = needle
|
||||
s.RankMatch = fuzzy.RankMatch(needle, s.Name)
|
||||
}
|
||||
|
||||
// LookUpImages attempts to return identifiers matching a pattern
|
||||
func (c *ScalewayCache) LookUpImages(needle string, acceptUUID bool) (types.ScalewayResolverResults, error) {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
var res types.ScalewayResolverResults
|
||||
var exactMatches types.ScalewayResolverResults
|
||||
|
||||
if acceptUUID && anonuuid.IsUUID(needle) == nil {
|
||||
if fields, ok := c.Images[needle]; ok {
|
||||
entry, err := types.NewScalewayResolverResult(needle, fields[CacheTitle], fields[CacheArch], fields[CacheRegion], types.IdentifierImage)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
ComputeRankMatch(&entry, needle)
|
||||
res = append(res, entry)
|
||||
}
|
||||
}
|
||||
|
||||
needle = regexp.MustCompile(`^user/`).ReplaceAllString(needle, "")
|
||||
// FIXME: if 'user/' is in needle, only watch for a user image
|
||||
nameRegex := regexp.MustCompile(`(?i)` + regexp.MustCompile(`[_-]`).ReplaceAllString(needle, ".*"))
|
||||
for identifier, fields := range c.Images {
|
||||
if fields[CacheTitle] == needle {
|
||||
entry, err := types.NewScalewayResolverResult(identifier, fields[CacheTitle], fields[CacheArch], fields[CacheRegion], types.IdentifierImage)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
ComputeRankMatch(&entry, needle)
|
||||
exactMatches = append(exactMatches, entry)
|
||||
}
|
||||
if strings.HasPrefix(identifier, needle) || nameRegex.MatchString(fields[CacheTitle]) {
|
||||
entry, err := types.NewScalewayResolverResult(identifier, fields[CacheTitle], fields[CacheArch], fields[CacheRegion], types.IdentifierImage)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
ComputeRankMatch(&entry, needle)
|
||||
res = append(res, entry)
|
||||
} else if strings.HasPrefix(fields[CacheMarketPlaceUUID], needle) || nameRegex.MatchString(fields[CacheMarketPlaceUUID]) {
|
||||
entry, err := types.NewScalewayResolverResult(identifier, fields[CacheTitle], fields[CacheArch], fields[CacheRegion], types.IdentifierImage)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
ComputeRankMatch(&entry, needle)
|
||||
res = append(res, entry)
|
||||
}
|
||||
}
|
||||
|
||||
if len(exactMatches) == 1 {
|
||||
return exactMatches, nil
|
||||
}
|
||||
|
||||
return removeDuplicatesResults(res), nil
|
||||
}
|
||||
|
||||
// LookUpSnapshots attempts to return identifiers matching a pattern
|
||||
func (c *ScalewayCache) LookUpSnapshots(needle string, acceptUUID bool) (types.ScalewayResolverResults, error) {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
var res types.ScalewayResolverResults
|
||||
var exactMatches types.ScalewayResolverResults
|
||||
|
||||
if acceptUUID && anonuuid.IsUUID(needle) == nil {
|
||||
if fields, ok := c.Snapshots[needle]; ok {
|
||||
entry, err := types.NewScalewayResolverResult(needle, fields[CacheTitle], fields[CacheArch], fields[CacheRegion], types.IdentifierSnapshot)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
ComputeRankMatch(&entry, needle)
|
||||
res = append(res, entry)
|
||||
}
|
||||
}
|
||||
|
||||
needle = regexp.MustCompile(`^user/`).ReplaceAllString(needle, "")
|
||||
nameRegex := regexp.MustCompile(`(?i)` + regexp.MustCompile(`[_-]`).ReplaceAllString(needle, ".*"))
|
||||
for identifier, fields := range c.Snapshots {
|
||||
if fields[CacheTitle] == needle {
|
||||
entry, err := types.NewScalewayResolverResult(identifier, fields[CacheTitle], fields[CacheArch], fields[CacheRegion], types.IdentifierSnapshot)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
ComputeRankMatch(&entry, needle)
|
||||
exactMatches = append(exactMatches, entry)
|
||||
}
|
||||
if strings.HasPrefix(identifier, needle) || nameRegex.MatchString(fields[CacheTitle]) {
|
||||
entry, err := types.NewScalewayResolverResult(identifier, fields[CacheTitle], fields[CacheArch], fields[CacheRegion], types.IdentifierSnapshot)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
ComputeRankMatch(&entry, needle)
|
||||
res = append(res, entry)
|
||||
}
|
||||
}
|
||||
|
||||
if len(exactMatches) == 1 {
|
||||
return exactMatches, nil
|
||||
}
|
||||
|
||||
return removeDuplicatesResults(res), nil
|
||||
}
|
||||
|
||||
// LookUpVolumes attempts to return identifiers matching a pattern
|
||||
func (c *ScalewayCache) LookUpVolumes(needle string, acceptUUID bool) (types.ScalewayResolverResults, error) {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
var res types.ScalewayResolverResults
|
||||
var exactMatches types.ScalewayResolverResults
|
||||
|
||||
if acceptUUID && anonuuid.IsUUID(needle) == nil {
|
||||
if fields, ok := c.Volumes[needle]; ok {
|
||||
entry, err := types.NewScalewayResolverResult(needle, fields[CacheTitle], fields[CacheArch], fields[CacheRegion], types.IdentifierVolume)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
ComputeRankMatch(&entry, needle)
|
||||
res = append(res, entry)
|
||||
}
|
||||
}
|
||||
|
||||
nameRegex := regexp.MustCompile(`(?i)` + regexp.MustCompile(`[_-]`).ReplaceAllString(needle, ".*"))
|
||||
for identifier, fields := range c.Volumes {
|
||||
if fields[CacheTitle] == needle {
|
||||
entry, err := types.NewScalewayResolverResult(identifier, fields[CacheTitle], fields[CacheArch], fields[CacheRegion], types.IdentifierVolume)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
ComputeRankMatch(&entry, needle)
|
||||
exactMatches = append(exactMatches, entry)
|
||||
}
|
||||
if strings.HasPrefix(identifier, needle) || nameRegex.MatchString(fields[CacheTitle]) {
|
||||
entry, err := types.NewScalewayResolverResult(identifier, fields[CacheTitle], fields[CacheArch], fields[CacheRegion], types.IdentifierVolume)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
ComputeRankMatch(&entry, needle)
|
||||
res = append(res, entry)
|
||||
}
|
||||
}
|
||||
|
||||
if len(exactMatches) == 1 {
|
||||
return exactMatches, nil
|
||||
}
|
||||
|
||||
return removeDuplicatesResults(res), nil
|
||||
}
|
||||
|
||||
// LookUpBootscripts attempts to return identifiers matching a pattern
|
||||
func (c *ScalewayCache) LookUpBootscripts(needle string, acceptUUID bool) (types.ScalewayResolverResults, error) {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
var res types.ScalewayResolverResults
|
||||
var exactMatches types.ScalewayResolverResults
|
||||
|
||||
if acceptUUID && anonuuid.IsUUID(needle) == nil {
|
||||
if fields, ok := c.Bootscripts[needle]; ok {
|
||||
entry, err := types.NewScalewayResolverResult(needle, fields[CacheTitle], fields[CacheArch], fields[CacheRegion], types.IdentifierBootscript)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
ComputeRankMatch(&entry, needle)
|
||||
res = append(res, entry)
|
||||
}
|
||||
}
|
||||
|
||||
nameRegex := regexp.MustCompile(`(?i)` + regexp.MustCompile(`[_-]`).ReplaceAllString(needle, ".*"))
|
||||
for identifier, fields := range c.Bootscripts {
|
||||
if fields[CacheTitle] == needle {
|
||||
entry, err := types.NewScalewayResolverResult(identifier, fields[CacheTitle], fields[CacheArch], fields[CacheRegion], types.IdentifierBootscript)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
ComputeRankMatch(&entry, needle)
|
||||
exactMatches = append(exactMatches, entry)
|
||||
}
|
||||
if strings.HasPrefix(identifier, needle) || nameRegex.MatchString(fields[CacheTitle]) {
|
||||
entry, err := types.NewScalewayResolverResult(identifier, fields[CacheTitle], fields[CacheArch], fields[CacheRegion], types.IdentifierBootscript)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
ComputeRankMatch(&entry, needle)
|
||||
res = append(res, entry)
|
||||
}
|
||||
}
|
||||
|
||||
if len(exactMatches) == 1 {
|
||||
return exactMatches, nil
|
||||
}
|
||||
|
||||
return removeDuplicatesResults(res), nil
|
||||
}
|
||||
|
||||
// LookUpServers attempts to return identifiers matching a pattern
|
||||
func (c *ScalewayCache) LookUpServers(needle string, acceptUUID bool) (types.ScalewayResolverResults, error) {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
var res types.ScalewayResolverResults
|
||||
var exactMatches types.ScalewayResolverResults
|
||||
|
||||
if acceptUUID && anonuuid.IsUUID(needle) == nil {
|
||||
if fields, ok := c.Servers[needle]; ok {
|
||||
entry, err := types.NewScalewayResolverResult(needle, fields[CacheTitle], fields[CacheArch], fields[CacheRegion], types.IdentifierServer)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
ComputeRankMatch(&entry, needle)
|
||||
res = append(res, entry)
|
||||
}
|
||||
}
|
||||
|
||||
nameRegex := regexp.MustCompile(`(?i)` + regexp.MustCompile(`[_-]`).ReplaceAllString(needle, ".*"))
|
||||
for identifier, fields := range c.Servers {
|
||||
if fields[CacheTitle] == needle {
|
||||
entry, err := types.NewScalewayResolverResult(identifier, fields[CacheTitle], fields[CacheArch], fields[CacheRegion], types.IdentifierServer)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
ComputeRankMatch(&entry, needle)
|
||||
exactMatches = append(exactMatches, entry)
|
||||
}
|
||||
if strings.HasPrefix(identifier, needle) || nameRegex.MatchString(fields[CacheTitle]) {
|
||||
entry, err := types.NewScalewayResolverResult(identifier, fields[CacheTitle], fields[CacheArch], fields[CacheRegion], types.IdentifierServer)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
ComputeRankMatch(&entry, needle)
|
||||
res = append(res, entry)
|
||||
}
|
||||
}
|
||||
|
||||
if len(exactMatches) == 1 {
|
||||
return exactMatches, nil
|
||||
}
|
||||
|
||||
return removeDuplicatesResults(res), nil
|
||||
}
|
||||
|
||||
// removeDuplicatesResults transforms an array into a unique array
|
||||
func removeDuplicatesResults(elements types.ScalewayResolverResults) types.ScalewayResolverResults {
|
||||
encountered := map[string]types.ScalewayResolverResult{}
|
||||
|
||||
// Create a map of all unique elements.
|
||||
for v := range elements {
|
||||
encountered[elements[v].Identifier] = elements[v]
|
||||
}
|
||||
|
||||
// Place all keys from the map into a slice.
|
||||
results := types.ScalewayResolverResults{}
|
||||
for _, result := range encountered {
|
||||
results = append(results, result)
|
||||
}
|
||||
return results
|
||||
}
|
||||
|
||||
// LookUpIdentifiers attempts to return identifiers matching a pattern
|
||||
func (c *ScalewayCache) LookUpIdentifiers(needle string) (types.ScalewayResolverResults, error) {
|
||||
results := types.ScalewayResolverResults{}
|
||||
|
||||
identifierType, needle := types.ParseNeedle(needle)
|
||||
|
||||
if identifierType&(types.IdentifierUnknown|types.IdentifierServer) > 0 {
|
||||
servers, err := c.LookUpServers(needle, false)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
for _, result := range servers {
|
||||
entry, err := types.NewScalewayResolverResult(result.Identifier, result.Name, result.Arch, result.Region, types.IdentifierServer)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
ComputeRankMatch(&entry, needle)
|
||||
results = append(results, entry)
|
||||
}
|
||||
}
|
||||
|
||||
if identifierType&(types.IdentifierUnknown|types.IdentifierImage) > 0 {
|
||||
images, err := c.LookUpImages(needle, false)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
for _, result := range images {
|
||||
entry, err := types.NewScalewayResolverResult(result.Identifier, result.Name, result.Arch, result.Region, types.IdentifierImage)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
ComputeRankMatch(&entry, needle)
|
||||
results = append(results, entry)
|
||||
}
|
||||
}
|
||||
|
||||
if identifierType&(types.IdentifierUnknown|types.IdentifierSnapshot) > 0 {
|
||||
snapshots, err := c.LookUpSnapshots(needle, false)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
for _, result := range snapshots {
|
||||
entry, err := types.NewScalewayResolverResult(result.Identifier, result.Name, result.Arch, result.Region, types.IdentifierSnapshot)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
ComputeRankMatch(&entry, needle)
|
||||
results = append(results, entry)
|
||||
}
|
||||
}
|
||||
|
||||
if identifierType&(types.IdentifierUnknown|types.IdentifierVolume) > 0 {
|
||||
volumes, err := c.LookUpVolumes(needle, false)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
for _, result := range volumes {
|
||||
entry, err := types.NewScalewayResolverResult(result.Identifier, result.Name, result.Arch, result.Region, types.IdentifierVolume)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
ComputeRankMatch(&entry, needle)
|
||||
results = append(results, entry)
|
||||
}
|
||||
}
|
||||
|
||||
if identifierType&(types.IdentifierUnknown|types.IdentifierBootscript) > 0 {
|
||||
bootscripts, err := c.LookUpBootscripts(needle, false)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
for _, result := range bootscripts {
|
||||
entry, err := types.NewScalewayResolverResult(result.Identifier, result.Name, result.Arch, result.Region, types.IdentifierBootscript)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
ComputeRankMatch(&entry, needle)
|
||||
results = append(results, entry)
|
||||
}
|
||||
}
|
||||
return results, nil
|
||||
}
|
||||
|
||||
// InsertServer registers a server in the cache
|
||||
func (c *ScalewayCache) InsertServer(identifier, region, arch, owner, name string) {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
fields, exists := c.Servers[identifier]
|
||||
if !exists || fields[CacheTitle] != name {
|
||||
c.Servers[identifier] = [CacheMaxfield]string{region, arch, owner, name}
|
||||
c.Modified = true
|
||||
}
|
||||
}
|
||||
|
||||
// RemoveServer removes a server from the cache
|
||||
func (c *ScalewayCache) RemoveServer(identifier string) {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
delete(c.Servers, identifier)
|
||||
c.Modified = true
|
||||
}
|
||||
|
||||
// ClearServers removes all servers from the cache
|
||||
func (c *ScalewayCache) ClearServers() {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
c.Servers = make(map[string][CacheMaxfield]string)
|
||||
c.Modified = true
|
||||
}
|
||||
|
||||
// InsertImage registers an image in the cache
|
||||
func (c *ScalewayCache) InsertImage(identifier, region, arch, owner, name, marketPlaceUUID string) {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
fields, exists := c.Images[identifier]
|
||||
if !exists || fields[CacheTitle] != name {
|
||||
c.Images[identifier] = [CacheMaxfield]string{region, arch, owner, name, marketPlaceUUID}
|
||||
c.Modified = true
|
||||
}
|
||||
}
|
||||
|
||||
// RemoveImage removes a server from the cache
|
||||
func (c *ScalewayCache) RemoveImage(identifier string) {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
delete(c.Images, identifier)
|
||||
c.Modified = true
|
||||
}
|
||||
|
||||
// ClearImages removes all images from the cache
|
||||
func (c *ScalewayCache) ClearImages() {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
c.Images = make(map[string][CacheMaxfield]string)
|
||||
c.Modified = true
|
||||
}
|
||||
|
||||
// InsertSnapshot registers an snapshot in the cache
|
||||
func (c *ScalewayCache) InsertSnapshot(identifier, region, arch, owner, name string) {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
fields, exists := c.Snapshots[identifier]
|
||||
if !exists || fields[CacheTitle] != name {
|
||||
c.Snapshots[identifier] = [CacheMaxfield]string{region, arch, owner, name}
|
||||
c.Modified = true
|
||||
}
|
||||
}
|
||||
|
||||
// RemoveSnapshot removes a server from the cache
|
||||
func (c *ScalewayCache) RemoveSnapshot(identifier string) {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
delete(c.Snapshots, identifier)
|
||||
c.Modified = true
|
||||
}
|
||||
|
||||
// ClearSnapshots removes all snapshots from the cache
|
||||
func (c *ScalewayCache) ClearSnapshots() {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
c.Snapshots = make(map[string][CacheMaxfield]string)
|
||||
c.Modified = true
|
||||
}
|
||||
|
||||
// InsertVolume registers an volume in the cache
|
||||
func (c *ScalewayCache) InsertVolume(identifier, region, arch, owner, name string) {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
fields, exists := c.Volumes[identifier]
|
||||
if !exists || fields[CacheTitle] != name {
|
||||
c.Volumes[identifier] = [CacheMaxfield]string{region, arch, owner, name}
|
||||
c.Modified = true
|
||||
}
|
||||
}
|
||||
|
||||
// RemoveVolume removes a server from the cache
|
||||
func (c *ScalewayCache) RemoveVolume(identifier string) {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
delete(c.Volumes, identifier)
|
||||
c.Modified = true
|
||||
}
|
||||
|
||||
// ClearVolumes removes all volumes from the cache
|
||||
func (c *ScalewayCache) ClearVolumes() {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
c.Volumes = make(map[string][CacheMaxfield]string)
|
||||
c.Modified = true
|
||||
}
|
||||
|
||||
// InsertBootscript registers an bootscript in the cache
|
||||
func (c *ScalewayCache) InsertBootscript(identifier, region, arch, owner, name string) {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
fields, exists := c.Bootscripts[identifier]
|
||||
if !exists || fields[CacheTitle] != name {
|
||||
c.Bootscripts[identifier] = [CacheMaxfield]string{region, arch, owner, name}
|
||||
c.Modified = true
|
||||
}
|
||||
}
|
||||
|
||||
// RemoveBootscript removes a bootscript from the cache
|
||||
func (c *ScalewayCache) RemoveBootscript(identifier string) {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
delete(c.Bootscripts, identifier)
|
||||
c.Modified = true
|
||||
}
|
||||
|
||||
// ClearBootscripts removes all bootscripts from the cache
|
||||
func (c *ScalewayCache) ClearBootscripts() {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
c.Bootscripts = make(map[string][CacheMaxfield]string)
|
||||
c.Modified = true
|
||||
}
|
||||
|
||||
// GetNbServers returns the number of servers in the cache
|
||||
func (c *ScalewayCache) GetNbServers() int {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
return len(c.Servers)
|
||||
}
|
||||
|
||||
// GetNbImages returns the number of images in the cache
|
||||
func (c *ScalewayCache) GetNbImages() int {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
return len(c.Images)
|
||||
}
|
||||
|
||||
// GetNbSnapshots returns the number of snapshots in the cache
|
||||
func (c *ScalewayCache) GetNbSnapshots() int {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
return len(c.Snapshots)
|
||||
}
|
||||
|
||||
// GetNbVolumes returns the number of volumes in the cache
|
||||
func (c *ScalewayCache) GetNbVolumes() int {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
return len(c.Volumes)
|
||||
}
|
||||
|
||||
// GetNbBootscripts returns the number of bootscripts in the cache
|
||||
func (c *ScalewayCache) GetNbBootscripts() int {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
return len(c.Bootscripts)
|
||||
}
|
77
src/cmd/linuxkit/vendor/github.com/scaleway/go-scaleway/logger/logger.go
generated
vendored
Normal file
77
src/cmd/linuxkit/vendor/github.com/scaleway/go-scaleway/logger/logger.go
generated
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
// Copyright (C) 2018 Scaleway. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE.md file.
|
||||
|
||||
package logger
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
)
|
||||
|
||||
// Logger handles logging concerns for the Scaleway API SDK
|
||||
type Logger interface {
|
||||
LogHTTP(*http.Request)
|
||||
Fatalf(format string, v ...interface{})
|
||||
Debugf(format string, v ...interface{})
|
||||
Infof(format string, v ...interface{})
|
||||
Warnf(format string, v ...interface{})
|
||||
}
|
||||
|
||||
// NewDefaultLogger returns a logger which is configured for stdout
|
||||
func NewDefaultLogger() Logger {
|
||||
return &defaultLogger{
|
||||
Logger: log.New(os.Stdout, "", log.LstdFlags),
|
||||
}
|
||||
}
|
||||
|
||||
type defaultLogger struct {
|
||||
*log.Logger
|
||||
}
|
||||
|
||||
func (l *defaultLogger) LogHTTP(r *http.Request) {
|
||||
l.Printf("%s %s\n", r.Method, r.URL.RawPath)
|
||||
}
|
||||
|
||||
func (l *defaultLogger) Fatalf(format string, v ...interface{}) {
|
||||
l.Printf("[FATAL] %s\n", fmt.Sprintf(format, v))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func (l *defaultLogger) Debugf(format string, v ...interface{}) {
|
||||
l.Printf("[DEBUG] %s\n", fmt.Sprintf(format, v))
|
||||
}
|
||||
|
||||
func (l *defaultLogger) Infof(format string, v ...interface{}) {
|
||||
l.Printf("[INFO ] %s\n", fmt.Sprintf(format, v))
|
||||
}
|
||||
|
||||
func (l *defaultLogger) Warnf(format string, v ...interface{}) {
|
||||
l.Printf("[WARN ] %s\n", fmt.Sprintf(format, v))
|
||||
}
|
||||
|
||||
type disableLogger struct {
|
||||
}
|
||||
|
||||
// NewDisableLogger returns a logger which is configured to do nothing
|
||||
func NewDisableLogger() Logger {
|
||||
return &disableLogger{}
|
||||
}
|
||||
|
||||
func (d *disableLogger) LogHTTP(r *http.Request) {
|
||||
}
|
||||
|
||||
func (d *disableLogger) Fatalf(format string, v ...interface{}) {
|
||||
panic(fmt.Sprintf(format, v))
|
||||
}
|
||||
|
||||
func (d *disableLogger) Debugf(format string, v ...interface{}) {
|
||||
}
|
||||
|
||||
func (d *disableLogger) Infof(format string, v ...interface{}) {
|
||||
}
|
||||
|
||||
func (d *disableLogger) Warnf(format string, v ...interface{}) {
|
||||
}
|
983
src/cmd/linuxkit/vendor/github.com/scaleway/go-scaleway/types/types.go
generated
vendored
Normal file
983
src/cmd/linuxkit/vendor/github.com/scaleway/go-scaleway/types/types.go
generated
vendored
Normal file
@@ -0,0 +1,983 @@
|
||||
// Copyright (C) 2018 Scaleway. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE.md file.
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/moul/anonuuid"
|
||||
)
|
||||
|
||||
// ParseNeedle parses a user needle and try to extract a forced object type
|
||||
// i.e:
|
||||
// - server:blah-blah -> kind=server, needle=blah-blah
|
||||
// - blah-blah -> kind="", needle=blah-blah
|
||||
// - not-existing-type:blah-blah
|
||||
func ParseNeedle(input string) (identifierType int, needle string) {
|
||||
parts := strings.Split(input, ":")
|
||||
if len(parts) == 2 {
|
||||
switch parts[0] {
|
||||
case "server":
|
||||
return IdentifierServer, parts[1]
|
||||
case "image":
|
||||
return IdentifierImage, parts[1]
|
||||
case "snapshot":
|
||||
return IdentifierSnapshot, parts[1]
|
||||
case "bootscript":
|
||||
return IdentifierBootscript, parts[1]
|
||||
case "volume":
|
||||
return IdentifierVolume, parts[1]
|
||||
}
|
||||
}
|
||||
return IdentifierUnknown, input
|
||||
}
|
||||
|
||||
const (
|
||||
// IdentifierUnknown is used when we don't know explicitly the type key of the object (used for nil comparison)
|
||||
IdentifierUnknown = 1 << iota
|
||||
// IdentifierServer is the type key of cached server objects
|
||||
IdentifierServer
|
||||
// IdentifierImage is the type key of cached image objects
|
||||
IdentifierImage
|
||||
// IdentifierSnapshot is the type key of cached snapshot objects
|
||||
IdentifierSnapshot
|
||||
// IdentifierBootscript is the type key of cached bootscript objects
|
||||
IdentifierBootscript
|
||||
// IdentifierVolume is the type key of cached volume objects
|
||||
IdentifierVolume
|
||||
)
|
||||
|
||||
// ScalewayResolverResult is a structure containing human-readable information
|
||||
// about resolver results. This structure is used to display the user choices.
|
||||
type ScalewayResolverResult struct {
|
||||
Identifier string
|
||||
Type int
|
||||
Name string
|
||||
Arch string
|
||||
Needle string
|
||||
RankMatch int
|
||||
Region string
|
||||
}
|
||||
|
||||
// ScalewayResolverResults is a list of `ScalewayResolverResult`
|
||||
type ScalewayResolverResults []ScalewayResolverResult
|
||||
|
||||
// NewScalewayResolverResult returns a new ScalewayResolverResult
|
||||
func NewScalewayResolverResult(Identifier, Name, Arch, Region string, Type int) (ScalewayResolverResult, error) {
|
||||
if err := anonuuid.IsUUID(Identifier); err != nil {
|
||||
return ScalewayResolverResult{}, err
|
||||
}
|
||||
return ScalewayResolverResult{
|
||||
Identifier: Identifier,
|
||||
Type: Type,
|
||||
Name: Name,
|
||||
Arch: Arch,
|
||||
Region: Region,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s ScalewayResolverResults) Len() int {
|
||||
return len(s)
|
||||
}
|
||||
|
||||
func (s ScalewayResolverResults) Swap(i, j int) {
|
||||
s[i], s[j] = s[j], s[i]
|
||||
}
|
||||
|
||||
func (s ScalewayResolverResults) Less(i, j int) bool {
|
||||
return s[i].RankMatch < s[j].RankMatch
|
||||
}
|
||||
|
||||
// TruncIdentifier returns first 8 characters of an Identifier (UUID)
|
||||
func (s *ScalewayResolverResult) TruncIdentifier() string {
|
||||
return s.Identifier[:8]
|
||||
}
|
||||
|
||||
func identifierTypeName(kind int) string {
|
||||
switch kind {
|
||||
case IdentifierServer:
|
||||
return "Server"
|
||||
case IdentifierImage:
|
||||
return "Image"
|
||||
case IdentifierSnapshot:
|
||||
return "Snapshot"
|
||||
case IdentifierVolume:
|
||||
return "Volume"
|
||||
case IdentifierBootscript:
|
||||
return "Bootscript"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// CodeName returns a full resource name with typed prefix
|
||||
func (s *ScalewayResolverResult) CodeName() string {
|
||||
name := strings.ToLower(s.Name)
|
||||
name = regexp.MustCompile(`[^a-z0-9-]`).ReplaceAllString(name, "-")
|
||||
name = regexp.MustCompile(`--+`).ReplaceAllString(name, "-")
|
||||
name = strings.Trim(name, "-")
|
||||
|
||||
return fmt.Sprintf("%s:%s", strings.ToLower(identifierTypeName(s.Type)), name)
|
||||
}
|
||||
|
||||
// FilterByArch deletes the elements which not match with arch
|
||||
func (s *ScalewayResolverResults) FilterByArch(arch string) {
|
||||
REDO:
|
||||
for i := range *s {
|
||||
if (*s)[i].Arch != arch {
|
||||
(*s)[i] = (*s)[len(*s)-1]
|
||||
*s = (*s)[:len(*s)-1]
|
||||
goto REDO
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ScalewayAPIError represents a Scaleway API Error
|
||||
type ScalewayAPIError struct {
|
||||
// Message is a human-friendly error message
|
||||
APIMessage string `json:"message,omitempty"`
|
||||
|
||||
// Type is a string code that defines the kind of error
|
||||
Type string `json:"type,omitempty"`
|
||||
|
||||
// Fields contains detail about validation error
|
||||
Fields map[string][]string `json:"fields,omitempty"`
|
||||
|
||||
// StatusCode is the HTTP status code received
|
||||
StatusCode int `json:"-"`
|
||||
|
||||
// Message
|
||||
Message string `json:"-"`
|
||||
}
|
||||
|
||||
// Error returns a string representing the error
|
||||
func (e ScalewayAPIError) Error() string {
|
||||
var b bytes.Buffer
|
||||
|
||||
fmt.Fprintf(&b, "StatusCode: %v, ", e.StatusCode)
|
||||
fmt.Fprintf(&b, "Type: %v, ", e.Type)
|
||||
fmt.Fprintf(&b, "APIMessage: \x1b[31m%v\x1b[0m", e.APIMessage)
|
||||
if len(e.Fields) > 0 {
|
||||
fmt.Fprintf(&b, ", Details: %v", e.Fields)
|
||||
}
|
||||
return b.String()
|
||||
}
|
||||
|
||||
// ScalewayIPAddress represents a Scaleway IP address
|
||||
type ScalewayIPAddress struct {
|
||||
// Identifier is a unique identifier for the IP address
|
||||
Identifier string `json:"id,omitempty"`
|
||||
|
||||
// IP is an IPv4 address
|
||||
IP string `json:"address,omitempty"`
|
||||
|
||||
// Dynamic is a flag that defines an IP that change on each reboot
|
||||
Dynamic *bool `json:"dynamic,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewayVolume represents a Scaleway Volume
|
||||
type ScalewayVolume struct {
|
||||
// Identifier is a unique identifier for the volume
|
||||
Identifier string `json:"id,omitempty"`
|
||||
|
||||
// Size is the allocated size of the volume
|
||||
Size uint64 `json:"size,omitempty"`
|
||||
|
||||
// CreationDate is the creation date of the volume
|
||||
CreationDate string `json:"creation_date,omitempty"`
|
||||
|
||||
// ModificationDate is the date of the last modification of the volume
|
||||
ModificationDate string `json:"modification_date,omitempty"`
|
||||
|
||||
// Organization is the organization owning the volume
|
||||
Organization string `json:"organization,omitempty"`
|
||||
|
||||
// Name is the name of the volume
|
||||
Name string `json:"name,omitempty"`
|
||||
|
||||
// Server is the server using this image
|
||||
Server *struct {
|
||||
Identifier string `json:"id,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
} `json:"server,omitempty"`
|
||||
|
||||
// VolumeType is a Scaleway identifier for the kind of volume (default: l_ssd)
|
||||
VolumeType string `json:"volume_type,omitempty"`
|
||||
|
||||
// ExportURI represents the url used by initrd/scripts to attach the volume
|
||||
ExportURI string `json:"export_uri,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewayOneVolume represents the response of a GET /volumes/UUID API call
|
||||
type ScalewayOneVolume struct {
|
||||
Volume ScalewayVolume `json:"volume,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewayVolumes represents a group of Scaleway volumes
|
||||
type ScalewayVolumes struct {
|
||||
// Volumes holds scaleway volumes of the response
|
||||
Volumes []ScalewayVolume `json:"volumes,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewayVolumeDefinition represents a Scaleway volume definition
|
||||
type ScalewayVolumeDefinition struct {
|
||||
// Name is the user-defined name of the volume
|
||||
Name string `json:"name"`
|
||||
|
||||
// Image is the image used by the volume
|
||||
Size uint64 `json:"size"`
|
||||
|
||||
// Bootscript is the bootscript used by the volume
|
||||
Type string `json:"volume_type"`
|
||||
|
||||
// Organization is the owner of the volume
|
||||
Organization string `json:"organization"`
|
||||
}
|
||||
|
||||
// ScalewayVolumePutDefinition represents a Scaleway volume with nullable fields (for PUT)
|
||||
type ScalewayVolumePutDefinition struct {
|
||||
Identifier *string `json:"id,omitempty"`
|
||||
Size *uint64 `json:"size,omitempty"`
|
||||
CreationDate *string `json:"creation_date,omitempty"`
|
||||
ModificationDate *string `json:"modification_date,omitempty"`
|
||||
Organization *string `json:"organization,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
Server struct {
|
||||
Identifier *string `json:"id,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
} `json:"server,omitempty"`
|
||||
VolumeType *string `json:"volume_type,omitempty"`
|
||||
ExportURI *string `json:"export_uri,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewayImage represents a Scaleway Image
|
||||
type ScalewayImage struct {
|
||||
// Identifier is a unique identifier for the image
|
||||
Identifier string `json:"id,omitempty"`
|
||||
|
||||
// Name is a user-defined name for the image
|
||||
Name string `json:"name,omitempty"`
|
||||
|
||||
// CreationDate is the creation date of the image
|
||||
CreationDate string `json:"creation_date,omitempty"`
|
||||
|
||||
// ModificationDate is the date of the last modification of the image
|
||||
ModificationDate string `json:"modification_date,omitempty"`
|
||||
|
||||
// RootVolume is the root volume bound to the image
|
||||
RootVolume ScalewayVolume `json:"root_volume,omitempty"`
|
||||
|
||||
// Public is true for public images and false for user images
|
||||
Public bool `json:"public,omitempty"`
|
||||
|
||||
// Bootscript is the bootscript bound to the image
|
||||
DefaultBootscript *ScalewayBootscript `json:"default_bootscript,omitempty"`
|
||||
|
||||
// Organization is the owner of the image
|
||||
Organization string `json:"organization,omitempty"`
|
||||
|
||||
// Arch is the architecture target of the image
|
||||
Arch string `json:"arch,omitempty"`
|
||||
|
||||
// FIXME: extra_volumes
|
||||
}
|
||||
|
||||
// ScalewayImageIdentifier represents a Scaleway Image Identifier
|
||||
type ScalewayImageIdentifier struct {
|
||||
Identifier string
|
||||
Arch string
|
||||
Region string
|
||||
Owner string
|
||||
}
|
||||
|
||||
// ScalewayOneImage represents the response of a GET /images/UUID API call
|
||||
type ScalewayOneImage struct {
|
||||
Image ScalewayImage `json:"image,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewayImages represents a group of Scaleway images
|
||||
type ScalewayImages struct {
|
||||
// Images holds scaleway images of the response
|
||||
Images []ScalewayImage `json:"images,omitempty"`
|
||||
}
|
||||
|
||||
// ProductNetworkInterface gives interval and external allowed bandwidth
|
||||
type ProductNetworkInterface struct {
|
||||
InternalBandwidth uint64 `json:"internal_bandwidth,omitempty"`
|
||||
InternetBandwidth uint64 `json:"internet_bandwidth,omitempty"`
|
||||
}
|
||||
|
||||
// ProductNetwork lists all the network interfaces
|
||||
type ProductNetwork struct {
|
||||
Interfaces []ProductNetworkInterface `json:"interfaces,omitempty"`
|
||||
TotalInternalBandwidth uint64 `json:"sum_internal_bandwidth,omitempty"`
|
||||
TotalInternetBandwidth uint64 `json:"sum_internet_bandwidth,omitempty"`
|
||||
IPv6_Support bool `json:"ipv6_support,omitempty"`
|
||||
}
|
||||
|
||||
// ProductVolumeConstraint contains any volume constraint that the offer has
|
||||
type ProductVolumeConstraint struct {
|
||||
MinSize uint64 `json:"min_size,omitempty"`
|
||||
MaxSize uint64 `json:"max_size,omitempty"`
|
||||
}
|
||||
|
||||
// ProductServerOffer represents a specific offer
|
||||
type ProductServer struct {
|
||||
Arch string `json:"arch,omitempty"`
|
||||
Ncpus uint64 `json:"ncpus,omitempty"`
|
||||
Ram uint64 `json:"ram,omitempty"`
|
||||
Baremetal bool `json:"baremetal,omitempty"`
|
||||
VolumesConstraint ProductVolumeConstraint `json:"volumes_constraint,omitempty"`
|
||||
AltNames []string `json:"alt_names,omitempty"`
|
||||
Network ProductNetwork `json:"network,omitempty"`
|
||||
}
|
||||
|
||||
// Products holds a map of all Scaleway servers
|
||||
type ScalewayProductsServers struct {
|
||||
Servers map[string]ProductServer `json:"servers"`
|
||||
}
|
||||
|
||||
// ScalewaySnapshot represents a Scaleway Snapshot
|
||||
type ScalewaySnapshot struct {
|
||||
// Identifier is a unique identifier for the snapshot
|
||||
Identifier string `json:"id,omitempty"`
|
||||
|
||||
// Name is a user-defined name for the snapshot
|
||||
Name string `json:"name,omitempty"`
|
||||
|
||||
// CreationDate is the creation date of the snapshot
|
||||
CreationDate string `json:"creation_date,omitempty"`
|
||||
|
||||
// ModificationDate is the date of the last modification of the snapshot
|
||||
ModificationDate string `json:"modification_date,omitempty"`
|
||||
|
||||
// Size is the allocated size of the volume
|
||||
Size uint64 `json:"size,omitempty"`
|
||||
|
||||
// Organization is the owner of the snapshot
|
||||
Organization string `json:"organization"`
|
||||
|
||||
// State is the current state of the snapshot
|
||||
State string `json:"state"`
|
||||
|
||||
// VolumeType is the kind of volume behind the snapshot
|
||||
VolumeType string `json:"volume_type"`
|
||||
|
||||
// BaseVolume is the volume from which the snapshot inherits
|
||||
BaseVolume ScalewayVolume `json:"base_volume,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewayOneSnapshot represents the response of a GET /snapshots/UUID API call
|
||||
type ScalewayOneSnapshot struct {
|
||||
Snapshot ScalewaySnapshot `json:"snapshot,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewaySnapshots represents a group of Scaleway snapshots
|
||||
type ScalewaySnapshots struct {
|
||||
// Snapshots holds scaleway snapshots of the response
|
||||
Snapshots []ScalewaySnapshot `json:"snapshots,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewayBootscript represents a Scaleway Bootscript
|
||||
type ScalewayBootscript struct {
|
||||
Bootcmdargs string `json:"bootcmdargs,omitempty"`
|
||||
Dtb string `json:"dtb,omitempty"`
|
||||
Initrd string `json:"initrd,omitempty"`
|
||||
Kernel string `json:"kernel,omitempty"`
|
||||
|
||||
// Arch is the architecture target of the bootscript
|
||||
Arch string `json:"architecture,omitempty"`
|
||||
|
||||
// Identifier is a unique identifier for the bootscript
|
||||
Identifier string `json:"id,omitempty"`
|
||||
|
||||
// Organization is the owner of the bootscript
|
||||
Organization string `json:"organization,omitempty"`
|
||||
|
||||
// Name is a user-defined name for the bootscript
|
||||
Title string `json:"title,omitempty"`
|
||||
|
||||
// Public is true for public bootscripts and false for user bootscripts
|
||||
Public bool `json:"public,omitempty"`
|
||||
|
||||
Default bool `json:"default,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewayOneBootscript represents the response of a GET /bootscripts/UUID API call
|
||||
type ScalewayOneBootscript struct {
|
||||
Bootscript ScalewayBootscript `json:"bootscript,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewayBootscripts represents a group of Scaleway bootscripts
|
||||
type ScalewayBootscripts struct {
|
||||
// Bootscripts holds Scaleway bootscripts of the response
|
||||
Bootscripts []ScalewayBootscript `json:"bootscripts,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewayTask represents a Scaleway Task
|
||||
type ScalewayTask struct {
|
||||
// Identifier is a unique identifier for the task
|
||||
Identifier string `json:"id,omitempty"`
|
||||
|
||||
// StartDate is the start date of the task
|
||||
StartDate string `json:"started_at,omitempty"`
|
||||
|
||||
// TerminationDate is the termination date of the task
|
||||
TerminationDate string `json:"terminated_at,omitempty"`
|
||||
|
||||
HrefFrom string `json:"href_from,omitempty"`
|
||||
|
||||
Description string `json:"description,omitempty"`
|
||||
|
||||
Status string `json:"status,omitempty"`
|
||||
|
||||
Progress int `json:"progress,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewayOneTask represents the response of a GET /tasks/UUID API call
|
||||
type ScalewayOneTask struct {
|
||||
Task ScalewayTask `json:"task,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewayTasks represents a group of Scaleway tasks
|
||||
type ScalewayTasks struct {
|
||||
// Tasks holds scaleway tasks of the response
|
||||
Tasks []ScalewayTask `json:"tasks,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewaySecurityGroupRule definition
|
||||
type ScalewaySecurityGroupRule struct {
|
||||
Direction string `json:"direction"`
|
||||
Protocol string `json:"protocol"`
|
||||
IPRange string `json:"ip_range"`
|
||||
DestPortFrom int `json:"dest_port_from,omitempty"`
|
||||
Action string `json:"action"`
|
||||
Position int `json:"position"`
|
||||
DestPortTo string `json:"dest_port_to"`
|
||||
Editable bool `json:"editable"`
|
||||
ID string `json:"id"`
|
||||
}
|
||||
|
||||
// ScalewayGetSecurityGroupRules represents the response of a GET /security_group/{groupID}/rules
|
||||
type ScalewayGetSecurityGroupRules struct {
|
||||
Rules []ScalewaySecurityGroupRule `json:"rules"`
|
||||
}
|
||||
|
||||
// ScalewayGetSecurityGroupRule represents the response of a GET /security_group/{groupID}/rules/{ruleID}
|
||||
type ScalewayGetSecurityGroupRule struct {
|
||||
Rules ScalewaySecurityGroupRule `json:"rule"`
|
||||
}
|
||||
|
||||
// ScalewayNewSecurityGroupRule definition POST/PUT request /security_group/{groupID}
|
||||
type ScalewayNewSecurityGroupRule struct {
|
||||
Action string `json:"action"`
|
||||
Direction string `json:"direction"`
|
||||
IPRange string `json:"ip_range"`
|
||||
Protocol string `json:"protocol"`
|
||||
DestPortFrom int `json:"dest_port_from,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewaySecurityGroups definition
|
||||
type ScalewaySecurityGroups struct {
|
||||
Description string `json:"description"`
|
||||
ID string `json:"id"`
|
||||
Organization string `json:"organization"`
|
||||
Name string `json:"name"`
|
||||
Servers []ScalewaySecurityGroup `json:"servers"`
|
||||
EnableDefaultSecurity bool `json:"enable_default_security"`
|
||||
OrganizationDefault bool `json:"organization_default"`
|
||||
}
|
||||
|
||||
// ScalewayGetSecurityGroups represents the response of a GET /security_groups/
|
||||
type ScalewayGetSecurityGroups struct {
|
||||
SecurityGroups []ScalewaySecurityGroups `json:"security_groups"`
|
||||
}
|
||||
|
||||
// ScalewayGetSecurityGroup represents the response of a GET /security_groups/{groupID}
|
||||
type ScalewayGetSecurityGroup struct {
|
||||
SecurityGroups ScalewaySecurityGroups `json:"security_group"`
|
||||
}
|
||||
|
||||
// ScalewayIPDefinition represents the IP's fields
|
||||
type ScalewayIPDefinition struct {
|
||||
Organization string `json:"organization"`
|
||||
Reverse *string `json:"reverse"`
|
||||
ID string `json:"id"`
|
||||
Server *struct {
|
||||
Identifier string `json:"id,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
} `json:"server"`
|
||||
Address string `json:"address"`
|
||||
}
|
||||
|
||||
// ScalewayGetIPS represents the response of a GET /ips/
|
||||
type ScalewayGetIPS struct {
|
||||
IPS []ScalewayIPDefinition `json:"ips"`
|
||||
}
|
||||
|
||||
// ScalewayGetIP represents the response of a GET /ips/{id_ip}
|
||||
type ScalewayGetIP struct {
|
||||
IP ScalewayIPDefinition `json:"ip"`
|
||||
}
|
||||
|
||||
// ScalewaySecurityGroup represents a Scaleway security group
|
||||
type ScalewaySecurityGroup struct {
|
||||
// Identifier is a unique identifier for the security group
|
||||
Identifier string `json:"id,omitempty"`
|
||||
|
||||
// Name is the user-defined name of the security group
|
||||
Name string `json:"name,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewayNewSecurityGroup definition POST request /security_groups
|
||||
type ScalewayNewSecurityGroup struct {
|
||||
Organization string `json:"organization"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
// ScalewayUpdateSecurityGroup definition PUT request /security_groups
|
||||
type ScalewayUpdateSecurityGroup struct {
|
||||
Organization string `json:"organization"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
OrganizationDefault bool `json:"organization_default"`
|
||||
}
|
||||
|
||||
// ScalewayServer represents a Scaleway server
|
||||
type ScalewayServer struct {
|
||||
// Arch is the architecture target of the server
|
||||
Arch string `json:"arch,omitempty"`
|
||||
|
||||
// Identifier is a unique identifier for the server
|
||||
Identifier string `json:"id,omitempty"`
|
||||
|
||||
// Name is the user-defined name of the server
|
||||
Name string `json:"name,omitempty"`
|
||||
|
||||
// CreationDate is the creation date of the server
|
||||
CreationDate string `json:"creation_date,omitempty"`
|
||||
|
||||
// ModificationDate is the date of the last modification of the server
|
||||
ModificationDate string `json:"modification_date,omitempty"`
|
||||
|
||||
// Image is the image used by the server
|
||||
Image ScalewayImage `json:"image,omitempty"`
|
||||
|
||||
// DynamicIPRequired is a flag that defines a server with a dynamic ip address attached
|
||||
DynamicIPRequired *bool `json:"dynamic_ip_required,omitempty"`
|
||||
|
||||
// PublicIP is the public IP address bound to the server
|
||||
PublicAddress ScalewayIPAddress `json:"public_ip,omitempty"`
|
||||
|
||||
// State is the current status of the server
|
||||
State string `json:"state,omitempty"`
|
||||
|
||||
// StateDetail is the detailed status of the server
|
||||
StateDetail string `json:"state_detail,omitempty"`
|
||||
|
||||
// PrivateIP represents the private IPV4 attached to the server (changes on each boot)
|
||||
PrivateIP string `json:"private_ip,omitempty"`
|
||||
|
||||
// Bootscript is the unique identifier of the selected bootscript
|
||||
Bootscript *ScalewayBootscript `json:"bootscript,omitempty"`
|
||||
|
||||
// Hostname represents the ServerName in a format compatible with unix's hostname
|
||||
Hostname string `json:"hostname,omitempty"`
|
||||
|
||||
// Tags represents user-defined tags
|
||||
Tags []string `json:"tags,omitempty"`
|
||||
|
||||
// Volumes are the attached volumes
|
||||
Volumes map[string]ScalewayVolume `json:"volumes,omitempty"`
|
||||
|
||||
// SecurityGroup is the selected security group object
|
||||
SecurityGroup ScalewaySecurityGroup `json:"security_group,omitempty"`
|
||||
|
||||
// Organization is the owner of the server
|
||||
Organization string `json:"organization,omitempty"`
|
||||
|
||||
// CommercialType is the commercial type of the server (i.e: C1, C2[SML], VC1S)
|
||||
CommercialType string `json:"commercial_type,omitempty"`
|
||||
|
||||
// Location of the server
|
||||
Location struct {
|
||||
Platform string `json:"platform_id,omitempty"`
|
||||
Chassis string `json:"chassis_id,omitempty"`
|
||||
Cluster string `json:"cluster_id,omitempty"`
|
||||
Hypervisor string `json:"hypervisor_id,omitempty"`
|
||||
Blade string `json:"blade_id,omitempty"`
|
||||
Node string `json:"node_id,omitempty"`
|
||||
ZoneID string `json:"zone_id,omitempty"`
|
||||
} `json:"location,omitempty"`
|
||||
|
||||
IPV6 *ScalewayIPV6Definition `json:"ipv6,omitempty"`
|
||||
|
||||
EnableIPV6 bool `json:"enable_ipv6,omitempty"`
|
||||
|
||||
// This fields are not returned by the API, we generate it
|
||||
DNSPublic string `json:"dns_public,omitempty"`
|
||||
DNSPrivate string `json:"dns_private,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewayIPV6Definition represents a Scaleway ipv6
|
||||
type ScalewayIPV6Definition struct {
|
||||
Netmask string `json:"netmask"`
|
||||
Gateway string `json:"gateway"`
|
||||
Address string `json:"address"`
|
||||
}
|
||||
|
||||
// ScalewayServerPatchDefinition represents a Scaleway server with nullable fields (for PATCH)
|
||||
type ScalewayServerPatchDefinition struct {
|
||||
Arch *string `json:"arch,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
CreationDate *string `json:"creation_date,omitempty"`
|
||||
ModificationDate *string `json:"modification_date,omitempty"`
|
||||
Image *ScalewayImage `json:"image,omitempty"`
|
||||
DynamicIPRequired *bool `json:"dynamic_ip_required,omitempty"`
|
||||
PublicAddress *ScalewayIPAddress `json:"public_ip,omitempty"`
|
||||
State *string `json:"state,omitempty"`
|
||||
StateDetail *string `json:"state_detail,omitempty"`
|
||||
PrivateIP *string `json:"private_ip,omitempty"`
|
||||
Bootscript *string `json:"bootscript,omitempty"`
|
||||
Hostname *string `json:"hostname,omitempty"`
|
||||
Volumes *map[string]ScalewayVolume `json:"volumes,omitempty"`
|
||||
SecurityGroup *ScalewaySecurityGroup `json:"security_group,omitempty"`
|
||||
Organization *string `json:"organization,omitempty"`
|
||||
Tags *[]string `json:"tags,omitempty"`
|
||||
IPV6 *ScalewayIPV6Definition `json:"ipv6,omitempty"`
|
||||
EnableIPV6 *bool `json:"enable_ipv6,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewayServerDefinition represents a Scaleway server with image definition
|
||||
type ScalewayServerDefinition struct {
|
||||
// Name is the user-defined name of the server
|
||||
Name string `json:"name"`
|
||||
|
||||
// Image is the image used by the server
|
||||
Image *string `json:"image,omitempty"`
|
||||
|
||||
// Volumes are the attached volumes
|
||||
Volumes map[string]string `json:"volumes,omitempty"`
|
||||
|
||||
// DynamicIPRequired is a flag that defines a server with a dynamic ip address attached
|
||||
DynamicIPRequired *bool `json:"dynamic_ip_required,omitempty"`
|
||||
|
||||
// BootType defines the type of boot
|
||||
BootType string `json:"boot_type,omitempty"`
|
||||
|
||||
// Bootscript is the bootscript used by the server
|
||||
Bootscript *string `json:"bootscript"`
|
||||
|
||||
// Tags are the metadata tags attached to the server
|
||||
Tags []string `json:"tags,omitempty"`
|
||||
|
||||
// Organization is the owner of the server
|
||||
Organization string `json:"organization"`
|
||||
|
||||
// CommercialType is the commercial type of the server (i.e: C1, C2[SML], VC1S)
|
||||
CommercialType string `json:"commercial_type"`
|
||||
|
||||
PublicIP string `json:"public_ip,omitempty"`
|
||||
|
||||
EnableIPV6 bool `json:"enable_ipv6,omitempty"`
|
||||
|
||||
SecurityGroup string `json:"security_group,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewayOneServer represents the response of a GET /servers/UUID API call
|
||||
type ScalewayOneServer struct {
|
||||
Server ScalewayServer `json:"server,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewayServers represents a group of Scaleway servers
|
||||
type ScalewayServers struct {
|
||||
// Servers holds scaleway servers of the response
|
||||
Servers []ScalewayServer `json:"servers,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewayServerAction represents an action to perform on a Scaleway server
|
||||
type ScalewayServerAction struct {
|
||||
// Action is the name of the action to trigger
|
||||
Action string `json:"action,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewaySnapshotDefinition represents a Scaleway snapshot definition
|
||||
type ScalewaySnapshotDefinition struct {
|
||||
VolumeIDentifier string `json:"volume_id"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Organization string `json:"organization"`
|
||||
}
|
||||
|
||||
// ScalewayImageDefinition represents a Scaleway image definition
|
||||
type ScalewayImageDefinition struct {
|
||||
SnapshotIDentifier string `json:"root_volume"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Organization string `json:"organization"`
|
||||
Arch string `json:"arch"`
|
||||
DefaultBootscript *string `json:"default_bootscript,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewayRoleDefinition represents a Scaleway Token UserId Role
|
||||
type ScalewayRoleDefinition struct {
|
||||
Organization ScalewayOrganizationDefinition `json:"organization,omitempty"`
|
||||
Role string `json:"role,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewayTokenDefinition represents a Scaleway Token
|
||||
type ScalewayTokenDefinition struct {
|
||||
UserID string `json:"user_id"`
|
||||
Description string `json:"description,omitempty"`
|
||||
Roles ScalewayRoleDefinition `json:"roles"`
|
||||
Expires string `json:"expires"`
|
||||
InheritsUsersPerms bool `json:"inherits_user_perms"`
|
||||
ID string `json:"id"`
|
||||
}
|
||||
|
||||
// ScalewayTokensDefinition represents a Scaleway Tokens
|
||||
type ScalewayTokensDefinition struct {
|
||||
Token ScalewayTokenDefinition `json:"token"`
|
||||
}
|
||||
|
||||
// ScalewayGetTokens represents a list of Scaleway Tokens
|
||||
type ScalewayGetTokens struct {
|
||||
Tokens []ScalewayTokenDefinition `json:"tokens"`
|
||||
}
|
||||
|
||||
// ScalewayContainerData represents a Scaleway container data (S3)
|
||||
type ScalewayContainerData struct {
|
||||
LastModified string `json:"last_modified"`
|
||||
Name string `json:"name"`
|
||||
Size string `json:"size"`
|
||||
}
|
||||
|
||||
// ScalewayGetContainerDatas represents a list of Scaleway containers data (S3)
|
||||
type ScalewayGetContainerDatas struct {
|
||||
Container []ScalewayContainerData `json:"container"`
|
||||
}
|
||||
|
||||
// ScalewayContainer represents a Scaleway container (S3)
|
||||
type ScalewayContainer struct {
|
||||
ScalewayOrganizationDefinition `json:"organization"`
|
||||
Name string `json:"name"`
|
||||
Size string `json:"size"`
|
||||
}
|
||||
|
||||
// ScalewayGetContainers represents a list of Scaleway containers (S3)
|
||||
type ScalewayGetContainers struct {
|
||||
Containers []ScalewayContainer `json:"containers"`
|
||||
}
|
||||
|
||||
// ScalewayConnectResponse represents the answer from POST /tokens
|
||||
type ScalewayConnectResponse struct {
|
||||
Token ScalewayTokenDefinition `json:"token"`
|
||||
}
|
||||
|
||||
// ScalewayConnect represents the data to connect
|
||||
type ScalewayConnect struct {
|
||||
Email string `json:"email"`
|
||||
Password string `json:"password"`
|
||||
Description string `json:"description"`
|
||||
Expires bool `json:"expires"`
|
||||
}
|
||||
|
||||
// ScalewayConnectInterface is the interface implemented by ScalewayConnect,
|
||||
// ScalewayConnectByOTP and ScalewayConnectByBackupCode
|
||||
type ScalewayConnectInterface interface {
|
||||
GetPassword() string
|
||||
}
|
||||
|
||||
func (s *ScalewayConnect) GetPassword() string {
|
||||
return s.Password
|
||||
}
|
||||
|
||||
type ScalewayConnectByOTP struct {
|
||||
ScalewayConnect
|
||||
TwoFAToken string `json:"2FA_token"`
|
||||
}
|
||||
|
||||
type ScalewayConnectByBackupCode struct {
|
||||
ScalewayConnect
|
||||
TwoFABackupCode string `json:"2FA_backup_code"`
|
||||
}
|
||||
|
||||
// ScalewayOrganizationDefinition represents a Scaleway Organization
|
||||
type ScalewayOrganizationDefinition struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Users []ScalewayUserDefinition `json:"users"`
|
||||
}
|
||||
|
||||
// ScalewayOrganizationsDefinition represents a Scaleway Organizations
|
||||
type ScalewayOrganizationsDefinition struct {
|
||||
Organizations []ScalewayOrganizationDefinition `json:"organizations"`
|
||||
}
|
||||
|
||||
// ScalewayUserDefinition represents a Scaleway User
|
||||
type ScalewayUserDefinition struct {
|
||||
Email string `json:"email"`
|
||||
Firstname string `json:"firstname"`
|
||||
Fullname string `json:"fullname"`
|
||||
ID string `json:"id"`
|
||||
Lastname string `json:"lastname"`
|
||||
Organizations []ScalewayOrganizationDefinition `json:"organizations"`
|
||||
Roles []ScalewayRoleDefinition `json:"roles"`
|
||||
SSHPublicKeys []ScalewayKeyDefinition `json:"ssh_public_keys"`
|
||||
}
|
||||
|
||||
// ScalewayUsersDefinition represents the response of a GET /user
|
||||
type ScalewayUsersDefinition struct {
|
||||
User ScalewayUserDefinition `json:"user"`
|
||||
}
|
||||
|
||||
// ScalewayKeyDefinition represents a key
|
||||
type ScalewayKeyDefinition struct {
|
||||
Key string `json:"key"`
|
||||
Fingerprint string `json:"fingerprint,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewayUserPatchSSHKeyDefinition represents a User Patch
|
||||
type ScalewayUserPatchSSHKeyDefinition struct {
|
||||
SSHPublicKeys []ScalewayKeyDefinition `json:"ssh_public_keys"`
|
||||
}
|
||||
|
||||
// ScalewayDashboardResp represents a dashboard received from the API
|
||||
type ScalewayDashboardResp struct {
|
||||
Dashboard ScalewayDashboard
|
||||
}
|
||||
|
||||
// ScalewayDashboard represents a dashboard
|
||||
type ScalewayDashboard struct {
|
||||
VolumesCount int `json:"volumes_count"`
|
||||
RunningServersCount int `json:"running_servers_count"`
|
||||
ImagesCount int `json:"images_count"`
|
||||
SnapshotsCount int `json:"snapshots_count"`
|
||||
ServersCount int `json:"servers_count"`
|
||||
IPsCount int `json:"ips_count"`
|
||||
}
|
||||
|
||||
// ScalewayPermissions represents the response of GET /permissions
|
||||
type ScalewayPermissions map[string]ScalewayPermCategory
|
||||
|
||||
// ScalewayPermCategory represents ScalewayPermissions's fields
|
||||
type ScalewayPermCategory map[string][]string
|
||||
|
||||
// ScalewayPermissionDefinition represents the permissions
|
||||
type ScalewayPermissionDefinition struct {
|
||||
Permissions ScalewayPermissions `json:"permissions"`
|
||||
}
|
||||
|
||||
// ScalewayUserdatas represents the response of a GET /user_data
|
||||
type ScalewayUserdatas struct {
|
||||
UserData []string `json:"user_data"`
|
||||
}
|
||||
|
||||
// ScalewayQuota represents a map of quota (name, value)
|
||||
type ScalewayQuota map[string]int
|
||||
|
||||
// ScalewayGetQuotas represents the response of GET /organizations/{orga_id}/quotas
|
||||
type ScalewayGetQuotas struct {
|
||||
Quotas ScalewayQuota `json:"quotas"`
|
||||
}
|
||||
|
||||
// ScalewayUserdata represents []byte
|
||||
type ScalewayUserdata []byte
|
||||
|
||||
// FuncMap used for json inspection
|
||||
var FuncMap = template.FuncMap{
|
||||
"json": func(v interface{}) string {
|
||||
a, _ := json.Marshal(v)
|
||||
return string(a)
|
||||
},
|
||||
}
|
||||
|
||||
// MarketLocalImageDefinition represents localImage of marketplace version
|
||||
type MarketLocalImageDefinition struct {
|
||||
Arch string `json:"arch"`
|
||||
ID string `json:"id"`
|
||||
Zone string `json:"zone"`
|
||||
}
|
||||
|
||||
// MarketLocalImages represents an array of local images
|
||||
type MarketLocalImages struct {
|
||||
LocalImages []MarketLocalImageDefinition `json:"local_images"`
|
||||
}
|
||||
|
||||
// MarketLocalImage represents local image
|
||||
type MarketLocalImage struct {
|
||||
LocalImages MarketLocalImageDefinition `json:"local_image"`
|
||||
}
|
||||
|
||||
// MarketVersionDefinition represents version of marketplace image
|
||||
type MarketVersionDefinition struct {
|
||||
CreationDate string `json:"creation_date"`
|
||||
ID string `json:"id"`
|
||||
Image struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
} `json:"image"`
|
||||
ModificationDate string `json:"modification_date"`
|
||||
Name string `json:"name"`
|
||||
MarketLocalImages
|
||||
}
|
||||
|
||||
// MarketVersions represents an array of marketplace image versions
|
||||
type MarketVersions struct {
|
||||
Versions []MarketVersionDefinition `json:"versions"`
|
||||
}
|
||||
|
||||
// MarketVersion represents version of marketplace image
|
||||
type MarketVersion struct {
|
||||
Version MarketVersionDefinition `json:"version"`
|
||||
}
|
||||
|
||||
// MarketImage represents MarketPlace image
|
||||
type MarketImage struct {
|
||||
Categories []string `json:"categories"`
|
||||
CreationDate string `json:"creation_date"`
|
||||
CurrentPublicVersion string `json:"current_public_version"`
|
||||
Description string `json:"description"`
|
||||
ID string `json:"id"`
|
||||
Logo string `json:"logo"`
|
||||
ModificationDate string `json:"modification_date"`
|
||||
Name string `json:"name"`
|
||||
Organization struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
} `json:"organization"`
|
||||
Public bool `json:"-"`
|
||||
MarketVersions
|
||||
}
|
||||
|
||||
// MarketImages represents MarketPlace images
|
||||
type MarketImages struct {
|
||||
Images []MarketImage `json:"images"`
|
||||
}
|
||||
|
||||
// ScalewaySortServers represents a wrapper to sort by CreationDate the servers
|
||||
type ScalewaySortServers []ScalewayServer
|
||||
|
||||
func (s ScalewaySortServers) Len() int {
|
||||
return len(s)
|
||||
}
|
||||
|
||||
func (s ScalewaySortServers) Swap(i, j int) {
|
||||
s[i], s[j] = s[j], s[i]
|
||||
}
|
||||
|
||||
func (s ScalewaySortServers) Less(i, j int) bool {
|
||||
date1, _ := time.Parse("2006-01-02T15:04:05.000000+00:00", s[i].CreationDate)
|
||||
date2, _ := time.Parse("2006-01-02T15:04:05.000000+00:00", s[j].CreationDate)
|
||||
return date2.Before(date1)
|
||||
}
|
||||
|
||||
func (s *ScalewayUserdata) String() string {
|
||||
return string(*s)
|
||||
}
|
27
src/cmd/linuxkit/vendor/golang.org/x/sync/LICENSE
generated
vendored
Normal file
27
src/cmd/linuxkit/vendor/golang.org/x/sync/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
Copyright (c) 2009 The Go Authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
22
src/cmd/linuxkit/vendor/golang.org/x/sync/PATENTS
generated
vendored
Normal file
22
src/cmd/linuxkit/vendor/golang.org/x/sync/PATENTS
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
Additional IP Rights Grant (Patents)
|
||||
|
||||
"This implementation" means the copyrightable works distributed by
|
||||
Google as part of the Go project.
|
||||
|
||||
Google 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,
|
||||
transfer and otherwise run, modify and propagate the contents of this
|
||||
implementation of Go, where such license applies only to those patent
|
||||
claims, both currently owned or controlled by Google and acquired in
|
||||
the future, licensable by Google that are necessarily infringed by this
|
||||
implementation of Go. This grant does not include claims that would be
|
||||
infringed only as a consequence of further modification of this
|
||||
implementation. If you or your agent or exclusive licensee institute or
|
||||
order or agree to the institution of patent litigation against any
|
||||
entity (including a cross-claim or counterclaim in a lawsuit) alleging
|
||||
that this implementation of Go or any code incorporated within this
|
||||
implementation of Go constitutes direct or contributory patent
|
||||
infringement, or inducement of patent infringement, then any patent
|
||||
rights granted to you under this License for this implementation of Go
|
||||
shall terminate as of the date such litigation is filed.
|
18
src/cmd/linuxkit/vendor/golang.org/x/sync/README.md
generated
vendored
Normal file
18
src/cmd/linuxkit/vendor/golang.org/x/sync/README.md
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
# Go Sync
|
||||
|
||||
This repository provides Go concurrency primitives in addition to the
|
||||
ones provided by the language and "sync" and "sync/atomic" packages.
|
||||
|
||||
## Download/Install
|
||||
|
||||
The easiest way to install is to run `go get -u golang.org/x/sync`. You can
|
||||
also manually git clone the repository to `$GOPATH/src/golang.org/x/sync`.
|
||||
|
||||
## Report Issues / Send Patches
|
||||
|
||||
This repository uses Gerrit for code changes. To learn how to submit changes to
|
||||
this repository, see https://golang.org/doc/contribute.html.
|
||||
|
||||
The main issue tracker for the sync repository is located at
|
||||
https://github.com/golang/go/issues. Prefix your issue with "x/sync:" in the
|
||||
subject line, so it is easy to find.
|
67
src/cmd/linuxkit/vendor/golang.org/x/sync/errgroup/errgroup.go
generated
vendored
Normal file
67
src/cmd/linuxkit/vendor/golang.org/x/sync/errgroup/errgroup.go
generated
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package errgroup provides synchronization, error propagation, and Context
|
||||
// cancelation for groups of goroutines working on subtasks of a common task.
|
||||
package errgroup
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// A Group is a collection of goroutines working on subtasks that are part of
|
||||
// the same overall task.
|
||||
//
|
||||
// A zero Group is valid and does not cancel on error.
|
||||
type Group struct {
|
||||
cancel func()
|
||||
|
||||
wg sync.WaitGroup
|
||||
|
||||
errOnce sync.Once
|
||||
err error
|
||||
}
|
||||
|
||||
// WithContext returns a new Group and an associated Context derived from ctx.
|
||||
//
|
||||
// The derived Context is canceled the first time a function passed to Go
|
||||
// returns a non-nil error or the first time Wait returns, whichever occurs
|
||||
// first.
|
||||
func WithContext(ctx context.Context) (*Group, context.Context) {
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
return &Group{cancel: cancel}, ctx
|
||||
}
|
||||
|
||||
// Wait blocks until all function calls from the Go method have returned, then
|
||||
// returns the first non-nil error (if any) from them.
|
||||
func (g *Group) Wait() error {
|
||||
g.wg.Wait()
|
||||
if g.cancel != nil {
|
||||
g.cancel()
|
||||
}
|
||||
return g.err
|
||||
}
|
||||
|
||||
// Go calls the given function in a new goroutine.
|
||||
//
|
||||
// The first call to return a non-nil error cancels the group; its error will be
|
||||
// returned by Wait.
|
||||
func (g *Group) Go(f func() error) {
|
||||
g.wg.Add(1)
|
||||
|
||||
go func() {
|
||||
defer g.wg.Done()
|
||||
|
||||
if err := f(); err != nil {
|
||||
g.errOnce.Do(func() {
|
||||
g.err = err
|
||||
if g.cancel != nil {
|
||||
g.cancel()
|
||||
}
|
||||
})
|
||||
}
|
||||
}()
|
||||
}
|
Reference in New Issue
Block a user